main.c revision 31061
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 *
2031061Sbrian * $Id: main.c,v 1.88 1997/11/08 00:28:09 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"
5031061Sbrian#include "id.h"
5130715Sbrian#include "timer.h"
5230715Sbrian#include "fsm.h"
536059Samurai#include "modem.h"
546059Samurai#include "os.h"
556059Samurai#include "hdlc.h"
5613389Sphk#include "ccp.h"
576059Samurai#include "lcp.h"
586059Samurai#include "ipcp.h"
5926142Sbrian#include "loadalias.h"
6030715Sbrian#include "command.h"
616059Samurai#include "vars.h"
626735Samurai#include "auth.h"
637001Samurai#include "filter.h"
6413389Sphk#include "systems.h"
6513389Sphk#include "ip.h"
6623840Sbrian#include "sig.h"
6726940Sbrian#include "server.h"
6828536Sbrian#include "lcpproto.h"
6930715Sbrian#include "main.h"
7030715Sbrian#include "vjcomp.h"
7130715Sbrian#include "async.h"
726059Samurai
736735Samurai#ifndef O_NONBLOCK
746735Samurai#ifdef O_NDELAY
756735Samurai#define	O_NONBLOCK O_NDELAY
766735Samurai#endif
776735Samurai#endif
786735Samurai
7930715Sbrianint TermMode = 0;
8030715Sbrianint tunno = 0;
816059Samurai
8228679Sbrianstatic struct termios oldtio;	/* Original tty mode */
8328679Sbrianstatic struct termios comtio;	/* Command level tty mode */
8420813Sjkhstatic pid_t BGPid = 0;
8525634Sbrianstatic char pid_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{
17630825Sbrian  OsInterfaceDown(1);
17730825Sbrian  HangupModem(1);
17830697Sbrian  nointr_sleep(1);
17925908Sbrian  if (mode & MODE_AUTO)
1806059Samurai    DeleteIfRoutes(1);
18131061Sbrian  ID0unlink(pid_filename);
18223863Sbrian  if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
18323863Sbrian    char c = EX_ERRDEAD;
18428679Sbrian
18528679Sbrian    if (write(BGFiledes[1], &c, 1) == 1)
18628679Sbrian      LogPrintf(LogPHASE, "Parent notified of failure.\n");
18723863Sbrian    else
18828679Sbrian      LogPrintf(LogPHASE, "Failed to notify parent of failure.\n");
18923863Sbrian    close(BGFiledes[1]);
19023863Sbrian  }
19128679Sbrian  LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
19226940Sbrian  ServerClose();
19310528Samurai  TtyOldMode();
19431061Sbrian  LogClose();
1956059Samurai
1966059Samurai  exit(excode);
1976059Samurai}
1986059Samurai
1996059Samuraistatic void
20028679SbrianCloseConnection(int signo)
2016059Samurai{
20226858Sbrian  /* NOTE, these are manual, we've done a setsid() */
20327157Sbrian  LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo);
20428679Sbrian  reconnectState = RECON_FALSE;
20528684Sbrian  reconnectCount = 0;
20628684Sbrian  DownConnection();
20730715Sbrian  dial_up = 0;
2086059Samurai}
2096059Samurai
2106059Samuraistatic void
21128679SbrianCloseSession(int signo)
2126059Samurai{
21328679Sbrian  if (BGPid) {
21428679Sbrian    kill(BGPid, SIGINT);
21528679Sbrian    exit(EX_TERM);
21628679Sbrian  }
21728679Sbrian  LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
21828679Sbrian  reconnect(RECON_FALSE);
21928679Sbrian  LcpClose();
22028679Sbrian  Cleanup(EX_TERM);
2216059Samurai}
2226059Samurai
22310528Samuraistatic void
22410528SamuraiTerminalCont()
22510528Samurai{
22623840Sbrian  pending_signal(SIGCONT, SIG_DFL);
22723840Sbrian  pending_signal(SIGTSTP, TerminalStop);
22810528Samurai  TtyCommandMode(getpgrp() == tcgetpgrp(0));
22910528Samurai}
23010528Samurai
23110528Samuraistatic void
23228679SbrianTerminalStop(int signo)
23310528Samurai{
23423840Sbrian  pending_signal(SIGCONT, TerminalCont);
23510528Samurai  TtyOldMode();
23623840Sbrian  pending_signal(SIGTSTP, SIG_DFL);
23710528Samurai  kill(getpid(), signo);
23810528Samurai}
23910528Samurai
24026940Sbrianstatic void
24128679SbrianSetUpServer(int signo)
24226940Sbrian{
24326940Sbrian  int res;
24428679Sbrian
24528679Sbrian  if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0)
24629083Sbrian    LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n",
24729083Sbrian	      res, SERVER_PORT + tunno);
24826940Sbrian}
24926940Sbrian
25025908Sbrianstatic char *
25125908Sbrianex_desc(int ex)
25225908Sbrian{
25325908Sbrian  static char num[12];
25428679Sbrian  static char *desc[] = {"normal", "start", "sock",
25525908Sbrian    "modem", "dial", "dead", "done", "reboot", "errdead",
25628679Sbrian  "hangup", "term", "nodial", "nologin"};
25710528Samurai
25828679Sbrian  if (ex >= 0 && ex < sizeof(desc) / sizeof(*desc))
25925908Sbrian    return desc[ex];
26025908Sbrian  snprintf(num, sizeof num, "%d", ex);
26125908Sbrian  return num;
26225908Sbrian}
26325908Sbrian
26430715Sbrianstatic void
2656059SamuraiUsage()
2666059Samurai{
26720120Snate  fprintf(stderr,
26828679Sbrian	  "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n");
2696059Samurai  exit(EX_START);
2706059Samurai}
2716059Samurai
27230715Sbrianstatic void
2736059SamuraiProcessArgs(int argc, char **argv)
2746059Samurai{
2756059Samurai  int optc;
2766059Samurai  char *cp;
2776059Samurai
2786059Samurai  optc = 0;
2796059Samurai  while (argc > 0 && **argv == '-') {
2806059Samurai    cp = *argv + 1;
2816059Samurai    if (strcmp(cp, "auto") == 0)
2826059Samurai      mode |= MODE_AUTO;
28320813Sjkh    else if (strcmp(cp, "background") == 0)
28428679Sbrian      mode |= MODE_BACKGROUND | MODE_AUTO;
2856059Samurai    else if (strcmp(cp, "direct") == 0)
2866059Samurai      mode |= MODE_DIRECT;
2876059Samurai    else if (strcmp(cp, "dedicated") == 0)
2886059Samurai      mode |= MODE_DEDICATED;
28920120Snate    else if (strcmp(cp, "ddial") == 0)
29028679Sbrian      mode |= MODE_DDIAL | MODE_AUTO;
29120365Sjkh    else if (strcmp(cp, "alias") == 0) {
29226142Sbrian      if (loadAliasHandlers(&VarAliasHandlers) == 0)
29328679Sbrian	mode |= MODE_ALIAS;
29426142Sbrian      else
29528679Sbrian	LogPrintf(LogWARN, "Cannot load alias library\n");
29628679Sbrian      optc--;			/* this option isn't exclusive */
29728679Sbrian    } else
2986059Samurai      Usage();
2996059Samurai    optc++;
30028679Sbrian    argv++;
30128679Sbrian    argc--;
3026059Samurai  }
3036059Samurai  if (argc > 1) {
3046059Samurai    fprintf(stderr, "specify only one system label.\n");
3056059Samurai    exit(EX_START);
3066059Samurai  }
30728679Sbrian  if (argc == 1)
30828679Sbrian    dstsystem = *argv;
3096059Samurai
3106059Samurai  if (optc > 1) {
3116059Samurai    fprintf(stderr, "specify only one mode.\n");
3126059Samurai    exit(EX_START);
3136059Samurai  }
3146059Samurai}
3156059Samurai
3166059Samuraistatic void
3176059SamuraiGreetings()
3186059Samurai{
31926516Sbrian  if (VarTerm) {
32026516Sbrian    fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n");
32126516Sbrian    fflush(VarTerm);
32226516Sbrian  }
3236059Samurai}
3246059Samurai
32526940Sbrianint
32628679Sbrianmain(int argc, char **argv)
3276059Samurai{
32825707Sbrian  FILE *lockfile;
32926516Sbrian  char *name;
33026516Sbrian
33126551Sbrian  VarTerm = 0;
33230715Sbrian  name = strrchr(argv[0], '/');
33328679Sbrian  LogOpen(name ? name + 1 : argv[0]);
33426516Sbrian
33528679Sbrian  argc--;
33628679Sbrian  argv++;
3376059Samurai  ProcessArgs(argc, argv);
33829083Sbrian  if (!(mode & MODE_DIRECT)) {
33929083Sbrian    if (getuid() != 0) {
34029083Sbrian      fprintf(stderr, "You may only run ppp in client mode as user id 0\n");
34129083Sbrian      LogClose();
34229083Sbrian      return EX_NOPERM;
34329083Sbrian    }
34426551Sbrian    VarTerm = stdout;
34529083Sbrian  }
34631061Sbrian  ID0init();
34726551Sbrian  Greetings();
3486059Samurai  IpcpDefAddress();
34929083Sbrian  LocalAuthInit();
3506059Samurai
35126516Sbrian  if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
35226516Sbrian    fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
3536059Samurai
3546059Samurai  if (OpenTunnel(&tunno) < 0) {
35526940Sbrian    LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno));
35626940Sbrian    return EX_START;
3576059Samurai  }
35828679Sbrian  if (mode & (MODE_AUTO | MODE_DIRECT | MODE_DEDICATED))
3596059Samurai    mode &= ~MODE_INTER;
3606059Samurai  if (mode & MODE_INTER) {
36126516Sbrian    fprintf(VarTerm, "Interactive mode\n");
36226690Sbrian    netfd = STDOUT_FILENO;
3636059Samurai  } else if (mode & MODE_AUTO) {
36426516Sbrian    fprintf(VarTerm, "Automatic Dialer mode\n");
3656059Samurai    if (dstsystem == NULL) {
36626516Sbrian      if (VarTerm)
36728679Sbrian	fprintf(VarTerm, "Destination system must be specified in"
36828679Sbrian		" auto, background or ddial mode.\n");
36926940Sbrian      return EX_START;
3706059Samurai    }
3716059Samurai  }
37228679Sbrian  tcgetattr(0, &oldtio);	/* Save original tty mode */
3736059Samurai
37427157Sbrian  pending_signal(SIGHUP, CloseSession);
37523840Sbrian  pending_signal(SIGTERM, CloseSession);
37627157Sbrian  pending_signal(SIGINT, CloseConnection);
37723840Sbrian  pending_signal(SIGQUIT, CloseSession);
3786735Samurai#ifdef SIGPIPE
37924753Sache  signal(SIGPIPE, SIG_IGN);
3806735Samurai#endif
3816735Samurai#ifdef SIGALRM
38223840Sbrian  pending_signal(SIGALRM, SIG_IGN);
3836735Samurai#endif
38428679Sbrian  if (mode & MODE_INTER) {
38510528Samurai#ifdef SIGTSTP
38626940Sbrian    pending_signal(SIGTSTP, TerminalStop);
38710528Samurai#endif
38810528Samurai#ifdef SIGTTIN
38926940Sbrian    pending_signal(SIGTTIN, TerminalStop);
39010528Samurai#endif
39110528Samurai#ifdef SIGTTOU
39226940Sbrian    pending_signal(SIGTTOU, SIG_IGN);
39310528Samurai#endif
39426940Sbrian  }
39526940Sbrian#ifdef SIGUSR1
39626940Sbrian  if (mode != MODE_INTER)
39726940Sbrian    pending_signal(SIGUSR1, SetUpServer);
39826940Sbrian#endif
3996059Samurai
4006059Samurai  if (dstsystem) {
4016059Samurai    if (SelectSystem(dstsystem, CONFFILE) < 0) {
40226551Sbrian      LogPrintf(LogWARN, "Destination system not found in conf file.\n");
4036059Samurai      Cleanup(EX_START);
4046059Samurai    }
4056059Samurai    if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
40626551Sbrian      LogPrintf(LogWARN, "Must specify dstaddr with"
40728679Sbrian		" auto, background or ddial mode.\n");
4086059Samurai      Cleanup(EX_START);
4096059Samurai    }
4106059Samurai  }
41126940Sbrian
4126059Samurai  if (!(mode & MODE_INTER)) {
41320813Sjkh    if (mode & MODE_BACKGROUND) {
41428679Sbrian      if (pipe(BGFiledes)) {
41528974Sbrian	LogPrintf(LogERROR, "pipe: %s\n", strerror(errno));
41620813Sjkh	Cleanup(EX_SOCK);
41720813Sjkh      }
4186059Samurai    }
41930715Sbrian    /* Create server socket and listen (initial value is -2) */
42029083Sbrian    if (server == -2)
42129083Sbrian      ServerTcpOpen(SERVER_PORT + tunno);
4226059Samurai
4236059Samurai    if (!(mode & MODE_DIRECT)) {
42420813Sjkh      pid_t bgpid;
42511336Samurai
42628679Sbrian      bgpid = fork();
42720813Sjkh      if (bgpid == -1) {
42828974Sbrian	LogPrintf(LogERROR, "fork: %s\n", strerror(errno));
42928679Sbrian	Cleanup(EX_SOCK);
43020813Sjkh      }
43120813Sjkh      if (bgpid) {
43220813Sjkh	char c = EX_NORMAL;
43311336Samurai
43420813Sjkh	if (mode & MODE_BACKGROUND) {
43520813Sjkh	  /* Wait for our child to close its pipe before we exit. */
43620813Sjkh	  BGPid = bgpid;
43728679Sbrian	  close(BGFiledes[1]);
43825908Sbrian	  if (read(BGFiledes[0], &c, 1) != 1) {
43926516Sbrian	    fprintf(VarTerm, "Child exit, no status.\n");
44028679Sbrian	    LogPrintf(LogPHASE, "Parent: Child exit, no status.\n");
44125908Sbrian	  } else if (c == EX_NORMAL) {
44226516Sbrian	    fprintf(VarTerm, "PPP enabled.\n");
44328679Sbrian	    LogPrintf(LogPHASE, "Parent: PPP enabled.\n");
44425908Sbrian	  } else {
44528679Sbrian	    fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c));
44626516Sbrian	    LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
44728679Sbrian		      ex_desc((int) c));
44828679Sbrian	  }
44928679Sbrian	  close(BGFiledes[0]);
45020813Sjkh	}
45128679Sbrian	return c;
45223863Sbrian      } else if (mode & MODE_BACKGROUND)
45328679Sbrian	close(BGFiledes[0]);
45425707Sbrian    }
45520813Sjkh
45628679Sbrian    VarTerm = 0;		/* We know it's currently stdout */
45729551Sbrian    close(1);
45826686Sbrian    close(2);
45926551Sbrian
4606059Samurai#ifdef DOTTYINIT
46128679Sbrian    if (mode & (MODE_DIRECT | MODE_DEDICATED))
4626059Samurai#else
46326686Sbrian    if (mode & MODE_DIRECT)
4646059Samurai#endif
46526858Sbrian      TtyInit(1);
46626686Sbrian    else {
46726686Sbrian      setsid();
46829551Sbrian      close(0);
46926686Sbrian    }
4706059Samurai  } else {
47126858Sbrian    TtyInit(0);
47210528Samurai    TtyCommandMode(1);
4736059Samurai  }
47429696Sbrian
47529696Sbrian  snprintf(pid_filename, sizeof(pid_filename), "%stun%d.pid",
47629696Sbrian           _PATH_VARRUN, tunno);
47731061Sbrian  lockfile = ID0fopen(pid_filename, "w");
47831061Sbrian  if (lockfile != NULL) {
47929696Sbrian    fprintf(lockfile, "%d\n", (int) getpid());
48029696Sbrian    fclose(lockfile);
48129696Sbrian  } else
48229696Sbrian    LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
48329696Sbrian              pid_filename, strerror(errno));
48429696Sbrian
48526516Sbrian  LogPrintf(LogPHASE, "PPP Started.\n");
4866059Samurai
4876059Samurai
4886059Samurai  do
48928679Sbrian    DoLoop();
4906059Samurai  while (mode & MODE_DEDICATED);
4916059Samurai
4926059Samurai  Cleanup(EX_DONE);
49326940Sbrian  return 0;
4946059Samurai}
4956059Samurai
4966059Samurai/*
49720813Sjkh *  Turn into packet mode, where we speak PPP.
4986059Samurai */
4996059Samuraivoid
5006059SamuraiPacketMode()
5016059Samurai{
50231034Sbrian  if (RawModem() < 0) {
50326516Sbrian    LogPrintf(LogWARN, "PacketMode: Not connected.\n");
5046059Samurai    return;
5056059Samurai  }
5066059Samurai  AsyncInit();
50730187Sbrian  VjInit(15);
5086059Samurai  LcpInit();
5096059Samurai  IpcpInit();
5106059Samurai  CcpInit();
5116059Samurai  LcpUp();
5126059Samurai
51325872Sbrian  LcpOpen(VarOpenMode);
51428679Sbrian  if ((mode & (MODE_INTER | MODE_AUTO)) == MODE_INTER) {
51510528Samurai    TtyCommandMode(1);
51626516Sbrian    if (VarTerm) {
51726516Sbrian      fprintf(VarTerm, "Packet mode.\n");
51826516Sbrian      aft_cmd = 1;
51926516Sbrian    }
5206059Samurai  }
5216059Samurai}
5226059Samurai
5236059Samuraistatic void
5246059SamuraiShowHelp()
5256059Samurai{
52626901Sbrian  fprintf(stderr, "The following commands are available:\r\n");
52726901Sbrian  fprintf(stderr, " ~p\tEnter Packet mode\r\n");
52826901Sbrian  fprintf(stderr, " ~-\tDecrease log level\r\n");
52926901Sbrian  fprintf(stderr, " ~+\tIncrease log level\r\n");
53026901Sbrian  fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
53126901Sbrian  fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
53226901Sbrian  fprintf(stderr, " ~.\tTerminate program\r\n");
53326901Sbrian  fprintf(stderr, " ~?\tThis help\r\n");
5346059Samurai}
5356059Samurai
5366059Samuraistatic void
5376059SamuraiReadTty()
5386059Samurai{
5396059Samurai  int n;
5406059Samurai  char ch;
5416059Samurai  static int ttystate;
54226516Sbrian  FILE *oVarTerm;
54328679Sbrian
5446059Samurai#define MAXLINESIZE 200
5456059Samurai  char linebuff[MAXLINESIZE];
5466059Samurai
54726516Sbrian  LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
54828679Sbrian	    TermMode, netfd, mode);
5496059Samurai  if (!TermMode) {
55028679Sbrian    n = read(netfd, linebuff, sizeof(linebuff) - 1);
5516735Samurai    if (n > 0) {
55226516Sbrian      aft_cmd = 1;
55330913Sbrian      if (linebuff[n-1] == '\n')
55430913Sbrian        linebuff[--n] = '\0';
55530913Sbrian      if (n) {
55630913Sbrian        if (IsInteractive(0))
55730913Sbrian          LogPrintf(LogCOMMAND, "%s\n", linebuff);
55830913Sbrian        else
55930913Sbrian          LogPrintf(LogCOMMAND, "Client: %s\n", linebuff);
56030913Sbrian        DecodeCommand(linebuff, n, 1);
56130913Sbrian      } else
56230913Sbrian        Prompt();
5636735Samurai    } else {
56426516Sbrian      LogPrintf(LogPHASE, "client connection closed.\n");
56524753Sache      VarLocalAuth = LOCAL_NO_AUTH;
56626516Sbrian      mode &= ~MODE_INTER;
56726516Sbrian      oVarTerm = VarTerm;
56826516Sbrian      VarTerm = 0;
56926516Sbrian      if (oVarTerm && oVarTerm != stdout)
57028679Sbrian	fclose(oVarTerm);
5716059Samurai      close(netfd);
5726059Samurai      netfd = -1;
5736059Samurai    }
5746059Samurai    return;
5756059Samurai  }
5766059Samurai
5776059Samurai  /*
57828679Sbrian   * We are in terminal mode, decode special sequences
5796059Samurai   */
58026516Sbrian  n = read(fileno(VarTerm), &ch, 1);
58128974Sbrian  LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
5826059Samurai
5836059Samurai  if (n > 0) {
5846059Samurai    switch (ttystate) {
5856059Samurai    case 0:
5866059Samurai      if (ch == '~')
5876059Samurai	ttystate++;
5886059Samurai      else
5896059Samurai	write(modem, &ch, n);
5906059Samurai      break;
5916059Samurai    case 1:
5926059Samurai      switch (ch) {
5936059Samurai      case '?':
5946059Samurai	ShowHelp();
5956059Samurai	break;
5966059Samurai      case 'p':
59728679Sbrian
5986059Samurai	/*
5996059Samurai	 * XXX: Should check carrier.
6006059Samurai	 */
6016059Samurai	if (LcpFsm.state <= ST_CLOSED) {
6026059Samurai	  VarOpenMode = OPEN_ACTIVE;
6036059Samurai	  PacketMode();
6046059Samurai	}
6056059Samurai	break;
6066059Samurai      case '.':
6076059Samurai	TermMode = 1;
60826516Sbrian	aft_cmd = 1;
60910528Samurai	TtyCommandMode(1);
6106059Samurai	break;
61126516Sbrian      case 't':
61226516Sbrian	if (LogIsKept(LogDEBUG)) {
61326516Sbrian	  ShowTimers();
61426516Sbrian	  break;
61526516Sbrian	}
61626516Sbrian      case 'm':
61726516Sbrian	if (LogIsKept(LogDEBUG)) {
61826516Sbrian	  ShowMemMap();
61926516Sbrian	  break;
62026516Sbrian	}
6216059Samurai      default:
6226059Samurai	if (write(modem, &ch, n) < 0)
62326516Sbrian	  LogPrintf(LogERROR, "error writing to modem.\n");
6246059Samurai	break;
6256059Samurai      }
6266059Samurai      ttystate = 0;
6276059Samurai      break;
6286059Samurai    }
6296059Samurai  }
6306059Samurai}
6316059Samurai
6326059Samurai
6336059Samurai/*
6346059Samurai *  Here, we'll try to detect HDLC frame
6356059Samurai */
6366059Samurai
6376059Samuraistatic char *FrameHeaders[] = {
6386735Samurai  "\176\377\003\300\041",
6396735Samurai  "\176\377\175\043\300\041",
6406735Samurai  "\176\177\175\043\100\041",
6416735Samurai  "\176\175\337\175\043\300\041",
6426735Samurai  "\176\175\137\175\043\100\041",
6436059Samurai  NULL,
6446059Samurai};
6456059Samurai
64630715Sbrianstatic u_char *
64728679SbrianHdlcDetect(u_char * cp, int n)
6486059Samurai{
6496735Samurai  char *ptr, *fp, **hp;
6506059Samurai
65128679Sbrian  cp[n] = '\0';			/* be sure to null terminated */
6526059Samurai  ptr = NULL;
6536059Samurai  for (hp = FrameHeaders; *hp; hp++) {
6546735Samurai    fp = *hp;
6556735Samurai    if (DEV_IS_SYNC)
6566735Samurai      fp++;
65728679Sbrian    ptr = strstr((char *) cp, fp);
65813389Sphk    if (ptr)
6596059Samurai      break;
6606059Samurai  }
66128679Sbrian  return ((u_char *) ptr);
6626059Samurai}
6636059Samurai
6646059Samuraistatic struct pppTimer RedialTimer;
6656059Samurai
6666059Samuraistatic void
6676059SamuraiRedialTimeout()
6686059Samurai{
6696059Samurai  StopTimer(&RedialTimer);
67026516Sbrian  LogPrintf(LogPHASE, "Redialing timer expired.\n");
6716059Samurai}
6726059Samurai
6736059Samuraistatic void
67428679SbrianStartRedialTimer(int Timeout)
6756059Samurai{
6766059Samurai  StopTimer(&RedialTimer);
67711336Samurai
67824939Sbrian  if (Timeout) {
67911336Samurai    RedialTimer.state = TIMER_STOPPED;
68011336Samurai
68124939Sbrian    if (Timeout > 0)
68228679Sbrian      RedialTimer.load = Timeout * SECTICKS;
68311336Samurai    else
68428679Sbrian      RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
68511336Samurai
68626516Sbrian    LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
68724939Sbrian	      RedialTimer.load / SECTICKS);
68824939Sbrian
68911336Samurai    RedialTimer.func = RedialTimeout;
69011336Samurai    StartTimer(&RedialTimer);
69111336Samurai  }
6926059Samurai}
6936059Samurai
6946059Samurai
6956059Samuraistatic void
6966059SamuraiDoLoop()
6976059Samurai{
6986059Samurai  fd_set rfds, wfds, efds;
69923598Sache  int pri, i, n, wfd, nfds;
7006059Samurai  struct sockaddr_in hisaddr;
7016059Samurai  struct timeval timeout, *tp;
7026059Samurai  int ssize = sizeof(hisaddr);
7036059Samurai  u_char *cp;
7046059Samurai  u_char rbuff[MAX_MRU];
70511336Samurai  int tries;
7069448Samurai  int qlen;
70726858Sbrian  int res;
70810528Samurai  pid_t pgroup;
7096059Samurai
71010528Samurai  pgroup = getpgrp();
71110528Samurai
71225908Sbrian  if (mode & MODE_DIRECT) {
71326551Sbrian    LogPrintf(LogDEBUG, "Opening modem\n");
71431034Sbrian    if (OpenModem() < 0)
71529521Sbrian      return;
71626516Sbrian    LogPrintf(LogPHASE, "Packet mode enabled\n");
7176059Samurai    PacketMode();
7186059Samurai  } else if (mode & MODE_DEDICATED) {
71923598Sache    if (modem < 0)
72031034Sbrian      while (OpenModem() < 0)
72130697Sbrian	nointr_sleep(VarReconnectTimer);
7226059Samurai  }
72326516Sbrian  fflush(VarTerm);
7246059Samurai
7257001Samurai  timeout.tv_sec = 0;
7266059Samurai  timeout.tv_usec = 0;
72726098Sbrian  reconnectState = RECON_UNKNOWN;
7286059Samurai
72923863Sbrian  if (mode & MODE_BACKGROUND)
73030715Sbrian    dial_up = 1;		/* Bring the line up */
73123863Sbrian  else
73230715Sbrian    dial_up = 0;		/* XXXX */
73311336Samurai  tries = 0;
7346059Samurai  for (;;) {
73523598Sache    nfds = 0;
73628679Sbrian    FD_ZERO(&rfds);
73728679Sbrian    FD_ZERO(&wfds);
73828679Sbrian    FD_ZERO(&efds);
7397001Samurai
74028679Sbrian    /*
74128679Sbrian     * If the link is down and we're in DDIAL mode, bring it back up.
74220120Snate     */
74320120Snate    if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
74430715Sbrian      dial_up = 1;
74520120Snate
74625067Sbrian    /*
74728679Sbrian     * If we lost carrier and want to re-establish the connection due to the
74828679Sbrian     * "set reconnect" value, we'd better bring the line back up.
74925067Sbrian     */
75025908Sbrian    if (LcpFsm.state <= ST_CLOSED) {
75130715Sbrian      if (!dial_up && reconnectState == RECON_TRUE) {
75228679Sbrian	if (++reconnectCount <= VarReconnectTries) {
75328679Sbrian	  LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
75428679Sbrian		    reconnectCount, VarReconnectTries);
75525908Sbrian	  StartRedialTimer(VarReconnectTimer);
75630715Sbrian	  dial_up = 1;
75728679Sbrian	} else {
75828679Sbrian	  if (VarReconnectTries)
75928679Sbrian	    LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
76028679Sbrian		      VarReconnectTries);
76128679Sbrian	  reconnectCount = 0;
76228679Sbrian	  if (mode & MODE_BACKGROUND)
76328679Sbrian	    Cleanup(EX_DEAD);
76428679Sbrian	}
76528679Sbrian	reconnectState = RECON_ENVOKED;
76625801Sbrian      }
76725908Sbrian    }
76825067Sbrian
76928679Sbrian    /*
77028679Sbrian     * If Ip packet for output is enqueued and require dial up, Just do it!
77128679Sbrian     */
77228679Sbrian    if (dial_up && RedialTimer.state != TIMER_RUNNING) {
77326516Sbrian      LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
77431034Sbrian      if (OpenModem() < 0) {
77528679Sbrian	tries++;
77628679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
77728679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
77828679Sbrian		    tries, VarDialTries);
77928679Sbrian	else
78028679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
78126551Sbrian
78226696Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
78326551Sbrian	  if (mode & MODE_BACKGROUND)
78428679Sbrian	    Cleanup(EX_DIAL);	/* Can't get the modem */
78530715Sbrian	  dial_up = 0;
78628679Sbrian	  reconnectState = RECON_UNKNOWN;
78728679Sbrian	  reconnectCount = 0;
78826551Sbrian	  tries = 0;
78928679Sbrian	} else
79026551Sbrian	  StartRedialTimer(VarRedialTimeout);
79111336Samurai      } else {
79228679Sbrian	tries++;		/* Tries are per number, not per list of
79328679Sbrian				 * numbers. */
79428679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
79526696Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
79628679Sbrian	else
79728679Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
79826696Sbrian
79926858Sbrian	if ((res = DialModem()) == EX_DONE) {
80030697Sbrian	  nointr_sleep(1);		/* little pause to allow peer starts */
80111336Samurai	  ModemTimeout();
80211336Samurai	  PacketMode();
80330715Sbrian	  dial_up = 0;
80428679Sbrian	  reconnectState = RECON_UNKNOWN;
80511336Samurai	  tries = 0;
80611336Samurai	} else {
80724844Sbrian	  if (mode & MODE_BACKGROUND) {
80826858Sbrian	    if (VarNextPhone == NULL || res == EX_SIG)
80928679Sbrian	      Cleanup(EX_DIAL);	/* Tried all numbers - no luck */
81024844Sbrian	    else
81124939Sbrian	      /* Try all numbers in background mode */
81224939Sbrian	      StartRedialTimer(VarRedialNextTimeout);
81326858Sbrian	  } else if (!(mode & MODE_DDIAL) &&
81428679Sbrian		     ((VarDialTries && tries >= VarDialTries) ||
81528679Sbrian		      res == EX_SIG)) {
81624843Sbrian	    /* I give up !  Can't get through :( */
81724939Sbrian	    StartRedialTimer(VarRedialTimeout);
81830715Sbrian	    dial_up = 0;
81928679Sbrian	    reconnectState = RECON_UNKNOWN;
82028679Sbrian	    reconnectCount = 0;
82124843Sbrian	    tries = 0;
82224843Sbrian	  } else if (VarNextPhone == NULL)
82324843Sbrian	    /* Dial failed. Keep quite during redial wait period. */
82424939Sbrian	    StartRedialTimer(VarRedialTimeout);
82524843Sbrian	  else
82624939Sbrian	    StartRedialTimer(VarRedialNextTimeout);
82711336Samurai	}
82811336Samurai      }
8297001Samurai    }
8309448Samurai    qlen = ModemQlen();
83113733Sdfr
83213733Sdfr    if (qlen == 0) {
83313733Sdfr      IpStartOutput();
83413733Sdfr      qlen = ModemQlen();
83513733Sdfr    }
83623598Sache    if (modem >= 0) {
83723598Sache      if (modem + 1 > nfds)
83823598Sache	nfds = modem + 1;
8397001Samurai      FD_SET(modem, &rfds);
8407001Samurai      FD_SET(modem, &efds);
8419448Samurai      if (qlen > 0) {
8427001Samurai	FD_SET(modem, &wfds);
8437001Samurai      }
8447001Samurai    }
84523598Sache    if (server >= 0) {
84623598Sache      if (server + 1 > nfds)
84723598Sache	nfds = server + 1;
84823598Sache      FD_SET(server, &rfds);
84923598Sache    }
8506059Samurai
85128679Sbrian    /*
85228679Sbrian     * *** IMPORTANT ***
85328679Sbrian     *
85428679Sbrian     * CPU is serviced every TICKUNIT micro seconds. This value must be chosen
85528679Sbrian     * with great care. If this values is too big, it results loss of
85628679Sbrian     * characters from modem and poor responce. If this values is too small,
85728679Sbrian     * ppp process eats many CPU time.
8586059Samurai     */
8596735Samurai#ifndef SIGALRM
86030697Sbrian    nointr_usleep(TICKUNIT);
8616059Samurai    TimerService();
86223840Sbrian#else
86323840Sbrian    handle_signals();
8646735Samurai#endif
86510877Sbde
86610877Sbde    /* If there are aren't many packets queued, look for some more. */
86723598Sache    if (qlen < 20 && tun_in >= 0) {
86823598Sache      if (tun_in + 1 > nfds)
86923598Sache	nfds = tun_in + 1;
87010877Sbde      FD_SET(tun_in, &rfds);
87123598Sache    }
87223598Sache    if (netfd >= 0) {
87323598Sache      if (netfd + 1 > nfds)
87423598Sache	nfds = netfd + 1;
8756059Samurai      FD_SET(netfd, &rfds);
8766059Samurai      FD_SET(netfd, &efds);
8776059Samurai    }
87828679Sbrian#ifndef SIGALRM
8797001Samurai
8806059Samurai    /*
88128679Sbrian     * Normally, select() will not block because modem is writable. In AUTO
88228679Sbrian     * mode, select will block until we find packet from tun
8836059Samurai     */
88428679Sbrian    tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL;
88523598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
8866735Samurai#else
88728679Sbrian
8888857Srgrimes    /*
88928679Sbrian     * When SIGALRM timer is running, a select function will be return -1 and
89028679Sbrian     * EINTR after a Time Service signal hundler is done.  If the redial
89128679Sbrian     * timer is not running and we are trying to dial, poll with a 0 value
89228679Sbrian     * timer.
8937001Samurai     */
89411336Samurai    tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
89523598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
8966735Samurai#endif
89722074Sbrian
89828679Sbrian    if (i == 0) {
89928679Sbrian      continue;
9006059Samurai    }
90128679Sbrian    if (i < 0) {
90228679Sbrian      if (errno == EINTR) {
90328679Sbrian	handle_signals();
90428679Sbrian	continue;
90528679Sbrian      }
90628974Sbrian      LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
90728679Sbrian      break;
9088857Srgrimes    }
90923598Sache    if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
91026516Sbrian      LogPrintf(LogALERT, "Exception detected.\n");
9116059Samurai      break;
9126059Samurai    }
91323598Sache    if (server >= 0 && FD_ISSET(server, &rfds)) {
91426516Sbrian      LogPrintf(LogPHASE, "connected to client.\n");
91528679Sbrian      wfd = accept(server, (struct sockaddr *) & hisaddr, &ssize);
91624753Sache      if (wfd < 0) {
91728974Sbrian	LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno));
91824753Sache	continue;
91924753Sache      }
92023598Sache      if (netfd >= 0) {
9216059Samurai	write(wfd, "already in use.\n", 16);
9226059Samurai	close(wfd);
9236059Samurai	continue;
9246059Samurai      } else
9256059Samurai	netfd = wfd;
92626516Sbrian      VarTerm = fdopen(netfd, "a+");
9276059Samurai      mode |= MODE_INTER;
9286059Samurai      Greetings();
92930913Sbrian      IsInteractive(1);
93025630Sbrian      Prompt();
9316059Samurai    }
93223598Sache    if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) &&
93310858Samurai	((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) {
9346059Samurai      /* something to read from tty */
9356059Samurai      ReadTty();
9366059Samurai    }
93723598Sache    if (modem >= 0) {
9386059Samurai      if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
93928679Sbrian	ModemStartOutput(modem);
9406059Samurai      }
9416059Samurai      if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
9426735Samurai	if (LcpFsm.state <= ST_CLOSED)
94330697Sbrian	  nointr_usleep(10000);
9446059Samurai	n = read(modem, rbuff, sizeof(rbuff));
9456059Samurai	if ((mode & MODE_DIRECT) && n <= 0) {
9466059Samurai	  DownConnection();
9476059Samurai	} else
94828679Sbrian	  LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
9496059Samurai
9506059Samurai	if (LcpFsm.state <= ST_CLOSED) {
95128679Sbrian
9526059Samurai	  /*
95328679Sbrian	   * In dedicated mode, we just discard input until LCP is started.
9546059Samurai	   */
9556059Samurai	  if (!(mode & MODE_DEDICATED)) {
9566059Samurai	    cp = HdlcDetect(rbuff, n);
9576059Samurai	    if (cp) {
95828679Sbrian
9596059Samurai	      /*
9606059Samurai	       * LCP packet is detected. Turn ourselves into packet mode.
9616059Samurai	       */
9626059Samurai	      if (cp != rbuff) {
96328679Sbrian		write(modem, rbuff, cp - rbuff);
96428679Sbrian		write(modem, "\r\n", 2);
9656059Samurai	      }
9666059Samurai	      PacketMode();
9676059Samurai	    } else
96826516Sbrian	      write(fileno(VarTerm), rbuff, n);
9696059Samurai	  }
9706059Samurai	} else {
9716059Samurai	  if (n > 0)
9726059Samurai	    AsyncInput(rbuff, n);
9736059Samurai	}
9746059Samurai      }
9756059Samurai    }
97628679Sbrian    if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {	/* something to read
97728679Sbrian							 * from tun */
9786059Samurai      n = read(tun_in, rbuff, sizeof(rbuff));
9796059Samurai      if (n < 0) {
98028974Sbrian	LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno));
9816059Samurai	continue;
9826059Samurai      }
98328679Sbrian      if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) {
98428536Sbrian	/* we've been asked to send something addressed *to* us :( */
98528536Sbrian	if (VarLoopback) {
98628536Sbrian	  pri = PacketCheck(rbuff, n, FL_IN);
98728536Sbrian	  if (pri >= 0) {
98828536Sbrian	    struct mbuf *bp;
98928679Sbrian
99028536Sbrian	    if (mode & MODE_ALIAS) {
99128536Sbrian	      VarPacketAliasIn(rbuff, sizeof rbuff);
99228679Sbrian	      n = ntohs(((struct ip *) rbuff)->ip_len);
99328536Sbrian	    }
99428536Sbrian	    bp = mballoc(n, MB_IPIN);
99530715Sbrian	    memcpy(MBUF_CTOP(bp), rbuff, n);
99628536Sbrian	    IpInput(bp);
99728536Sbrian	    LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n");
99828536Sbrian	  }
99928536Sbrian	  continue;
100028679Sbrian	} else
100128536Sbrian	  LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
100228536Sbrian      }
100328536Sbrian
10046059Samurai      /*
100528679Sbrian       * Process on-demand dialup. Output packets are queued within tunnel
100628679Sbrian       * device until IPCP is opened.
10076059Samurai       */
10086059Samurai      if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
10097001Samurai	pri = PacketCheck(rbuff, n, FL_DIAL);
10106059Samurai	if (pri >= 0) {
101120365Sjkh	  if (mode & MODE_ALIAS) {
101226142Sbrian	    VarPacketAliasOut(rbuff, sizeof rbuff);
101328679Sbrian	    n = ntohs(((struct ip *) rbuff)->ip_len);
101420365Sjkh	  }
10156059Samurai	  IpEnqueue(pri, rbuff, n);
101630715Sbrian	  dial_up = 1;	/* XXX */
10176059Samurai	}
10186059Samurai	continue;
10196059Samurai      }
10207001Samurai      pri = PacketCheck(rbuff, n, FL_OUT);
102120365Sjkh      if (pri >= 0) {
102228679Sbrian	if (mode & MODE_ALIAS) {
102328679Sbrian	  VarPacketAliasOut(rbuff, sizeof rbuff);
102428679Sbrian	  n = ntohs(((struct ip *) rbuff)->ip_len);
102528679Sbrian	}
10266059Samurai	IpEnqueue(pri, rbuff, n);
102720365Sjkh      }
10286059Samurai    }
10296059Samurai  }
103026516Sbrian  LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
10316059Samurai}
1032