main.c revision 26858
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 *
2026858Sbrian * $Id: main.c,v 1.64 1997/06/17 01:46:05 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"
536059Samurai
546764Samurai#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n"
5526516Sbrian#define LAUTH_M2 "Warning: Manipulation is allowed by anyone\n"
566764Samurai
576735Samurai#ifndef O_NONBLOCK
586735Samurai#ifdef O_NDELAY
596735Samurai#define	O_NONBLOCK O_NDELAY
606735Samurai#endif
616735Samurai#endif
626735Samurai
636059Samuraiextern void VjInit(), AsyncInit();
6425630Sbrianextern void AsyncInput();
656059Samuraiextern 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
746059Samuraistatic struct termios oldtio;		/* Original tty mode */
756059Samuraistatic struct termios comtio;		/* Command level tty mode */
7614418Sacheint TermMode;
7713379Sphkstatic int server;
7820813Sjkhstatic pid_t BGPid = 0;
796059Samuraistruct sockaddr_in ifsin;
8025634Sbrianstatic char pid_filename[MAXPATHLEN];
8125634Sbrianstatic char if_filename[MAXPATHLEN];
8225445Sacheint tunno;
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();
18823598Sache  if (server >= 0) {
1896059Samurai    close(server);
19023598Sache    server = -1;
19123598Sache  }
19225707Sbrian
19310528Samurai  TtyOldMode();
1946059Samurai
1956059Samurai  exit(excode);
1966059Samurai}
1976059Samurai
1986059Samuraistatic void
19914930SacheHangup(signo)
20014930Sacheint signo;
2016059Samurai{
20226858Sbrian  /* NOTE, these are manual, we've done a setsid() */
20326858Sbrian  reconnect(RECON_FALSE);
20426858Sbrian  DownConnection();
2056059Samurai}
2066059Samurai
2076059Samuraistatic void
20814930SacheCloseSession(signo)
20914930Sacheint signo;
2106059Samurai{
21120813Sjkh   if (BGPid) {
21220813Sjkh     kill (BGPid, SIGINT);
21320813Sjkh     exit (EX_TERM);
21420813Sjkh   }
21526516Sbrian   LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
21626516Sbrian   reconnect(RECON_FALSE);
21726516Sbrian   LcpClose();
21826516Sbrian   Cleanup(EX_TERM);
2196059Samurai}
2206059Samurai
22110528Samuraistatic void
22210528SamuraiTerminalCont()
22310528Samurai{
22423840Sbrian  pending_signal(SIGCONT, SIG_DFL);
22523840Sbrian  pending_signal(SIGTSTP, TerminalStop);
22610528Samurai  TtyCommandMode(getpgrp() == tcgetpgrp(0));
22710528Samurai}
22810528Samurai
22910528Samuraistatic void
23010528SamuraiTerminalStop(signo)
23110528Samuraiint signo;
23210528Samurai{
23323840Sbrian  pending_signal(SIGCONT, TerminalCont);
23410528Samurai  TtyOldMode();
23523840Sbrian  pending_signal(SIGTSTP, SIG_DFL);
23610528Samurai  kill(getpid(), signo);
23710528Samurai}
23810528Samurai
23925908Sbrianstatic char *
24025908Sbrianex_desc(int ex)
24125908Sbrian{
24225908Sbrian  static char num[12];
24325908Sbrian  static char *desc[] = { "normal", "start", "sock",
24425908Sbrian    "modem", "dial", "dead", "done", "reboot", "errdead",
24525908Sbrian    "hangup", "term", "nodial", "nologin" };
24610528Samurai
24725908Sbrian  if (ex >= 0 && ex < sizeof(desc)/sizeof(*desc))
24825908Sbrian    return desc[ex];
24925908Sbrian  snprintf(num, sizeof num, "%d", ex);
25025908Sbrian  return num;
25125908Sbrian}
25225908Sbrian
2536059Samuraivoid
2546059SamuraiUsage()
2556059Samurai{
25620120Snate  fprintf(stderr,
25720813Sjkh          "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n");
2586059Samurai  exit(EX_START);
2596059Samurai}
2606059Samurai
2616059Samuraivoid
2626059SamuraiProcessArgs(int argc, char **argv)
2636059Samurai{
2646059Samurai  int optc;
2656059Samurai  char *cp;
2666059Samurai
2676059Samurai  optc = 0;
2686059Samurai  while (argc > 0 && **argv == '-') {
2696059Samurai    cp = *argv + 1;
2706059Samurai    if (strcmp(cp, "auto") == 0)
2716059Samurai      mode |= MODE_AUTO;
27220813Sjkh    else if (strcmp(cp, "background") == 0)
27325908Sbrian      mode |= MODE_BACKGROUND|MODE_AUTO;
2746059Samurai    else if (strcmp(cp, "direct") == 0)
2756059Samurai      mode |= MODE_DIRECT;
2766059Samurai    else if (strcmp(cp, "dedicated") == 0)
2776059Samurai      mode |= MODE_DEDICATED;
27820120Snate    else if (strcmp(cp, "ddial") == 0)
27920120Snate      mode |= MODE_DDIAL|MODE_AUTO;
28020365Sjkh    else if (strcmp(cp, "alias") == 0) {
28126142Sbrian      if (loadAliasHandlers(&VarAliasHandlers) == 0)
28226142Sbrian        mode |= MODE_ALIAS;
28326142Sbrian      else
28426516Sbrian        LogPrintf(LogWARN, "Cannot load alias library\n");
28520365Sjkh      optc--;             /* this option isn't exclusive */
28620365Sjkh    }
2876059Samurai    else
2886059Samurai      Usage();
2896059Samurai    optc++;
2906059Samurai    argv++; argc--;
2916059Samurai  }
2926059Samurai  if (argc > 1) {
2936059Samurai    fprintf(stderr, "specify only one system label.\n");
2946059Samurai    exit(EX_START);
2956059Samurai  }
2966059Samurai  if (argc == 1) dstsystem = *argv;
2976059Samurai
2986059Samurai  if (optc > 1) {
2996059Samurai    fprintf(stderr, "specify only one mode.\n");
3006059Samurai    exit(EX_START);
3016059Samurai  }
3026059Samurai}
3036059Samurai
3046059Samuraistatic void
3056059SamuraiGreetings()
3066059Samurai{
30726516Sbrian  if (VarTerm) {
30826516Sbrian    fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n");
30926516Sbrian    fflush(VarTerm);
31026516Sbrian  }
3116059Samurai}
3126059Samurai
3136059Samuraivoid
3146059Samuraimain(argc, argv)
3156059Samuraiint argc;
3166059Samuraichar **argv;
3176059Samurai{
31825707Sbrian  FILE *lockfile;
31926516Sbrian  char *name;
32026516Sbrian
32126551Sbrian  VarTerm = 0;
32226516Sbrian  name = rindex(argv[0], '/');
32326516Sbrian  LogOpen(name ? name+1 : argv[0]);
32426516Sbrian
3256059Samurai  argc--; argv++;
3266059Samurai  mode = MODE_INTER;		/* default operation is interactive mode */
32723598Sache  netfd = server = modem = tun_in = -1;
3286059Samurai  ProcessArgs(argc, argv);
32926328Sbrian  if (!(mode & MODE_DIRECT))
33026551Sbrian    VarTerm = stdout;
33126551Sbrian  Greetings();
3326059Samurai  GetUid();
3336059Samurai  IpcpDefAddress();
3346059Samurai
33526516Sbrian  if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
33626516Sbrian    fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
3376059Samurai
3386735Samurai  switch ( LocalAuthInit() ) {
3396735Samurai    case NOT_FOUND:
34026516Sbrian        if (VarTerm) {
34126516Sbrian    	  fprintf(VarTerm,LAUTH_M1);
34226516Sbrian    	  fprintf(VarTerm,LAUTH_M2);
34326551Sbrian          fflush(VarTerm);
34426328Sbrian        }
3456764Samurai	/* Fall down */
3466764Samurai    case VALID:
3476735Samurai	VarLocalAuth = LOCAL_AUTH;
3486735Samurai	break;
3496735Samurai    default:
3506735Samurai	break;
3516735Samurai  }
3526735Samurai
3536059Samurai  if (OpenTunnel(&tunno) < 0) {
35426516Sbrian    LogPrintf(LogWARN, "open_tun: %s", strerror(errno));
3556059Samurai    exit(EX_START);
3566059Samurai  }
3576059Samurai
35825908Sbrian  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)
36726516Sbrian        fprintf(VarTerm, "Destination system must be specified in"
36825908Sbrian              " auto, background or ddial mode.\n");
3696059Samurai      exit(EX_START);
3706059Samurai    }
3716059Samurai  }
3726059Samurai
3736735Samurai  tcgetattr(0, &oldtio);		/* Save original tty mode */
3746059Samurai
37526516Sbrian  pending_signal(SIGHUP, Hangup);
37623840Sbrian  pending_signal(SIGTERM, CloseSession);
37723840Sbrian  pending_signal(SIGINT, CloseSession);
37823840Sbrian  pending_signal(SIGQUIT, CloseSession);
3796735Samurai#ifdef SIGPIPE
38024753Sache  signal(SIGPIPE, SIG_IGN);
3816735Samurai#endif
3826735Samurai#ifdef SIGALRM
38323840Sbrian  pending_signal(SIGALRM, SIG_IGN);
3846735Samurai#endif
38510528Samurai  if(mode & MODE_INTER)
38610528Samurai    {
38710528Samurai#ifdef SIGTSTP
38823840Sbrian      pending_signal(SIGTSTP, TerminalStop);
38910528Samurai#endif
39010528Samurai#ifdef SIGTTIN
39123840Sbrian      pending_signal(SIGTTIN, TerminalStop);
39210528Samurai#endif
39310528Samurai#ifdef SIGTTOU
39423840Sbrian      pending_signal(SIGTTOU, SIG_IGN);
39510528Samurai#endif
39610528Samurai    }
3976059Samurai
3986059Samurai  if (dstsystem) {
3996059Samurai    if (SelectSystem(dstsystem, CONFFILE) < 0) {
40026551Sbrian      LogPrintf(LogWARN, "Destination system not found in conf file.\n");
4016059Samurai      Cleanup(EX_START);
4026059Samurai    }
4036059Samurai    if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
40426551Sbrian      LogPrintf(LogWARN, "Must specify dstaddr with"
40525908Sbrian              " auto, background or ddial mode.\n");
4066059Samurai      Cleanup(EX_START);
4076059Samurai    }
4086059Samurai  }
4096059Samurai
4106059Samurai  if (!(mode & MODE_INTER)) {
41120813Sjkh    int port = SERVER_PORT + tunno;
41225908Sbrian
41320813Sjkh    if (mode & MODE_BACKGROUND) {
41420813Sjkh      if (pipe (BGFiledes)) {
41526516Sbrian        LogPrintf(LogERROR, "pipe: %s", strerror(errno));
41620813Sjkh	Cleanup(EX_SOCK);
41720813Sjkh      }
4186059Samurai    }
41925908Sbrian
42025908Sbrian    /* Create server socket and listen at there. */
42125908Sbrian    server = socket(PF_INET, SOCK_STREAM, 0);
42225908Sbrian    if (server < 0) {
42326516Sbrian      LogPrintf(LogERROR, "socket: %s", strerror(errno));
42425908Sbrian      Cleanup(EX_SOCK);
4256059Samurai    }
42625908Sbrian    ifsin.sin_family = AF_INET;
42725908Sbrian    ifsin.sin_addr.s_addr = INADDR_ANY;
42825908Sbrian    ifsin.sin_port = htons(port);
42926032Sbrian    setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &server, sizeof server);
43025908Sbrian    if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) {
43126516Sbrian      LogPrintf(LogERROR, "bind: %s", strerror(errno));
43226516Sbrian      if (errno == EADDRINUSE && VarTerm)
43326516Sbrian        fprintf(VarTerm, "Wait for a while, then try again.\n");
43425908Sbrian      Cleanup(EX_SOCK);
43525908Sbrian    }
43625908Sbrian    if (listen(server, 5) != 0) {
43726516Sbrian      LogPrintf(LogERROR, "Unable to listen to socket - OS overload?\n");
43826516Sbrian      Cleanup(EX_SOCK);
43925908Sbrian    }
4406059Samurai
4416059Samurai    if (!(mode & MODE_DIRECT)) {
44220813Sjkh      pid_t bgpid;
44311336Samurai
44420813Sjkh      bgpid = fork ();
44520813Sjkh      if (bgpid == -1) {
44626516Sbrian        LogPrintf(LogERROR, "fork: %s", strerror(errno));
44720813Sjkh	Cleanup (EX_SOCK);
44820813Sjkh      }
44920813Sjkh      if (bgpid) {
45020813Sjkh	char c = EX_NORMAL;
45111336Samurai
45220813Sjkh	if (mode & MODE_BACKGROUND) {
45320813Sjkh	  /* Wait for our child to close its pipe before we exit. */
45420813Sjkh	  BGPid = bgpid;
45526516Sbrian          close(BGFiledes[1]);
45625908Sbrian	  if (read(BGFiledes[0], &c, 1) != 1) {
45726516Sbrian	    fprintf(VarTerm, "Child exit, no status.\n");
45826516Sbrian	    LogPrintf (LogPHASE, "Parent: Child exit, no status.\n");
45925908Sbrian	  } else if (c == EX_NORMAL) {
46026516Sbrian	    fprintf(VarTerm, "PPP enabled.\n");
46126516Sbrian	    LogPrintf (LogPHASE, "Parent: PPP enabled.\n");
46225908Sbrian	  } else {
46326516Sbrian	    fprintf(VarTerm, "Child failed (%s).\n",ex_desc((int)c));
46426516Sbrian	    LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
46525910Sbrian                      ex_desc((int)c));
46625908Sbrian          }
46726516Sbrian          close(BGFiledes[0]);
46820813Sjkh	}
46920813Sjkh        exit(c);
47023863Sbrian      } else if (mode & MODE_BACKGROUND)
47123863Sbrian          close(BGFiledes[0]);
47225707Sbrian    }
47320813Sjkh
47425801Sbrian    snprintf(pid_filename, sizeof (pid_filename), "%stun%d.pid",
47525707Sbrian             _PATH_VARRUN, tunno);
47625707Sbrian    (void)unlink(pid_filename);
47711336Samurai
47825707Sbrian    if ((lockfile = fopen(pid_filename, "w")) != NULL) {
47925707Sbrian      fprintf(lockfile, "%d\n", (int)getpid());
48025707Sbrian      fclose(lockfile);
48125707Sbrian    } else
48226516Sbrian      LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
48326516Sbrian                pid_filename, strerror(errno));
48425634Sbrian
48525707Sbrian    snprintf(if_filename, sizeof if_filename, "%s%s.if",
48625707Sbrian             _PATH_VARRUN, VarBaseDevice);
48725707Sbrian    (void)unlink(if_filename);
48825634Sbrian
48925707Sbrian    if ((lockfile = fopen(if_filename, "w")) != NULL) {
49025707Sbrian      fprintf(lockfile, "tun%d\n", tunno);
49125707Sbrian      fclose(lockfile);
49225707Sbrian    } else
49326516Sbrian      LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
49426516Sbrian                if_filename, strerror(errno));
49525707Sbrian
49623598Sache    if (server >= 0)
49726516Sbrian	LogPrintf(LogPHASE, "Listening at %d.\n", port);
49826551Sbrian
49926686Sbrian    VarTerm = 0;   /* We know it's currently stdout */
50026686Sbrian    close(0);
50126686Sbrian    close(2);
50226551Sbrian
5036059Samurai#ifdef DOTTYINIT
50426686Sbrian    if (mode & (MODE_DIRECT|MODE_DEDICATED))
5056059Samurai#else
50626686Sbrian    if (mode & MODE_DIRECT)
5076059Samurai#endif
50826858Sbrian      TtyInit(1);
50926686Sbrian    else {
51026686Sbrian      setsid();
51126686Sbrian      close(1);
51226686Sbrian    }
5136059Samurai  } else {
51426858Sbrian    TtyInit(0);
51510528Samurai    TtyCommandMode(1);
5166059Samurai  }
51726516Sbrian  LogPrintf(LogPHASE, "PPP Started.\n");
5186059Samurai
5196059Samurai
5206059Samurai  do
5216059Samurai   DoLoop();
5226059Samurai  while (mode & MODE_DEDICATED);
5236059Samurai
5246059Samurai  Cleanup(EX_DONE);
5256059Samurai}
5266059Samurai
5276059Samurai/*
52820813Sjkh *  Turn into packet mode, where we speak PPP.
5296059Samurai */
5306059Samuraivoid
5316059SamuraiPacketMode()
5326059Samurai{
5336059Samurai  if (RawModem(modem) < 0) {
53426516Sbrian    LogPrintf(LogWARN, "PacketMode: Not connected.\n");
5356059Samurai    return;
5366059Samurai  }
5376059Samurai
5386059Samurai  AsyncInit();
5396059Samurai  VjInit();
5406059Samurai  LcpInit();
5416059Samurai  IpcpInit();
5426059Samurai  CcpInit();
5436059Samurai  LcpUp();
5446059Samurai
54525872Sbrian  LcpOpen(VarOpenMode);
5466059Samurai  if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) {
54710528Samurai    TtyCommandMode(1);
54826516Sbrian    if (VarTerm) {
54926516Sbrian      fprintf(VarTerm, "Packet mode.\n");
55026516Sbrian      aft_cmd = 1;
55126516Sbrian    }
5526059Samurai  }
5536059Samurai}
5546059Samurai
5556059Samuraistatic void
5566059SamuraiShowHelp()
5576059Samurai{
55826516Sbrian  fprintf(stderr, "The following commands are available:\n");
55926516Sbrian  fprintf(stderr, " ~p\tEnter Packet mode\n");
56026516Sbrian  fprintf(stderr, " ~-\tDecrease log level\n");
56126516Sbrian  fprintf(stderr, " ~+\tIncrease log level\n");
56226516Sbrian  fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\n");
56326516Sbrian  fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\n");
56426516Sbrian  fprintf(stderr, " ~.\tTerminate program\n");
56526516Sbrian  fprintf(stderr, " ~?\tThis help\n");
5666059Samurai}
5676059Samurai
5686059Samuraistatic void
5696059SamuraiReadTty()
5706059Samurai{
5716059Samurai  int n;
5726059Samurai  char ch;
5736059Samurai  static int ttystate;
57426516Sbrian  FILE *oVarTerm;
5756059Samurai#define MAXLINESIZE 200
5766059Samurai  char linebuff[MAXLINESIZE];
5776059Samurai
57826516Sbrian  LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
57926516Sbrian            TermMode, netfd, mode);
5806059Samurai  if (!TermMode) {
5816059Samurai    n = read(netfd, linebuff, sizeof(linebuff)-1);
5826735Samurai    if (n > 0) {
58326516Sbrian      aft_cmd = 1;
5846059Samurai      DecodeCommand(linebuff, n, 1);
5856735Samurai    } else {
58626516Sbrian      LogPrintf(LogPHASE, "client connection closed.\n");
58724753Sache      VarLocalAuth = LOCAL_NO_AUTH;
58826516Sbrian      mode &= ~MODE_INTER;
58926516Sbrian      oVarTerm = VarTerm;
59026516Sbrian      VarTerm = 0;
59126516Sbrian      if (oVarTerm && oVarTerm != stdout)
59226516Sbrian        fclose(oVarTerm);
5936059Samurai      close(netfd);
5946059Samurai      netfd = -1;
5956059Samurai    }
5966059Samurai    return;
5976059Samurai  }
5986059Samurai
5996059Samurai  /*
6006059Samurai   *  We are in terminal mode, decode special sequences
6016059Samurai   */
60226516Sbrian  n = read(fileno(VarTerm), &ch, 1);
60326516Sbrian  LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)", n);
6046059Samurai
6056059Samurai  if (n > 0) {
6066059Samurai    switch (ttystate) {
6076059Samurai    case 0:
6086059Samurai      if (ch == '~')
6096059Samurai	ttystate++;
6106059Samurai      else
6116059Samurai	write(modem, &ch, n);
6126059Samurai      break;
6136059Samurai    case 1:
6146059Samurai      switch (ch) {
6156059Samurai      case '?':
6166059Samurai	ShowHelp();
6176059Samurai	break;
6186059Samurai      case 'p':
6196059Samurai	/*
6206059Samurai	 * XXX: Should check carrier.
6216059Samurai	 */
6226059Samurai	if (LcpFsm.state <= ST_CLOSED) {
6236059Samurai	  VarOpenMode = OPEN_ACTIVE;
6246059Samurai	  PacketMode();
6256059Samurai	}
6266059Samurai	break;
6276059Samurai      case '.':
6286059Samurai	TermMode = 1;
62926516Sbrian	aft_cmd = 1;
63010528Samurai	TtyCommandMode(1);
6316059Samurai	break;
63226516Sbrian      case 't':
63326516Sbrian	if (LogIsKept(LogDEBUG)) {
63426516Sbrian	  ShowTimers();
63526516Sbrian	  break;
63626516Sbrian	}
63726516Sbrian      case 'm':
63826516Sbrian	if (LogIsKept(LogDEBUG)) {
63926516Sbrian	  ShowMemMap();
64026516Sbrian	  break;
64126516Sbrian	}
6426059Samurai      default:
6436059Samurai	if (write(modem, &ch, n) < 0)
64426516Sbrian	  LogPrintf(LogERROR, "error writing to modem.\n");
6456059Samurai	break;
6466059Samurai      }
6476059Samurai      ttystate = 0;
6486059Samurai      break;
6496059Samurai    }
6506059Samurai  }
6516059Samurai}
6526059Samurai
6536059Samurai
6546059Samurai/*
6556059Samurai *  Here, we'll try to detect HDLC frame
6566059Samurai */
6576059Samurai
6586059Samuraistatic char *FrameHeaders[] = {
6596735Samurai  "\176\377\003\300\041",
6606735Samurai  "\176\377\175\043\300\041",
6616735Samurai  "\176\177\175\043\100\041",
6626735Samurai  "\176\175\337\175\043\300\041",
6636735Samurai  "\176\175\137\175\043\100\041",
6646059Samurai  NULL,
6656059Samurai};
6666059Samurai
6676059Samuraiu_char *
6686059SamuraiHdlcDetect(cp, n)
6696059Samuraiu_char *cp;
6706059Samuraiint n;
6716059Samurai{
6726735Samurai  char *ptr, *fp, **hp;
6736059Samurai
6746059Samurai  cp[n] = '\0';	/* be sure to null terminated */
6756059Samurai  ptr = NULL;
6766059Samurai  for (hp = FrameHeaders; *hp; hp++) {
6776735Samurai    fp = *hp;
6786735Samurai    if (DEV_IS_SYNC)
6796735Samurai      fp++;
68013389Sphk    ptr = strstr((char *)cp, fp);
68113389Sphk    if (ptr)
6826059Samurai      break;
6836059Samurai  }
6846059Samurai  return((u_char *)ptr);
6856059Samurai}
6866059Samurai
6876059Samuraistatic struct pppTimer RedialTimer;
6886059Samurai
6896059Samuraistatic void
6906059SamuraiRedialTimeout()
6916059Samurai{
6926059Samurai  StopTimer(&RedialTimer);
69326516Sbrian  LogPrintf(LogPHASE, "Redialing timer expired.\n");
6946059Samurai}
6956059Samurai
6966059Samuraistatic void
69724939SbrianStartRedialTimer(Timeout)
69824939Sbrian	int Timeout;
6996059Samurai{
7006059Samurai  StopTimer(&RedialTimer);
70111336Samurai
70224939Sbrian  if (Timeout) {
70311336Samurai    RedialTimer.state = TIMER_STOPPED;
70411336Samurai
70524939Sbrian    if (Timeout > 0)
70624939Sbrian	RedialTimer.load = Timeout * SECTICKS;
70711336Samurai    else
70811336Samurai	RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
70911336Samurai
71026516Sbrian    LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
71124939Sbrian	      RedialTimer.load / SECTICKS);
71224939Sbrian
71311336Samurai    RedialTimer.func = RedialTimeout;
71411336Samurai    StartTimer(&RedialTimer);
71511336Samurai  }
7166059Samurai}
7176059Samurai
7186059Samurai
7196059Samuraistatic void
7206059SamuraiDoLoop()
7216059Samurai{
7226059Samurai  fd_set rfds, wfds, efds;
72323598Sache  int pri, i, n, wfd, nfds;
7246059Samurai  struct sockaddr_in hisaddr;
7256059Samurai  struct timeval timeout, *tp;
7266059Samurai  int ssize = sizeof(hisaddr);
7276059Samurai  u_char *cp;
7286059Samurai  u_char rbuff[MAX_MRU];
7297001Samurai  int dial_up;
73011336Samurai  int tries;
7319448Samurai  int qlen;
73226858Sbrian  int res;
73310528Samurai  pid_t pgroup;
7346059Samurai
73510528Samurai  pgroup = getpgrp();
73610528Samurai
73725908Sbrian  if (mode & MODE_DIRECT) {
73826551Sbrian    LogPrintf(LogDEBUG, "Opening modem\n");
7396059Samurai    modem = OpenModem(mode);
74026516Sbrian    LogPrintf(LogPHASE, "Packet mode enabled\n");
7416059Samurai    PacketMode();
7426059Samurai  } else if (mode & MODE_DEDICATED) {
74323598Sache    if (modem < 0)
7446059Samurai      modem = OpenModem(mode);
7456059Samurai  }
7466059Samurai
74726516Sbrian  fflush(VarTerm);
7486059Samurai
7497001Samurai  timeout.tv_sec = 0;
7506059Samurai  timeout.tv_usec = 0;
75126098Sbrian  reconnectState = RECON_UNKNOWN;
7526059Samurai
75323863Sbrian  if (mode & MODE_BACKGROUND)
75423863Sbrian    dial_up = TRUE;			/* Bring the line up */
75523863Sbrian  else
75623863Sbrian    dial_up = FALSE;			/* XXXX */
75711336Samurai  tries = 0;
7586059Samurai  for (;;) {
75923598Sache    nfds = 0;
7606059Samurai    FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
7617001Samurai
76220120Snate    /*
76320120Snate     * If the link is down and we're in DDIAL mode, bring it back
76420120Snate     * up.
76520120Snate     */
76620120Snate    if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
76720120Snate        dial_up = TRUE;
76820120Snate
76925067Sbrian    /*
77025067Sbrian     * If we lost carrier and want to re-establish the connection
77125067Sbrian     * due to the "set reconnect" value, we'd better bring the line
77225908Sbrian     * back up.
77325067Sbrian     */
77425908Sbrian    if (LcpFsm.state <= ST_CLOSED) {
77526098Sbrian      if (dial_up != TRUE && reconnectState == RECON_TRUE) {
77625908Sbrian        if (++reconnectCount <= VarReconnectTries) {
77726516Sbrian          LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
77825908Sbrian                    reconnectCount, VarReconnectTries);
77925908Sbrian	  StartRedialTimer(VarReconnectTimer);
78025908Sbrian          dial_up = TRUE;
78125908Sbrian        } else {
78225908Sbrian          if (VarReconnectTries)
78326516Sbrian            LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
78425908Sbrian                      VarReconnectTries);
78525908Sbrian          reconnectCount = 0;
78625908Sbrian          if (mode & MODE_BACKGROUND)
78725908Sbrian            Cleanup(EX_DEAD);
78825908Sbrian        }
78926098Sbrian        reconnectState = RECON_ENVOKED;
79025801Sbrian      }
79125908Sbrian    }
79225067Sbrian
7937001Samurai   /*
79425067Sbrian    * If Ip packet for output is enqueued and require dial up,
7957001Samurai    * Just do it!
7967001Samurai    */
79725067Sbrian    if ( dial_up && RedialTimer.state != TIMER_RUNNING ) {
79826516Sbrian      LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
79911336Samurai      modem = OpenModem(mode);
80011336Samurai      if (modem < 0) {
80126551Sbrian        tries++;
80226696Sbrian        if (!(mode & MODE_DDIAL) && VarDialTries)
80326551Sbrian          LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
80426696Sbrian             tries, VarDialTries);
80526551Sbrian        else
80626696Sbrian          LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
80726551Sbrian
80826696Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
80926551Sbrian	  if (mode & MODE_BACKGROUND)
81026551Sbrian	    Cleanup(EX_DIAL);  /* Can't get the modem */
81126551Sbrian	  dial_up = FALSE;
81226551Sbrian          reconnectState = RECON_UNKNOWN;
81326551Sbrian          reconnectCount = 0;
81426551Sbrian	  tries = 0;
81526551Sbrian        } else
81626551Sbrian	  StartRedialTimer(VarRedialTimeout);
81711336Samurai      } else {
81824843Sbrian	tries++;    /* Tries are per number, not per list of numbers. */
81926696Sbrian        if (!(mode & MODE_DDIAL) && VarDialTries)
82026696Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
82124843Sbrian        else
82226696Sbrian          LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
82326696Sbrian
82426858Sbrian	if ((res = DialModem()) == EX_DONE) {
82511336Samurai	  sleep(1);	       /* little pause to allow peer starts */
82611336Samurai	  ModemTimeout();
82711336Samurai	  PacketMode();
82811336Samurai	  dial_up = FALSE;
82926098Sbrian          reconnectState = RECON_UNKNOWN;
83011336Samurai	  tries = 0;
83111336Samurai	} else {
83211336Samurai	  CloseModem();
83324844Sbrian	  if (mode & MODE_BACKGROUND) {
83426858Sbrian	    if (VarNextPhone == NULL || res == EX_SIG)
83524844Sbrian	      Cleanup(EX_DIAL);  /* Tried all numbers - no luck */
83624844Sbrian	    else
83724939Sbrian	      /* Try all numbers in background mode */
83824939Sbrian	      StartRedialTimer(VarRedialNextTimeout);
83926858Sbrian	  } else if (!(mode & MODE_DDIAL) &&
84026858Sbrian                     ((VarDialTries && tries >= VarDialTries) ||
84126858Sbrian                      res == EX_SIG)) {
84224843Sbrian	    /* I give up !  Can't get through :( */
84324939Sbrian	    StartRedialTimer(VarRedialTimeout);
84424843Sbrian	    dial_up = FALSE;
84526098Sbrian            reconnectState = RECON_UNKNOWN;
84626098Sbrian            reconnectCount = 0;
84724843Sbrian	    tries = 0;
84824843Sbrian	  } else if (VarNextPhone == NULL)
84924843Sbrian	    /* Dial failed. Keep quite during redial wait period. */
85024939Sbrian	    StartRedialTimer(VarRedialTimeout);
85124843Sbrian	  else
85224939Sbrian	    StartRedialTimer(VarRedialNextTimeout);
85311336Samurai	}
85411336Samurai      }
8557001Samurai    }
8569448Samurai    qlen = ModemQlen();
85713733Sdfr
85813733Sdfr    if (qlen == 0) {
85913733Sdfr      IpStartOutput();
86013733Sdfr      qlen = ModemQlen();
86113733Sdfr    }
86213733Sdfr
86323598Sache    if (modem >= 0) {
86423598Sache      if (modem + 1 > nfds)
86523598Sache	nfds = modem + 1;
8667001Samurai      FD_SET(modem, &rfds);
8677001Samurai      FD_SET(modem, &efds);
8689448Samurai      if (qlen > 0) {
8697001Samurai	FD_SET(modem, &wfds);
8707001Samurai      }
8717001Samurai    }
87223598Sache    if (server >= 0) {
87323598Sache      if (server + 1 > nfds)
87423598Sache	nfds = server + 1;
87523598Sache      FD_SET(server, &rfds);
87623598Sache    }
8776059Samurai
8786059Samurai    /*  *** IMPORTANT ***
8796059Samurai     *
8806059Samurai     *  CPU is serviced every TICKUNIT micro seconds.
8816059Samurai     *	This value must be chosen with great care. If this values is
8826059Samurai     *  too big, it results loss of characters from modem and poor responce.
8836059Samurai     *  If this values is too small, ppp process eats many CPU time.
8846059Samurai     */
8856735Samurai#ifndef SIGALRM
8866059Samurai    usleep(TICKUNIT);
8876059Samurai    TimerService();
88823840Sbrian#else
88923840Sbrian    handle_signals();
8906735Samurai#endif
89110877Sbde
89210877Sbde    /* If there are aren't many packets queued, look for some more. */
89323598Sache    if (qlen < 20 && tun_in >= 0) {
89423598Sache      if (tun_in + 1 > nfds)
89523598Sache	nfds = tun_in + 1;
89610877Sbde      FD_SET(tun_in, &rfds);
89723598Sache    }
89810877Sbde
89923598Sache    if (netfd >= 0) {
90023598Sache      if (netfd + 1 > nfds)
90123598Sache	nfds = netfd + 1;
9026059Samurai      FD_SET(netfd, &rfds);
9036059Samurai      FD_SET(netfd, &efds);
9046059Samurai    }
9057001Samurai
9066735Samurai#ifndef SIGALRM
9076059Samurai    /*
9087001Samurai     *  Normally, select() will not block because modem is writable.
9097001Samurai     *  In AUTO mode, select will block until we find packet from tun
9106059Samurai     */
9116059Samurai    tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL;
91223598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
9136735Samurai#else
9148857Srgrimes    /*
9157001Samurai     * When SIGALRM timer is running, a select function will be
9168857Srgrimes     * return -1 and EINTR after a Time Service signal hundler
91711336Samurai     * is done.  If the redial timer is not running and we are
91811336Samurai     * trying to dial, poll with a 0 value timer.
9197001Samurai     */
92011336Samurai    tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
92123598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
9226735Samurai#endif
92322074Sbrian
9247001Samurai    if ( i == 0 ) {
9257001Samurai        continue;
9266059Samurai    }
9276735Samurai
9287001Samurai    if ( i < 0 ) {
9297001Samurai       if ( errno == EINTR ) {
93023840Sbrian          handle_signals();
93123840Sbrian          continue;
9327001Samurai       }
93326516Sbrian       LogPrintf(LogERROR, "select: %s", strerror(errno));
9347001Samurai       break;
9358857Srgrimes    }
9367001Samurai
93723598Sache    if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
93826516Sbrian      LogPrintf(LogALERT, "Exception detected.\n");
9396059Samurai      break;
9406059Samurai    }
9416059Samurai
94223598Sache    if (server >= 0 && FD_ISSET(server, &rfds)) {
94326516Sbrian      LogPrintf(LogPHASE, "connected to client.\n");
9446059Samurai      wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize);
94524753Sache      if (wfd < 0) {
94626516Sbrian        LogPrintf(LogERROR, "accept: %s", strerror(errno));
94724753Sache	continue;
94824753Sache      }
94923598Sache      if (netfd >= 0) {
9506059Samurai	write(wfd, "already in use.\n", 16);
9516059Samurai	close(wfd);
9526059Samurai	continue;
9536059Samurai      } else
9546059Samurai	netfd = wfd;
95526516Sbrian      VarTerm = fdopen(netfd, "a+");
9566059Samurai      mode |= MODE_INTER;
9576059Samurai      Greetings();
9586764Samurai      switch ( LocalAuthInit() ) {
9596764Samurai         case NOT_FOUND:
96026516Sbrian	    if (VarTerm) {
96126516Sbrian    	      fprintf(VarTerm,LAUTH_M1);
96226516Sbrian    	      fprintf(VarTerm,LAUTH_M2);
96326516Sbrian              fflush(VarTerm);
96426516Sbrian            }
9656764Samurai	    /* Fall down */
9666764Samurai         case VALID:
9676764Samurai	    VarLocalAuth = LOCAL_AUTH;
9686764Samurai	    break;
9696764Samurai         default:
9706764Samurai	    break;
9716764Samurai      }
9726059Samurai      (void) IsInteractive();
97325630Sbrian      Prompt();
9746059Samurai    }
9756059Samurai
97623598Sache    if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) &&
97710858Samurai	((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) {
9786059Samurai      /* something to read from tty */
9796059Samurai      ReadTty();
9806059Samurai    }
98123598Sache    if (modem >= 0) {
9826059Samurai      if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
9836059Samurai	 ModemStartOutput(modem);
9846059Samurai      }
9856059Samurai      if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
9866735Samurai	if (LcpFsm.state <= ST_CLOSED)
9876735Samurai	  usleep(10000);
9886059Samurai	n = read(modem, rbuff, sizeof(rbuff));
9896059Samurai	if ((mode & MODE_DIRECT) && n <= 0) {
9906059Samurai	  DownConnection();
9916059Samurai	} else
99226516Sbrian          LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
9936059Samurai
9946059Samurai	if (LcpFsm.state <= ST_CLOSED) {
9956059Samurai	  /*
9966059Samurai	   *  In dedicated mode, we just discard input until LCP is started.
9976059Samurai	   */
9986059Samurai	  if (!(mode & MODE_DEDICATED)) {
9996059Samurai	    cp = HdlcDetect(rbuff, n);
10006059Samurai	    if (cp) {
10016059Samurai	      /*
10026059Samurai	       * LCP packet is detected. Turn ourselves into packet mode.
10036059Samurai	       */
10046059Samurai	      if (cp != rbuff) {
100526516Sbrian	        write(modem, rbuff, cp - rbuff);
100626516Sbrian	        write(modem, "\r\n", 2);
10076059Samurai	      }
10086059Samurai	      PacketMode();
10096059Samurai	    } else
101026516Sbrian	      write(fileno(VarTerm), rbuff, n);
10116059Samurai	  }
10126059Samurai	} else {
10136059Samurai	  if (n > 0)
10146059Samurai	    AsyncInput(rbuff, n);
10156059Samurai	}
10166059Samurai      }
10176059Samurai    }
10187001Samurai
101923598Sache    if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {       /* something to read from tun */
10206059Samurai      n = read(tun_in, rbuff, sizeof(rbuff));
10216059Samurai      if (n < 0) {
102226516Sbrian        LogPrintf(LogERROR, "read from tun: %s", strerror(errno));
10236059Samurai	continue;
10246059Samurai      }
10256059Samurai      /*
10266059Samurai       *  Process on-demand dialup. Output packets are queued within tunnel
10276059Samurai       *  device until IPCP is opened.
10286059Samurai       */
10296059Samurai      if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
10307001Samurai	pri = PacketCheck(rbuff, n, FL_DIAL);
10316059Samurai	if (pri >= 0) {
103220365Sjkh	  if (mode & MODE_ALIAS) {
103326142Sbrian	    VarPacketAliasOut(rbuff, sizeof rbuff);
103420666Snate	    n = ntohs(((struct ip *)rbuff)->ip_len);
103520365Sjkh	  }
10366059Samurai	  IpEnqueue(pri, rbuff, n);
103720365Sjkh	  dial_up = TRUE;		/* XXX */
10386059Samurai	}
10396059Samurai	continue;
10406059Samurai      }
10417001Samurai      pri = PacketCheck(rbuff, n, FL_OUT);
104220365Sjkh      if (pri >= 0) {
104320365Sjkh        if (mode & MODE_ALIAS) {
104426142Sbrian          VarPacketAliasOut(rbuff, sizeof rbuff);
104520666Snate          n = ntohs(((struct ip *)rbuff)->ip_len);
104620365Sjkh        }
10476059Samurai	IpEnqueue(pri, rbuff, n);
104820365Sjkh      }
10496059Samurai    }
10506059Samurai  }
105126516Sbrian  LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
10526059Samurai}
1053