main.c revision 28684
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 *
2028684Sbrian * $Id: main.c,v 1.71 1997/08/25 00:29:19 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"
5428536Sbrian#include "lcpproto.h"
556059Samurai
566764Samurai#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n"
5726516Sbrian#define LAUTH_M2 "Warning: Manipulation is allowed by anyone\n"
586764Samurai
596735Samurai#ifndef O_NONBLOCK
606735Samurai#ifdef O_NDELAY
616735Samurai#define	O_NONBLOCK O_NDELAY
626735Samurai#endif
636735Samurai#endif
646735Samurai
656059Samuraiextern void VjInit(), AsyncInit();
6625630Sbrianextern void AsyncInput();
6728679Sbrianextern int SelectSystem();
686059Samurai
696059Samuraiextern void DecodeCommand(), Prompt();
7018885Sjkhextern int aft_cmd;
716059Samuraiextern int IsInteractive();
726059Samuraistatic void DoLoop(void);
7310528Samuraistatic void TerminalStop();
7425908Sbrianstatic char *ex_desc();
756059Samurai
7628679Sbrianstatic struct termios oldtio;	/* Original tty mode */
7728679Sbrianstatic struct termios comtio;	/* Command level tty mode */
7814418Sacheint TermMode;
7920813Sjkhstatic pid_t BGPid = 0;
8025634Sbrianstatic char pid_filename[MAXPATHLEN];
8125634Sbrianstatic char if_filename[MAXPATHLEN];
8225445Sacheint tunno;
8327061Sbrianstatic int dial_up;
846059Samurai
856059Samuraistatic void
8626858SbrianTtyInit(int DontWantInt)
876059Samurai{
886059Samurai  struct termios newtio;
896059Samurai  int stat;
906059Samurai
916059Samurai  stat = fcntl(0, F_GETFL, 0);
9225630Sbrian  if (stat > 0) {
9328679Sbrian    stat |= O_NONBLOCK;
9428679Sbrian    (void) fcntl(0, F_SETFL, stat);
9525630Sbrian  }
966059Samurai  newtio = oldtio;
9728679Sbrian  newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
986059Samurai  newtio.c_iflag = 0;
996059Samurai  newtio.c_oflag &= ~OPOST;
1006059Samurai  newtio.c_cc[VEOF] = _POSIX_VDISABLE;
10126858Sbrian  if (DontWantInt)
10226858Sbrian    newtio.c_cc[VINTR] = _POSIX_VDISABLE;
1036059Samurai  newtio.c_cc[VMIN] = 1;
1046059Samurai  newtio.c_cc[VTIME] = 0;
1056059Samurai  newtio.c_cflag |= CS8;
1066735Samurai  tcsetattr(0, TCSADRAIN, &newtio);
1076059Samurai  comtio = newtio;
1086059Samurai}
1096059Samurai
1106059Samurai/*
1116059Samurai *  Set tty into command mode. We allow canonical input and echo processing.
1126059Samurai */
11310528Samuraivoid
11428679SbrianTtyCommandMode(int prompt)
1156059Samurai{
1166059Samurai  struct termios newtio;
1176059Samurai  int stat;
1186059Samurai
1196059Samurai  if (!(mode & MODE_INTER))
1206059Samurai    return;
1216735Samurai  tcgetattr(0, &newtio);
12228679Sbrian  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) {
12828679Sbrian    stat |= O_NONBLOCK;
12928679Sbrian    (void) fcntl(0, F_SETFL, stat);
13025630Sbrian  }
1316059Samurai  TermMode = 0;
13228679Sbrian  if (prompt)
13328679Sbrian    Prompt();
1346059Samurai}
1356059Samurai
1366059Samurai/*
1376059Samurai * Set tty into terminal mode which is used while we invoke term command.
1386059Samurai */
1396059Samuraivoid
1406059SamuraiTtyTermMode()
1416059Samurai{
1426059Samurai  int stat;
1436059Samurai
1446735Samurai  tcsetattr(0, TCSADRAIN, &comtio);
1456059Samurai  stat = fcntl(0, F_GETFL, 0);
14625630Sbrian  if (stat > 0) {
14728679Sbrian    stat &= ~O_NONBLOCK;
14828679Sbrian    (void) fcntl(0, F_SETFL, stat);
14925630Sbrian  }
1506059Samurai  TermMode = 1;
1516059Samurai}
1526059Samurai
1536059Samuraivoid
15410528SamuraiTtyOldMode()
1556059Samurai{
1566059Samurai  int stat;
1576059Samurai
1586059Samurai  stat = fcntl(0, F_GETFL, 0);
15925630Sbrian  if (stat > 0) {
16028679Sbrian    stat &= ~O_NONBLOCK;
16128679Sbrian    (void) fcntl(0, F_SETFL, stat);
16225630Sbrian  }
1636735Samurai  tcsetattr(0, TCSANOW, &oldtio);
16410528Samurai}
16510528Samurai
16610528Samuraivoid
16728679SbrianCleanup(int excode)
16810528Samurai{
16910528Samurai
17010528Samurai  OsLinkdown();
1716059Samurai  OsCloseLink(1);
1726059Samurai  sleep(1);
17325908Sbrian  if (mode & MODE_AUTO)
1746059Samurai    DeleteIfRoutes(1);
17528679Sbrian  (void) unlink(pid_filename);
17628679Sbrian  (void) unlink(if_filename);
1776059Samurai  OsInterfaceDown(1);
17823863Sbrian  if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
17923863Sbrian    char c = EX_ERRDEAD;
18028679Sbrian
18128679Sbrian    if (write(BGFiledes[1], &c, 1) == 1)
18228679Sbrian      LogPrintf(LogPHASE, "Parent notified of failure.\n");
18323863Sbrian    else
18428679Sbrian      LogPrintf(LogPHASE, "Failed to notify parent of failure.\n");
18523863Sbrian    close(BGFiledes[1]);
18623863Sbrian  }
18728679Sbrian  LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
1886059Samurai  LogClose();
18926940Sbrian  ServerClose();
19010528Samurai  TtyOldMode();
1916059Samurai
1926059Samurai  exit(excode);
1936059Samurai}
1946059Samurai
1956059Samuraistatic void
19628679SbrianCloseConnection(int signo)
1976059Samurai{
19826858Sbrian  /* NOTE, these are manual, we've done a setsid() */
19927157Sbrian  LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo);
20028679Sbrian  reconnectState = RECON_FALSE;
20128684Sbrian  reconnectCount = 0;
20228684Sbrian  DownConnection();
20327061Sbrian  dial_up = FALSE;
2046059Samurai}
2056059Samurai
2066059Samuraistatic void
20728679SbrianCloseSession(int signo)
2086059Samurai{
20928679Sbrian  if (BGPid) {
21028679Sbrian    kill(BGPid, SIGINT);
21128679Sbrian    exit(EX_TERM);
21228679Sbrian  }
21328679Sbrian  LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
21428679Sbrian  reconnect(RECON_FALSE);
21528679Sbrian  LcpClose();
21628679Sbrian  Cleanup(EX_TERM);
2176059Samurai}
2186059Samurai
21910528Samuraistatic void
22010528SamuraiTerminalCont()
22110528Samurai{
22223840Sbrian  pending_signal(SIGCONT, SIG_DFL);
22323840Sbrian  pending_signal(SIGTSTP, TerminalStop);
22410528Samurai  TtyCommandMode(getpgrp() == tcgetpgrp(0));
22510528Samurai}
22610528Samurai
22710528Samuraistatic void
22828679SbrianTerminalStop(int signo)
22910528Samurai{
23023840Sbrian  pending_signal(SIGCONT, TerminalCont);
23110528Samurai  TtyOldMode();
23223840Sbrian  pending_signal(SIGTSTP, SIG_DFL);
23310528Samurai  kill(getpid(), signo);
23410528Samurai}
23510528Samurai
23626940Sbrianstatic void
23728679SbrianSetUpServer(int signo)
23826940Sbrian{
23926940Sbrian  int res;
24028679Sbrian
24128679Sbrian  if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0)
24228679Sbrian    LogPrintf(LogERROR, "Failed %d to open port %d\n", res, SERVER_PORT + tunno);
24326940Sbrian}
24426940Sbrian
24525908Sbrianstatic char *
24625908Sbrianex_desc(int ex)
24725908Sbrian{
24825908Sbrian  static char num[12];
24928679Sbrian  static char *desc[] = {"normal", "start", "sock",
25025908Sbrian    "modem", "dial", "dead", "done", "reboot", "errdead",
25128679Sbrian  "hangup", "term", "nodial", "nologin"};
25210528Samurai
25328679Sbrian  if (ex >= 0 && ex < sizeof(desc) / sizeof(*desc))
25425908Sbrian    return desc[ex];
25525908Sbrian  snprintf(num, sizeof num, "%d", ex);
25625908Sbrian  return num;
25725908Sbrian}
25825908Sbrian
2596059Samuraivoid
2606059SamuraiUsage()
2616059Samurai{
26220120Snate  fprintf(stderr,
26328679Sbrian	  "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n");
2646059Samurai  exit(EX_START);
2656059Samurai}
2666059Samurai
2676059Samuraivoid
2686059SamuraiProcessArgs(int argc, char **argv)
2696059Samurai{
2706059Samurai  int optc;
2716059Samurai  char *cp;
2726059Samurai
2736059Samurai  optc = 0;
2746059Samurai  while (argc > 0 && **argv == '-') {
2756059Samurai    cp = *argv + 1;
2766059Samurai    if (strcmp(cp, "auto") == 0)
2776059Samurai      mode |= MODE_AUTO;
27820813Sjkh    else if (strcmp(cp, "background") == 0)
27928679Sbrian      mode |= MODE_BACKGROUND | MODE_AUTO;
2806059Samurai    else if (strcmp(cp, "direct") == 0)
2816059Samurai      mode |= MODE_DIRECT;
2826059Samurai    else if (strcmp(cp, "dedicated") == 0)
2836059Samurai      mode |= MODE_DEDICATED;
28420120Snate    else if (strcmp(cp, "ddial") == 0)
28528679Sbrian      mode |= MODE_DDIAL | MODE_AUTO;
28620365Sjkh    else if (strcmp(cp, "alias") == 0) {
28726142Sbrian      if (loadAliasHandlers(&VarAliasHandlers) == 0)
28828679Sbrian	mode |= MODE_ALIAS;
28926142Sbrian      else
29028679Sbrian	LogPrintf(LogWARN, "Cannot load alias library\n");
29128679Sbrian      optc--;			/* this option isn't exclusive */
29228679Sbrian    } else
2936059Samurai      Usage();
2946059Samurai    optc++;
29528679Sbrian    argv++;
29628679Sbrian    argc--;
2976059Samurai  }
2986059Samurai  if (argc > 1) {
2996059Samurai    fprintf(stderr, "specify only one system label.\n");
3006059Samurai    exit(EX_START);
3016059Samurai  }
30228679Sbrian  if (argc == 1)
30328679Sbrian    dstsystem = *argv;
3046059Samurai
3056059Samurai  if (optc > 1) {
3066059Samurai    fprintf(stderr, "specify only one mode.\n");
3076059Samurai    exit(EX_START);
3086059Samurai  }
3096059Samurai}
3106059Samurai
3116059Samuraistatic void
3126059SamuraiGreetings()
3136059Samurai{
31426516Sbrian  if (VarTerm) {
31526516Sbrian    fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n");
31626516Sbrian    fflush(VarTerm);
31726516Sbrian  }
3186059Samurai}
3196059Samurai
32026940Sbrianint
32128679Sbrianmain(int argc, char **argv)
3226059Samurai{
32325707Sbrian  FILE *lockfile;
32426516Sbrian  char *name;
32526516Sbrian
32626551Sbrian  VarTerm = 0;
32726516Sbrian  name = rindex(argv[0], '/');
32828679Sbrian  LogOpen(name ? name + 1 : argv[0]);
32926516Sbrian
33028679Sbrian  argc--;
33128679Sbrian  argv++;
3326059Samurai  mode = MODE_INTER;		/* default operation is interactive mode */
33326940Sbrian  netfd = modem = tun_in = -1;
33426940Sbrian  server = -2;
3356059Samurai  ProcessArgs(argc, argv);
33626328Sbrian  if (!(mode & MODE_DIRECT))
33726551Sbrian    VarTerm = stdout;
33826551Sbrian  Greetings();
3396059Samurai  GetUid();
3406059Samurai  IpcpDefAddress();
3416059Samurai
34226516Sbrian  if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
34326516Sbrian    fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
3446059Samurai
3456059Samurai  if (OpenTunnel(&tunno) < 0) {
34626940Sbrian    LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno));
34726940Sbrian    return EX_START;
3486059Samurai  }
34928679Sbrian  if (mode & (MODE_AUTO | MODE_DIRECT | MODE_DEDICATED))
3506059Samurai    mode &= ~MODE_INTER;
3516059Samurai  if (mode & MODE_INTER) {
35226516Sbrian    fprintf(VarTerm, "Interactive mode\n");
35326690Sbrian    netfd = STDOUT_FILENO;
3546059Samurai  } else if (mode & MODE_AUTO) {
35526516Sbrian    fprintf(VarTerm, "Automatic Dialer mode\n");
3566059Samurai    if (dstsystem == NULL) {
35726516Sbrian      if (VarTerm)
35828679Sbrian	fprintf(VarTerm, "Destination system must be specified in"
35928679Sbrian		" auto, background or ddial mode.\n");
36026940Sbrian      return EX_START;
3616059Samurai    }
3626059Samurai  }
36328679Sbrian  tcgetattr(0, &oldtio);	/* Save original tty mode */
3646059Samurai
36527157Sbrian  pending_signal(SIGHUP, CloseSession);
36623840Sbrian  pending_signal(SIGTERM, CloseSession);
36727157Sbrian  pending_signal(SIGINT, CloseConnection);
36823840Sbrian  pending_signal(SIGQUIT, CloseSession);
3696735Samurai#ifdef SIGPIPE
37024753Sache  signal(SIGPIPE, SIG_IGN);
3716735Samurai#endif
3726735Samurai#ifdef SIGALRM
37323840Sbrian  pending_signal(SIGALRM, SIG_IGN);
3746735Samurai#endif
37528679Sbrian  if (mode & MODE_INTER) {
37610528Samurai#ifdef SIGTSTP
37726940Sbrian    pending_signal(SIGTSTP, TerminalStop);
37810528Samurai#endif
37910528Samurai#ifdef SIGTTIN
38026940Sbrian    pending_signal(SIGTTIN, TerminalStop);
38110528Samurai#endif
38210528Samurai#ifdef SIGTTOU
38326940Sbrian    pending_signal(SIGTTOU, SIG_IGN);
38410528Samurai#endif
38526940Sbrian  }
38626940Sbrian#ifdef SIGUSR1
38726940Sbrian  if (mode != MODE_INTER)
38826940Sbrian    pending_signal(SIGUSR1, SetUpServer);
38926940Sbrian#endif
3906059Samurai
3916059Samurai  if (dstsystem) {
3926059Samurai    if (SelectSystem(dstsystem, CONFFILE) < 0) {
39326551Sbrian      LogPrintf(LogWARN, "Destination system not found in conf file.\n");
3946059Samurai      Cleanup(EX_START);
3956059Samurai    }
3966059Samurai    if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
39726551Sbrian      LogPrintf(LogWARN, "Must specify dstaddr with"
39828679Sbrian		" auto, background or ddial mode.\n");
3996059Samurai      Cleanup(EX_START);
4006059Samurai    }
4016059Samurai  }
40226940Sbrian  if (ServerType() != NO_SERVER)
40328679Sbrian    switch (LocalAuthInit()) {
40428679Sbrian    case NOT_FOUND:
40528679Sbrian      if (VarTerm) {
40628679Sbrian	fprintf(VarTerm, LAUTH_M1);
40728679Sbrian	fprintf(VarTerm, LAUTH_M2);
40828679Sbrian	fflush(VarTerm);
40928679Sbrian      }
41028679Sbrian      /* Fall down */
41128679Sbrian    case VALID:
41228679Sbrian      VarLocalAuth = LOCAL_AUTH;
41328679Sbrian      break;
41428679Sbrian    default:
41528679Sbrian      break;
41626940Sbrian    }
41726940Sbrian
4186059Samurai  if (!(mode & MODE_INTER)) {
41920813Sjkh    if (mode & MODE_BACKGROUND) {
42028679Sbrian      if (pipe(BGFiledes)) {
42128679Sbrian	LogPrintf(LogERROR, "pipe: %s", strerror(errno));
42220813Sjkh	Cleanup(EX_SOCK);
42320813Sjkh      }
4246059Samurai    }
42526940Sbrian    /* Create server socket and listen. */
42626940Sbrian    if (server == -2 && ServerTcpOpen(SERVER_PORT + tunno) != 0)
42728679Sbrian      Cleanup(EX_SOCK);
4286059Samurai
4296059Samurai    if (!(mode & MODE_DIRECT)) {
43020813Sjkh      pid_t bgpid;
43111336Samurai
43228679Sbrian      bgpid = fork();
43320813Sjkh      if (bgpid == -1) {
43428679Sbrian	LogPrintf(LogERROR, "fork: %s", strerror(errno));
43528679Sbrian	Cleanup(EX_SOCK);
43620813Sjkh      }
43720813Sjkh      if (bgpid) {
43820813Sjkh	char c = EX_NORMAL;
43911336Samurai
44020813Sjkh	if (mode & MODE_BACKGROUND) {
44120813Sjkh	  /* Wait for our child to close its pipe before we exit. */
44220813Sjkh	  BGPid = bgpid;
44328679Sbrian	  close(BGFiledes[1]);
44425908Sbrian	  if (read(BGFiledes[0], &c, 1) != 1) {
44526516Sbrian	    fprintf(VarTerm, "Child exit, no status.\n");
44628679Sbrian	    LogPrintf(LogPHASE, "Parent: Child exit, no status.\n");
44725908Sbrian	  } else if (c == EX_NORMAL) {
44826516Sbrian	    fprintf(VarTerm, "PPP enabled.\n");
44928679Sbrian	    LogPrintf(LogPHASE, "Parent: PPP enabled.\n");
45025908Sbrian	  } else {
45128679Sbrian	    fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c));
45226516Sbrian	    LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
45328679Sbrian		      ex_desc((int) c));
45428679Sbrian	  }
45528679Sbrian	  close(BGFiledes[0]);
45620813Sjkh	}
45728679Sbrian	return c;
45823863Sbrian      } else if (mode & MODE_BACKGROUND)
45928679Sbrian	close(BGFiledes[0]);
46025707Sbrian    }
46128679Sbrian    snprintf(pid_filename, sizeof(pid_filename), "%stun%d.pid",
46228679Sbrian	     _PATH_VARRUN, tunno);
46328679Sbrian    (void) unlink(pid_filename);
46420813Sjkh
46525707Sbrian    if ((lockfile = fopen(pid_filename, "w")) != NULL) {
46628679Sbrian      fprintf(lockfile, "%d\n", (int) getpid());
46725707Sbrian      fclose(lockfile);
46825707Sbrian    } else
46926516Sbrian      LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
47028679Sbrian		pid_filename, strerror(errno));
47125634Sbrian
47225707Sbrian    snprintf(if_filename, sizeof if_filename, "%s%s.if",
47328679Sbrian	     _PATH_VARRUN, VarBaseDevice);
47428679Sbrian    (void) unlink(if_filename);
47525634Sbrian
47625707Sbrian    if ((lockfile = fopen(if_filename, "w")) != NULL) {
47725707Sbrian      fprintf(lockfile, "tun%d\n", tunno);
47825707Sbrian      fclose(lockfile);
47925707Sbrian    } else
48026516Sbrian      LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
48128679Sbrian		if_filename, strerror(errno));
48225707Sbrian
48328679Sbrian    VarTerm = 0;		/* We know it's currently stdout */
48426686Sbrian    close(0);
48526686Sbrian    close(2);
48626551Sbrian
4876059Samurai#ifdef DOTTYINIT
48828679Sbrian    if (mode & (MODE_DIRECT | MODE_DEDICATED))
4896059Samurai#else
49026686Sbrian    if (mode & MODE_DIRECT)
4916059Samurai#endif
49226858Sbrian      TtyInit(1);
49326686Sbrian    else {
49426686Sbrian      setsid();
49526686Sbrian      close(1);
49626686Sbrian    }
4976059Samurai  } else {
49826858Sbrian    TtyInit(0);
49910528Samurai    TtyCommandMode(1);
5006059Samurai  }
50126516Sbrian  LogPrintf(LogPHASE, "PPP Started.\n");
5026059Samurai
5036059Samurai
5046059Samurai  do
50528679Sbrian    DoLoop();
5066059Samurai  while (mode & MODE_DEDICATED);
5076059Samurai
5086059Samurai  Cleanup(EX_DONE);
50926940Sbrian  return 0;
5106059Samurai}
5116059Samurai
5126059Samurai/*
51320813Sjkh *  Turn into packet mode, where we speak PPP.
5146059Samurai */
5156059Samuraivoid
5166059SamuraiPacketMode()
5176059Samurai{
5186059Samurai  if (RawModem(modem) < 0) {
51926516Sbrian    LogPrintf(LogWARN, "PacketMode: Not connected.\n");
5206059Samurai    return;
5216059Samurai  }
5226059Samurai  AsyncInit();
5236059Samurai  VjInit();
5246059Samurai  LcpInit();
5256059Samurai  IpcpInit();
5266059Samurai  CcpInit();
5276059Samurai  LcpUp();
5286059Samurai
52925872Sbrian  LcpOpen(VarOpenMode);
53028679Sbrian  if ((mode & (MODE_INTER | MODE_AUTO)) == MODE_INTER) {
53110528Samurai    TtyCommandMode(1);
53226516Sbrian    if (VarTerm) {
53326516Sbrian      fprintf(VarTerm, "Packet mode.\n");
53426516Sbrian      aft_cmd = 1;
53526516Sbrian    }
5366059Samurai  }
5376059Samurai}
5386059Samurai
5396059Samuraistatic void
5406059SamuraiShowHelp()
5416059Samurai{
54226901Sbrian  fprintf(stderr, "The following commands are available:\r\n");
54326901Sbrian  fprintf(stderr, " ~p\tEnter Packet mode\r\n");
54426901Sbrian  fprintf(stderr, " ~-\tDecrease log level\r\n");
54526901Sbrian  fprintf(stderr, " ~+\tIncrease log level\r\n");
54626901Sbrian  fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
54726901Sbrian  fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
54826901Sbrian  fprintf(stderr, " ~.\tTerminate program\r\n");
54926901Sbrian  fprintf(stderr, " ~?\tThis help\r\n");
5506059Samurai}
5516059Samurai
5526059Samuraistatic void
5536059SamuraiReadTty()
5546059Samurai{
5556059Samurai  int n;
5566059Samurai  char ch;
5576059Samurai  static int ttystate;
55826516Sbrian  FILE *oVarTerm;
55928679Sbrian
5606059Samurai#define MAXLINESIZE 200
5616059Samurai  char linebuff[MAXLINESIZE];
5626059Samurai
56326516Sbrian  LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
56428679Sbrian	    TermMode, netfd, mode);
5656059Samurai  if (!TermMode) {
56628679Sbrian    n = read(netfd, linebuff, sizeof(linebuff) - 1);
5676735Samurai    if (n > 0) {
56826516Sbrian      aft_cmd = 1;
5696059Samurai      DecodeCommand(linebuff, n, 1);
5706735Samurai    } else {
57126516Sbrian      LogPrintf(LogPHASE, "client connection closed.\n");
57224753Sache      VarLocalAuth = LOCAL_NO_AUTH;
57326516Sbrian      mode &= ~MODE_INTER;
57426516Sbrian      oVarTerm = VarTerm;
57526516Sbrian      VarTerm = 0;
57626516Sbrian      if (oVarTerm && oVarTerm != stdout)
57728679Sbrian	fclose(oVarTerm);
5786059Samurai      close(netfd);
5796059Samurai      netfd = -1;
5806059Samurai    }
5816059Samurai    return;
5826059Samurai  }
5836059Samurai
5846059Samurai  /*
58528679Sbrian   * We are in terminal mode, decode special sequences
5866059Samurai   */
58726516Sbrian  n = read(fileno(VarTerm), &ch, 1);
58826516Sbrian  LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)", n);
5896059Samurai
5906059Samurai  if (n > 0) {
5916059Samurai    switch (ttystate) {
5926059Samurai    case 0:
5936059Samurai      if (ch == '~')
5946059Samurai	ttystate++;
5956059Samurai      else
5966059Samurai	write(modem, &ch, n);
5976059Samurai      break;
5986059Samurai    case 1:
5996059Samurai      switch (ch) {
6006059Samurai      case '?':
6016059Samurai	ShowHelp();
6026059Samurai	break;
6036059Samurai      case 'p':
60428679Sbrian
6056059Samurai	/*
6066059Samurai	 * XXX: Should check carrier.
6076059Samurai	 */
6086059Samurai	if (LcpFsm.state <= ST_CLOSED) {
6096059Samurai	  VarOpenMode = OPEN_ACTIVE;
6106059Samurai	  PacketMode();
6116059Samurai	}
6126059Samurai	break;
6136059Samurai      case '.':
6146059Samurai	TermMode = 1;
61526516Sbrian	aft_cmd = 1;
61610528Samurai	TtyCommandMode(1);
6176059Samurai	break;
61826516Sbrian      case 't':
61926516Sbrian	if (LogIsKept(LogDEBUG)) {
62026516Sbrian	  ShowTimers();
62126516Sbrian	  break;
62226516Sbrian	}
62326516Sbrian      case 'm':
62426516Sbrian	if (LogIsKept(LogDEBUG)) {
62526516Sbrian	  ShowMemMap();
62626516Sbrian	  break;
62726516Sbrian	}
6286059Samurai      default:
6296059Samurai	if (write(modem, &ch, n) < 0)
63026516Sbrian	  LogPrintf(LogERROR, "error writing to modem.\n");
6316059Samurai	break;
6326059Samurai      }
6336059Samurai      ttystate = 0;
6346059Samurai      break;
6356059Samurai    }
6366059Samurai  }
6376059Samurai}
6386059Samurai
6396059Samurai
6406059Samurai/*
6416059Samurai *  Here, we'll try to detect HDLC frame
6426059Samurai */
6436059Samurai
6446059Samuraistatic char *FrameHeaders[] = {
6456735Samurai  "\176\377\003\300\041",
6466735Samurai  "\176\377\175\043\300\041",
6476735Samurai  "\176\177\175\043\100\041",
6486735Samurai  "\176\175\337\175\043\300\041",
6496735Samurai  "\176\175\137\175\043\100\041",
6506059Samurai  NULL,
6516059Samurai};
6526059Samurai
6536059Samuraiu_char *
65428679SbrianHdlcDetect(u_char * cp, int n)
6556059Samurai{
6566735Samurai  char *ptr, *fp, **hp;
6576059Samurai
65828679Sbrian  cp[n] = '\0';			/* be sure to null terminated */
6596059Samurai  ptr = NULL;
6606059Samurai  for (hp = FrameHeaders; *hp; hp++) {
6616735Samurai    fp = *hp;
6626735Samurai    if (DEV_IS_SYNC)
6636735Samurai      fp++;
66428679Sbrian    ptr = strstr((char *) cp, fp);
66513389Sphk    if (ptr)
6666059Samurai      break;
6676059Samurai  }
66828679Sbrian  return ((u_char *) ptr);
6696059Samurai}
6706059Samurai
6716059Samuraistatic struct pppTimer RedialTimer;
6726059Samurai
6736059Samuraistatic void
6746059SamuraiRedialTimeout()
6756059Samurai{
6766059Samurai  StopTimer(&RedialTimer);
67726516Sbrian  LogPrintf(LogPHASE, "Redialing timer expired.\n");
6786059Samurai}
6796059Samurai
6806059Samuraistatic void
68128679SbrianStartRedialTimer(int Timeout)
6826059Samurai{
6836059Samurai  StopTimer(&RedialTimer);
68411336Samurai
68524939Sbrian  if (Timeout) {
68611336Samurai    RedialTimer.state = TIMER_STOPPED;
68711336Samurai
68824939Sbrian    if (Timeout > 0)
68928679Sbrian      RedialTimer.load = Timeout * SECTICKS;
69011336Samurai    else
69128679Sbrian      RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
69211336Samurai
69326516Sbrian    LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
69424939Sbrian	      RedialTimer.load / SECTICKS);
69524939Sbrian
69611336Samurai    RedialTimer.func = RedialTimeout;
69711336Samurai    StartTimer(&RedialTimer);
69811336Samurai  }
6996059Samurai}
7006059Samurai
7016059Samurai
7026059Samuraistatic void
7036059SamuraiDoLoop()
7046059Samurai{
7056059Samurai  fd_set rfds, wfds, efds;
70623598Sache  int pri, i, n, wfd, nfds;
7076059Samurai  struct sockaddr_in hisaddr;
7086059Samurai  struct timeval timeout, *tp;
7096059Samurai  int ssize = sizeof(hisaddr);
7106059Samurai  u_char *cp;
7116059Samurai  u_char rbuff[MAX_MRU];
71211336Samurai  int tries;
7139448Samurai  int qlen;
71426858Sbrian  int res;
71510528Samurai  pid_t pgroup;
7166059Samurai
71710528Samurai  pgroup = getpgrp();
71810528Samurai
71925908Sbrian  if (mode & MODE_DIRECT) {
72026551Sbrian    LogPrintf(LogDEBUG, "Opening modem\n");
7216059Samurai    modem = OpenModem(mode);
72226516Sbrian    LogPrintf(LogPHASE, "Packet mode enabled\n");
7236059Samurai    PacketMode();
7246059Samurai  } else if (mode & MODE_DEDICATED) {
72523598Sache    if (modem < 0)
7266059Samurai      modem = OpenModem(mode);
7276059Samurai  }
72826516Sbrian  fflush(VarTerm);
7296059Samurai
7307001Samurai  timeout.tv_sec = 0;
7316059Samurai  timeout.tv_usec = 0;
73226098Sbrian  reconnectState = RECON_UNKNOWN;
7336059Samurai
73423863Sbrian  if (mode & MODE_BACKGROUND)
73528679Sbrian    dial_up = TRUE;		/* Bring the line up */
73623863Sbrian  else
73728679Sbrian    dial_up = FALSE;		/* XXXX */
73811336Samurai  tries = 0;
7396059Samurai  for (;;) {
74023598Sache    nfds = 0;
74128679Sbrian    FD_ZERO(&rfds);
74228679Sbrian    FD_ZERO(&wfds);
74328679Sbrian    FD_ZERO(&efds);
7447001Samurai
74528679Sbrian    /*
74628679Sbrian     * If the link is down and we're in DDIAL mode, bring it back up.
74720120Snate     */
74820120Snate    if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
74928679Sbrian      dial_up = TRUE;
75020120Snate
75125067Sbrian    /*
75228679Sbrian     * If we lost carrier and want to re-establish the connection due to the
75328679Sbrian     * "set reconnect" value, we'd better bring the line back up.
75425067Sbrian     */
75525908Sbrian    if (LcpFsm.state <= ST_CLOSED) {
75626098Sbrian      if (dial_up != TRUE && reconnectState == RECON_TRUE) {
75728679Sbrian	if (++reconnectCount <= VarReconnectTries) {
75828679Sbrian	  LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
75928679Sbrian		    reconnectCount, VarReconnectTries);
76025908Sbrian	  StartRedialTimer(VarReconnectTimer);
76128679Sbrian	  dial_up = TRUE;
76228679Sbrian	} else {
76328679Sbrian	  if (VarReconnectTries)
76428679Sbrian	    LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
76528679Sbrian		      VarReconnectTries);
76628679Sbrian	  reconnectCount = 0;
76728679Sbrian	  if (mode & MODE_BACKGROUND)
76828679Sbrian	    Cleanup(EX_DEAD);
76928679Sbrian	}
77028679Sbrian	reconnectState = RECON_ENVOKED;
77125801Sbrian      }
77225908Sbrian    }
77325067Sbrian
77428679Sbrian    /*
77528679Sbrian     * If Ip packet for output is enqueued and require dial up, Just do it!
77628679Sbrian     */
77728679Sbrian    if (dial_up && RedialTimer.state != TIMER_RUNNING) {
77826516Sbrian      LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
77911336Samurai      modem = OpenModem(mode);
78011336Samurai      if (modem < 0) {
78128679Sbrian	tries++;
78228679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
78328679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
78428679Sbrian		    tries, VarDialTries);
78528679Sbrian	else
78628679Sbrian	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
78726551Sbrian
78826696Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
78926551Sbrian	  if (mode & MODE_BACKGROUND)
79028679Sbrian	    Cleanup(EX_DIAL);	/* Can't get the modem */
79126551Sbrian	  dial_up = FALSE;
79228679Sbrian	  reconnectState = RECON_UNKNOWN;
79328679Sbrian	  reconnectCount = 0;
79426551Sbrian	  tries = 0;
79528679Sbrian	} else
79626551Sbrian	  StartRedialTimer(VarRedialTimeout);
79711336Samurai      } else {
79828679Sbrian	tries++;		/* Tries are per number, not per list of
79928679Sbrian				 * numbers. */
80028679Sbrian	if (!(mode & MODE_DDIAL) && VarDialTries)
80126696Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
80228679Sbrian	else
80328679Sbrian	  LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
80426696Sbrian
80526858Sbrian	if ((res = DialModem()) == EX_DONE) {
80628679Sbrian	  sleep(1);		/* little pause to allow peer starts */
80711336Samurai	  ModemTimeout();
80811336Samurai	  PacketMode();
80911336Samurai	  dial_up = FALSE;
81028679Sbrian	  reconnectState = RECON_UNKNOWN;
81111336Samurai	  tries = 0;
81211336Samurai	} else {
81311336Samurai	  CloseModem();
81424844Sbrian	  if (mode & MODE_BACKGROUND) {
81526858Sbrian	    if (VarNextPhone == NULL || res == EX_SIG)
81628679Sbrian	      Cleanup(EX_DIAL);	/* Tried all numbers - no luck */
81724844Sbrian	    else
81824939Sbrian	      /* Try all numbers in background mode */
81924939Sbrian	      StartRedialTimer(VarRedialNextTimeout);
82026858Sbrian	  } else if (!(mode & MODE_DDIAL) &&
82128679Sbrian		     ((VarDialTries && tries >= VarDialTries) ||
82228679Sbrian		      res == EX_SIG)) {
82324843Sbrian	    /* I give up !  Can't get through :( */
82424939Sbrian	    StartRedialTimer(VarRedialTimeout);
82524843Sbrian	    dial_up = FALSE;
82628679Sbrian	    reconnectState = RECON_UNKNOWN;
82728679Sbrian	    reconnectCount = 0;
82824843Sbrian	    tries = 0;
82924843Sbrian	  } else if (VarNextPhone == NULL)
83024843Sbrian	    /* Dial failed. Keep quite during redial wait period. */
83124939Sbrian	    StartRedialTimer(VarRedialTimeout);
83224843Sbrian	  else
83324939Sbrian	    StartRedialTimer(VarRedialNextTimeout);
83411336Samurai	}
83511336Samurai      }
8367001Samurai    }
8379448Samurai    qlen = ModemQlen();
83813733Sdfr
83913733Sdfr    if (qlen == 0) {
84013733Sdfr      IpStartOutput();
84113733Sdfr      qlen = ModemQlen();
84213733Sdfr    }
84323598Sache    if (modem >= 0) {
84423598Sache      if (modem + 1 > nfds)
84523598Sache	nfds = modem + 1;
8467001Samurai      FD_SET(modem, &rfds);
8477001Samurai      FD_SET(modem, &efds);
8489448Samurai      if (qlen > 0) {
8497001Samurai	FD_SET(modem, &wfds);
8507001Samurai      }
8517001Samurai    }
85223598Sache    if (server >= 0) {
85323598Sache      if (server + 1 > nfds)
85423598Sache	nfds = server + 1;
85523598Sache      FD_SET(server, &rfds);
85623598Sache    }
8576059Samurai
85828679Sbrian    /*
85928679Sbrian     * *** IMPORTANT ***
86028679Sbrian     *
86128679Sbrian     * CPU is serviced every TICKUNIT micro seconds. This value must be chosen
86228679Sbrian     * with great care. If this values is too big, it results loss of
86328679Sbrian     * characters from modem and poor responce. If this values is too small,
86428679Sbrian     * ppp process eats many CPU time.
8656059Samurai     */
8666735Samurai#ifndef SIGALRM
8676059Samurai    usleep(TICKUNIT);
8686059Samurai    TimerService();
86923840Sbrian#else
87023840Sbrian    handle_signals();
8716735Samurai#endif
87210877Sbde
87310877Sbde    /* If there are aren't many packets queued, look for some more. */
87423598Sache    if (qlen < 20 && tun_in >= 0) {
87523598Sache      if (tun_in + 1 > nfds)
87623598Sache	nfds = tun_in + 1;
87710877Sbde      FD_SET(tun_in, &rfds);
87823598Sache    }
87923598Sache    if (netfd >= 0) {
88023598Sache      if (netfd + 1 > nfds)
88123598Sache	nfds = netfd + 1;
8826059Samurai      FD_SET(netfd, &rfds);
8836059Samurai      FD_SET(netfd, &efds);
8846059Samurai    }
88528679Sbrian#ifndef SIGALRM
8867001Samurai
8876059Samurai    /*
88828679Sbrian     * Normally, select() will not block because modem is writable. In AUTO
88928679Sbrian     * mode, select will block until we find packet from tun
8906059Samurai     */
89128679Sbrian    tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL;
89223598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
8936735Samurai#else
89428679Sbrian
8958857Srgrimes    /*
89628679Sbrian     * When SIGALRM timer is running, a select function will be return -1 and
89728679Sbrian     * EINTR after a Time Service signal hundler is done.  If the redial
89828679Sbrian     * timer is not running and we are trying to dial, poll with a 0 value
89928679Sbrian     * timer.
9007001Samurai     */
90111336Samurai    tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
90223598Sache    i = select(nfds, &rfds, &wfds, &efds, tp);
9036735Samurai#endif
90422074Sbrian
90528679Sbrian    if (i == 0) {
90628679Sbrian      continue;
9076059Samurai    }
90828679Sbrian    if (i < 0) {
90928679Sbrian      if (errno == EINTR) {
91028679Sbrian	handle_signals();
91128679Sbrian	continue;
91228679Sbrian      }
91328679Sbrian      LogPrintf(LogERROR, "select: %s", strerror(errno));
91428679Sbrian      break;
9158857Srgrimes    }
91623598Sache    if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
91726516Sbrian      LogPrintf(LogALERT, "Exception detected.\n");
9186059Samurai      break;
9196059Samurai    }
92023598Sache    if (server >= 0 && FD_ISSET(server, &rfds)) {
92126516Sbrian      LogPrintf(LogPHASE, "connected to client.\n");
92228679Sbrian      wfd = accept(server, (struct sockaddr *) & hisaddr, &ssize);
92324753Sache      if (wfd < 0) {
92428679Sbrian	LogPrintf(LogERROR, "accept: %s", strerror(errno));
92524753Sache	continue;
92624753Sache      }
92723598Sache      if (netfd >= 0) {
9286059Samurai	write(wfd, "already in use.\n", 16);
9296059Samurai	close(wfd);
9306059Samurai	continue;
9316059Samurai      } else
9326059Samurai	netfd = wfd;
93326516Sbrian      VarTerm = fdopen(netfd, "a+");
9346059Samurai      mode |= MODE_INTER;
9356059Samurai      Greetings();
93628679Sbrian      switch (LocalAuthInit()) {
93728679Sbrian      case NOT_FOUND:
93828679Sbrian	if (VarTerm) {
93928679Sbrian	  fprintf(VarTerm, LAUTH_M1);
94028679Sbrian	  fprintf(VarTerm, LAUTH_M2);
94128679Sbrian	  fflush(VarTerm);
94228679Sbrian	}
94328679Sbrian	/* Fall down */
94428679Sbrian      case VALID:
94528679Sbrian	VarLocalAuth = LOCAL_AUTH;
94628679Sbrian	break;
94728679Sbrian      default:
94828679Sbrian	break;
9496764Samurai      }
9506059Samurai      (void) IsInteractive();
95125630Sbrian      Prompt();
9526059Samurai    }
95323598Sache    if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) &&
95410858Samurai	((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) {
9556059Samurai      /* something to read from tty */
9566059Samurai      ReadTty();
9576059Samurai    }
95823598Sache    if (modem >= 0) {
9596059Samurai      if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
96028679Sbrian	ModemStartOutput(modem);
9616059Samurai      }
9626059Samurai      if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
9636735Samurai	if (LcpFsm.state <= ST_CLOSED)
9646735Samurai	  usleep(10000);
9656059Samurai	n = read(modem, rbuff, sizeof(rbuff));
9666059Samurai	if ((mode & MODE_DIRECT) && n <= 0) {
9676059Samurai	  DownConnection();
9686059Samurai	} else
96928679Sbrian	  LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
9706059Samurai
9716059Samurai	if (LcpFsm.state <= ST_CLOSED) {
97228679Sbrian
9736059Samurai	  /*
97428679Sbrian	   * In dedicated mode, we just discard input until LCP is started.
9756059Samurai	   */
9766059Samurai	  if (!(mode & MODE_DEDICATED)) {
9776059Samurai	    cp = HdlcDetect(rbuff, n);
9786059Samurai	    if (cp) {
97928679Sbrian
9806059Samurai	      /*
9816059Samurai	       * LCP packet is detected. Turn ourselves into packet mode.
9826059Samurai	       */
9836059Samurai	      if (cp != rbuff) {
98428679Sbrian		write(modem, rbuff, cp - rbuff);
98528679Sbrian		write(modem, "\r\n", 2);
9866059Samurai	      }
9876059Samurai	      PacketMode();
9886059Samurai	    } else
98926516Sbrian	      write(fileno(VarTerm), rbuff, n);
9906059Samurai	  }
9916059Samurai	} else {
9926059Samurai	  if (n > 0)
9936059Samurai	    AsyncInput(rbuff, n);
9946059Samurai	}
9956059Samurai      }
9966059Samurai    }
99728679Sbrian    if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {	/* something to read
99828679Sbrian							 * from tun */
9996059Samurai      n = read(tun_in, rbuff, sizeof(rbuff));
10006059Samurai      if (n < 0) {
100128679Sbrian	LogPrintf(LogERROR, "read from tun: %s", strerror(errno));
10026059Samurai	continue;
10036059Samurai      }
100428679Sbrian      if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) {
100528536Sbrian	/* we've been asked to send something addressed *to* us :( */
100628536Sbrian	if (VarLoopback) {
100728536Sbrian	  pri = PacketCheck(rbuff, n, FL_IN);
100828536Sbrian	  if (pri >= 0) {
100928536Sbrian	    struct mbuf *bp;
101028679Sbrian
101128536Sbrian	    if (mode & MODE_ALIAS) {
101228536Sbrian	      VarPacketAliasIn(rbuff, sizeof rbuff);
101328679Sbrian	      n = ntohs(((struct ip *) rbuff)->ip_len);
101428536Sbrian	    }
101528536Sbrian	    bp = mballoc(n, MB_IPIN);
101628536Sbrian	    bcopy(rbuff, MBUF_CTOP(bp), n);
101728536Sbrian	    IpInput(bp);
101828536Sbrian	    LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n");
101928536Sbrian	  }
102028536Sbrian	  continue;
102128679Sbrian	} else
102228536Sbrian	  LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
102328536Sbrian      }
102428536Sbrian
10256059Samurai      /*
102628679Sbrian       * Process on-demand dialup. Output packets are queued within tunnel
102728679Sbrian       * 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);
103428679Sbrian	    n = ntohs(((struct ip *) rbuff)->ip_len);
103520365Sjkh	  }
10366059Samurai	  IpEnqueue(pri, rbuff, n);
103728679Sbrian	  dial_up = TRUE;	/* XXX */
10386059Samurai	}
10396059Samurai	continue;
10406059Samurai      }
10417001Samurai      pri = PacketCheck(rbuff, n, FL_OUT);
104220365Sjkh      if (pri >= 0) {
104328679Sbrian	if (mode & MODE_ALIAS) {
104428679Sbrian	  VarPacketAliasOut(rbuff, sizeof rbuff);
104528679Sbrian	  n = ntohs(((struct ip *) rbuff)->ip_len);
104628679Sbrian	}
10476059Samurai	IpEnqueue(pri, rbuff, n);
104820365Sjkh      }
10496059Samurai    }
10506059Samurai  }
105126516Sbrian  LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
10526059Samurai}
1053