main.c revision 30715
16059Samurai/*
26059Samurai *			User Process PPP
36059Samurai *
46059Samurai *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
56059Samurai *
66059Samurai *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
76059Samurai *
86059Samurai * Redistribution and use in source and binary forms are permitted
96059Samurai * provided that the above copyright notice and this paragraph are
106059Samurai * duplicated in all such forms and that any documentation,
116059Samurai * advertising materials, and other materials related to such
126059Samurai * distribution and use acknowledge that the software was developed
136059Samurai * by the Internet Initiative Japan, Inc.  The name of the
146059Samurai * IIJ may not be used to endorse or promote products derived
156059Samurai * from this software without specific prior written permission.
166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
196059Samurai *
2030715Sbrian * $Id: main.c,v 1.84 1997/10/24 22:36:30 brian Exp $
218857Srgrimes *
226059Samurai *	TODO:
236059Samurai *		o Add commands for traffic summary, version display, etc.
246059Samurai *		o Add signal handler for misc controls.
256059Samurai */
2630715Sbrian#include <sys/param.h>
2730715Sbrian#include <sys/socket.h>
2830715Sbrian#include <netinet/in.h>
2930715Sbrian#include <netinet/in_systm.h>
3030715Sbrian#include <netinet/ip.h>
3130715Sbrian#include <arpa/inet.h>
3230715Sbrian#include <netdb.h>
3330715Sbrian
3430715Sbrian#include <errno.h>
356059Samurai#include <fcntl.h>
3611336Samurai#include <paths.h>
3730715Sbrian#include <signal.h>
3830715Sbrian#include <stdio.h>
3930715Sbrian#include <stdlib.h>
4030715Sbrian#include <string.h>
416059Samurai#include <sys/time.h>
4230715Sbrian#include <sys/wait.h>
4330715Sbrian#include <sysexits.h>
446059Samurai#include <termios.h>
4518786Sjkh#include <unistd.h>
4630715Sbrian
4730715Sbrian#include "mbuf.h"
4830715Sbrian#include "log.h"
4930715Sbrian#include "defs.h"
5030715Sbrian#include "timer.h"
5130715Sbrian#include "fsm.h"
526059Samurai#include "modem.h"
536059Samurai#include "os.h"
546059Samurai#include "hdlc.h"
5513389Sphk#include "ccp.h"
566059Samurai#include "lcp.h"
576059Samurai#include "ipcp.h"
5826142Sbrian#include "loadalias.h"
5930715Sbrian#include "command.h"
606059Samurai#include "vars.h"
616735Samurai#include "auth.h"
627001Samurai#include "filter.h"
6313389Sphk#include "systems.h"
6413389Sphk#include "ip.h"
6523840Sbrian#include "sig.h"
6626940Sbrian#include "server.h"
6728536Sbrian#include "lcpproto.h"
6830715Sbrian#include "main.h"
6930715Sbrian#include "vjcomp.h"
7030715Sbrian#include "async.h"
716059Samurai
726735Samurai#ifndef O_NONBLOCK
736735Samurai#ifdef O_NDELAY
746735Samurai#define	O_NONBLOCK O_NDELAY
756735Samurai#endif
766735Samurai#endif
776735Samurai
7830715Sbrianint TermMode = 0;
7930715Sbrianint tunno = 0;
806059Samurai
8128679Sbrianstatic struct termios oldtio;	/* Original tty mode */
8228679Sbrianstatic struct termios comtio;	/* Command level tty mode */
8320813Sjkhstatic pid_t BGPid = 0;
8425634Sbrianstatic char pid_filename[MAXPATHLEN];
8525634Sbrianstatic char if_filename[MAXPATHLEN];
8627061Sbrianstatic int dial_up;
876059Samurai
8830715Sbrianstatic void DoLoop(void);
8930715Sbrianstatic void TerminalStop(int);
9030715Sbrianstatic char *ex_desc(int);
9130715Sbrian
926059Samuraistatic void
9326858SbrianTtyInit(int DontWantInt)
946059Samurai{
956059Samurai  struct termios newtio;
966059Samurai  int stat;
976059Samurai
986059Samurai  stat = fcntl(0, F_GETFL, 0);
9925630Sbrian  if (stat > 0) {
10028679Sbrian    stat |= O_NONBLOCK;
10128679Sbrian    (void) fcntl(0, F_SETFL, stat);
10225630Sbrian  }
1036059Samurai  newtio = oldtio;
10428679Sbrian  newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
1056059Samurai  newtio.c_iflag = 0;
1066059Samurai  newtio.c_oflag &= ~OPOST;
1076059Samurai  newtio.c_cc[VEOF] = _POSIX_VDISABLE;
10826858Sbrian  if (DontWantInt)
10926858Sbrian    newtio.c_cc[VINTR] = _POSIX_VDISABLE;
1106059Samurai  newtio.c_cc[VMIN] = 1;
1116059Samurai  newtio.c_cc[VTIME] = 0;
1126059Samurai  newtio.c_cflag |= CS8;
1136735Samurai  tcsetattr(0, TCSADRAIN, &newtio);
1146059Samurai  comtio = newtio;
1156059Samurai}
1166059Samurai
1176059Samurai/*
1186059Samurai *  Set tty into command mode. We allow canonical input and echo processing.
1196059Samurai */
12010528Samuraivoid
12128679SbrianTtyCommandMode(int prompt)
1226059Samurai{
1236059Samurai  struct termios newtio;
1246059Samurai  int stat;
1256059Samurai
1266059Samurai  if (!(mode & MODE_INTER))
1276059Samurai    return;
1286735Samurai  tcgetattr(0, &newtio);
12928679Sbrian  newtio.c_lflag |= (ECHO | ISIG | ICANON);
1306059Samurai  newtio.c_iflag = oldtio.c_iflag;
1316059Samurai  newtio.c_oflag |= OPOST;
1326735Samurai  tcsetattr(0, TCSADRAIN, &newtio);
1336059Samurai  stat = fcntl(0, F_GETFL, 0);
13425630Sbrian  if (stat > 0) {
13528679Sbrian    stat |= O_NONBLOCK;
13628679Sbrian    (void) fcntl(0, F_SETFL, stat);
13725630Sbrian  }
1386059Samurai  TermMode = 0;
13928679Sbrian  if (prompt)
14028679Sbrian    Prompt();
1416059Samurai}
1426059Samurai
1436059Samurai/*
1446059Samurai * Set tty into terminal mode which is used while we invoke term command.
1456059Samurai */
1466059Samuraivoid
1476059SamuraiTtyTermMode()
1486059Samurai{
1496059Samurai  int stat;
1506059Samurai
1516735Samurai  tcsetattr(0, TCSADRAIN, &comtio);
1526059Samurai  stat = fcntl(0, F_GETFL, 0);
15325630Sbrian  if (stat > 0) {
15428679Sbrian    stat &= ~O_NONBLOCK;
15528679Sbrian    (void) fcntl(0, F_SETFL, stat);
15625630Sbrian  }
1576059Samurai  TermMode = 1;
1586059Samurai}
1596059Samurai
1606059Samuraivoid
16110528SamuraiTtyOldMode()
1626059Samurai{
1636059Samurai  int stat;
1646059Samurai
1656059Samurai  stat = fcntl(0, F_GETFL, 0);
16625630Sbrian  if (stat > 0) {
16728679Sbrian    stat &= ~O_NONBLOCK;
16828679Sbrian    (void) fcntl(0, F_SETFL, stat);
16925630Sbrian  }
1706735Samurai  tcsetattr(0, TCSANOW, &oldtio);
17110528Samurai}
17210528Samurai
17310528Samuraivoid
17428679SbrianCleanup(int excode)
17510528Samurai{
17610528Samurai  OsLinkdown();
1776059Samurai  OsCloseLink(1);
17830697Sbrian  nointr_sleep(1);
17925908Sbrian  if (mode & MODE_AUTO)
1806059Samurai    DeleteIfRoutes(1);
18128679Sbrian  (void) unlink(pid_filename);
18228679Sbrian  (void) unlink(if_filename);
1836059Samurai  OsInterfaceDown(1);
18423863Sbrian  if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
18523863Sbrian    char c = EX_ERRDEAD;
18628679Sbrian
18728679Sbrian    if (write(BGFiledes[1], &c, 1) == 1)
18828679Sbrian      LogPrintf(LogPHASE, "Parent notified of failure.\n");
18923863Sbrian    else
19028679Sbrian      LogPrintf(LogPHASE, "Failed to notify parent of failure.\n");
19123863Sbrian    close(BGFiledes[1]);
19223863Sbrian  }
19328679Sbrian  LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
1946059Samurai  LogClose();
19526940Sbrian  ServerClose();
19610528Samurai  TtyOldMode();
1976059Samurai
1986059Samurai  exit(excode);
1996059Samurai}
2006059Samurai
2016059Samuraistatic void
20228679SbrianCloseConnection(int signo)
2036059Samurai{
20426858Sbrian  /* NOTE, these are manual, we've done a setsid() */
20527157Sbrian  LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo);
20628679Sbrian  reconnectState = RECON_FALSE;
20728684Sbrian  reconnectCount = 0;
20828684Sbrian  DownConnection();
20930715Sbrian  dial_up = 0;
2106059Samurai}
2116059Samurai
2126059Samuraistatic void
21328679SbrianCloseSession(int signo)
2146059Samurai{
21528679Sbrian  if (BGPid) {
21628679Sbrian    kill(BGPid, SIGINT);
21728679Sbrian    exit(EX_TERM);
21828679Sbrian  }
21928679Sbrian  LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
22028679Sbrian  reconnect(RECON_FALSE);
22128679Sbrian  LcpClose();
22228679Sbrian  Cleanup(EX_TERM);
2236059Samurai}
2246059Samurai
22510528Samuraistatic void
22610528SamuraiTerminalCont()
22710528Samurai{
22823840Sbrian  pending_signal(SIGCONT, SIG_DFL);
22923840Sbrian  pending_signal(SIGTSTP, TerminalStop);
23010528Samurai  TtyCommandMode(getpgrp() == tcgetpgrp(0));
23110528Samurai}
23210528Samurai
23310528Samuraistatic void
23428679SbrianTerminalStop(int signo)
23510528Samurai{
23623840Sbrian  pending_signal(SIGCONT, TerminalCont);
23710528Samurai  TtyOldMode();
23823840Sbrian  pending_signal(SIGTSTP, SIG_DFL);
23910528Samurai  kill(getpid(), signo);
24010528Samurai}
24110528Samurai
24226940Sbrianstatic void
24328679SbrianSetUpServer(int signo)
24426940Sbrian{
24526940Sbrian  int res;
24628679Sbrian
24728679Sbrian  if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0)
24829083Sbrian    LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n",
24929083Sbrian	      res, SERVER_PORT + tunno);
25026940Sbrian}
25126940Sbrian
25225908Sbrianstatic char *
25325908Sbrianex_desc(int ex)
25425908Sbrian{
25525908Sbrian  static char num[12];
25628679Sbrian  static char *desc[] = {"normal", "start", "sock",
25725908Sbrian    "modem", "dial", "dead", "done", "reboot", "errdead",
25828679Sbrian  "hangup", "term", "nodial", "nologin"};
25910528Samurai
26028679Sbrian  if (ex >= 0 && ex < sizeof(desc) / sizeof(*desc))
26125908Sbrian    return desc[ex];
26225908Sbrian  snprintf(num, sizeof num, "%d", ex);
26325908Sbrian  return num;
26425908Sbrian}
26525908Sbrian
26630715Sbrianstatic void
2676059SamuraiUsage()
2686059Samurai{
26920120Snate  fprintf(stderr,
27028679Sbrian	  "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n");
2716059Samurai  exit(EX_START);
2726059Samurai}
2736059Samurai
27430715Sbrianstatic void
2756059SamuraiProcessArgs(int argc, char **argv)
2766059Samurai{
2776059Samurai  int optc;
2786059Samurai  char *cp;
2796059Samurai
2806059Samurai  optc = 0;
2816059Samurai  while (argc > 0 && **argv == '-') {
2826059Samurai    cp = *argv + 1;
2836059Samurai    if (strcmp(cp, "auto") == 0)
2846059Samurai      mode |= MODE_AUTO;
28520813Sjkh    else if (strcmp(cp, "background") == 0)
28628679Sbrian      mode |= MODE_BACKGROUND | MODE_AUTO;
2876059Samurai    else if (strcmp(cp, "direct") == 0)
2886059Samurai      mode |= MODE_DIRECT;
2896059Samurai    else if (strcmp(cp, "dedicated") == 0)
2906059Samurai      mode |= MODE_DEDICATED;
29120120Snate    else if (strcmp(cp, "ddial") == 0)
29228679Sbrian      mode |= MODE_DDIAL | MODE_AUTO;
29320365Sjkh    else if (strcmp(cp, "alias") == 0) {
29426142Sbrian      if (loadAliasHandlers(&VarAliasHandlers) == 0)
29528679Sbrian	mode |= MODE_ALIAS;
29626142Sbrian      else
29728679Sbrian	LogPrintf(LogWARN, "Cannot load alias library\n");
29828679Sbrian      optc--;			/* this option isn't exclusive */
29928679Sbrian    } else
3006059Samurai      Usage();
3016059Samurai    optc++;
30228679Sbrian    argv++;
30328679Sbrian    argc--;
3046059Samurai  }
3056059Samurai  if (argc > 1) {
3066059Samurai    fprintf(stderr, "specify only one system label.\n");
3076059Samurai    exit(EX_START);
3086059Samurai  }
30928679Sbrian  if (argc == 1)
31028679Sbrian    dstsystem = *argv;
3116059Samurai
3126059Samurai  if (optc > 1) {
3136059Samurai    fprintf(stderr, "specify only one mode.\n");
3146059Samurai    exit(EX_START);
3156059Samurai  }
3166059Samurai}
3176059Samurai
3186059Samuraistatic void
3196059SamuraiGreetings()
3206059Samurai{
32126516Sbrian  if (VarTerm) {
32226516Sbrian    fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n");
32326516Sbrian    fflush(VarTerm);
32426516Sbrian  }
3256059Samurai}
3266059Samurai
32726940Sbrianint
32828679Sbrianmain(int argc, char **argv)
3296059Samurai{
33025707Sbrian  FILE *lockfile;
33126516Sbrian  char *name;
33226516Sbrian
33326551Sbrian  VarTerm = 0;
33430715Sbrian  name = strrchr(argv[0], '/');
33528679Sbrian  LogOpen(name ? name + 1 : argv[0]);
33626516Sbrian
33728679Sbrian  argc--;
33828679Sbrian  argv++;
3396059Samurai  ProcessArgs(argc, argv);
34029083Sbrian  if (!(mode & MODE_DIRECT)) {
34129083Sbrian    if (getuid() != 0) {
34229083Sbrian      fprintf(stderr, "You may only run ppp in client mode as user id 0\n");
34329083Sbrian      LogClose();
34429083Sbrian      return EX_NOPERM;
34529083Sbrian    }
34626551Sbrian    VarTerm = stdout;
34729083Sbrian  }
34826551Sbrian  Greetings();
3496059Samurai  GetUid();
3506059Samurai  IpcpDefAddress();
35129083Sbrian  LocalAuthInit();
3526059Samurai
35326516Sbrian  if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
35426516Sbrian    fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
3556059Samurai
3566059Samurai  if (OpenTunnel(&tunno) < 0) {
35726940Sbrian    LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno));
35826940Sbrian    return EX_START;
3596059Samurai  }
36028679Sbrian  if (mode & (MODE_AUTO | MODE_DIRECT | MODE_DEDICATED))
3616059Samurai    mode &= ~MODE_INTER;
3626059Samurai  if (mode & MODE_INTER) {
36326516Sbrian    fprintf(VarTerm, "Interactive mode\n");
36426690Sbrian    netfd = STDOUT_FILENO;
3656059Samurai  } else if (mode & MODE_AUTO) {
36626516Sbrian    fprintf(VarTerm, "Automatic Dialer mode\n");
3676059Samurai    if (dstsystem == NULL) {
36826516Sbrian      if (VarTerm)
36928679Sbrian	fprintf(VarTerm, "Destination system must be specified in"
37028679Sbrian		" auto, background or ddial mode.\n");
37126940Sbrian      return EX_START;
3726059Samurai    }
3736059Samurai  }
37428679Sbrian  tcgetattr(0, &oldtio);	/* Save original tty mode */
3756059Samurai
37627157Sbrian  pending_signal(SIGHUP, CloseSession);
37723840Sbrian  pending_signal(SIGTERM, CloseSession);
37827157Sbrian  pending_signal(SIGINT, CloseConnection);
37923840Sbrian  pending_signal(SIGQUIT, CloseSession);
3806735Samurai#ifdef SIGPIPE
38124753Sache  signal(SIGPIPE, SIG_IGN);
3826735Samurai#endif
3836735Samurai#ifdef SIGALRM
38423840Sbrian  pending_signal(SIGALRM, SIG_IGN);
3856735Samurai#endif
38628679Sbrian  if (mode & MODE_INTER) {
38710528Samurai#ifdef SIGTSTP
38826940Sbrian    pending_signal(SIGTSTP, TerminalStop);
38910528Samurai#endif
39010528Samurai#ifdef SIGTTIN
39126940Sbrian    pending_signal(SIGTTIN, TerminalStop);
39210528Samurai#endif
39310528Samurai#ifdef SIGTTOU
39426940Sbrian    pending_signal(SIGTTOU, SIG_IGN);
39510528Samurai#endif
39626940Sbrian  }
39726940Sbrian#ifdef SIGUSR1
39826940Sbrian  if (mode != MODE_INTER)
39926940Sbrian    pending_signal(SIGUSR1, SetUpServer);
40026940Sbrian#endif
4016059Samurai
4026059Samurai  if (dstsystem) {
4036059Samurai    if (SelectSystem(dstsystem, CONFFILE) < 0) {
40426551Sbrian      LogPrintf(LogWARN, "Destination system not found in conf file.\n");
4056059Samurai      Cleanup(EX_START);
4066059Samurai    }
4076059Samurai    if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
40826551Sbrian      LogPrintf(LogWARN, "Must specify dstaddr with"
40928679Sbrian		" auto, background or ddial mode.\n");
4106059Samurai      Cleanup(EX_START);
4116059Samurai    }
4126059Samurai  }
41326940Sbrian
4146059Samurai  if (!(mode & MODE_INTER)) {
41520813Sjkh    if (mode & MODE_BACKGROUND) {
41628679Sbrian      if (pipe(BGFiledes)) {
41728974Sbrian	LogPrintf(LogERROR, "pipe: %s\n", strerror(errno));
41820813Sjkh	Cleanup(EX_SOCK);
41920813Sjkh      }
4206059Samurai    }
42130715Sbrian    /* Create server socket and listen (initial value is -2) */
42229083Sbrian    if (server == -2)
42329083Sbrian      ServerTcpOpen(SERVER_PORT + tunno);
4246059Samurai
4256059Samurai    if (!(mode & MODE_DIRECT)) {
42620813Sjkh      pid_t bgpid;
42711336Samurai
42828679Sbrian      bgpid = fork();
42920813Sjkh      if (bgpid == -1) {
43028974Sbrian	LogPrintf(LogERROR, "fork: %s\n", strerror(errno));
43128679Sbrian	Cleanup(EX_SOCK);
43220813Sjkh      }
43320813Sjkh      if (bgpid) {
43420813Sjkh	char c = EX_NORMAL;
43511336Samurai
43620813Sjkh	if (mode & MODE_BACKGROUND) {
43720813Sjkh	  /* Wait for our child to close its pipe before we exit. */
43820813Sjkh	  BGPid = bgpid;
43928679Sbrian	  close(BGFiledes[1]);
44025908Sbrian	  if (read(BGFiledes[0], &c, 1) != 1) {
44126516Sbrian	    fprintf(VarTerm, "Child exit, no status.\n");
44228679Sbrian	    LogPrintf(LogPHASE, "Parent: Child exit, no status.\n");
44325908Sbrian	  } else if (c == EX_NORMAL) {
44426516Sbrian	    fprintf(VarTerm, "PPP enabled.\n");
44528679Sbrian	    LogPrintf(LogPHASE, "Parent: PPP enabled.\n");
44625908Sbrian	  } else {
44728679Sbrian	    fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c));
44826516Sbrian	    LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
44928679Sbrian		      ex_desc((int) c));
45028679Sbrian	  }
45128679Sbrian	  close(BGFiledes[0]);
45220813Sjkh	}
45328679Sbrian	return c;
45423863Sbrian      } else if (mode & MODE_BACKGROUND)
45528679Sbrian	close(BGFiledes[0]);
45625707Sbrian    }
45720813Sjkh
45828679Sbrian    VarTerm = 0;		/* We know it's currently stdout */
45929551Sbrian    close(1);
46026686Sbrian    close(2);
46126551Sbrian
4626059Samurai#ifdef DOTTYINIT
46328679Sbrian    if (mode & (MODE_DIRECT | MODE_DEDICATED))
4646059Samurai#else
46526686Sbrian    if (mode & MODE_DIRECT)
4666059Samurai#endif
46726858Sbrian      TtyInit(1);
46826686Sbrian    else {
46926686Sbrian      setsid();
47029551Sbrian      close(0);
47126686Sbrian    }
4726059Samurai  } else {
47326858Sbrian    TtyInit(0);
47410528Samurai    TtyCommandMode(1);
4756059Samurai  }
47629696Sbrian
47729696Sbrian  snprintf(pid_filename, sizeof(pid_filename), "%stun%d.pid",
47829696Sbrian           _PATH_VARRUN, tunno);
47929696Sbrian  (void) unlink(pid_filename);
48029696Sbrian
48129696Sbrian  if ((lockfile = fopen(pid_filename, "w")) != NULL) {
48229696Sbrian    fprintf(lockfile, "%d\n", (int) getpid());
48329696Sbrian    fclose(lockfile);
48429696Sbrian  } else
48529696Sbrian    LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
48629696Sbrian              pid_filename, strerror(errno));
48729696Sbrian
48826516Sbrian  LogPrintf(LogPHASE, "PPP Started.\n");
4896059Samurai
4906059Samurai
4916059Samurai  do
49228679Sbrian    DoLoop();
4936059Samurai  while (mode & MODE_DEDICATED);
4946059Samurai
4956059Samurai  Cleanup(EX_DONE);
49626940Sbrian  return 0;
4976059Samurai}
4986059Samurai
4996059Samurai/*
50020813Sjkh *  Turn into packet mode, where we speak PPP.
5016059Samurai */
5026059Samuraivoid
5036059SamuraiPacketMode()
5046059Samurai{
5056059Samurai  if (RawModem(modem) < 0) {
50626516Sbrian    LogPrintf(LogWARN, "PacketMode: Not connected.\n");
5076059Samurai    return;
5086059Samurai  }
5096059Samurai  AsyncInit();
51030187Sbrian  VjInit(15);
5116059Samurai  LcpInit();
5126059Samurai  IpcpInit();
5136059Samurai  CcpInit();
5146059Samurai  LcpUp();
5156059Samurai
51625872Sbrian  LcpOpen(VarOpenMode);
51728679Sbrian  if ((mode & (MODE_INTER | MODE_AUTO)) == MODE_INTER) {
51810528Samurai    TtyCommandMode(1);
51926516Sbrian    if (VarTerm) {
52026516Sbrian      fprintf(VarTerm, "Packet mode.\n");
52126516Sbrian      aft_cmd = 1;
52226516Sbrian    }
5236059Samurai  }
5246059Samurai}
5256059Samurai
5266059Samuraistatic void
5276059SamuraiShowHelp()
5286059Samurai{
52926901Sbrian  fprintf(stderr, "The following commands are available:\r\n");
53026901Sbrian  fprintf(stderr, " ~p\tEnter Packet mode\r\n");
53126901Sbrian  fprintf(stderr, " ~-\tDecrease log level\r\n");
53226901Sbrian  fprintf(stderr, " ~+\tIncrease log level\r\n");
53326901Sbrian  fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
53426901Sbrian  fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
53526901Sbrian  fprintf(stderr, " ~.\tTerminate program\r\n");
53626901Sbrian  fprintf(stderr, " ~?\tThis help\r\n");
5376059Samurai}
5386059Samurai
5396059Samuraistatic void
5406059SamuraiReadTty()
5416059Samurai{
5426059Samurai  int n;
5436059Samurai  char ch;
5446059Samurai  static int ttystate;
54526516Sbrian  FILE *oVarTerm;
54628679Sbrian
5476059Samurai#define MAXLINESIZE 200
5486059Samurai  char linebuff[MAXLINESIZE];
5496059Samurai
55026516Sbrian  LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
55128679Sbrian	    TermMode, netfd, mode);
5526059Samurai  if (!TermMode) {
55328679Sbrian    n = read(netfd, linebuff, sizeof(linebuff) - 1);
5546735Samurai    if (n > 0) {
55526516Sbrian      aft_cmd = 1;
55630497Sbrian      linebuff[n] = '\0';
55730497Sbrian      LogPrintf(LogCOMMAND, "Client: %s\n", linebuff);
5586059Samurai      DecodeCommand(linebuff, n, 1);
5596735Samurai    } else {
56026516Sbrian      LogPrintf(LogPHASE, "client connection closed.\n");
56124753Sache      VarLocalAuth = LOCAL_NO_AUTH;
56226516Sbrian      mode &= ~MODE_INTER;
56326516Sbrian      oVarTerm = VarTerm;
56426516Sbrian      VarTerm = 0;
56526516Sbrian      if (oVarTerm && oVarTerm != stdout)
56628679Sbrian	fclose(oVarTerm);
5676059Samurai      close(netfd);
5686059Samurai      netfd = -1;
5696059Samurai    }
5706059Samurai    return;
5716059Samurai  }
5726059Samurai
5736059Samurai  /*
57428679Sbrian   * We are in terminal mode, decode special sequences
5756059Samurai   */
57626516Sbrian  n = read(fileno(VarTerm), &ch, 1);
57728974Sbrian  LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
5786059Samurai
5796059Samurai  if (n > 0) {
5806059Samurai    switch (ttystate) {
5816059Samurai    case 0:
5826059Samurai      if (ch == '~')
5836059Samurai	ttystate++;
5846059Samurai      else
5856059Samurai	write(modem, &ch, n);
5866059Samurai      break;
5876059Samurai    case 1:
5886059Samurai      switch (ch) {
5896059Samurai      case '?':
5906059Samurai	ShowHelp();
5916059Samurai	break;
5926059Samurai      case 'p':
59328679Sbrian
5946059Samurai	/*
5956059Samurai	 * XXX: Should check carrier.
5966059Samurai	 */
5976059Samurai	if (LcpFsm.state <= ST_CLOSED) {
5986059Samurai	  VarOpenMode = OPEN_ACTIVE;
5996059Samurai	  PacketMode();
6006059Samurai	}
6016059Samurai	break;
6026059Samurai      case '.':
6036059Samurai	TermMode = 1;
60426516Sbrian	aft_cmd = 1;
60510528Samurai	TtyCommandMode(1);
6066059Samurai	break;
60726516Sbrian      case 't':
60826516Sbrian	if (LogIsKept(LogDEBUG)) {
60926516Sbrian	  ShowTimers();
61026516Sbrian	  break;
61126516Sbrian	}
61226516Sbrian      case 'm':
61326516Sbrian	if (LogIsKept(LogDEBUG)) {
61426516Sbrian	  ShowMemMap();
61526516Sbrian	  break;
61626516Sbrian	}
6176059Samurai      default:
6186059Samurai	if (write(modem, &ch, n) < 0)
61926516Sbrian	  LogPrintf(LogERROR, "error writing to modem.\n");
6206059Samurai	break;
6216059Samurai      }
6226059Samurai      ttystate = 0;
6236059Samurai      break;
6246059Samurai    }
6256059Samurai  }
6266059Samurai}
6276059Samurai
6286059Samurai
6296059Samurai/*
6306059Samurai *  Here, we'll try to detect HDLC frame
6316059Samurai */
6326059Samurai
6336059Samuraistatic char *FrameHeaders[] = {
6346735Samurai  "\176\377\003\300\041",
6356735Samurai  "\176\377\175\043\300\041",
6366735Samurai  "\176\177\175\043\100\041",
6376735Samurai  "\176\175\337\175\043\300\041",
6386735Samurai  "\176\175\137\175\043\100\041",
6396059Samurai  NULL,
6406059Samurai};
6416059Samurai
64230715Sbrianstatic u_char *
64328679SbrianHdlcDetect(u_char * cp, int n)
6446059Samurai{
6456735Samurai  char *ptr, *fp, **hp;
6466059Samurai
64728679Sbrian  cp[n] = '\0';			/* be sure to null terminated */
6486059Samurai  ptr = NULL;
6496059Samurai  for (hp = FrameHeaders; *hp; hp++) {
6506735Samurai    fp = *hp;
6516735Samurai    if (DEV_IS_SYNC)
6526735Samurai      fp++;
65328679Sbrian    ptr = strstr((char *) cp, fp);
65413389Sphk    if (ptr)
6556059Samurai      break;
6566059Samurai  }
65728679Sbrian  return ((u_char *) ptr);
6586059Samurai}
6596059Samurai
6606059Samuraistatic struct pppTimer RedialTimer;
6616059Samurai
6626059Samuraistatic void
6636059SamuraiRedialTimeout()
6646059Samurai{
6656059Samurai  StopTimer(&RedialTimer);
66626516Sbrian  LogPrintf(LogPHASE, "Redialing timer expired.\n");
6676059Samurai}
6686059Samurai
6696059Samuraistatic void
67028679SbrianStartRedialTimer(int Timeout)
6716059Samurai{
6726059Samurai  StopTimer(&RedialTimer);
67311336Samurai
67424939Sbrian  if (Timeout) {
67511336Samurai    RedialTimer.state = TIMER_STOPPED;
67611336Samurai
67724939Sbrian    if (Timeout > 0)
67828679Sbrian      RedialTimer.load = Timeout * SECTICKS;
67911336Samurai    else
68028679Sbrian      RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
68111336Samurai
68226516Sbrian    LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
68324939Sbrian	      RedialTimer.load / SECTICKS);
68424939Sbrian
68511336Samurai    RedialTimer.func = RedialTimeout;
68611336Samurai    StartTimer(&RedialTimer);
68711336Samurai  }
6886059Samurai}
6896059Samurai
6906059Samurai
6916059Samuraistatic void
6926059SamuraiDoLoop()
6936059Samurai{
6946059Samurai  fd_set rfds, wfds, efds;
69523598Sache  int pri, i, n, wfd, nfds;
6966059Samurai  struct sockaddr_in hisaddr;
6976059Samurai  struct timeval timeout, *tp;
6986059Samurai  int ssize = sizeof(hisaddr);
6996059Samurai  u_char *cp;
7006059Samurai  u_char rbuff[MAX_MRU];
70111336Samurai  int tries;
7029448Samurai  int qlen;
70326858Sbrian  int res;
70410528Samurai  pid_t pgroup;
7056059Samurai
70610528Samurai  pgroup = getpgrp();
70710528Samurai
70825908Sbrian  if (mode & MODE_DIRECT) {
70926551Sbrian    LogPrintf(LogDEBUG, "Opening modem\n");
71029521Sbrian    if (OpenModem(mode) < 0)
71129521Sbrian      return;
71226516Sbrian    LogPrintf(LogPHASE, "Packet mode enabled\n");
7136059Samurai    PacketMode();
7146059Samurai  } else if (mode & MODE_DEDICATED) {
71523598Sache    if (modem < 0)
71629521Sbrian      while (OpenModem(mode) < 0)
71730697Sbrian	nointr_sleep(VarReconnectTimer);
7186059Samurai  }
71926516Sbrian  fflush(VarTerm);
7206059Samurai
7217001Samurai  timeout.tv_sec = 0;
7226059Samurai  timeout.tv_usec = 0;
72326098Sbrian  reconnectState = RECON_UNKNOWN;
7246059Samurai
72523863Sbrian  if (mode & MODE_BACKGROUND)
72630715Sbrian    dial_up = 1;		/* Bring the line up */
72723863Sbrian  else
72830715Sbrian    dial_up = 0;		/* XXXX */
72911336Samurai  tries = 0;
7306059Samurai  for (;;) {
73123598Sache    nfds = 0;
73228679Sbrian    FD_ZERO(&rfds);
73328679Sbrian    FD_ZERO(&wfds);
73428679Sbrian    FD_ZERO(&efds);
7357001Samurai
73628679Sbrian    /*
73728679Sbrian     * If the link is down and we're in DDIAL mode, bring it back up.
73820120Snate     */
73920120Snate    if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
74030715Sbrian      dial_up = 1;
74120120Snate
74225067Sbrian    /*
74328679Sbrian     * If we lost carrier and want to re-establish the connection due to the
74428679Sbrian     * "set reconnect" value, we'd better bring the line back up.
74525067Sbrian     */
74625908Sbrian    if (LcpFsm.state <= ST_CLOSED) {
74730715Sbrian      if (!dial_up && reconnectState == RECON_TRUE) {
74828679Sbrian	if (++reconnectCount <= VarReconnectTries) {
74928679Sbrian	  LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
75028679Sbrian		    reconnectCount, VarReconnectTries);
75125908Sbrian	  StartRedialTimer(VarReconnectTimer);
75230715Sbrian	  dial_up = 1;
75328679Sbrian	} else {
75428679Sbrian	  if (VarReconnectTries)
75528679Sbrian	    LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
75628679Sbrian		      VarReconnectTries);
75728679Sbrian	  reconnectCount = 0;
75828679Sbrian	  if (mode & MODE_BACKGROUND)
75928679Sbrian	    Cleanup(EX_DEAD);
76028679Sbrian	}
76128679Sbrian	reconnectState = RECON_ENVOKED;
76225801Sbrian      }
76325908Sbrian    }
76425067Sbrian
76528679Sbrian    /*
76628679Sbrian     * If Ip packet for output is enqueued and require dial up, Just do it!
76728679Sbrian     */
76828679Sbrian    if (dial_up && RedialTimer.state != TIMER_RUNNING) {
76926516Sbrian      LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
77029521Sbrian      if (OpenModem(mode) < 0) {
77128679Sbrian	tries++;
77228679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
77328679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
77428679Sbrian		    tries, VarDialTries);
77528679Sbrian	else
77628679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
77726551Sbrian
77826696Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
77926551Sbrian	  if (mode & MODE_BACKGROUND)
78028679Sbrian	    Cleanup(EX_DIAL);	/* Can't get the modem */
78130715Sbrian	  dial_up = 0;
78228679Sbrian	  reconnectState = RECON_UNKNOWN;
78328679Sbrian	  reconnectCount = 0;
78426551Sbrian	  tries = 0;
78528679Sbrian	} else
78626551Sbrian	  StartRedialTimer(VarRedialTimeout);
78711336Samurai      } else {
78828679Sbrian	tries++;		/* Tries are per number, not per list of
78928679Sbrian				 * numbers. */
79028679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
79126696Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
79228679Sbrian	else
79328679Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
79426696Sbrian
79526858Sbrian	if ((res = DialModem()) == EX_DONE) {
79630697Sbrian	  nointr_sleep(1);		/* little pause to allow peer starts */
79711336Samurai	  ModemTimeout();
79811336Samurai	  PacketMode();
79930715Sbrian	  dial_up = 0;
80028679Sbrian	  reconnectState = RECON_UNKNOWN;
80111336Samurai	  tries = 0;
80211336Samurai	} else {
80311336Samurai	  CloseModem();
80424844Sbrian	  if (mode & MODE_BACKGROUND) {
80526858Sbrian	    if (VarNextPhone == NULL || res == EX_SIG)
80628679Sbrian	      Cleanup(EX_DIAL);	/* Tried all numbers - no luck */
80724844Sbrian	    else
80824939Sbrian	      /* Try all numbers in background mode */
80924939Sbrian	      StartRedialTimer(VarRedialNextTimeout);
81026858Sbrian	  } else if (!(mode & MODE_DDIAL) &&
81128679Sbrian		     ((VarDialTries && tries >= VarDialTries) ||
81228679Sbrian		      res == EX_SIG)) {
81324843Sbrian	    /* I give up !  Can't get through :( */
81424939Sbrian	    StartRedialTimer(VarRedialTimeout);
81530715Sbrian	    dial_up = 0;
81628679Sbrian	    reconnectState = RECON_UNKNOWN;
81728679Sbrian	    reconnectCount = 0;
81824843Sbrian	    tries = 0;
81924843Sbrian	  } else if (VarNextPhone == NULL)
82024843Sbrian	    /* Dial failed. Keep quite during redial wait period. */
82124939Sbrian	    StartRedialTimer(VarRedialTimeout);
82224843Sbrian	  else
82324939Sbrian	    StartRedialTimer(VarRedialNextTimeout);
82411336Samurai	}
82511336Samurai      }
8267001Samurai    }
8279448Samurai    qlen = ModemQlen();
82813733Sdfr
82913733Sdfr    if (qlen == 0) {
83013733Sdfr      IpStartOutput();
83113733Sdfr      qlen = ModemQlen();
83213733Sdfr    }
83323598Sache    if (modem >= 0) {
83423598Sache      if (modem + 1 > nfds)
83523598Sache	nfds = modem + 1;
8367001Samurai      FD_SET(modem, &rfds);
8377001Samurai      FD_SET(modem, &efds);
8389448Samurai      if (qlen > 0) {
8397001Samurai	FD_SET(modem, &wfds);
8407001Samurai      }
8417001Samurai    }
84223598Sache    if (server >= 0) {
84323598Sache      if (server + 1 > nfds)
84423598Sache	nfds = server + 1;
84523598Sache      FD_SET(server, &rfds);
84623598Sache    }
8476059Samurai
84828679Sbrian    /*
84928679Sbrian     * *** IMPORTANT ***
85028679Sbrian     *
85128679Sbrian     * CPU is serviced every TICKUNIT micro seconds. This value must be chosen
85228679Sbrian     * with great care. If this values is too big, it results loss of
85328679Sbrian     * characters from modem and poor responce. If this values is too small,
85428679Sbrian     * ppp process eats many CPU time.
8556059Samurai     */
8566735Samurai#ifndef SIGALRM
85730697Sbrian    nointr_usleep(TICKUNIT);
8586059Samurai    TimerService();
85923840Sbrian#else
86023840Sbrian    handle_signals();
8616735Samurai#endif
86210877Sbde
86310877Sbde    /* If there are aren't many packets queued, look for some more. */
86423598Sache    if (qlen < 20 && tun_in >= 0) {
86523598Sache      if (tun_in + 1 > nfds)
86623598Sache	nfds = tun_in + 1;
86710877Sbde      FD_SET(tun_in, &rfds);
86823598Sache    }
86923598Sache    if (netfd >= 0) {
87023598Sache      if (netfd + 1 > nfds)
87123598Sache	nfds = netfd + 1;
8726059Samurai      FD_SET(netfd, &rfds);
8736059Samurai      FD_SET(netfd, &efds);
8746059Samurai    }
87528679Sbrian#ifndef SIGALRM
8767001Samurai
8776059Samurai    /*
87828679Sbrian     * Normally, select() will not block because modem is writable. In AUTO
87928679Sbrian     * mode, select will block until we find packet from tun
8806059Samurai     */
88128679Sbrian    tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL;
88223598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
8836735Samurai#else
88428679Sbrian
8858857Srgrimes    /*
88628679Sbrian     * When SIGALRM timer is running, a select function will be return -1 and
88728679Sbrian     * EINTR after a Time Service signal hundler is done.  If the redial
88828679Sbrian     * timer is not running and we are trying to dial, poll with a 0 value
88928679Sbrian     * timer.
8907001Samurai     */
89111336Samurai    tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
89223598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
8936735Samurai#endif
89422074Sbrian
89528679Sbrian    if (i == 0) {
89628679Sbrian      continue;
8976059Samurai    }
89828679Sbrian    if (i < 0) {
89928679Sbrian      if (errno == EINTR) {
90028679Sbrian	handle_signals();
90128679Sbrian	continue;
90228679Sbrian      }
90328974Sbrian      LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
90428679Sbrian      break;
9058857Srgrimes    }
90623598Sache    if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
90726516Sbrian      LogPrintf(LogALERT, "Exception detected.\n");
9086059Samurai      break;
9096059Samurai    }
91023598Sache    if (server >= 0 && FD_ISSET(server, &rfds)) {
91126516Sbrian      LogPrintf(LogPHASE, "connected to client.\n");
91228679Sbrian      wfd = accept(server, (struct sockaddr *) & hisaddr, &ssize);
91324753Sache      if (wfd < 0) {
91428974Sbrian	LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno));
91524753Sache	continue;
91624753Sache      }
91723598Sache      if (netfd >= 0) {
9186059Samurai	write(wfd, "already in use.\n", 16);
9196059Samurai	close(wfd);
9206059Samurai	continue;
9216059Samurai      } else
9226059Samurai	netfd = wfd;
92326516Sbrian      VarTerm = fdopen(netfd, "a+");
9246059Samurai      mode |= MODE_INTER;
9256059Samurai      Greetings();
9266059Samurai      (void) IsInteractive();
92725630Sbrian      Prompt();
9286059Samurai    }
92923598Sache    if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) &&
93010858Samurai	((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) {
9316059Samurai      /* something to read from tty */
9326059Samurai      ReadTty();
9336059Samurai    }
93423598Sache    if (modem >= 0) {
9356059Samurai      if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
93628679Sbrian	ModemStartOutput(modem);
9376059Samurai      }
9386059Samurai      if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
9396735Samurai	if (LcpFsm.state <= ST_CLOSED)
94030697Sbrian	  nointr_usleep(10000);
9416059Samurai	n = read(modem, rbuff, sizeof(rbuff));
9426059Samurai	if ((mode & MODE_DIRECT) && n <= 0) {
9436059Samurai	  DownConnection();
9446059Samurai	} else
94528679Sbrian	  LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
9466059Samurai
9476059Samurai	if (LcpFsm.state <= ST_CLOSED) {
94828679Sbrian
9496059Samurai	  /*
95028679Sbrian	   * In dedicated mode, we just discard input until LCP is started.
9516059Samurai	   */
9526059Samurai	  if (!(mode & MODE_DEDICATED)) {
9536059Samurai	    cp = HdlcDetect(rbuff, n);
9546059Samurai	    if (cp) {
95528679Sbrian
9566059Samurai	      /*
9576059Samurai	       * LCP packet is detected. Turn ourselves into packet mode.
9586059Samurai	       */
9596059Samurai	      if (cp != rbuff) {
96028679Sbrian		write(modem, rbuff, cp - rbuff);
96128679Sbrian		write(modem, "\r\n", 2);
9626059Samurai	      }
9636059Samurai	      PacketMode();
9646059Samurai	    } else
96526516Sbrian	      write(fileno(VarTerm), rbuff, n);
9666059Samurai	  }
9676059Samurai	} else {
9686059Samurai	  if (n > 0)
9696059Samurai	    AsyncInput(rbuff, n);
9706059Samurai	}
9716059Samurai      }
9726059Samurai    }
97328679Sbrian    if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {	/* something to read
97428679Sbrian							 * from tun */
9756059Samurai      n = read(tun_in, rbuff, sizeof(rbuff));
9766059Samurai      if (n < 0) {
97728974Sbrian	LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno));
9786059Samurai	continue;
9796059Samurai      }
98028679Sbrian      if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) {
98128536Sbrian	/* we've been asked to send something addressed *to* us :( */
98228536Sbrian	if (VarLoopback) {
98328536Sbrian	  pri = PacketCheck(rbuff, n, FL_IN);
98428536Sbrian	  if (pri >= 0) {
98528536Sbrian	    struct mbuf *bp;
98628679Sbrian
98728536Sbrian	    if (mode & MODE_ALIAS) {
98828536Sbrian	      VarPacketAliasIn(rbuff, sizeof rbuff);
98928679Sbrian	      n = ntohs(((struct ip *) rbuff)->ip_len);
99028536Sbrian	    }
99128536Sbrian	    bp = mballoc(n, MB_IPIN);
99230715Sbrian	    memcpy(MBUF_CTOP(bp), rbuff, n);
99328536Sbrian	    IpInput(bp);
99428536Sbrian	    LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n");
99528536Sbrian	  }
99628536Sbrian	  continue;
99728679Sbrian	} else
99828536Sbrian	  LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
99928536Sbrian      }
100028536Sbrian
10016059Samurai      /*
100228679Sbrian       * Process on-demand dialup. Output packets are queued within tunnel
100328679Sbrian       * device until IPCP is opened.
10046059Samurai       */
10056059Samurai      if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
10067001Samurai	pri = PacketCheck(rbuff, n, FL_DIAL);
10076059Samurai	if (pri >= 0) {
100820365Sjkh	  if (mode & MODE_ALIAS) {
100926142Sbrian	    VarPacketAliasOut(rbuff, sizeof rbuff);
101028679Sbrian	    n = ntohs(((struct ip *) rbuff)->ip_len);
101120365Sjkh	  }
10126059Samurai	  IpEnqueue(pri, rbuff, n);
101330715Sbrian	  dial_up = 1;	/* XXX */
10146059Samurai	}
10156059Samurai	continue;
10166059Samurai      }
10177001Samurai      pri = PacketCheck(rbuff, n, FL_OUT);
101820365Sjkh      if (pri >= 0) {
101928679Sbrian	if (mode & MODE_ALIAS) {
102028679Sbrian	  VarPacketAliasOut(rbuff, sizeof rbuff);
102128679Sbrian	  n = ntohs(((struct ip *) rbuff)->ip_len);
102228679Sbrian	}
10236059Samurai	IpEnqueue(pri, rbuff, n);
102420365Sjkh      }
10256059Samurai    }
10266059Samurai  }
102726516Sbrian  LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
10286059Samurai}
1029