main.c revision 27157
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 *
2027157Sbrian * $Id: main.c,v 1.68 1997/06/29 13:54:31 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>
406059Samurai#include "modem.h"
416059Samurai#include "os.h"
426059Samurai#include "hdlc.h"
4313389Sphk#include "ccp.h"
446059Samurai#include "lcp.h"
456059Samurai#include "ipcp.h"
4626142Sbrian#include "loadalias.h"
476059Samurai#include "vars.h"
486735Samurai#include "auth.h"
497001Samurai#include "filter.h"
5013389Sphk#include "systems.h"
5113389Sphk#include "ip.h"
5223840Sbrian#include "sig.h"
5326940Sbrian#include "server.h"
546059Samurai
556764Samurai#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n"
5626516Sbrian#define LAUTH_M2 "Warning: Manipulation is allowed by anyone\n"
576764Samurai
586735Samurai#ifndef O_NONBLOCK
596735Samurai#ifdef O_NDELAY
606735Samurai#define	O_NONBLOCK O_NDELAY
616735Samurai#endif
626735Samurai#endif
636735Samurai
646059Samuraiextern void VjInit(), AsyncInit();
6525630Sbrianextern void AsyncInput();
666059Samuraiextern int  SelectSystem();
676059Samurai
686059Samuraiextern void DecodeCommand(), Prompt();
6918885Sjkhextern int aft_cmd;
706059Samuraiextern int IsInteractive();
716059Samuraistatic void DoLoop(void);
7210528Samuraistatic void TerminalStop();
7325908Sbrianstatic char *ex_desc();
746059Samurai
756059Samuraistatic struct termios oldtio;		/* Original tty mode */
766059Samuraistatic struct termios comtio;		/* Command level tty mode */
7714418Sacheint TermMode;
7820813Sjkhstatic pid_t BGPid = 0;
7925634Sbrianstatic char pid_filename[MAXPATHLEN];
8025634Sbrianstatic char if_filename[MAXPATHLEN];
8125445Sacheint tunno;
8227061Sbrianstatic int dial_up;
836059Samurai
846059Samuraistatic void
8526858SbrianTtyInit(int DontWantInt)
866059Samurai{
876059Samurai  struct termios newtio;
886059Samurai  int stat;
896059Samurai
906059Samurai  stat = fcntl(0, F_GETFL, 0);
9125630Sbrian  if (stat > 0) {
9225630Sbrian	 stat |= O_NONBLOCK;
9325630Sbrian	 (void)fcntl(0, F_SETFL, stat);
9425630Sbrian  }
956059Samurai  newtio = oldtio;
966059Samurai  newtio.c_lflag &= ~(ECHO|ISIG|ICANON);
976059Samurai  newtio.c_iflag = 0;
986059Samurai  newtio.c_oflag &= ~OPOST;
996059Samurai  newtio.c_cc[VEOF] = _POSIX_VDISABLE;
10026858Sbrian  if (DontWantInt)
10126858Sbrian    newtio.c_cc[VINTR] = _POSIX_VDISABLE;
1026059Samurai  newtio.c_cc[VMIN] = 1;
1036059Samurai  newtio.c_cc[VTIME] = 0;
1046059Samurai  newtio.c_cflag |= CS8;
1056735Samurai  tcsetattr(0, TCSADRAIN, &newtio);
1066059Samurai  comtio = newtio;
1076059Samurai}
1086059Samurai
1096059Samurai/*
1106059Samurai *  Set tty into command mode. We allow canonical input and echo processing.
1116059Samurai */
11210528Samuraivoid
11310528SamuraiTtyCommandMode(prompt)
11410528Samuraiint prompt;
1156059Samurai{
1166059Samurai  struct termios newtio;
1176059Samurai  int stat;
1186059Samurai
1196059Samurai  if (!(mode & MODE_INTER))
1206059Samurai    return;
1216735Samurai  tcgetattr(0, &newtio);
12210528Samurai  newtio.c_lflag |= (ECHO|ISIG|ICANON);
1236059Samurai  newtio.c_iflag = oldtio.c_iflag;
1246059Samurai  newtio.c_oflag |= OPOST;
1256735Samurai  tcsetattr(0, TCSADRAIN, &newtio);
1266059Samurai  stat = fcntl(0, F_GETFL, 0);
12725630Sbrian  if (stat > 0) {
12825630Sbrian	 stat |= O_NONBLOCK;
12925630Sbrian	 (void)fcntl(0, F_SETFL, stat);
13025630Sbrian  }
1316059Samurai  TermMode = 0;
13225630Sbrian  if(prompt) Prompt();
1336059Samurai}
1346059Samurai
1356059Samurai/*
1366059Samurai * Set tty into terminal mode which is used while we invoke term command.
1376059Samurai */
1386059Samuraivoid
1396059SamuraiTtyTermMode()
1406059Samurai{
1416059Samurai  int stat;
1426059Samurai
1436735Samurai  tcsetattr(0, TCSADRAIN, &comtio);
1446059Samurai  stat = fcntl(0, F_GETFL, 0);
14525630Sbrian  if (stat > 0) {
14625630Sbrian	 stat &= ~O_NONBLOCK;
14725630Sbrian	 (void)fcntl(0, F_SETFL, stat);
14825630Sbrian  }
1496059Samurai  TermMode = 1;
1506059Samurai}
1516059Samurai
1526059Samuraivoid
15310528SamuraiTtyOldMode()
1546059Samurai{
1556059Samurai  int stat;
1566059Samurai
1576059Samurai  stat = fcntl(0, F_GETFL, 0);
15825630Sbrian  if (stat > 0) {
15925630Sbrian	  stat &= ~O_NONBLOCK;
16025630Sbrian	  (void)fcntl(0, F_SETFL, stat);
16125630Sbrian  }
1626735Samurai  tcsetattr(0, TCSANOW, &oldtio);
16310528Samurai}
16410528Samurai
16510528Samuraivoid
16610528SamuraiCleanup(excode)
16710528Samuraiint excode;
16810528Samurai{
16910528Samurai
17010528Samurai  OsLinkdown();
1716059Samurai  OsCloseLink(1);
1726059Samurai  sleep(1);
17325908Sbrian  if (mode & MODE_AUTO)
1746059Samurai    DeleteIfRoutes(1);
17525707Sbrian  (void)unlink(pid_filename);
17625707Sbrian  (void)unlink(if_filename);
1776059Samurai  OsInterfaceDown(1);
17823863Sbrian  if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
17923863Sbrian    char c = EX_ERRDEAD;
18023863Sbrian    if (write(BGFiledes[1],&c,1) == 1)
18126516Sbrian      LogPrintf(LogPHASE,"Parent notified of failure.\n");
18223863Sbrian    else
18326516Sbrian      LogPrintf(LogPHASE,"Failed to notify parent of failure.\n");
18423863Sbrian    close(BGFiledes[1]);
18523863Sbrian  }
18626516Sbrian  LogPrintf(LogPHASE, "PPP Terminated (%s).\n",ex_desc(excode));
1876059Samurai  LogClose();
18826940Sbrian  ServerClose();
18910528Samurai  TtyOldMode();
1906059Samurai
1916059Samurai  exit(excode);
1926059Samurai}
1936059Samurai
1946059Samuraistatic void
19527157SbrianCloseConnection(signo)
19614930Sacheint signo;
1976059Samurai{
19826858Sbrian  /* NOTE, these are manual, we've done a setsid() */
19927157Sbrian  LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo);
20027061Sbrian  reconnectState = RECON_FALSE;                  \
20127061Sbrian  reconnectCount = 0;                   \
20226858Sbrian  DownConnection();
20327061Sbrian  dial_up = FALSE;
2046059Samurai}
2056059Samurai
2066059Samuraistatic void
20714930SacheCloseSession(signo)
20814930Sacheint signo;
2096059Samurai{
21020813Sjkh   if (BGPid) {
21120813Sjkh     kill (BGPid, SIGINT);
21220813Sjkh     exit (EX_TERM);
21320813Sjkh   }
21426516Sbrian   LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
21526516Sbrian   reconnect(RECON_FALSE);
21626516Sbrian   LcpClose();
21726516Sbrian   Cleanup(EX_TERM);
2186059Samurai}
2196059Samurai
22010528Samuraistatic void
22110528SamuraiTerminalCont()
22210528Samurai{
22323840Sbrian  pending_signal(SIGCONT, SIG_DFL);
22423840Sbrian  pending_signal(SIGTSTP, TerminalStop);
22510528Samurai  TtyCommandMode(getpgrp() == tcgetpgrp(0));
22610528Samurai}
22710528Samurai
22810528Samuraistatic void
22910528SamuraiTerminalStop(signo)
23010528Samuraiint signo;
23110528Samurai{
23223840Sbrian  pending_signal(SIGCONT, TerminalCont);
23310528Samurai  TtyOldMode();
23423840Sbrian  pending_signal(SIGTSTP, SIG_DFL);
23510528Samurai  kill(getpid(), signo);
23610528Samurai}
23710528Samurai
23826940Sbrianstatic void
23926940SbrianSetUpServer(signo)
24026940Sbrianint signo;
24126940Sbrian{
24226940Sbrian  int res;
24326940Sbrian  if ((res = ServerTcpOpen(SERVER_PORT+tunno)) != 0)
24426940Sbrian    LogPrintf(LogERROR, "Failed %d to open port %d\n", res, SERVER_PORT+tunno);
24526940Sbrian}
24626940Sbrian
24725908Sbrianstatic char *
24825908Sbrianex_desc(int ex)
24925908Sbrian{
25025908Sbrian  static char num[12];
25125908Sbrian  static char *desc[] = { "normal", "start", "sock",
25225908Sbrian    "modem", "dial", "dead", "done", "reboot", "errdead",
25325908Sbrian    "hangup", "term", "nodial", "nologin" };
25410528Samurai
25525908Sbrian  if (ex >= 0 && ex < sizeof(desc)/sizeof(*desc))
25625908Sbrian    return desc[ex];
25725908Sbrian  snprintf(num, sizeof num, "%d", ex);
25825908Sbrian  return num;
25925908Sbrian}
26025908Sbrian
2616059Samuraivoid
2626059SamuraiUsage()
2636059Samurai{
26420120Snate  fprintf(stderr,
26520813Sjkh          "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n");
2666059Samurai  exit(EX_START);
2676059Samurai}
2686059Samurai
2696059Samuraivoid
2706059SamuraiProcessArgs(int argc, char **argv)
2716059Samurai{
2726059Samurai  int optc;
2736059Samurai  char *cp;
2746059Samurai
2756059Samurai  optc = 0;
2766059Samurai  while (argc > 0 && **argv == '-') {
2776059Samurai    cp = *argv + 1;
2786059Samurai    if (strcmp(cp, "auto") == 0)
2796059Samurai      mode |= MODE_AUTO;
28020813Sjkh    else if (strcmp(cp, "background") == 0)
28125908Sbrian      mode |= MODE_BACKGROUND|MODE_AUTO;
2826059Samurai    else if (strcmp(cp, "direct") == 0)
2836059Samurai      mode |= MODE_DIRECT;
2846059Samurai    else if (strcmp(cp, "dedicated") == 0)
2856059Samurai      mode |= MODE_DEDICATED;
28620120Snate    else if (strcmp(cp, "ddial") == 0)
28720120Snate      mode |= MODE_DDIAL|MODE_AUTO;
28820365Sjkh    else if (strcmp(cp, "alias") == 0) {
28926142Sbrian      if (loadAliasHandlers(&VarAliasHandlers) == 0)
29026142Sbrian        mode |= MODE_ALIAS;
29126142Sbrian      else
29226516Sbrian        LogPrintf(LogWARN, "Cannot load alias library\n");
29320365Sjkh      optc--;             /* this option isn't exclusive */
29420365Sjkh    }
2956059Samurai    else
2966059Samurai      Usage();
2976059Samurai    optc++;
2986059Samurai    argv++; argc--;
2996059Samurai  }
3006059Samurai  if (argc > 1) {
3016059Samurai    fprintf(stderr, "specify only one system label.\n");
3026059Samurai    exit(EX_START);
3036059Samurai  }
3046059Samurai  if (argc == 1) dstsystem = *argv;
3056059Samurai
3066059Samurai  if (optc > 1) {
3076059Samurai    fprintf(stderr, "specify only one mode.\n");
3086059Samurai    exit(EX_START);
3096059Samurai  }
3106059Samurai}
3116059Samurai
3126059Samuraistatic void
3136059SamuraiGreetings()
3146059Samurai{
31526516Sbrian  if (VarTerm) {
31626516Sbrian    fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n");
31726516Sbrian    fflush(VarTerm);
31826516Sbrian  }
3196059Samurai}
3206059Samurai
32126940Sbrianint
3226059Samuraimain(argc, argv)
3236059Samuraiint argc;
3246059Samuraichar **argv;
3256059Samurai{
32625707Sbrian  FILE *lockfile;
32726516Sbrian  char *name;
32826516Sbrian
32926551Sbrian  VarTerm = 0;
33026516Sbrian  name = rindex(argv[0], '/');
33126516Sbrian  LogOpen(name ? name+1 : argv[0]);
33226516Sbrian
3336059Samurai  argc--; argv++;
3346059Samurai  mode = MODE_INTER;		/* default operation is interactive mode */
33526940Sbrian  netfd = modem = tun_in = -1;
33626940Sbrian  server = -2;
3376059Samurai  ProcessArgs(argc, argv);
33826328Sbrian  if (!(mode & MODE_DIRECT))
33926551Sbrian    VarTerm = stdout;
34026551Sbrian  Greetings();
3416059Samurai  GetUid();
3426059Samurai  IpcpDefAddress();
3436059Samurai
34426516Sbrian  if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
34526516Sbrian    fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
3466059Samurai
3476059Samurai  if (OpenTunnel(&tunno) < 0) {
34826940Sbrian    LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno));
34926940Sbrian    return EX_START;
3506059Samurai  }
3516059Samurai
35225908Sbrian  if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED))
3536059Samurai    mode &= ~MODE_INTER;
3546059Samurai  if (mode & MODE_INTER) {
35526516Sbrian    fprintf(VarTerm, "Interactive mode\n");
35626690Sbrian    netfd = STDOUT_FILENO;
3576059Samurai  } else if (mode & MODE_AUTO) {
35826516Sbrian    fprintf(VarTerm, "Automatic Dialer mode\n");
3596059Samurai    if (dstsystem == NULL) {
36026516Sbrian      if (VarTerm)
36126516Sbrian        fprintf(VarTerm, "Destination system must be specified in"
36225908Sbrian              " auto, background or ddial mode.\n");
36326940Sbrian      return EX_START;
3646059Samurai    }
3656059Samurai  }
3666059Samurai
3676735Samurai  tcgetattr(0, &oldtio);		/* Save original tty mode */
3686059Samurai
36927157Sbrian  pending_signal(SIGHUP, CloseSession);
37023840Sbrian  pending_signal(SIGTERM, CloseSession);
37127157Sbrian  pending_signal(SIGINT, CloseConnection);
37223840Sbrian  pending_signal(SIGQUIT, CloseSession);
3736735Samurai#ifdef SIGPIPE
37424753Sache  signal(SIGPIPE, SIG_IGN);
3756735Samurai#endif
3766735Samurai#ifdef SIGALRM
37723840Sbrian  pending_signal(SIGALRM, SIG_IGN);
3786735Samurai#endif
37926940Sbrian  if(mode & MODE_INTER) {
38010528Samurai#ifdef SIGTSTP
38126940Sbrian    pending_signal(SIGTSTP, TerminalStop);
38210528Samurai#endif
38310528Samurai#ifdef SIGTTIN
38426940Sbrian    pending_signal(SIGTTIN, TerminalStop);
38510528Samurai#endif
38610528Samurai#ifdef SIGTTOU
38726940Sbrian    pending_signal(SIGTTOU, SIG_IGN);
38810528Samurai#endif
38926940Sbrian  }
39026940Sbrian#ifdef SIGUSR1
39126940Sbrian  if (mode != MODE_INTER)
39226940Sbrian    pending_signal(SIGUSR1, SetUpServer);
39326940Sbrian#endif
3946059Samurai
3956059Samurai  if (dstsystem) {
3966059Samurai    if (SelectSystem(dstsystem, CONFFILE) < 0) {
39726551Sbrian      LogPrintf(LogWARN, "Destination system not found in conf file.\n");
3986059Samurai      Cleanup(EX_START);
3996059Samurai    }
4006059Samurai    if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
40126551Sbrian      LogPrintf(LogWARN, "Must specify dstaddr with"
40225908Sbrian              " auto, background or ddial mode.\n");
4036059Samurai      Cleanup(EX_START);
4046059Samurai    }
4056059Samurai  }
4066059Samurai
40726940Sbrian  if (ServerType() != NO_SERVER)
40826940Sbrian    switch ( LocalAuthInit() ) {
40926940Sbrian      case NOT_FOUND:
41026940Sbrian        if (VarTerm) {
41126940Sbrian    	  fprintf(VarTerm,LAUTH_M1);
41226940Sbrian    	  fprintf(VarTerm,LAUTH_M2);
41326940Sbrian          fflush(VarTerm);
41426940Sbrian        }
41526940Sbrian	/* Fall down */
41626940Sbrian      case VALID:
41726940Sbrian	VarLocalAuth = LOCAL_AUTH;
41826940Sbrian	break;
41926940Sbrian      default:
42026940Sbrian	break;
42126940Sbrian    }
42226940Sbrian
4236059Samurai  if (!(mode & MODE_INTER)) {
42420813Sjkh    if (mode & MODE_BACKGROUND) {
42520813Sjkh      if (pipe (BGFiledes)) {
42626516Sbrian        LogPrintf(LogERROR, "pipe: %s", strerror(errno));
42720813Sjkh	Cleanup(EX_SOCK);
42820813Sjkh      }
4296059Samurai    }
43025908Sbrian
43126940Sbrian    /* Create server socket and listen. */
43226940Sbrian    if (server == -2 && ServerTcpOpen(SERVER_PORT + tunno) != 0)
43326940Sbrian	Cleanup(EX_SOCK);
4346059Samurai
4356059Samurai    if (!(mode & MODE_DIRECT)) {
43620813Sjkh      pid_t bgpid;
43711336Samurai
43820813Sjkh      bgpid = fork ();
43920813Sjkh      if (bgpid == -1) {
44026516Sbrian        LogPrintf(LogERROR, "fork: %s", strerror(errno));
44120813Sjkh	Cleanup (EX_SOCK);
44220813Sjkh      }
44320813Sjkh      if (bgpid) {
44420813Sjkh	char c = EX_NORMAL;
44511336Samurai
44620813Sjkh	if (mode & MODE_BACKGROUND) {
44720813Sjkh	  /* Wait for our child to close its pipe before we exit. */
44820813Sjkh	  BGPid = bgpid;
44926516Sbrian          close(BGFiledes[1]);
45025908Sbrian	  if (read(BGFiledes[0], &c, 1) != 1) {
45126516Sbrian	    fprintf(VarTerm, "Child exit, no status.\n");
45226516Sbrian	    LogPrintf (LogPHASE, "Parent: Child exit, no status.\n");
45325908Sbrian	  } else if (c == EX_NORMAL) {
45426516Sbrian	    fprintf(VarTerm, "PPP enabled.\n");
45526516Sbrian	    LogPrintf (LogPHASE, "Parent: PPP enabled.\n");
45625908Sbrian	  } else {
45726516Sbrian	    fprintf(VarTerm, "Child failed (%s).\n",ex_desc((int)c));
45826516Sbrian	    LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
45925910Sbrian                      ex_desc((int)c));
46025908Sbrian          }
46126516Sbrian          close(BGFiledes[0]);
46220813Sjkh	}
46326940Sbrian        return c;
46423863Sbrian      } else if (mode & MODE_BACKGROUND)
46523863Sbrian          close(BGFiledes[0]);
46625707Sbrian    }
46720813Sjkh
46825801Sbrian    snprintf(pid_filename, sizeof (pid_filename), "%stun%d.pid",
46925707Sbrian             _PATH_VARRUN, tunno);
47025707Sbrian    (void)unlink(pid_filename);
47111336Samurai
47225707Sbrian    if ((lockfile = fopen(pid_filename, "w")) != NULL) {
47325707Sbrian      fprintf(lockfile, "%d\n", (int)getpid());
47425707Sbrian      fclose(lockfile);
47525707Sbrian    } else
47626516Sbrian      LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
47726516Sbrian                pid_filename, strerror(errno));
47825634Sbrian
47925707Sbrian    snprintf(if_filename, sizeof if_filename, "%s%s.if",
48025707Sbrian             _PATH_VARRUN, VarBaseDevice);
48125707Sbrian    (void)unlink(if_filename);
48225634Sbrian
48325707Sbrian    if ((lockfile = fopen(if_filename, "w")) != NULL) {
48425707Sbrian      fprintf(lockfile, "tun%d\n", tunno);
48525707Sbrian      fclose(lockfile);
48625707Sbrian    } else
48726516Sbrian      LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
48826516Sbrian                if_filename, strerror(errno));
48925707Sbrian
49026686Sbrian    VarTerm = 0;   /* We know it's currently stdout */
49126686Sbrian    close(0);
49226686Sbrian    close(2);
49326551Sbrian
4946059Samurai#ifdef DOTTYINIT
49526686Sbrian    if (mode & (MODE_DIRECT|MODE_DEDICATED))
4966059Samurai#else
49726686Sbrian    if (mode & MODE_DIRECT)
4986059Samurai#endif
49926858Sbrian      TtyInit(1);
50026686Sbrian    else {
50126686Sbrian      setsid();
50226686Sbrian      close(1);
50326686Sbrian    }
5046059Samurai  } else {
50526858Sbrian    TtyInit(0);
50610528Samurai    TtyCommandMode(1);
5076059Samurai  }
50826516Sbrian  LogPrintf(LogPHASE, "PPP Started.\n");
5096059Samurai
5106059Samurai
5116059Samurai  do
5126059Samurai   DoLoop();
5136059Samurai  while (mode & MODE_DEDICATED);
5146059Samurai
5156059Samurai  Cleanup(EX_DONE);
51626940Sbrian  return 0;
5176059Samurai}
5186059Samurai
5196059Samurai/*
52020813Sjkh *  Turn into packet mode, where we speak PPP.
5216059Samurai */
5226059Samuraivoid
5236059SamuraiPacketMode()
5246059Samurai{
5256059Samurai  if (RawModem(modem) < 0) {
52626516Sbrian    LogPrintf(LogWARN, "PacketMode: Not connected.\n");
5276059Samurai    return;
5286059Samurai  }
5296059Samurai
5306059Samurai  AsyncInit();
5316059Samurai  VjInit();
5326059Samurai  LcpInit();
5336059Samurai  IpcpInit();
5346059Samurai  CcpInit();
5356059Samurai  LcpUp();
5366059Samurai
53725872Sbrian  LcpOpen(VarOpenMode);
5386059Samurai  if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) {
53910528Samurai    TtyCommandMode(1);
54026516Sbrian    if (VarTerm) {
54126516Sbrian      fprintf(VarTerm, "Packet mode.\n");
54226516Sbrian      aft_cmd = 1;
54326516Sbrian    }
5446059Samurai  }
5456059Samurai}
5466059Samurai
5476059Samuraistatic void
5486059SamuraiShowHelp()
5496059Samurai{
55026901Sbrian  fprintf(stderr, "The following commands are available:\r\n");
55126901Sbrian  fprintf(stderr, " ~p\tEnter Packet mode\r\n");
55226901Sbrian  fprintf(stderr, " ~-\tDecrease log level\r\n");
55326901Sbrian  fprintf(stderr, " ~+\tIncrease log level\r\n");
55426901Sbrian  fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
55526901Sbrian  fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
55626901Sbrian  fprintf(stderr, " ~.\tTerminate program\r\n");
55726901Sbrian  fprintf(stderr, " ~?\tThis help\r\n");
5586059Samurai}
5596059Samurai
5606059Samuraistatic void
5616059SamuraiReadTty()
5626059Samurai{
5636059Samurai  int n;
5646059Samurai  char ch;
5656059Samurai  static int ttystate;
56626516Sbrian  FILE *oVarTerm;
5676059Samurai#define MAXLINESIZE 200
5686059Samurai  char linebuff[MAXLINESIZE];
5696059Samurai
57026516Sbrian  LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
57126516Sbrian            TermMode, netfd, mode);
5726059Samurai  if (!TermMode) {
5736059Samurai    n = read(netfd, linebuff, sizeof(linebuff)-1);
5746735Samurai    if (n > 0) {
57526516Sbrian      aft_cmd = 1;
5766059Samurai      DecodeCommand(linebuff, n, 1);
5776735Samurai    } else {
57826516Sbrian      LogPrintf(LogPHASE, "client connection closed.\n");
57924753Sache      VarLocalAuth = LOCAL_NO_AUTH;
58026516Sbrian      mode &= ~MODE_INTER;
58126516Sbrian      oVarTerm = VarTerm;
58226516Sbrian      VarTerm = 0;
58326516Sbrian      if (oVarTerm && oVarTerm != stdout)
58426516Sbrian        fclose(oVarTerm);
5856059Samurai      close(netfd);
5866059Samurai      netfd = -1;
5876059Samurai    }
5886059Samurai    return;
5896059Samurai  }
5906059Samurai
5916059Samurai  /*
5926059Samurai   *  We are in terminal mode, decode special sequences
5936059Samurai   */
59426516Sbrian  n = read(fileno(VarTerm), &ch, 1);
59526516Sbrian  LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)", n);
5966059Samurai
5976059Samurai  if (n > 0) {
5986059Samurai    switch (ttystate) {
5996059Samurai    case 0:
6006059Samurai      if (ch == '~')
6016059Samurai	ttystate++;
6026059Samurai      else
6036059Samurai	write(modem, &ch, n);
6046059Samurai      break;
6056059Samurai    case 1:
6066059Samurai      switch (ch) {
6076059Samurai      case '?':
6086059Samurai	ShowHelp();
6096059Samurai	break;
6106059Samurai      case 'p':
6116059Samurai	/*
6126059Samurai	 * XXX: Should check carrier.
6136059Samurai	 */
6146059Samurai	if (LcpFsm.state <= ST_CLOSED) {
6156059Samurai	  VarOpenMode = OPEN_ACTIVE;
6166059Samurai	  PacketMode();
6176059Samurai	}
6186059Samurai	break;
6196059Samurai      case '.':
6206059Samurai	TermMode = 1;
62126516Sbrian	aft_cmd = 1;
62210528Samurai	TtyCommandMode(1);
6236059Samurai	break;
62426516Sbrian      case 't':
62526516Sbrian	if (LogIsKept(LogDEBUG)) {
62626516Sbrian	  ShowTimers();
62726516Sbrian	  break;
62826516Sbrian	}
62926516Sbrian      case 'm':
63026516Sbrian	if (LogIsKept(LogDEBUG)) {
63126516Sbrian	  ShowMemMap();
63226516Sbrian	  break;
63326516Sbrian	}
6346059Samurai      default:
6356059Samurai	if (write(modem, &ch, n) < 0)
63626516Sbrian	  LogPrintf(LogERROR, "error writing to modem.\n");
6376059Samurai	break;
6386059Samurai      }
6396059Samurai      ttystate = 0;
6406059Samurai      break;
6416059Samurai    }
6426059Samurai  }
6436059Samurai}
6446059Samurai
6456059Samurai
6466059Samurai/*
6476059Samurai *  Here, we'll try to detect HDLC frame
6486059Samurai */
6496059Samurai
6506059Samuraistatic char *FrameHeaders[] = {
6516735Samurai  "\176\377\003\300\041",
6526735Samurai  "\176\377\175\043\300\041",
6536735Samurai  "\176\177\175\043\100\041",
6546735Samurai  "\176\175\337\175\043\300\041",
6556735Samurai  "\176\175\137\175\043\100\041",
6566059Samurai  NULL,
6576059Samurai};
6586059Samurai
6596059Samuraiu_char *
6606059SamuraiHdlcDetect(cp, n)
6616059Samuraiu_char *cp;
6626059Samuraiint n;
6636059Samurai{
6646735Samurai  char *ptr, *fp, **hp;
6656059Samurai
6666059Samurai  cp[n] = '\0';	/* be sure to null terminated */
6676059Samurai  ptr = NULL;
6686059Samurai  for (hp = FrameHeaders; *hp; hp++) {
6696735Samurai    fp = *hp;
6706735Samurai    if (DEV_IS_SYNC)
6716735Samurai      fp++;
67213389Sphk    ptr = strstr((char *)cp, fp);
67313389Sphk    if (ptr)
6746059Samurai      break;
6756059Samurai  }
6766059Samurai  return((u_char *)ptr);
6776059Samurai}
6786059Samurai
6796059Samuraistatic struct pppTimer RedialTimer;
6806059Samurai
6816059Samuraistatic void
6826059SamuraiRedialTimeout()
6836059Samurai{
6846059Samurai  StopTimer(&RedialTimer);
68526516Sbrian  LogPrintf(LogPHASE, "Redialing timer expired.\n");
6866059Samurai}
6876059Samurai
6886059Samuraistatic void
68924939SbrianStartRedialTimer(Timeout)
69024939Sbrian	int Timeout;
6916059Samurai{
6926059Samurai  StopTimer(&RedialTimer);
69311336Samurai
69424939Sbrian  if (Timeout) {
69511336Samurai    RedialTimer.state = TIMER_STOPPED;
69611336Samurai
69724939Sbrian    if (Timeout > 0)
69824939Sbrian	RedialTimer.load = Timeout * SECTICKS;
69911336Samurai    else
70011336Samurai	RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
70111336Samurai
70226516Sbrian    LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
70324939Sbrian	      RedialTimer.load / SECTICKS);
70424939Sbrian
70511336Samurai    RedialTimer.func = RedialTimeout;
70611336Samurai    StartTimer(&RedialTimer);
70711336Samurai  }
7086059Samurai}
7096059Samurai
7106059Samurai
7116059Samuraistatic void
7126059SamuraiDoLoop()
7136059Samurai{
7146059Samurai  fd_set rfds, wfds, efds;
71523598Sache  int pri, i, n, wfd, nfds;
7166059Samurai  struct sockaddr_in hisaddr;
7176059Samurai  struct timeval timeout, *tp;
7186059Samurai  int ssize = sizeof(hisaddr);
7196059Samurai  u_char *cp;
7206059Samurai  u_char rbuff[MAX_MRU];
72111336Samurai  int tries;
7229448Samurai  int qlen;
72326858Sbrian  int res;
72410528Samurai  pid_t pgroup;
7256059Samurai
72610528Samurai  pgroup = getpgrp();
72710528Samurai
72825908Sbrian  if (mode & MODE_DIRECT) {
72926551Sbrian    LogPrintf(LogDEBUG, "Opening modem\n");
7306059Samurai    modem = OpenModem(mode);
73126516Sbrian    LogPrintf(LogPHASE, "Packet mode enabled\n");
7326059Samurai    PacketMode();
7336059Samurai  } else if (mode & MODE_DEDICATED) {
73423598Sache    if (modem < 0)
7356059Samurai      modem = OpenModem(mode);
7366059Samurai  }
7376059Samurai
73826516Sbrian  fflush(VarTerm);
7396059Samurai
7407001Samurai  timeout.tv_sec = 0;
7416059Samurai  timeout.tv_usec = 0;
74226098Sbrian  reconnectState = RECON_UNKNOWN;
7436059Samurai
74423863Sbrian  if (mode & MODE_BACKGROUND)
74523863Sbrian    dial_up = TRUE;			/* Bring the line up */
74623863Sbrian  else
74723863Sbrian    dial_up = FALSE;			/* XXXX */
74811336Samurai  tries = 0;
7496059Samurai  for (;;) {
75023598Sache    nfds = 0;
7516059Samurai    FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
7527001Samurai
75320120Snate    /*
75420120Snate     * If the link is down and we're in DDIAL mode, bring it back
75520120Snate     * up.
75620120Snate     */
75720120Snate    if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
75820120Snate        dial_up = TRUE;
75920120Snate
76025067Sbrian    /*
76125067Sbrian     * If we lost carrier and want to re-establish the connection
76225067Sbrian     * due to the "set reconnect" value, we'd better bring the line
76325908Sbrian     * back up.
76425067Sbrian     */
76525908Sbrian    if (LcpFsm.state <= ST_CLOSED) {
76626098Sbrian      if (dial_up != TRUE && reconnectState == RECON_TRUE) {
76725908Sbrian        if (++reconnectCount <= VarReconnectTries) {
76826516Sbrian          LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
76925908Sbrian                    reconnectCount, VarReconnectTries);
77025908Sbrian	  StartRedialTimer(VarReconnectTimer);
77125908Sbrian          dial_up = TRUE;
77225908Sbrian        } else {
77325908Sbrian          if (VarReconnectTries)
77426516Sbrian            LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
77525908Sbrian                      VarReconnectTries);
77625908Sbrian          reconnectCount = 0;
77725908Sbrian          if (mode & MODE_BACKGROUND)
77825908Sbrian            Cleanup(EX_DEAD);
77925908Sbrian        }
78026098Sbrian        reconnectState = RECON_ENVOKED;
78125801Sbrian      }
78225908Sbrian    }
78325067Sbrian
7847001Samurai   /*
78525067Sbrian    * If Ip packet for output is enqueued and require dial up,
7867001Samurai    * Just do it!
7877001Samurai    */
78825067Sbrian    if ( dial_up && RedialTimer.state != TIMER_RUNNING ) {
78926516Sbrian      LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
79011336Samurai      modem = OpenModem(mode);
79111336Samurai      if (modem < 0) {
79226551Sbrian        tries++;
79326696Sbrian        if (!(mode & MODE_DDIAL) && VarDialTries)
79426551Sbrian          LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
79526696Sbrian             tries, VarDialTries);
79626551Sbrian        else
79726696Sbrian          LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
79826551Sbrian
79926696Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
80026551Sbrian	  if (mode & MODE_BACKGROUND)
80126551Sbrian	    Cleanup(EX_DIAL);  /* Can't get the modem */
80226551Sbrian	  dial_up = FALSE;
80326551Sbrian          reconnectState = RECON_UNKNOWN;
80426551Sbrian          reconnectCount = 0;
80526551Sbrian	  tries = 0;
80626551Sbrian        } else
80726551Sbrian	  StartRedialTimer(VarRedialTimeout);
80811336Samurai      } else {
80924843Sbrian	tries++;    /* Tries are per number, not per list of numbers. */
81026696Sbrian        if (!(mode & MODE_DDIAL) && VarDialTries)
81126696Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
81224843Sbrian        else
81326696Sbrian          LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
81426696Sbrian
81526858Sbrian	if ((res = DialModem()) == EX_DONE) {
81611336Samurai	  sleep(1);	       /* little pause to allow peer starts */
81711336Samurai	  ModemTimeout();
81811336Samurai	  PacketMode();
81911336Samurai	  dial_up = FALSE;
82026098Sbrian          reconnectState = RECON_UNKNOWN;
82111336Samurai	  tries = 0;
82211336Samurai	} else {
82311336Samurai	  CloseModem();
82424844Sbrian	  if (mode & MODE_BACKGROUND) {
82526858Sbrian	    if (VarNextPhone == NULL || res == EX_SIG)
82624844Sbrian	      Cleanup(EX_DIAL);  /* Tried all numbers - no luck */
82724844Sbrian	    else
82824939Sbrian	      /* Try all numbers in background mode */
82924939Sbrian	      StartRedialTimer(VarRedialNextTimeout);
83026858Sbrian	  } else if (!(mode & MODE_DDIAL) &&
83126858Sbrian                     ((VarDialTries && tries >= VarDialTries) ||
83226858Sbrian                      res == EX_SIG)) {
83324843Sbrian	    /* I give up !  Can't get through :( */
83424939Sbrian	    StartRedialTimer(VarRedialTimeout);
83524843Sbrian	    dial_up = FALSE;
83626098Sbrian            reconnectState = RECON_UNKNOWN;
83726098Sbrian            reconnectCount = 0;
83824843Sbrian	    tries = 0;
83924843Sbrian	  } else if (VarNextPhone == NULL)
84024843Sbrian	    /* Dial failed. Keep quite during redial wait period. */
84124939Sbrian	    StartRedialTimer(VarRedialTimeout);
84224843Sbrian	  else
84324939Sbrian	    StartRedialTimer(VarRedialNextTimeout);
84411336Samurai	}
84511336Samurai      }
8467001Samurai    }
8479448Samurai    qlen = ModemQlen();
84813733Sdfr
84913733Sdfr    if (qlen == 0) {
85013733Sdfr      IpStartOutput();
85113733Sdfr      qlen = ModemQlen();
85213733Sdfr    }
85313733Sdfr
85423598Sache    if (modem >= 0) {
85523598Sache      if (modem + 1 > nfds)
85623598Sache	nfds = modem + 1;
8577001Samurai      FD_SET(modem, &rfds);
8587001Samurai      FD_SET(modem, &efds);
8599448Samurai      if (qlen > 0) {
8607001Samurai	FD_SET(modem, &wfds);
8617001Samurai      }
8627001Samurai    }
86323598Sache    if (server >= 0) {
86423598Sache      if (server + 1 > nfds)
86523598Sache	nfds = server + 1;
86623598Sache      FD_SET(server, &rfds);
86723598Sache    }
8686059Samurai
8696059Samurai    /*  *** IMPORTANT ***
8706059Samurai     *
8716059Samurai     *  CPU is serviced every TICKUNIT micro seconds.
8726059Samurai     *	This value must be chosen with great care. If this values is
8736059Samurai     *  too big, it results loss of characters from modem and poor responce.
8746059Samurai     *  If this values is too small, ppp process eats many CPU time.
8756059Samurai     */
8766735Samurai#ifndef SIGALRM
8776059Samurai    usleep(TICKUNIT);
8786059Samurai    TimerService();
87923840Sbrian#else
88023840Sbrian    handle_signals();
8816735Samurai#endif
88210877Sbde
88310877Sbde    /* If there are aren't many packets queued, look for some more. */
88423598Sache    if (qlen < 20 && tun_in >= 0) {
88523598Sache      if (tun_in + 1 > nfds)
88623598Sache	nfds = tun_in + 1;
88710877Sbde      FD_SET(tun_in, &rfds);
88823598Sache    }
88910877Sbde
89023598Sache    if (netfd >= 0) {
89123598Sache      if (netfd + 1 > nfds)
89223598Sache	nfds = netfd + 1;
8936059Samurai      FD_SET(netfd, &rfds);
8946059Samurai      FD_SET(netfd, &efds);
8956059Samurai    }
8967001Samurai
8976735Samurai#ifndef SIGALRM
8986059Samurai    /*
8997001Samurai     *  Normally, select() will not block because modem is writable.
9007001Samurai     *  In AUTO mode, select will block until we find packet from tun
9016059Samurai     */
9026059Samurai    tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL;
90323598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
9046735Samurai#else
9058857Srgrimes    /*
9067001Samurai     * When SIGALRM timer is running, a select function will be
9078857Srgrimes     * return -1 and EINTR after a Time Service signal hundler
90811336Samurai     * is done.  If the redial timer is not running and we are
90911336Samurai     * trying to dial, poll with a 0 value timer.
9107001Samurai     */
91111336Samurai    tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
91223598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
9136735Samurai#endif
91422074Sbrian
9157001Samurai    if ( i == 0 ) {
9167001Samurai        continue;
9176059Samurai    }
9186735Samurai
9197001Samurai    if ( i < 0 ) {
9207001Samurai       if ( errno == EINTR ) {
92123840Sbrian          handle_signals();
92223840Sbrian          continue;
9237001Samurai       }
92426516Sbrian       LogPrintf(LogERROR, "select: %s", strerror(errno));
9257001Samurai       break;
9268857Srgrimes    }
9277001Samurai
92823598Sache    if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
92926516Sbrian      LogPrintf(LogALERT, "Exception detected.\n");
9306059Samurai      break;
9316059Samurai    }
9326059Samurai
93323598Sache    if (server >= 0 && FD_ISSET(server, &rfds)) {
93426516Sbrian      LogPrintf(LogPHASE, "connected to client.\n");
9356059Samurai      wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize);
93624753Sache      if (wfd < 0) {
93726516Sbrian        LogPrintf(LogERROR, "accept: %s", strerror(errno));
93824753Sache	continue;
93924753Sache      }
94023598Sache      if (netfd >= 0) {
9416059Samurai	write(wfd, "already in use.\n", 16);
9426059Samurai	close(wfd);
9436059Samurai	continue;
9446059Samurai      } else
9456059Samurai	netfd = wfd;
94626516Sbrian      VarTerm = fdopen(netfd, "a+");
9476059Samurai      mode |= MODE_INTER;
9486059Samurai      Greetings();
9496764Samurai      switch ( LocalAuthInit() ) {
9506764Samurai         case NOT_FOUND:
95126516Sbrian	    if (VarTerm) {
95226516Sbrian    	      fprintf(VarTerm,LAUTH_M1);
95326516Sbrian    	      fprintf(VarTerm,LAUTH_M2);
95426516Sbrian              fflush(VarTerm);
95526516Sbrian            }
9566764Samurai	    /* Fall down */
9576764Samurai         case VALID:
9586764Samurai	    VarLocalAuth = LOCAL_AUTH;
9596764Samurai	    break;
9606764Samurai         default:
9616764Samurai	    break;
9626764Samurai      }
9636059Samurai      (void) IsInteractive();
96425630Sbrian      Prompt();
9656059Samurai    }
9666059Samurai
96723598Sache    if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) &&
96810858Samurai	((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) {
9696059Samurai      /* something to read from tty */
9706059Samurai      ReadTty();
9716059Samurai    }
97223598Sache    if (modem >= 0) {
9736059Samurai      if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
9746059Samurai	 ModemStartOutput(modem);
9756059Samurai      }
9766059Samurai      if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
9776735Samurai	if (LcpFsm.state <= ST_CLOSED)
9786735Samurai	  usleep(10000);
9796059Samurai	n = read(modem, rbuff, sizeof(rbuff));
9806059Samurai	if ((mode & MODE_DIRECT) && n <= 0) {
9816059Samurai	  DownConnection();
9826059Samurai	} else
98326516Sbrian          LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
9846059Samurai
9856059Samurai	if (LcpFsm.state <= ST_CLOSED) {
9866059Samurai	  /*
9876059Samurai	   *  In dedicated mode, we just discard input until LCP is started.
9886059Samurai	   */
9896059Samurai	  if (!(mode & MODE_DEDICATED)) {
9906059Samurai	    cp = HdlcDetect(rbuff, n);
9916059Samurai	    if (cp) {
9926059Samurai	      /*
9936059Samurai	       * LCP packet is detected. Turn ourselves into packet mode.
9946059Samurai	       */
9956059Samurai	      if (cp != rbuff) {
99626516Sbrian	        write(modem, rbuff, cp - rbuff);
99726516Sbrian	        write(modem, "\r\n", 2);
9986059Samurai	      }
9996059Samurai	      PacketMode();
10006059Samurai	    } else
100126516Sbrian	      write(fileno(VarTerm), rbuff, n);
10026059Samurai	  }
10036059Samurai	} else {
10046059Samurai	  if (n > 0)
10056059Samurai	    AsyncInput(rbuff, n);
10066059Samurai	}
10076059Samurai      }
10086059Samurai    }
10097001Samurai
101023598Sache    if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {       /* something to read from tun */
10116059Samurai      n = read(tun_in, rbuff, sizeof(rbuff));
10126059Samurai      if (n < 0) {
101326516Sbrian        LogPrintf(LogERROR, "read from tun: %s", strerror(errno));
10146059Samurai	continue;
10156059Samurai      }
10166059Samurai      /*
10176059Samurai       *  Process on-demand dialup. Output packets are queued within tunnel
10186059Samurai       *  device until IPCP is opened.
10196059Samurai       */
10206059Samurai      if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
10217001Samurai	pri = PacketCheck(rbuff, n, FL_DIAL);
10226059Samurai	if (pri >= 0) {
102320365Sjkh	  if (mode & MODE_ALIAS) {
102426142Sbrian	    VarPacketAliasOut(rbuff, sizeof rbuff);
102520666Snate	    n = ntohs(((struct ip *)rbuff)->ip_len);
102620365Sjkh	  }
10276059Samurai	  IpEnqueue(pri, rbuff, n);
102820365Sjkh	  dial_up = TRUE;		/* XXX */
10296059Samurai	}
10306059Samurai	continue;
10316059Samurai      }
10327001Samurai      pri = PacketCheck(rbuff, n, FL_OUT);
103320365Sjkh      if (pri >= 0) {
103420365Sjkh        if (mode & MODE_ALIAS) {
103526142Sbrian          VarPacketAliasOut(rbuff, sizeof rbuff);
103620666Snate          n = ntohs(((struct ip *)rbuff)->ip_len);
103720365Sjkh        }
10386059Samurai	IpEnqueue(pri, rbuff, n);
103920365Sjkh      }
10406059Samurai    }
10416059Samurai  }
104226516Sbrian  LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
10436059Samurai}
1044