main.c revision 30697
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 *
2030697Sbrian * $Id: main.c,v 1.83 1997/10/16 23:55:18 brian Exp $
218857Srgrimes *
226059Samurai *	TODO:
236059Samurai *		o Add commands for traffic summary, version display, etc.
246059Samurai *		o Add signal handler for misc controls.
256059Samurai */
266059Samurai#include "fsm.h"
276059Samurai#include <fcntl.h>
2811336Samurai#include <paths.h>
296059Samurai#include <sys/time.h>
306059Samurai#include <termios.h>
3123114Sbrian#include <signal.h>
326059Samurai#include <sys/wait.h>
336059Samurai#include <errno.h>
346059Samurai#include <netdb.h>
3518786Sjkh#include <unistd.h>
366059Samurai#include <sys/socket.h>
376059Samurai#include <arpa/inet.h>
3820365Sjkh#include <netinet/in_systm.h>
3920365Sjkh#include <netinet/ip.h>
4029083Sbrian#include <sysexits.h>
416059Samurai#include "modem.h"
426059Samurai#include "os.h"
436059Samurai#include "hdlc.h"
4413389Sphk#include "ccp.h"
456059Samurai#include "lcp.h"
466059Samurai#include "ipcp.h"
4726142Sbrian#include "loadalias.h"
486059Samurai#include "vars.h"
496735Samurai#include "auth.h"
507001Samurai#include "filter.h"
5113389Sphk#include "systems.h"
5213389Sphk#include "ip.h"
5323840Sbrian#include "sig.h"
5426940Sbrian#include "server.h"
5528536Sbrian#include "lcpproto.h"
566059Samurai
576735Samurai#ifndef O_NONBLOCK
586735Samurai#ifdef O_NDELAY
596735Samurai#define	O_NONBLOCK O_NDELAY
606735Samurai#endif
616735Samurai#endif
626735Samurai
6330187Sbrianextern void VjInit(int), AsyncInit();
6425630Sbrianextern void AsyncInput();
6528679Sbrianextern int SelectSystem();
666059Samurai
676059Samuraiextern void DecodeCommand(), Prompt();
6818885Sjkhextern int aft_cmd;
696059Samuraiextern int IsInteractive();
706059Samuraistatic void DoLoop(void);
7110528Samuraistatic void TerminalStop();
7225908Sbrianstatic char *ex_desc();
736059Samurai
7428679Sbrianstatic struct termios oldtio;	/* Original tty mode */
7528679Sbrianstatic struct termios comtio;	/* Command level tty mode */
7614418Sacheint TermMode;
7720813Sjkhstatic pid_t BGPid = 0;
7825634Sbrianstatic char pid_filename[MAXPATHLEN];
7925634Sbrianstatic char if_filename[MAXPATHLEN];
8025445Sacheint tunno;
8127061Sbrianstatic int dial_up;
826059Samurai
836059Samuraistatic void
8426858SbrianTtyInit(int DontWantInt)
856059Samurai{
866059Samurai  struct termios newtio;
876059Samurai  int stat;
886059Samurai
896059Samurai  stat = fcntl(0, F_GETFL, 0);
9025630Sbrian  if (stat > 0) {
9128679Sbrian    stat |= O_NONBLOCK;
9228679Sbrian    (void) fcntl(0, F_SETFL, stat);
9325630Sbrian  }
946059Samurai  newtio = oldtio;
9528679Sbrian  newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
966059Samurai  newtio.c_iflag = 0;
976059Samurai  newtio.c_oflag &= ~OPOST;
986059Samurai  newtio.c_cc[VEOF] = _POSIX_VDISABLE;
9926858Sbrian  if (DontWantInt)
10026858Sbrian    newtio.c_cc[VINTR] = _POSIX_VDISABLE;
1016059Samurai  newtio.c_cc[VMIN] = 1;
1026059Samurai  newtio.c_cc[VTIME] = 0;
1036059Samurai  newtio.c_cflag |= CS8;
1046735Samurai  tcsetattr(0, TCSADRAIN, &newtio);
1056059Samurai  comtio = newtio;
1066059Samurai}
1076059Samurai
1086059Samurai/*
1096059Samurai *  Set tty into command mode. We allow canonical input and echo processing.
1106059Samurai */
11110528Samuraivoid
11228679SbrianTtyCommandMode(int prompt)
1136059Samurai{
1146059Samurai  struct termios newtio;
1156059Samurai  int stat;
1166059Samurai
1176059Samurai  if (!(mode & MODE_INTER))
1186059Samurai    return;
1196735Samurai  tcgetattr(0, &newtio);
12028679Sbrian  newtio.c_lflag |= (ECHO | ISIG | ICANON);
1216059Samurai  newtio.c_iflag = oldtio.c_iflag;
1226059Samurai  newtio.c_oflag |= OPOST;
1236735Samurai  tcsetattr(0, TCSADRAIN, &newtio);
1246059Samurai  stat = fcntl(0, F_GETFL, 0);
12525630Sbrian  if (stat > 0) {
12628679Sbrian    stat |= O_NONBLOCK;
12728679Sbrian    (void) fcntl(0, F_SETFL, stat);
12825630Sbrian  }
1296059Samurai  TermMode = 0;
13028679Sbrian  if (prompt)
13128679Sbrian    Prompt();
1326059Samurai}
1336059Samurai
1346059Samurai/*
1356059Samurai * Set tty into terminal mode which is used while we invoke term command.
1366059Samurai */
1376059Samuraivoid
1386059SamuraiTtyTermMode()
1396059Samurai{
1406059Samurai  int stat;
1416059Samurai
1426735Samurai  tcsetattr(0, TCSADRAIN, &comtio);
1436059Samurai  stat = fcntl(0, F_GETFL, 0);
14425630Sbrian  if (stat > 0) {
14528679Sbrian    stat &= ~O_NONBLOCK;
14628679Sbrian    (void) fcntl(0, F_SETFL, stat);
14725630Sbrian  }
1486059Samurai  TermMode = 1;
1496059Samurai}
1506059Samurai
1516059Samuraivoid
15210528SamuraiTtyOldMode()
1536059Samurai{
1546059Samurai  int stat;
1556059Samurai
1566059Samurai  stat = fcntl(0, F_GETFL, 0);
15725630Sbrian  if (stat > 0) {
15828679Sbrian    stat &= ~O_NONBLOCK;
15928679Sbrian    (void) fcntl(0, F_SETFL, stat);
16025630Sbrian  }
1616735Samurai  tcsetattr(0, TCSANOW, &oldtio);
16210528Samurai}
16310528Samurai
16410528Samuraivoid
16528679SbrianCleanup(int excode)
16610528Samurai{
16710528Samurai  OsLinkdown();
1686059Samurai  OsCloseLink(1);
16930697Sbrian  nointr_sleep(1);
17025908Sbrian  if (mode & MODE_AUTO)
1716059Samurai    DeleteIfRoutes(1);
17228679Sbrian  (void) unlink(pid_filename);
17328679Sbrian  (void) unlink(if_filename);
1746059Samurai  OsInterfaceDown(1);
17523863Sbrian  if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
17623863Sbrian    char c = EX_ERRDEAD;
17728679Sbrian
17828679Sbrian    if (write(BGFiledes[1], &c, 1) == 1)
17928679Sbrian      LogPrintf(LogPHASE, "Parent notified of failure.\n");
18023863Sbrian    else
18128679Sbrian      LogPrintf(LogPHASE, "Failed to notify parent of failure.\n");
18223863Sbrian    close(BGFiledes[1]);
18323863Sbrian  }
18428679Sbrian  LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
1856059Samurai  LogClose();
18626940Sbrian  ServerClose();
18710528Samurai  TtyOldMode();
1886059Samurai
1896059Samurai  exit(excode);
1906059Samurai}
1916059Samurai
1926059Samuraistatic void
19328679SbrianCloseConnection(int signo)
1946059Samurai{
19526858Sbrian  /* NOTE, these are manual, we've done a setsid() */
19627157Sbrian  LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo);
19728679Sbrian  reconnectState = RECON_FALSE;
19828684Sbrian  reconnectCount = 0;
19928684Sbrian  DownConnection();
20027061Sbrian  dial_up = FALSE;
2016059Samurai}
2026059Samurai
2036059Samuraistatic void
20428679SbrianCloseSession(int signo)
2056059Samurai{
20628679Sbrian  if (BGPid) {
20728679Sbrian    kill(BGPid, SIGINT);
20828679Sbrian    exit(EX_TERM);
20928679Sbrian  }
21028679Sbrian  LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
21128679Sbrian  reconnect(RECON_FALSE);
21228679Sbrian  LcpClose();
21328679Sbrian  Cleanup(EX_TERM);
2146059Samurai}
2156059Samurai
21610528Samuraistatic void
21710528SamuraiTerminalCont()
21810528Samurai{
21923840Sbrian  pending_signal(SIGCONT, SIG_DFL);
22023840Sbrian  pending_signal(SIGTSTP, TerminalStop);
22110528Samurai  TtyCommandMode(getpgrp() == tcgetpgrp(0));
22210528Samurai}
22310528Samurai
22410528Samuraistatic void
22528679SbrianTerminalStop(int signo)
22610528Samurai{
22723840Sbrian  pending_signal(SIGCONT, TerminalCont);
22810528Samurai  TtyOldMode();
22923840Sbrian  pending_signal(SIGTSTP, SIG_DFL);
23010528Samurai  kill(getpid(), signo);
23110528Samurai}
23210528Samurai
23326940Sbrianstatic void
23428679SbrianSetUpServer(int signo)
23526940Sbrian{
23626940Sbrian  int res;
23728679Sbrian
23828679Sbrian  if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0)
23929083Sbrian    LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n",
24029083Sbrian	      res, SERVER_PORT + tunno);
24126940Sbrian}
24226940Sbrian
24325908Sbrianstatic char *
24425908Sbrianex_desc(int ex)
24525908Sbrian{
24625908Sbrian  static char num[12];
24728679Sbrian  static char *desc[] = {"normal", "start", "sock",
24825908Sbrian    "modem", "dial", "dead", "done", "reboot", "errdead",
24928679Sbrian  "hangup", "term", "nodial", "nologin"};
25010528Samurai
25128679Sbrian  if (ex >= 0 && ex < sizeof(desc) / sizeof(*desc))
25225908Sbrian    return desc[ex];
25325908Sbrian  snprintf(num, sizeof num, "%d", ex);
25425908Sbrian  return num;
25525908Sbrian}
25625908Sbrian
2576059Samuraivoid
2586059SamuraiUsage()
2596059Samurai{
26020120Snate  fprintf(stderr,
26128679Sbrian	  "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n");
2626059Samurai  exit(EX_START);
2636059Samurai}
2646059Samurai
2656059Samuraivoid
2666059SamuraiProcessArgs(int argc, char **argv)
2676059Samurai{
2686059Samurai  int optc;
2696059Samurai  char *cp;
2706059Samurai
2716059Samurai  optc = 0;
2726059Samurai  while (argc > 0 && **argv == '-') {
2736059Samurai    cp = *argv + 1;
2746059Samurai    if (strcmp(cp, "auto") == 0)
2756059Samurai      mode |= MODE_AUTO;
27620813Sjkh    else if (strcmp(cp, "background") == 0)
27728679Sbrian      mode |= MODE_BACKGROUND | MODE_AUTO;
2786059Samurai    else if (strcmp(cp, "direct") == 0)
2796059Samurai      mode |= MODE_DIRECT;
2806059Samurai    else if (strcmp(cp, "dedicated") == 0)
2816059Samurai      mode |= MODE_DEDICATED;
28220120Snate    else if (strcmp(cp, "ddial") == 0)
28328679Sbrian      mode |= MODE_DDIAL | MODE_AUTO;
28420365Sjkh    else if (strcmp(cp, "alias") == 0) {
28526142Sbrian      if (loadAliasHandlers(&VarAliasHandlers) == 0)
28628679Sbrian	mode |= MODE_ALIAS;
28726142Sbrian      else
28828679Sbrian	LogPrintf(LogWARN, "Cannot load alias library\n");
28928679Sbrian      optc--;			/* this option isn't exclusive */
29028679Sbrian    } else
2916059Samurai      Usage();
2926059Samurai    optc++;
29328679Sbrian    argv++;
29428679Sbrian    argc--;
2956059Samurai  }
2966059Samurai  if (argc > 1) {
2976059Samurai    fprintf(stderr, "specify only one system label.\n");
2986059Samurai    exit(EX_START);
2996059Samurai  }
30028679Sbrian  if (argc == 1)
30128679Sbrian    dstsystem = *argv;
3026059Samurai
3036059Samurai  if (optc > 1) {
3046059Samurai    fprintf(stderr, "specify only one mode.\n");
3056059Samurai    exit(EX_START);
3066059Samurai  }
3076059Samurai}
3086059Samurai
3096059Samuraistatic void
3106059SamuraiGreetings()
3116059Samurai{
31226516Sbrian  if (VarTerm) {
31326516Sbrian    fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n");
31426516Sbrian    fflush(VarTerm);
31526516Sbrian  }
3166059Samurai}
3176059Samurai
31826940Sbrianint
31928679Sbrianmain(int argc, char **argv)
3206059Samurai{
32125707Sbrian  FILE *lockfile;
32226516Sbrian  char *name;
32326516Sbrian
32426551Sbrian  VarTerm = 0;
32526516Sbrian  name = rindex(argv[0], '/');
32628679Sbrian  LogOpen(name ? name + 1 : argv[0]);
32726516Sbrian
32828679Sbrian  argc--;
32928679Sbrian  argv++;
3306059Samurai  mode = MODE_INTER;		/* default operation is interactive mode */
33126940Sbrian  netfd = modem = tun_in = -1;
33226940Sbrian  server = -2;
3336059Samurai  ProcessArgs(argc, argv);
33429083Sbrian  if (!(mode & MODE_DIRECT)) {
33529083Sbrian    if (getuid() != 0) {
33629083Sbrian      fprintf(stderr, "You may only run ppp in client mode as user id 0\n");
33729083Sbrian      LogClose();
33829083Sbrian      return EX_NOPERM;
33929083Sbrian    }
34026551Sbrian    VarTerm = stdout;
34129083Sbrian  }
34226551Sbrian  Greetings();
3436059Samurai  GetUid();
3446059Samurai  IpcpDefAddress();
34529083Sbrian  LocalAuthInit();
3466059Samurai
34726516Sbrian  if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
34826516Sbrian    fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
3496059Samurai
3506059Samurai  if (OpenTunnel(&tunno) < 0) {
35126940Sbrian    LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno));
35226940Sbrian    return EX_START;
3536059Samurai  }
35428679Sbrian  if (mode & (MODE_AUTO | MODE_DIRECT | MODE_DEDICATED))
3556059Samurai    mode &= ~MODE_INTER;
3566059Samurai  if (mode & MODE_INTER) {
35726516Sbrian    fprintf(VarTerm, "Interactive mode\n");
35826690Sbrian    netfd = STDOUT_FILENO;
3596059Samurai  } else if (mode & MODE_AUTO) {
36026516Sbrian    fprintf(VarTerm, "Automatic Dialer mode\n");
3616059Samurai    if (dstsystem == NULL) {
36226516Sbrian      if (VarTerm)
36328679Sbrian	fprintf(VarTerm, "Destination system must be specified in"
36428679Sbrian		" auto, background or ddial mode.\n");
36526940Sbrian      return EX_START;
3666059Samurai    }
3676059Samurai  }
36828679Sbrian  tcgetattr(0, &oldtio);	/* Save original tty mode */
3696059Samurai
37027157Sbrian  pending_signal(SIGHUP, CloseSession);
37123840Sbrian  pending_signal(SIGTERM, CloseSession);
37227157Sbrian  pending_signal(SIGINT, CloseConnection);
37323840Sbrian  pending_signal(SIGQUIT, CloseSession);
3746735Samurai#ifdef SIGPIPE
37524753Sache  signal(SIGPIPE, SIG_IGN);
3766735Samurai#endif
3776735Samurai#ifdef SIGALRM
37823840Sbrian  pending_signal(SIGALRM, SIG_IGN);
3796735Samurai#endif
38028679Sbrian  if (mode & MODE_INTER) {
38110528Samurai#ifdef SIGTSTP
38226940Sbrian    pending_signal(SIGTSTP, TerminalStop);
38310528Samurai#endif
38410528Samurai#ifdef SIGTTIN
38526940Sbrian    pending_signal(SIGTTIN, TerminalStop);
38610528Samurai#endif
38710528Samurai#ifdef SIGTTOU
38826940Sbrian    pending_signal(SIGTTOU, SIG_IGN);
38910528Samurai#endif
39026940Sbrian  }
39126940Sbrian#ifdef SIGUSR1
39226940Sbrian  if (mode != MODE_INTER)
39326940Sbrian    pending_signal(SIGUSR1, SetUpServer);
39426940Sbrian#endif
3956059Samurai
3966059Samurai  if (dstsystem) {
3976059Samurai    if (SelectSystem(dstsystem, CONFFILE) < 0) {
39826551Sbrian      LogPrintf(LogWARN, "Destination system not found in conf file.\n");
3996059Samurai      Cleanup(EX_START);
4006059Samurai    }
4016059Samurai    if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
40226551Sbrian      LogPrintf(LogWARN, "Must specify dstaddr with"
40328679Sbrian		" auto, background or ddial mode.\n");
4046059Samurai      Cleanup(EX_START);
4056059Samurai    }
4066059Samurai  }
40726940Sbrian
4086059Samurai  if (!(mode & MODE_INTER)) {
40920813Sjkh    if (mode & MODE_BACKGROUND) {
41028679Sbrian      if (pipe(BGFiledes)) {
41128974Sbrian	LogPrintf(LogERROR, "pipe: %s\n", strerror(errno));
41220813Sjkh	Cleanup(EX_SOCK);
41320813Sjkh      }
4146059Samurai    }
41526940Sbrian    /* Create server socket and listen. */
41629083Sbrian    if (server == -2)
41729083Sbrian      ServerTcpOpen(SERVER_PORT + tunno);
4186059Samurai
4196059Samurai    if (!(mode & MODE_DIRECT)) {
42020813Sjkh      pid_t bgpid;
42111336Samurai
42228679Sbrian      bgpid = fork();
42320813Sjkh      if (bgpid == -1) {
42428974Sbrian	LogPrintf(LogERROR, "fork: %s\n", strerror(errno));
42528679Sbrian	Cleanup(EX_SOCK);
42620813Sjkh      }
42720813Sjkh      if (bgpid) {
42820813Sjkh	char c = EX_NORMAL;
42911336Samurai
43020813Sjkh	if (mode & MODE_BACKGROUND) {
43120813Sjkh	  /* Wait for our child to close its pipe before we exit. */
43220813Sjkh	  BGPid = bgpid;
43328679Sbrian	  close(BGFiledes[1]);
43425908Sbrian	  if (read(BGFiledes[0], &c, 1) != 1) {
43526516Sbrian	    fprintf(VarTerm, "Child exit, no status.\n");
43628679Sbrian	    LogPrintf(LogPHASE, "Parent: Child exit, no status.\n");
43725908Sbrian	  } else if (c == EX_NORMAL) {
43826516Sbrian	    fprintf(VarTerm, "PPP enabled.\n");
43928679Sbrian	    LogPrintf(LogPHASE, "Parent: PPP enabled.\n");
44025908Sbrian	  } else {
44128679Sbrian	    fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c));
44226516Sbrian	    LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
44328679Sbrian		      ex_desc((int) c));
44428679Sbrian	  }
44528679Sbrian	  close(BGFiledes[0]);
44620813Sjkh	}
44728679Sbrian	return c;
44823863Sbrian      } else if (mode & MODE_BACKGROUND)
44928679Sbrian	close(BGFiledes[0]);
45025707Sbrian    }
45120813Sjkh
45228679Sbrian    VarTerm = 0;		/* We know it's currently stdout */
45329551Sbrian    close(1);
45426686Sbrian    close(2);
45526551Sbrian
4566059Samurai#ifdef DOTTYINIT
45728679Sbrian    if (mode & (MODE_DIRECT | MODE_DEDICATED))
4586059Samurai#else
45926686Sbrian    if (mode & MODE_DIRECT)
4606059Samurai#endif
46126858Sbrian      TtyInit(1);
46226686Sbrian    else {
46326686Sbrian      setsid();
46429551Sbrian      close(0);
46526686Sbrian    }
4666059Samurai  } else {
46726858Sbrian    TtyInit(0);
46810528Samurai    TtyCommandMode(1);
4696059Samurai  }
47029696Sbrian
47129696Sbrian  snprintf(pid_filename, sizeof(pid_filename), "%stun%d.pid",
47229696Sbrian           _PATH_VARRUN, tunno);
47329696Sbrian  (void) unlink(pid_filename);
47429696Sbrian
47529696Sbrian  if ((lockfile = fopen(pid_filename, "w")) != NULL) {
47629696Sbrian    fprintf(lockfile, "%d\n", (int) getpid());
47729696Sbrian    fclose(lockfile);
47829696Sbrian  } else
47929696Sbrian    LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
48029696Sbrian              pid_filename, strerror(errno));
48129696Sbrian
48226516Sbrian  LogPrintf(LogPHASE, "PPP Started.\n");
4836059Samurai
4846059Samurai
4856059Samurai  do
48628679Sbrian    DoLoop();
4876059Samurai  while (mode & MODE_DEDICATED);
4886059Samurai
4896059Samurai  Cleanup(EX_DONE);
49026940Sbrian  return 0;
4916059Samurai}
4926059Samurai
4936059Samurai/*
49420813Sjkh *  Turn into packet mode, where we speak PPP.
4956059Samurai */
4966059Samuraivoid
4976059SamuraiPacketMode()
4986059Samurai{
4996059Samurai  if (RawModem(modem) < 0) {
50026516Sbrian    LogPrintf(LogWARN, "PacketMode: Not connected.\n");
5016059Samurai    return;
5026059Samurai  }
5036059Samurai  AsyncInit();
50430187Sbrian  VjInit(15);
5056059Samurai  LcpInit();
5066059Samurai  IpcpInit();
5076059Samurai  CcpInit();
5086059Samurai  LcpUp();
5096059Samurai
51025872Sbrian  LcpOpen(VarOpenMode);
51128679Sbrian  if ((mode & (MODE_INTER | MODE_AUTO)) == MODE_INTER) {
51210528Samurai    TtyCommandMode(1);
51326516Sbrian    if (VarTerm) {
51426516Sbrian      fprintf(VarTerm, "Packet mode.\n");
51526516Sbrian      aft_cmd = 1;
51626516Sbrian    }
5176059Samurai  }
5186059Samurai}
5196059Samurai
5206059Samuraistatic void
5216059SamuraiShowHelp()
5226059Samurai{
52326901Sbrian  fprintf(stderr, "The following commands are available:\r\n");
52426901Sbrian  fprintf(stderr, " ~p\tEnter Packet mode\r\n");
52526901Sbrian  fprintf(stderr, " ~-\tDecrease log level\r\n");
52626901Sbrian  fprintf(stderr, " ~+\tIncrease log level\r\n");
52726901Sbrian  fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
52826901Sbrian  fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
52926901Sbrian  fprintf(stderr, " ~.\tTerminate program\r\n");
53026901Sbrian  fprintf(stderr, " ~?\tThis help\r\n");
5316059Samurai}
5326059Samurai
5336059Samuraistatic void
5346059SamuraiReadTty()
5356059Samurai{
5366059Samurai  int n;
5376059Samurai  char ch;
5386059Samurai  static int ttystate;
53926516Sbrian  FILE *oVarTerm;
54028679Sbrian
5416059Samurai#define MAXLINESIZE 200
5426059Samurai  char linebuff[MAXLINESIZE];
5436059Samurai
54426516Sbrian  LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
54528679Sbrian	    TermMode, netfd, mode);
5466059Samurai  if (!TermMode) {
54728679Sbrian    n = read(netfd, linebuff, sizeof(linebuff) - 1);
5486735Samurai    if (n > 0) {
54926516Sbrian      aft_cmd = 1;
55030497Sbrian      linebuff[n] = '\0';
55130497Sbrian      LogPrintf(LogCOMMAND, "Client: %s\n", linebuff);
5526059Samurai      DecodeCommand(linebuff, n, 1);
5536735Samurai    } else {
55426516Sbrian      LogPrintf(LogPHASE, "client connection closed.\n");
55524753Sache      VarLocalAuth = LOCAL_NO_AUTH;
55626516Sbrian      mode &= ~MODE_INTER;
55726516Sbrian      oVarTerm = VarTerm;
55826516Sbrian      VarTerm = 0;
55926516Sbrian      if (oVarTerm && oVarTerm != stdout)
56028679Sbrian	fclose(oVarTerm);
5616059Samurai      close(netfd);
5626059Samurai      netfd = -1;
5636059Samurai    }
5646059Samurai    return;
5656059Samurai  }
5666059Samurai
5676059Samurai  /*
56828679Sbrian   * We are in terminal mode, decode special sequences
5696059Samurai   */
57026516Sbrian  n = read(fileno(VarTerm), &ch, 1);
57128974Sbrian  LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
5726059Samurai
5736059Samurai  if (n > 0) {
5746059Samurai    switch (ttystate) {
5756059Samurai    case 0:
5766059Samurai      if (ch == '~')
5776059Samurai	ttystate++;
5786059Samurai      else
5796059Samurai	write(modem, &ch, n);
5806059Samurai      break;
5816059Samurai    case 1:
5826059Samurai      switch (ch) {
5836059Samurai      case '?':
5846059Samurai	ShowHelp();
5856059Samurai	break;
5866059Samurai      case 'p':
58728679Sbrian
5886059Samurai	/*
5896059Samurai	 * XXX: Should check carrier.
5906059Samurai	 */
5916059Samurai	if (LcpFsm.state <= ST_CLOSED) {
5926059Samurai	  VarOpenMode = OPEN_ACTIVE;
5936059Samurai	  PacketMode();
5946059Samurai	}
5956059Samurai	break;
5966059Samurai      case '.':
5976059Samurai	TermMode = 1;
59826516Sbrian	aft_cmd = 1;
59910528Samurai	TtyCommandMode(1);
6006059Samurai	break;
60126516Sbrian      case 't':
60226516Sbrian	if (LogIsKept(LogDEBUG)) {
60326516Sbrian	  ShowTimers();
60426516Sbrian	  break;
60526516Sbrian	}
60626516Sbrian      case 'm':
60726516Sbrian	if (LogIsKept(LogDEBUG)) {
60826516Sbrian	  ShowMemMap();
60926516Sbrian	  break;
61026516Sbrian	}
6116059Samurai      default:
6126059Samurai	if (write(modem, &ch, n) < 0)
61326516Sbrian	  LogPrintf(LogERROR, "error writing to modem.\n");
6146059Samurai	break;
6156059Samurai      }
6166059Samurai      ttystate = 0;
6176059Samurai      break;
6186059Samurai    }
6196059Samurai  }
6206059Samurai}
6216059Samurai
6226059Samurai
6236059Samurai/*
6246059Samurai *  Here, we'll try to detect HDLC frame
6256059Samurai */
6266059Samurai
6276059Samuraistatic char *FrameHeaders[] = {
6286735Samurai  "\176\377\003\300\041",
6296735Samurai  "\176\377\175\043\300\041",
6306735Samurai  "\176\177\175\043\100\041",
6316735Samurai  "\176\175\337\175\043\300\041",
6326735Samurai  "\176\175\137\175\043\100\041",
6336059Samurai  NULL,
6346059Samurai};
6356059Samurai
6366059Samuraiu_char *
63728679SbrianHdlcDetect(u_char * cp, int n)
6386059Samurai{
6396735Samurai  char *ptr, *fp, **hp;
6406059Samurai
64128679Sbrian  cp[n] = '\0';			/* be sure to null terminated */
6426059Samurai  ptr = NULL;
6436059Samurai  for (hp = FrameHeaders; *hp; hp++) {
6446735Samurai    fp = *hp;
6456735Samurai    if (DEV_IS_SYNC)
6466735Samurai      fp++;
64728679Sbrian    ptr = strstr((char *) cp, fp);
64813389Sphk    if (ptr)
6496059Samurai      break;
6506059Samurai  }
65128679Sbrian  return ((u_char *) ptr);
6526059Samurai}
6536059Samurai
6546059Samuraistatic struct pppTimer RedialTimer;
6556059Samurai
6566059Samuraistatic void
6576059SamuraiRedialTimeout()
6586059Samurai{
6596059Samurai  StopTimer(&RedialTimer);
66026516Sbrian  LogPrintf(LogPHASE, "Redialing timer expired.\n");
6616059Samurai}
6626059Samurai
6636059Samuraistatic void
66428679SbrianStartRedialTimer(int Timeout)
6656059Samurai{
6666059Samurai  StopTimer(&RedialTimer);
66711336Samurai
66824939Sbrian  if (Timeout) {
66911336Samurai    RedialTimer.state = TIMER_STOPPED;
67011336Samurai
67124939Sbrian    if (Timeout > 0)
67228679Sbrian      RedialTimer.load = Timeout * SECTICKS;
67311336Samurai    else
67428679Sbrian      RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
67511336Samurai
67626516Sbrian    LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
67724939Sbrian	      RedialTimer.load / SECTICKS);
67824939Sbrian
67911336Samurai    RedialTimer.func = RedialTimeout;
68011336Samurai    StartTimer(&RedialTimer);
68111336Samurai  }
6826059Samurai}
6836059Samurai
6846059Samurai
6856059Samuraistatic void
6866059SamuraiDoLoop()
6876059Samurai{
6886059Samurai  fd_set rfds, wfds, efds;
68923598Sache  int pri, i, n, wfd, nfds;
6906059Samurai  struct sockaddr_in hisaddr;
6916059Samurai  struct timeval timeout, *tp;
6926059Samurai  int ssize = sizeof(hisaddr);
6936059Samurai  u_char *cp;
6946059Samurai  u_char rbuff[MAX_MRU];
69511336Samurai  int tries;
6969448Samurai  int qlen;
69726858Sbrian  int res;
69810528Samurai  pid_t pgroup;
6996059Samurai
70010528Samurai  pgroup = getpgrp();
70110528Samurai
70225908Sbrian  if (mode & MODE_DIRECT) {
70326551Sbrian    LogPrintf(LogDEBUG, "Opening modem\n");
70429521Sbrian    if (OpenModem(mode) < 0)
70529521Sbrian      return;
70626516Sbrian    LogPrintf(LogPHASE, "Packet mode enabled\n");
7076059Samurai    PacketMode();
7086059Samurai  } else if (mode & MODE_DEDICATED) {
70923598Sache    if (modem < 0)
71029521Sbrian      while (OpenModem(mode) < 0)
71130697Sbrian	nointr_sleep(VarReconnectTimer);
7126059Samurai  }
71326516Sbrian  fflush(VarTerm);
7146059Samurai
7157001Samurai  timeout.tv_sec = 0;
7166059Samurai  timeout.tv_usec = 0;
71726098Sbrian  reconnectState = RECON_UNKNOWN;
7186059Samurai
71923863Sbrian  if (mode & MODE_BACKGROUND)
72028679Sbrian    dial_up = TRUE;		/* Bring the line up */
72123863Sbrian  else
72228679Sbrian    dial_up = FALSE;		/* XXXX */
72311336Samurai  tries = 0;
7246059Samurai  for (;;) {
72523598Sache    nfds = 0;
72628679Sbrian    FD_ZERO(&rfds);
72728679Sbrian    FD_ZERO(&wfds);
72828679Sbrian    FD_ZERO(&efds);
7297001Samurai
73028679Sbrian    /*
73128679Sbrian     * If the link is down and we're in DDIAL mode, bring it back up.
73220120Snate     */
73320120Snate    if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
73428679Sbrian      dial_up = TRUE;
73520120Snate
73625067Sbrian    /*
73728679Sbrian     * If we lost carrier and want to re-establish the connection due to the
73828679Sbrian     * "set reconnect" value, we'd better bring the line back up.
73925067Sbrian     */
74025908Sbrian    if (LcpFsm.state <= ST_CLOSED) {
74126098Sbrian      if (dial_up != TRUE && reconnectState == RECON_TRUE) {
74228679Sbrian	if (++reconnectCount <= VarReconnectTries) {
74328679Sbrian	  LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
74428679Sbrian		    reconnectCount, VarReconnectTries);
74525908Sbrian	  StartRedialTimer(VarReconnectTimer);
74628679Sbrian	  dial_up = TRUE;
74728679Sbrian	} else {
74828679Sbrian	  if (VarReconnectTries)
74928679Sbrian	    LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
75028679Sbrian		      VarReconnectTries);
75128679Sbrian	  reconnectCount = 0;
75228679Sbrian	  if (mode & MODE_BACKGROUND)
75328679Sbrian	    Cleanup(EX_DEAD);
75428679Sbrian	}
75528679Sbrian	reconnectState = RECON_ENVOKED;
75625801Sbrian      }
75725908Sbrian    }
75825067Sbrian
75928679Sbrian    /*
76028679Sbrian     * If Ip packet for output is enqueued and require dial up, Just do it!
76128679Sbrian     */
76228679Sbrian    if (dial_up && RedialTimer.state != TIMER_RUNNING) {
76326516Sbrian      LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
76429521Sbrian      if (OpenModem(mode) < 0) {
76528679Sbrian	tries++;
76628679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
76728679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
76828679Sbrian		    tries, VarDialTries);
76928679Sbrian	else
77028679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
77126551Sbrian
77226696Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
77326551Sbrian	  if (mode & MODE_BACKGROUND)
77428679Sbrian	    Cleanup(EX_DIAL);	/* Can't get the modem */
77526551Sbrian	  dial_up = FALSE;
77628679Sbrian	  reconnectState = RECON_UNKNOWN;
77728679Sbrian	  reconnectCount = 0;
77826551Sbrian	  tries = 0;
77928679Sbrian	} else
78026551Sbrian	  StartRedialTimer(VarRedialTimeout);
78111336Samurai      } else {
78228679Sbrian	tries++;		/* Tries are per number, not per list of
78328679Sbrian				 * numbers. */
78428679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
78526696Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
78628679Sbrian	else
78728679Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
78826696Sbrian
78926858Sbrian	if ((res = DialModem()) == EX_DONE) {
79030697Sbrian	  nointr_sleep(1);		/* little pause to allow peer starts */
79111336Samurai	  ModemTimeout();
79211336Samurai	  PacketMode();
79311336Samurai	  dial_up = FALSE;
79428679Sbrian	  reconnectState = RECON_UNKNOWN;
79511336Samurai	  tries = 0;
79611336Samurai	} else {
79711336Samurai	  CloseModem();
79824844Sbrian	  if (mode & MODE_BACKGROUND) {
79926858Sbrian	    if (VarNextPhone == NULL || res == EX_SIG)
80028679Sbrian	      Cleanup(EX_DIAL);	/* Tried all numbers - no luck */
80124844Sbrian	    else
80224939Sbrian	      /* Try all numbers in background mode */
80324939Sbrian	      StartRedialTimer(VarRedialNextTimeout);
80426858Sbrian	  } else if (!(mode & MODE_DDIAL) &&
80528679Sbrian		     ((VarDialTries && tries >= VarDialTries) ||
80628679Sbrian		      res == EX_SIG)) {
80724843Sbrian	    /* I give up !  Can't get through :( */
80824939Sbrian	    StartRedialTimer(VarRedialTimeout);
80924843Sbrian	    dial_up = FALSE;
81028679Sbrian	    reconnectState = RECON_UNKNOWN;
81128679Sbrian	    reconnectCount = 0;
81224843Sbrian	    tries = 0;
81324843Sbrian	  } else if (VarNextPhone == NULL)
81424843Sbrian	    /* Dial failed. Keep quite during redial wait period. */
81524939Sbrian	    StartRedialTimer(VarRedialTimeout);
81624843Sbrian	  else
81724939Sbrian	    StartRedialTimer(VarRedialNextTimeout);
81811336Samurai	}
81911336Samurai      }
8207001Samurai    }
8219448Samurai    qlen = ModemQlen();
82213733Sdfr
82313733Sdfr    if (qlen == 0) {
82413733Sdfr      IpStartOutput();
82513733Sdfr      qlen = ModemQlen();
82613733Sdfr    }
82723598Sache    if (modem >= 0) {
82823598Sache      if (modem + 1 > nfds)
82923598Sache	nfds = modem + 1;
8307001Samurai      FD_SET(modem, &rfds);
8317001Samurai      FD_SET(modem, &efds);
8329448Samurai      if (qlen > 0) {
8337001Samurai	FD_SET(modem, &wfds);
8347001Samurai      }
8357001Samurai    }
83623598Sache    if (server >= 0) {
83723598Sache      if (server + 1 > nfds)
83823598Sache	nfds = server + 1;
83923598Sache      FD_SET(server, &rfds);
84023598Sache    }
8416059Samurai
84228679Sbrian    /*
84328679Sbrian     * *** IMPORTANT ***
84428679Sbrian     *
84528679Sbrian     * CPU is serviced every TICKUNIT micro seconds. This value must be chosen
84628679Sbrian     * with great care. If this values is too big, it results loss of
84728679Sbrian     * characters from modem and poor responce. If this values is too small,
84828679Sbrian     * ppp process eats many CPU time.
8496059Samurai     */
8506735Samurai#ifndef SIGALRM
85130697Sbrian    nointr_usleep(TICKUNIT);
8526059Samurai    TimerService();
85323840Sbrian#else
85423840Sbrian    handle_signals();
8556735Samurai#endif
85610877Sbde
85710877Sbde    /* If there are aren't many packets queued, look for some more. */
85823598Sache    if (qlen < 20 && tun_in >= 0) {
85923598Sache      if (tun_in + 1 > nfds)
86023598Sache	nfds = tun_in + 1;
86110877Sbde      FD_SET(tun_in, &rfds);
86223598Sache    }
86323598Sache    if (netfd >= 0) {
86423598Sache      if (netfd + 1 > nfds)
86523598Sache	nfds = netfd + 1;
8666059Samurai      FD_SET(netfd, &rfds);
8676059Samurai      FD_SET(netfd, &efds);
8686059Samurai    }
86928679Sbrian#ifndef SIGALRM
8707001Samurai
8716059Samurai    /*
87228679Sbrian     * Normally, select() will not block because modem is writable. In AUTO
87328679Sbrian     * mode, select will block until we find packet from tun
8746059Samurai     */
87528679Sbrian    tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL;
87623598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
8776735Samurai#else
87828679Sbrian
8798857Srgrimes    /*
88028679Sbrian     * When SIGALRM timer is running, a select function will be return -1 and
88128679Sbrian     * EINTR after a Time Service signal hundler is done.  If the redial
88228679Sbrian     * timer is not running and we are trying to dial, poll with a 0 value
88328679Sbrian     * timer.
8847001Samurai     */
88511336Samurai    tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
88623598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
8876735Samurai#endif
88822074Sbrian
88928679Sbrian    if (i == 0) {
89028679Sbrian      continue;
8916059Samurai    }
89228679Sbrian    if (i < 0) {
89328679Sbrian      if (errno == EINTR) {
89428679Sbrian	handle_signals();
89528679Sbrian	continue;
89628679Sbrian      }
89728974Sbrian      LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
89828679Sbrian      break;
8998857Srgrimes    }
90023598Sache    if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
90126516Sbrian      LogPrintf(LogALERT, "Exception detected.\n");
9026059Samurai      break;
9036059Samurai    }
90423598Sache    if (server >= 0 && FD_ISSET(server, &rfds)) {
90526516Sbrian      LogPrintf(LogPHASE, "connected to client.\n");
90628679Sbrian      wfd = accept(server, (struct sockaddr *) & hisaddr, &ssize);
90724753Sache      if (wfd < 0) {
90828974Sbrian	LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno));
90924753Sache	continue;
91024753Sache      }
91123598Sache      if (netfd >= 0) {
9126059Samurai	write(wfd, "already in use.\n", 16);
9136059Samurai	close(wfd);
9146059Samurai	continue;
9156059Samurai      } else
9166059Samurai	netfd = wfd;
91726516Sbrian      VarTerm = fdopen(netfd, "a+");
9186059Samurai      mode |= MODE_INTER;
9196059Samurai      Greetings();
9206059Samurai      (void) IsInteractive();
92125630Sbrian      Prompt();
9226059Samurai    }
92323598Sache    if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) &&
92410858Samurai	((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) {
9256059Samurai      /* something to read from tty */
9266059Samurai      ReadTty();
9276059Samurai    }
92823598Sache    if (modem >= 0) {
9296059Samurai      if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
93028679Sbrian	ModemStartOutput(modem);
9316059Samurai      }
9326059Samurai      if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
9336735Samurai	if (LcpFsm.state <= ST_CLOSED)
93430697Sbrian	  nointr_usleep(10000);
9356059Samurai	n = read(modem, rbuff, sizeof(rbuff));
9366059Samurai	if ((mode & MODE_DIRECT) && n <= 0) {
9376059Samurai	  DownConnection();
9386059Samurai	} else
93928679Sbrian	  LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
9406059Samurai
9416059Samurai	if (LcpFsm.state <= ST_CLOSED) {
94228679Sbrian
9436059Samurai	  /*
94428679Sbrian	   * In dedicated mode, we just discard input until LCP is started.
9456059Samurai	   */
9466059Samurai	  if (!(mode & MODE_DEDICATED)) {
9476059Samurai	    cp = HdlcDetect(rbuff, n);
9486059Samurai	    if (cp) {
94928679Sbrian
9506059Samurai	      /*
9516059Samurai	       * LCP packet is detected. Turn ourselves into packet mode.
9526059Samurai	       */
9536059Samurai	      if (cp != rbuff) {
95428679Sbrian		write(modem, rbuff, cp - rbuff);
95528679Sbrian		write(modem, "\r\n", 2);
9566059Samurai	      }
9576059Samurai	      PacketMode();
9586059Samurai	    } else
95926516Sbrian	      write(fileno(VarTerm), rbuff, n);
9606059Samurai	  }
9616059Samurai	} else {
9626059Samurai	  if (n > 0)
9636059Samurai	    AsyncInput(rbuff, n);
9646059Samurai	}
9656059Samurai      }
9666059Samurai    }
96728679Sbrian    if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {	/* something to read
96828679Sbrian							 * from tun */
9696059Samurai      n = read(tun_in, rbuff, sizeof(rbuff));
9706059Samurai      if (n < 0) {
97128974Sbrian	LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno));
9726059Samurai	continue;
9736059Samurai      }
97428679Sbrian      if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) {
97528536Sbrian	/* we've been asked to send something addressed *to* us :( */
97628536Sbrian	if (VarLoopback) {
97728536Sbrian	  pri = PacketCheck(rbuff, n, FL_IN);
97828536Sbrian	  if (pri >= 0) {
97928536Sbrian	    struct mbuf *bp;
98028679Sbrian
98128536Sbrian	    if (mode & MODE_ALIAS) {
98228536Sbrian	      VarPacketAliasIn(rbuff, sizeof rbuff);
98328679Sbrian	      n = ntohs(((struct ip *) rbuff)->ip_len);
98428536Sbrian	    }
98528536Sbrian	    bp = mballoc(n, MB_IPIN);
98628536Sbrian	    bcopy(rbuff, MBUF_CTOP(bp), n);
98728536Sbrian	    IpInput(bp);
98828536Sbrian	    LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n");
98928536Sbrian	  }
99028536Sbrian	  continue;
99128679Sbrian	} else
99228536Sbrian	  LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
99328536Sbrian      }
99428536Sbrian
9956059Samurai      /*
99628679Sbrian       * Process on-demand dialup. Output packets are queued within tunnel
99728679Sbrian       * device until IPCP is opened.
9986059Samurai       */
9996059Samurai      if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
10007001Samurai	pri = PacketCheck(rbuff, n, FL_DIAL);
10016059Samurai	if (pri >= 0) {
100220365Sjkh	  if (mode & MODE_ALIAS) {
100326142Sbrian	    VarPacketAliasOut(rbuff, sizeof rbuff);
100428679Sbrian	    n = ntohs(((struct ip *) rbuff)->ip_len);
100520365Sjkh	  }
10066059Samurai	  IpEnqueue(pri, rbuff, n);
100728679Sbrian	  dial_up = TRUE;	/* XXX */
10086059Samurai	}
10096059Samurai	continue;
10106059Samurai      }
10117001Samurai      pri = PacketCheck(rbuff, n, FL_OUT);
101220365Sjkh      if (pri >= 0) {
101328679Sbrian	if (mode & MODE_ALIAS) {
101428679Sbrian	  VarPacketAliasOut(rbuff, sizeof rbuff);
101528679Sbrian	  n = ntohs(((struct ip *) rbuff)->ip_len);
101628679Sbrian	}
10176059Samurai	IpEnqueue(pri, rbuff, n);
101820365Sjkh      }
10196059Samurai    }
10206059Samurai  }
102126516Sbrian  LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
10226059Samurai}
1023