command.c revision 32267
16059Samurai/*
26059Samurai *		PPP User command processing module
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.
198857Srgrimes *
2032267Sbrian * $Id: command.c,v 1.124 1997/12/30 23:22:27 brian Exp $
218857Srgrimes *
226059Samurai */
2330715Sbrian#include <sys/param.h>
2430715Sbrian#include <netinet/in_systm.h>
2526031Sbrian#include <netinet/in.h>
2630715Sbrian#include <netinet/ip.h>
2726031Sbrian#include <arpa/inet.h>
2830715Sbrian#include <sys/socket.h>
2926031Sbrian#include <net/route.h>
3030715Sbrian#include <netdb.h>
3130715Sbrian
3231343Sbrian#ifndef NOALIAS
3326031Sbrian#include <alias.h>
3431343Sbrian#endif
3530715Sbrian#include <ctype.h>
3630715Sbrian#include <errno.h>
3726516Sbrian#include <fcntl.h>
3830715Sbrian#include <paths.h>
3930715Sbrian#include <stdio.h>
4030715Sbrian#include <stdlib.h>
4130715Sbrian#include <string.h>
4230715Sbrian#include <sys/stat.h>
4330715Sbrian#include <sys/wait.h>
4430715Sbrian#include <termios.h>
4530715Sbrian#include <time.h>
4630715Sbrian#include <unistd.h>
4730715Sbrian
4831343Sbrian#include "command.h"
4930715Sbrian#include "mbuf.h"
5030715Sbrian#include "log.h"
5130715Sbrian#include "defs.h"
5230715Sbrian#include "timer.h"
536059Samurai#include "fsm.h"
546059Samurai#include "phase.h"
556059Samurai#include "lcp.h"
5631690Sbrian#include "iplist.h"
576059Samurai#include "ipcp.h"
586059Samurai#include "modem.h"
5913389Sphk#include "filter.h"
6031343Sbrian#ifndef NOALIAS
6126031Sbrian#include "alias_cmd.h"
6231343Sbrian#endif
636059Samurai#include "hdlc.h"
6426142Sbrian#include "loadalias.h"
656059Samurai#include "vars.h"
6625630Sbrian#include "systems.h"
6725630Sbrian#include "chat.h"
686059Samurai#include "os.h"
6926940Sbrian#include "server.h"
7030715Sbrian#include "main.h"
7130715Sbrian#include "route.h"
7230715Sbrian#include "ccp.h"
7330733Sbrian#include "ip.h"
7430715Sbrian#include "slcompress.h"
7531080Sbrian#include "auth.h"
766059Samurai
776059Samuraistruct in_addr ifnetmask;
7831822Sbrianstatic const char *HIDDEN = "********";
796059Samurai
8031343Sbrianstatic int ShowCommand(struct cmdargs const *arg);
8131343Sbrianstatic int TerminalCommand(struct cmdargs const *arg);
8231343Sbrianstatic int QuitCommand(struct cmdargs const *arg);
8331343Sbrianstatic int CloseCommand(struct cmdargs const *arg);
8431343Sbrianstatic int DialCommand(struct cmdargs const *arg);
8531343Sbrianstatic int DownCommand(struct cmdargs const *arg);
8631343Sbrianstatic int AllowCommand(struct cmdargs const *arg);
8731343Sbrianstatic int SetCommand(struct cmdargs const *arg);
8831343Sbrianstatic int AddCommand(struct cmdargs const *arg);
8931343Sbrianstatic int DeleteCommand(struct cmdargs const *arg);
9031343Sbrianstatic int BgShellCommand(struct cmdargs const *arg);
9131343Sbrianstatic int FgShellCommand(struct cmdargs const *arg);
9231343Sbrian#ifndef NOALIAS
9331343Sbrianstatic int AliasCommand(struct cmdargs const *arg);
9431343Sbrianstatic int AliasEnable(struct cmdargs const *arg);
9531343Sbrianstatic int AliasOption(struct cmdargs const *arg);
9631343Sbrian#endif
976059Samurai
986059Samuraistatic int
9931343SbrianHelpCommand(struct cmdargs const *arg)
1006059Samurai{
10128679Sbrian  struct cmdtab const *cmd;
10231372Sbrian  int n, cmax, dmax, cols;
1036059Samurai
10426516Sbrian  if (!VarTerm)
10526516Sbrian    return 0;
10626516Sbrian
10731343Sbrian  if (arg->argc > 0) {
10831343Sbrian    for (cmd = arg->cmd; cmd->name; cmd++)
10931372Sbrian      if (strcasecmp(cmd->name, *arg->argv) == 0 &&
11031372Sbrian          (cmd->lauth & VarLocalAuth)) {
11128679Sbrian	fprintf(VarTerm, "%s\n", cmd->syntax);
11228679Sbrian	return 0;
1136059Samurai      }
11426516Sbrian    return -1;
1156059Samurai  }
11631372Sbrian  cmax = dmax = 0;
11731372Sbrian  for (cmd = arg->cmd; cmd->func; cmd++)
11831372Sbrian    if (cmd->name && (cmd->lauth & VarLocalAuth)) {
11931372Sbrian      if ((n = strlen(cmd->name)) > cmax)
12031372Sbrian        cmax = n;
12131372Sbrian      if ((n = strlen(cmd->helpmes)) > dmax)
12231372Sbrian        dmax = n;
12331372Sbrian    }
12431372Sbrian
12531372Sbrian  cols = 80 / (dmax + cmax + 3);
1266059Samurai  n = 0;
12731343Sbrian  for (cmd = arg->cmd; cmd->func; cmd++)
1286764Samurai    if (cmd->name && (cmd->lauth & VarLocalAuth)) {
12931372Sbrian      fprintf(VarTerm, " %-*.*s: %-*.*s",
13031372Sbrian              cmax, cmax, cmd->name, dmax, dmax, cmd->helpmes);
13131372Sbrian      if (++n % cols == 0)
13231372Sbrian        fprintf(VarTerm, "\n");
1336059Samurai    }
13431372Sbrian  if (n % cols != 0)
13526516Sbrian    fprintf(VarTerm, "\n");
13626516Sbrian
13726516Sbrian  return 0;
1386059Samurai}
1396059Samurai
1406059Samuraiint
14130913SbrianIsInteractive(int Display)
1426059Samurai{
14331343Sbrian  const char *mes = NULL;
1446059Samurai
14520120Snate  if (mode & MODE_DDIAL)
14620120Snate    mes = "Working in dedicated dial mode.";
14725908Sbrian  else if (mode & MODE_BACKGROUND)
14825908Sbrian    mes = "Working in background mode.";
14920120Snate  else if (mode & MODE_AUTO)
15010528Samurai    mes = "Working in auto mode.";
1516059Samurai  else if (mode & MODE_DIRECT)
15210528Samurai    mes = "Working in direct mode.";
1536059Samurai  else if (mode & MODE_DEDICATED)
15410528Samurai    mes = "Working in dedicated mode.";
1556059Samurai  if (mes) {
15630913Sbrian    if (Display && VarTerm)
15726516Sbrian      fprintf(VarTerm, "%s\n", mes);
15826516Sbrian    return 0;
1596059Samurai  }
16026516Sbrian  return 1;
1616059Samurai}
1626059Samurai
1636059Samuraistatic int
16431343SbrianDialCommand(struct cmdargs const *arg)
1656059Samurai{
16611336Samurai  int tries;
16726858Sbrian  int res;
16811336Samurai
1696059Samurai  if (LcpFsm.state > ST_CLOSED) {
17026516Sbrian    if (VarTerm)
17126516Sbrian      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
17226516Sbrian    return 0;
1736059Samurai  }
17426516Sbrian
17531343Sbrian  if (arg->argc > 0 && (res = LoadCommand(arg)) != 0)
17631140Sbrian    return res;
17731121Sbrian
17811336Samurai  tries = 0;
17911336Samurai  do {
18026516Sbrian    if (VarTerm)
18126516Sbrian      fprintf(VarTerm, "Dial attempt %u of %d\n", ++tries, VarDialTries);
18231034Sbrian    if (OpenModem() < 0) {
18326516Sbrian      if (VarTerm)
18428679Sbrian	fprintf(VarTerm, "Failed to open modem.\n");
18511336Samurai      break;
18611336Samurai    }
18726858Sbrian    if ((res = DialModem()) == EX_DONE) {
18830697Sbrian      nointr_sleep(1);
18931343Sbrian      ModemTimeout(NULL);
19011336Samurai      PacketMode();
19111336Samurai      break;
19226858Sbrian    } else if (res == EX_SIG)
19326858Sbrian      return 1;
19411336Samurai  } while (VarDialTries == 0 || tries < VarDialTries);
19526516Sbrian
19626516Sbrian  return 0;
1976059Samurai}
1986059Samurai
19910528Samuraistatic int
20031343SbrianSetLoopback(struct cmdargs const *arg)
20128536Sbrian{
20231343Sbrian  if (arg->argc == 1)
20331343Sbrian    if (!strcasecmp(*arg->argv, "on")) {
20428536Sbrian      VarLoopback = 1;
20531141Sbrian      return 0;
20631141Sbrian    }
20731343Sbrian    else if (!strcasecmp(*arg->argv, "off")) {
20828536Sbrian      VarLoopback = 0;
20931141Sbrian      return 0;
21031141Sbrian    }
21128536Sbrian  return -1;
21228536Sbrian}
21328536Sbrian
21428536Sbrianstatic int
21531343SbrianShellCommand(struct cmdargs const *arg, int bg)
21610528Samurai{
21710528Samurai  const char *shell;
21810528Samurai  pid_t shpid;
21931343Sbrian  int argc;
22031343Sbrian  char *argv[MAXARGS];
22120813Sjkh
22218856Ssos#ifdef SHELL_ONLY_INTERACTIVELY
22326911Sbrian  /* we're only allowed to shell when we run ppp interactively */
22426516Sbrian  if (mode != MODE_INTER) {
22526516Sbrian    LogPrintf(LogWARN, "Can only start a shell in interactive mode\n");
22626516Sbrian    return 1;
22710528Samurai  }
22826911Sbrian#endif
22926911Sbrian#ifdef NO_SHELL_IN_AUTO_INTERACTIVE
23028679Sbrian
23126911Sbrian  /*
23228679Sbrian   * we want to stop shell commands when we've got a telnet connection to an
23328679Sbrian   * auto mode ppp
23426911Sbrian   */
23531121Sbrian  if (VarTerm && !(mode & MODE_INTER)) {
23628679Sbrian    LogPrintf(LogWARN, "Shell is not allowed interactively in auto mode\n");
23726516Sbrian    return 1;
23826516Sbrian  }
23926516Sbrian#endif
24026516Sbrian
24131343Sbrian  if (arg->argc == 0)
24228381Sbrian    if (!(mode & MODE_INTER)) {
24331121Sbrian      if (VarTerm)
24431121Sbrian        LogPrintf(LogWARN, "Can't start an interactive shell from"
24531121Sbrian		  " a telnet session\n");
24631121Sbrian      else
24731121Sbrian        LogPrintf(LogWARN, "Can only start an interactive shell in"
24831121Sbrian		  " interactive mode\n");
24928381Sbrian      return 1;
25028381Sbrian    } else if (bg) {
25128381Sbrian      LogPrintf(LogWARN, "Can only start an interactive shell in"
25228679Sbrian		" the foreground mode\n");
25328381Sbrian      return 1;
25428381Sbrian    }
25528679Sbrian  if ((shell = getenv("SHELL")) == 0)
25626516Sbrian    shell = _PATH_BSHELL;
25726516Sbrian
25828679Sbrian  if ((shpid = fork()) == 0) {
25928679Sbrian    int dtablesize, i, fd;
26018531Sbde
26132017Sbrian    TermTimerService();
26232017Sbrian    signal(SIGINT, SIG_DFL);
26332017Sbrian    signal(SIGQUIT, SIG_DFL);
26432017Sbrian    signal(SIGTERM, SIG_DFL);
26532017Sbrian    signal(SIGHUP, SIG_DFL);
26632017Sbrian    signal(SIGALRM, SIG_DFL);
26732017Sbrian
26828679Sbrian    if (VarTerm)
26928679Sbrian      fd = fileno(VarTerm);
27028679Sbrian    else if ((fd = open("/dev/null", O_RDWR)) == -1) {
27128679Sbrian      LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno));
27228679Sbrian      exit(1);
27328679Sbrian    }
27428679Sbrian    for (i = 0; i < 3; i++)
27528679Sbrian      dup2(fd, i);
27626516Sbrian
27728679Sbrian    for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++)
27831343Sbrian      close(i);
27926516Sbrian
28028679Sbrian    TtyOldMode();
28131061Sbrian    setuid(geteuid());
28231343Sbrian    if (arg->argc > 0) {
28328679Sbrian      /* substitute pseudo args */
28431343Sbrian      argv[0] = strdup(arg->argv[0]);
28531343Sbrian      for (argc = 1; argc < arg->argc; argc++) {
28631343Sbrian	if (strcasecmp(arg->argv[argc], "HISADDR") == 0)
28731343Sbrian	  argv[argc] = strdup(inet_ntoa(IpcpInfo.his_ipaddr));
28831343Sbrian	else if (strcasecmp(arg->argv[argc], "INTERFACE") == 0)
28931343Sbrian	  argv[argc] = strdup(IfDevName);
29031343Sbrian	else if (strcasecmp(arg->argv[argc], "MYADDR") == 0)
29131343Sbrian	  argv[argc] = strdup(inet_ntoa(IpcpInfo.want_ipaddr));
29231343Sbrian        else
29331343Sbrian          argv[argc] = strdup(arg->argv[argc]);
29431343Sbrian      }
29531343Sbrian      argv[argc] = NULL;
29628679Sbrian      if (bg) {
29728679Sbrian	pid_t p;
29810528Samurai
29928679Sbrian	p = getpid();
30028679Sbrian	if (daemon(1, 1) == -1) {
30128974Sbrian	  LogPrintf(LogERROR, "%d: daemon: %s\n", p, strerror(errno));
30228679Sbrian	  exit(1);
30328679Sbrian	}
30431125Sbrian      } else if (VarTerm)
30532017Sbrian        printf("ppp: Pausing until %s finishes\n", arg->argv[0]);
30631343Sbrian      execvp(argv[0], argv);
30730316Sbrian    } else {
30830316Sbrian      if (VarTerm)
30932017Sbrian        printf("ppp: Pausing until %s finishes\n", shell);
31031343Sbrian      execl(shell, shell, NULL);
31130316Sbrian    }
31220813Sjkh
31332017Sbrian    LogPrintf(LogWARN, "exec() of %s failed\n",
31432017Sbrian              arg->argc > 0 ? arg->argv[0] : shell);
31528679Sbrian    exit(255);
31610528Samurai  }
31728679Sbrian  if (shpid == (pid_t) - 1) {
31826516Sbrian    LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno));
31910528Samurai  } else {
32010528Samurai    int status;
32128679Sbrian
32231343Sbrian    waitpid(shpid, &status, 0);
32310528Samurai  }
32420813Sjkh
32532017Sbrian  TtyCommandMode(0);
32620813Sjkh
32728679Sbrian  return (0);
32810528Samurai}
32910528Samurai
33031343Sbrianstatic int
33131343SbrianBgShellCommand(struct cmdargs const *arg)
33231343Sbrian{
33331343Sbrian  if (arg->argc == 0)
33431343Sbrian    return -1;
33531343Sbrian  return ShellCommand(arg, 1);
33631343Sbrian}
33731343Sbrian
33831343Sbrianstatic int
33931343SbrianFgShellCommand(struct cmdargs const *arg)
34031343Sbrian{
34131343Sbrian  return ShellCommand(arg, 0);
34231343Sbrian}
34331343Sbrian
34430715Sbrianstatic struct cmdtab const Commands[] = {
34528679Sbrian  {"accept", NULL, AcceptCommand, LOCAL_AUTH,
34628679Sbrian  "accept option request", "accept option .."},
34728679Sbrian  {"add", NULL, AddCommand, LOCAL_AUTH,
34832109Sbrian  "add route", "add dest mask gateway", NULL},
34932109Sbrian  {"add!", NULL, AddCommand, LOCAL_AUTH,
35032109Sbrian  "add or change route", "add! dest mask gateway", (void *)1},
35131121Sbrian  {"allow", "auth", AllowCommand, LOCAL_AUTH,
35231121Sbrian  "Allow ppp access", "allow users|modes ...."},
35328679Sbrian  {"bg", "!bg", BgShellCommand, LOCAL_AUTH,
35431372Sbrian  "Run a background command", "[!]bg command"},
35528679Sbrian  {"close", NULL, CloseCommand, LOCAL_AUTH,
35628679Sbrian  "Close connection", "close"},
35728679Sbrian  {"delete", NULL, DeleteCommand, LOCAL_AUTH,
35832109Sbrian  "delete route", "delete dest", NULL},
35932109Sbrian  {"delete!", NULL, DeleteCommand, LOCAL_AUTH,
36032109Sbrian  "delete a route if it exists", "delete! dest", (void *)1},
36128679Sbrian  {"deny", NULL, DenyCommand, LOCAL_AUTH,
36228679Sbrian  "Deny option request", "deny option .."},
36328679Sbrian  {"dial", "call", DialCommand, LOCAL_AUTH,
36428679Sbrian  "Dial and login", "dial|call [remote]"},
36528679Sbrian  {"disable", NULL, DisableCommand, LOCAL_AUTH,
36628679Sbrian  "Disable option", "disable option .."},
36728679Sbrian  {"display", NULL, DisplayCommand, LOCAL_AUTH,
36828679Sbrian  "Display option configs", "display"},
36928679Sbrian  {"enable", NULL, EnableCommand, LOCAL_AUTH,
37028679Sbrian  "Enable option", "enable option .."},
37128679Sbrian  {"passwd", NULL, LocalAuthCommand, LOCAL_NO_AUTH,
37229083Sbrian  "Password for manipulation", "passwd LocalPassword"},
37328679Sbrian  {"load", NULL, LoadCommand, LOCAL_AUTH,
37428679Sbrian  "Load settings", "load [remote]"},
37528679Sbrian  {"save", NULL, SaveCommand, LOCAL_AUTH,
37628679Sbrian  "Save settings", "save"},
37728679Sbrian  {"set", "setup", SetCommand, LOCAL_AUTH,
37828679Sbrian  "Set parameters", "set[up] var value"},
37928679Sbrian  {"shell", "!", FgShellCommand, LOCAL_AUTH,
38028679Sbrian  "Run a subshell", "shell|! [sh command]"},
38128679Sbrian  {"show", NULL, ShowCommand, LOCAL_AUTH,
38231372Sbrian  "Show status and stats", "show var"},
38328679Sbrian  {"term", NULL, TerminalCommand, LOCAL_AUTH,
38431372Sbrian  "Enter terminal mode", "term"},
38531343Sbrian#ifndef NOALIAS
38628679Sbrian  {"alias", NULL, AliasCommand, LOCAL_AUTH,
38728679Sbrian  "alias control", "alias option [yes|no]"},
38831343Sbrian#endif
38928679Sbrian  {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
39028679Sbrian  "Quit PPP program", "quit|bye [all]"},
39128679Sbrian  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
39231343Sbrian  "Display this message", "help|? [command]", Commands},
39328679Sbrian  {NULL, "down", DownCommand, LOCAL_AUTH,
39428679Sbrian  "Generate down event", "down"},
39528679Sbrian  {NULL, NULL, NULL},
3966059Samurai};
3976059Samurai
39828536Sbrianstatic int
39931343SbrianShowLoopback(struct cmdargs const *arg)
40028536Sbrian{
40128536Sbrian  if (VarTerm)
40228536Sbrian    fprintf(VarTerm, "Local loopback is %s\n", VarLoopback ? "on" : "off");
40328536Sbrian
40428536Sbrian  return 0;
40528536Sbrian}
40628536Sbrian
40728679Sbrianstatic int
40831343SbrianShowLogLevel(struct cmdargs const *arg)
4096059Samurai{
4106059Samurai  int i;
4116059Samurai
41226516Sbrian  if (!VarTerm)
41326516Sbrian    return 0;
41430913Sbrian
41530913Sbrian  fprintf(VarTerm, "Log:  ");
41630913Sbrian  for (i = LogMIN; i <= LogMAX; i++)
41730913Sbrian    if (LogIsKept(i) & LOG_KEPT_SYSLOG)
41826516Sbrian      fprintf(VarTerm, " %s", LogName(i));
41930913Sbrian
42030913Sbrian  fprintf(VarTerm, "\nLocal:");
42130913Sbrian  for (i = LogMIN; i <= LogMAX; i++)
42230913Sbrian    if (LogIsKept(i) & LOG_KEPT_LOCAL)
42330913Sbrian      fprintf(VarTerm, " %s", LogName(i));
42430913Sbrian
42526516Sbrian  fprintf(VarTerm, "\n");
42626516Sbrian
42726516Sbrian  return 0;
4286059Samurai}
4296059Samurai
43028679Sbrianstatic int
43131343SbrianShowEscape(struct cmdargs const *arg)
4326059Samurai{
4336059Samurai  int code, bit;
4346059Samurai
43526516Sbrian  if (!VarTerm)
43626516Sbrian    return 0;
4376059Samurai  if (EscMap[32]) {
43826516Sbrian    for (code = 0; code < 32; code++)
43926516Sbrian      if (EscMap[code])
44028679Sbrian	for (bit = 0; bit < 8; bit++)
44128679Sbrian	  if (EscMap[code] & (1 << bit))
44228679Sbrian	    fprintf(VarTerm, " 0x%02x", (code << 3) + bit);
44326516Sbrian    fprintf(VarTerm, "\n");
4446059Samurai  }
44531077Sbrian  return 0;
4466059Samurai}
4476059Samurai
44828679Sbrianstatic int
44931343SbrianShowTimeout(struct cmdargs const *arg)
4506059Samurai{
45132102Sbrian  if (VarTerm) {
45232102Sbrian    int remaining;
45332102Sbrian
45431077Sbrian    fprintf(VarTerm, " Idle Timer: %d secs   LQR Timer: %d secs"
45531077Sbrian	    "   Retry Timer: %d secs\n", VarIdleTimeout, VarLqrTimeout,
45631077Sbrian	    VarRetryTimeout);
45732102Sbrian    remaining = RemainingIdleTime();
45832102Sbrian    if (remaining != -1)
45932102Sbrian    fprintf(VarTerm, " %d secs remaining\n", remaining);
46032102Sbrian  }
46131077Sbrian  return 0;
4626059Samurai}
4636059Samurai
46428679Sbrianstatic int
46531343SbrianShowStopped(struct cmdargs const *arg)
46628327Sbrian{
46728327Sbrian  if (!VarTerm)
46828327Sbrian    return 0;
46928461Sbrian
47028461Sbrian  fprintf(VarTerm, " Stopped Timer:  LCP: ");
47128461Sbrian  if (!LcpFsm.StoppedTimer.load)
47228461Sbrian    fprintf(VarTerm, "Disabled");
47328327Sbrian  else
47428461Sbrian    fprintf(VarTerm, "%ld secs", LcpFsm.StoppedTimer.load / SECTICKS);
47528461Sbrian
47628461Sbrian  fprintf(VarTerm, ", IPCP: ");
47728461Sbrian  if (!IpcpFsm.StoppedTimer.load)
47828461Sbrian    fprintf(VarTerm, "Disabled");
47928461Sbrian  else
48028461Sbrian    fprintf(VarTerm, "%ld secs", IpcpFsm.StoppedTimer.load / SECTICKS);
48128461Sbrian
48228461Sbrian  fprintf(VarTerm, ", CCP: ");
48328461Sbrian  if (!CcpFsm.StoppedTimer.load)
48428461Sbrian    fprintf(VarTerm, "Disabled");
48528461Sbrian  else
48628461Sbrian    fprintf(VarTerm, "%ld secs", CcpFsm.StoppedTimer.load / SECTICKS);
48728461Sbrian
48828461Sbrian  fprintf(VarTerm, "\n");
48928461Sbrian
49031077Sbrian  return 0;
49128327Sbrian}
49228327Sbrian
49328679Sbrianstatic int
49431343SbrianShowAuthKey(struct cmdargs const *arg)
4956059Samurai{
49626516Sbrian  if (!VarTerm)
49726516Sbrian    return 0;
49826516Sbrian  fprintf(VarTerm, "AuthName = %s\n", VarAuthName);
49931822Sbrian  fprintf(VarTerm, "AuthKey  = %s\n", HIDDEN);
50029840Sbrian#ifdef HAVE_DES
50129840Sbrian  fprintf(VarTerm, "Encrypt  = %s\n", VarMSChap ? "MSChap" : "MD5" );
50229840Sbrian#endif
50331077Sbrian  return 0;
5046059Samurai}
5056059Samurai
50628679Sbrianstatic int
50731343SbrianShowVersion(struct cmdargs const *arg)
5086059Samurai{
50931077Sbrian  if (VarTerm)
51031077Sbrian    fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
51131077Sbrian  return 0;
5126059Samurai}
5136059Samurai
51428679Sbrianstatic int
51531343SbrianShowInitialMRU(struct cmdargs const *arg)
51626326Sbrian{
51731077Sbrian  if (VarTerm)
51831077Sbrian    fprintf(VarTerm, " Initial MRU: %ld\n", VarMRU);
51931077Sbrian  return 0;
52026326Sbrian}
52126326Sbrian
52228679Sbrianstatic int
52331343SbrianShowPreferredMTU(struct cmdargs const *arg)
52426326Sbrian{
52531077Sbrian  if (VarTerm)
52631077Sbrian    if (VarPrefMTU)
52731077Sbrian      fprintf(VarTerm, " Preferred MTU: %ld\n", VarPrefMTU);
52831077Sbrian    else
52931077Sbrian      fprintf(VarTerm, " Preferred MTU: unspecified\n");
53031077Sbrian  return 0;
53126326Sbrian}
53226326Sbrian
53328679Sbrianstatic int
53431343SbrianShowReconnect(struct cmdargs const *arg)
53525067Sbrian{
53631077Sbrian  if (VarTerm)
53731077Sbrian    fprintf(VarTerm, " Reconnect Timer:  %d,  %d tries\n",
53831077Sbrian	    VarReconnectTimer, VarReconnectTries);
53931077Sbrian  return 0;
54025067Sbrian}
54125067Sbrian
54228679Sbrianstatic int
54331343SbrianShowRedial(struct cmdargs const *arg)
54411336Samurai{
54526516Sbrian  if (!VarTerm)
54626516Sbrian    return 0;
54726516Sbrian  fprintf(VarTerm, " Redial Timer: ");
54811336Samurai
54911336Samurai  if (VarRedialTimeout >= 0) {
55026516Sbrian    fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
55128679Sbrian  } else {
55226516Sbrian    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
55311336Samurai  }
55411336Samurai
55526516Sbrian  fprintf(VarTerm, " Redial Next Timer: ");
55624939Sbrian
55724939Sbrian  if (VarRedialNextTimeout >= 0) {
55826516Sbrian    fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
55928679Sbrian  } else {
56026516Sbrian    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
56124939Sbrian  }
56224939Sbrian
56311336Samurai  if (VarDialTries)
56428679Sbrian    fprintf(VarTerm, "%d dial tries", VarDialTries);
56511336Samurai
56626516Sbrian  fprintf(VarTerm, "\n");
56711336Samurai
56831077Sbrian  return 0;
56911336Samurai}
57011336Samurai
57126516Sbrian#ifndef NOMSEXT
57228679Sbrianstatic int
57331343SbrianShowMSExt(struct cmdargs const *arg)
57418752Sjkh{
57531077Sbrian  if (VarTerm) {
57631077Sbrian    fprintf(VarTerm, " MS PPP extention values \n");
57731077Sbrian    fprintf(VarTerm, "   Primary NS     : %s\n", inet_ntoa(ns_entries[0]));
57831077Sbrian    fprintf(VarTerm, "   Secondary NS   : %s\n", inet_ntoa(ns_entries[1]));
57931077Sbrian    fprintf(VarTerm, "   Primary NBNS   : %s\n", inet_ntoa(nbns_entries[0]));
58031077Sbrian    fprintf(VarTerm, "   Secondary NBNS : %s\n", inet_ntoa(nbns_entries[1]));
58131077Sbrian  }
58231077Sbrian  return 0;
58318752Sjkh}
58428679Sbrian
58526516Sbrian#endif
58618752Sjkh
58730715Sbrianstatic struct cmdtab const ShowCommands[] = {
58828679Sbrian  {"afilter", NULL, ShowAfilter, LOCAL_AUTH,
58931372Sbrian  "Show keep-alive filters", "show afilter option .."},
59028679Sbrian  {"auth", NULL, ShowAuthKey, LOCAL_AUTH,
59131372Sbrian  "Show auth details", "show auth"},
59228679Sbrian  {"ccp", NULL, ReportCcpStatus, LOCAL_AUTH,
59328679Sbrian  "Show CCP status", "show cpp"},
59428679Sbrian  {"compress", NULL, ReportCompress, LOCAL_AUTH,
59531372Sbrian  "Show compression stats", "show compress"},
59628679Sbrian  {"dfilter", NULL, ShowDfilter, LOCAL_AUTH,
59728679Sbrian  "Show Demand filters", "show dfilteroption .."},
59828679Sbrian  {"escape", NULL, ShowEscape, LOCAL_AUTH,
59928679Sbrian  "Show escape characters", "show escape"},
60028679Sbrian  {"hdlc", NULL, ReportHdlcStatus, LOCAL_AUTH,
60131372Sbrian  "Show HDLC errors", "show hdlc"},
60228679Sbrian  {"ifilter", NULL, ShowIfilter, LOCAL_AUTH,
60328679Sbrian  "Show Input filters", "show ifilter option .."},
60428679Sbrian  {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH,
60528679Sbrian  "Show IPCP status", "show ipcp"},
60628679Sbrian  {"lcp", NULL, ReportLcpStatus, LOCAL_AUTH,
60728679Sbrian  "Show LCP status", "show lcp"},
60828679Sbrian  {"loopback", NULL, ShowLoopback, LOCAL_AUTH,
60931372Sbrian  "Show loopback setting", "show loopback"},
61028679Sbrian  {"log", NULL, ShowLogLevel, LOCAL_AUTH,
61131372Sbrian  "Show log levels", "show log"},
61228679Sbrian  {"mem", NULL, ShowMemMap, LOCAL_AUTH,
61328679Sbrian  "Show memory map", "show mem"},
61428679Sbrian  {"modem", NULL, ShowModemStatus, LOCAL_AUTH,
61528679Sbrian  "Show modem setups", "show modem"},
61628679Sbrian  {"mru", NULL, ShowInitialMRU, LOCAL_AUTH,
61728679Sbrian  "Show Initial MRU", "show mru"},
61828679Sbrian  {"mtu", NULL, ShowPreferredMTU, LOCAL_AUTH,
61928679Sbrian  "Show Preferred MTU", "show mtu"},
62028679Sbrian  {"ofilter", NULL, ShowOfilter, LOCAL_AUTH,
62128679Sbrian  "Show Output filters", "show ofilter option .."},
62228679Sbrian  {"proto", NULL, ReportProtStatus, LOCAL_AUTH,
62328679Sbrian  "Show protocol summary", "show proto"},
62428679Sbrian  {"reconnect", NULL, ShowReconnect, LOCAL_AUTH,
62531372Sbrian  "Show reconnect timer", "show reconnect"},
62628679Sbrian  {"redial", NULL, ShowRedial, LOCAL_AUTH,
62731372Sbrian  "Show Redial timeout", "show redial"},
62828679Sbrian  {"route", NULL, ShowRoute, LOCAL_AUTH,
62928679Sbrian  "Show routing table", "show route"},
63028679Sbrian  {"timeout", NULL, ShowTimeout, LOCAL_AUTH,
63131372Sbrian  "Show Idle timeout", "show timeout"},
63228679Sbrian  {"stopped", NULL, ShowStopped, LOCAL_AUTH,
63331372Sbrian  "Show STOPPED timeout", "show stopped"},
63426516Sbrian#ifndef NOMSEXT
63528679Sbrian  {"msext", NULL, ShowMSExt, LOCAL_AUTH,
63628679Sbrian  "Show MS PPP extentions", "show msext"},
63726516Sbrian#endif
63828679Sbrian  {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
63928679Sbrian  "Show version string", "show version"},
64028679Sbrian  {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
64131343Sbrian  "Display this message", "show help|? [command]", ShowCommands},
64228679Sbrian  {NULL, NULL, NULL},
6436059Samurai};
6446059Samurai
64530715Sbrianstatic struct cmdtab const *
64631343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch)
6476059Samurai{
64826516Sbrian  int nmatch;
64926516Sbrian  int len;
65028679Sbrian  struct cmdtab const *found;
6516059Samurai
65226516Sbrian  found = NULL;
65326516Sbrian  len = strlen(str);
65426516Sbrian  nmatch = 0;
6556059Samurai  while (cmds->func) {
65625566Sbrian    if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
65726516Sbrian      if (cmds->name[len] == '\0') {
65828679Sbrian	*pmatch = 1;
65928679Sbrian	return cmds;
66026516Sbrian      }
6616059Samurai      nmatch++;
6626059Samurai      found = cmds;
66328679Sbrian    } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
66426516Sbrian      if (cmds->alias[len] == '\0') {
66528679Sbrian	*pmatch = 1;
66628679Sbrian	return cmds;
66726516Sbrian      }
6686059Samurai      nmatch++;
6696059Samurai      found = cmds;
6706059Samurai    }
6716059Samurai    cmds++;
6726059Samurai  }
6736059Samurai  *pmatch = nmatch;
67426516Sbrian  return found;
6756059Samurai}
6766059Samurai
67730715Sbrianstatic int
67831822SbrianFindExec(struct cmdtab const *cmds, int argc, char const *const *argv,
67931822Sbrian         const char *prefix)
6806059Samurai{
68128679Sbrian  struct cmdtab const *cmd;
6826059Samurai  int val = 1;
6836059Samurai  int nmatch;
68431343Sbrian  struct cmdargs arg;
6856059Samurai
68631343Sbrian  cmd = FindCommand(cmds, *argv, &nmatch);
6876059Samurai  if (nmatch > 1)
68831822Sbrian    LogPrintf(LogWARN, "%s%s: Ambiguous command\n", prefix, *argv);
68931343Sbrian  else if (cmd && (cmd->lauth & VarLocalAuth)) {
69031372Sbrian    arg.cmd = cmds;
69131343Sbrian    arg.argc = argc-1;
69231343Sbrian    arg.argv = argv+1;
69331343Sbrian    arg.data = cmd->args;
69431343Sbrian    val = (cmd->func) (&arg);
69531343Sbrian  } else
69631822Sbrian    LogPrintf(LogWARN, "%s%s: Invalid command\n", prefix, *argv);
69726516Sbrian
69826516Sbrian  if (val == -1)
69926516Sbrian    LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
70028679Sbrian  else if (val)
70131822Sbrian    LogPrintf(LogWARN, "%s%s: Failed %d\n", prefix, *argv, val);
70226516Sbrian
70326516Sbrian  return val;
7046059Samurai}
7056059Samurai
70618885Sjkhint aft_cmd = 1;
70718885Sjkh
7086059Samuraivoid
70918885SjkhPrompt()
7106059Samurai{
71131343Sbrian  const char *pconnect, *pauth;
7126735Samurai
71331121Sbrian  if (!VarTerm || TermMode)
7146059Samurai    return;
7156735Samurai
71618885Sjkh  if (!aft_cmd)
71726516Sbrian    fprintf(VarTerm, "\n");
71818885Sjkh  else
71918885Sjkh    aft_cmd = 0;
7206735Samurai
72128679Sbrian  if (VarLocalAuth == LOCAL_AUTH)
7226735Samurai    pauth = " ON ";
7236735Samurai  else
7246735Samurai    pauth = " on ";
7256059Samurai  if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
7266735Samurai    pconnect = "PPP";
7276059Samurai  else
7286735Samurai    pconnect = "ppp";
72926516Sbrian  fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
73026516Sbrian  fflush(VarTerm);
7316059Samurai}
7326059Samurai
7336059Samuraivoid
73431121SbrianInterpretCommand(char *buff, int nb, int *argc, char ***argv)
7356059Samurai{
73631343Sbrian  static char *vector[MAXARGS];
7376059Samurai  char *cp;
7386059Samurai
7396059Samurai  if (nb > 0) {
7406059Samurai    cp = buff + strcspn(buff, "\r\n");
7416059Samurai    if (cp)
7426059Samurai      *cp = '\0';
74331121Sbrian    *argc = MakeArgs(buff, vector, VECSIZE(vector));
74431121Sbrian    *argv = vector;
74531121Sbrian  } else
74631121Sbrian    *argc = 0;
74731121Sbrian}
7486059Samurai
74931822Sbrianstatic int
75031822Sbrianarghidden(int argc, char const *const *argv, int n)
75131822Sbrian{
75231822Sbrian  /* Is arg n of the given command to be hidden from the log ? */
75331828Sbrian
75431828Sbrian  /* set authkey xxxxx */
75531828Sbrian  /* set key xxxxx */
75631822Sbrian  if (n == 2 && !strncasecmp(argv[0], "se", 2) &&
75731822Sbrian      (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2)))
75831822Sbrian    return 1;
75931822Sbrian
76031828Sbrian  /* passwd xxxxx */
76131828Sbrian  if (n == 1 && !strncasecmp(argv[0], "p", 1))
76231828Sbrian    return 1;
76331828Sbrian
76431822Sbrian  return 0;
76531822Sbrian}
76631822Sbrian
76731121Sbrianvoid
76831343SbrianRunCommand(int argc, char const *const *argv, const char *label)
76931121Sbrian{
77031156Sbrian  if (argc > 0) {
77131156Sbrian    if (LogIsKept(LogCOMMAND)) {
77231156Sbrian      static char buf[LINE_LEN];
77331156Sbrian      int f, n;
77431156Sbrian
77531156Sbrian      *buf = '\0';
77631156Sbrian      if (label) {
77731962Sbrian        strncpy(buf, label, sizeof buf - 3);
77831962Sbrian        buf[sizeof buf - 3] = '\0';
77931156Sbrian        strcat(buf, ": ");
78031156Sbrian      }
78131156Sbrian      n = strlen(buf);
78231156Sbrian      for (f = 0; f < argc; f++) {
78331962Sbrian        if (n < sizeof buf - 1 && f)
78431156Sbrian          buf[n++] = ' ';
78531822Sbrian        if (arghidden(argc, argv, f))
78631962Sbrian          strncpy(buf+n, HIDDEN, sizeof buf - n - 1);
78731822Sbrian        else
78831962Sbrian          strncpy(buf+n, argv[f], sizeof buf - n - 1);
78931156Sbrian        n += strlen(buf+n);
79031156Sbrian      }
79131156Sbrian      LogPrintf(LogCOMMAND, "%s\n", buf);
79231156Sbrian    }
79331822Sbrian    FindExec(Commands, argc, argv, "");
79431156Sbrian  }
7956059Samurai}
7966059Samurai
79731121Sbrianvoid
79831156SbrianDecodeCommand(char *buff, int nb, const char *label)
79931121Sbrian{
80031121Sbrian  int argc;
80131121Sbrian  char **argv;
80231121Sbrian
80331121Sbrian  InterpretCommand(buff, nb, &argc, &argv);
80431343Sbrian  RunCommand(argc, (char const *const *)argv, label);
80531121Sbrian}
80631121Sbrian
8076059Samuraistatic int
80831343SbrianShowCommand(struct cmdargs const *arg)
8096059Samurai{
81031343Sbrian  if (arg->argc > 0)
81131822Sbrian    FindExec(ShowCommands, arg->argc, arg->argv, "show ");
81226516Sbrian  else if (VarTerm)
81331343Sbrian    fprintf(VarTerm, "Use ``show ?'' to get a arg->cmd.\n");
8146059Samurai  else
81526516Sbrian    LogPrintf(LogWARN, "show command must have arguments\n");
81626516Sbrian
81726516Sbrian  return 0;
8186059Samurai}
8196059Samurai
8206059Samuraistatic int
82131343SbrianTerminalCommand(struct cmdargs const *arg)
8226059Samurai{
8236059Samurai  if (LcpFsm.state > ST_CLOSED) {
82426516Sbrian    if (VarTerm)
82526516Sbrian      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
82626516Sbrian    return 1;
8276059Samurai  }
82830913Sbrian  if (!IsInteractive(1))
82928679Sbrian    return (1);
83031034Sbrian  if (OpenModem() < 0) {
83126516Sbrian    if (VarTerm)
83226516Sbrian      fprintf(VarTerm, "Failed to open modem.\n");
83328679Sbrian    return (1);
8346059Samurai  }
83526516Sbrian  if (VarTerm) {
83626516Sbrian    fprintf(VarTerm, "Enter to terminal mode.\n");
83726516Sbrian    fprintf(VarTerm, "Type `~?' for help.\n");
83826516Sbrian  }
8396059Samurai  TtyTermMode();
84028679Sbrian  return (0);
8416059Samurai}
8426059Samurai
8436059Samuraistatic int
84431343SbrianQuitCommand(struct cmdargs const *arg)
8456059Samurai{
84631203Sbrian  if (VarTerm) {
84732021Sbrian    DropClient(1);
84831203Sbrian    if (mode & MODE_INTER)
84931203Sbrian      Cleanup(EX_NORMAL);
85031343Sbrian    else if (arg->argc > 0 && !strcasecmp(*arg->argv, "all") && VarLocalAuth&LOCAL_AUTH)
85131203Sbrian      Cleanup(EX_NORMAL);
85231121Sbrian  }
85326516Sbrian
85426516Sbrian  return 0;
8556059Samurai}
8566059Samurai
8576059Samuraistatic int
85831343SbrianCloseCommand(struct cmdargs const *arg)
8596059Samurai{
86026098Sbrian  reconnect(RECON_FALSE);
8616059Samurai  LcpClose();
86226516Sbrian  return 0;
8636059Samurai}
8646059Samurai
8656059Samuraistatic int
86631343SbrianDownCommand(struct cmdargs const *arg)
8676059Samurai{
8686059Samurai  LcpDown();
86926516Sbrian  return 0;
8706059Samurai}
8716059Samurai
87225067Sbrianstatic int
87331343SbrianSetModemSpeed(struct cmdargs const *arg)
8746059Samurai{
8756059Samurai  int speed;
8766059Samurai
87731343Sbrian  if (arg->argc > 0) {
87831343Sbrian    if (strcasecmp(*arg->argv, "sync") == 0) {
8796735Samurai      VarSpeed = 0;
88026516Sbrian      return 0;
8816735Samurai    }
88231343Sbrian    speed = atoi(*arg->argv);
8836735Samurai    if (IntToSpeed(speed) != B0) {
8846735Samurai      VarSpeed = speed;
88526516Sbrian      return 0;
8866059Samurai    }
88731343Sbrian    LogPrintf(LogWARN, "%s: Invalid speed\n", *arg->argv);
8886059Samurai  }
88926516Sbrian  return -1;
8906059Samurai}
8916059Samurai
89225067Sbrianstatic int
89331343SbrianSetReconnect(struct cmdargs const *arg)
89411336Samurai{
89531343Sbrian  if (arg->argc == 2) {
89631343Sbrian    VarReconnectTimer = atoi(arg->argv[0]);
89731343Sbrian    VarReconnectTries = atoi(arg->argv[1]);
89826516Sbrian    return 0;
89926516Sbrian  }
90026516Sbrian  return -1;
90125067Sbrian}
90225067Sbrian
90325067Sbrianstatic int
90431343SbrianSetRedialTimeout(struct cmdargs const *arg)
90525067Sbrian{
90611336Samurai  int timeout;
90711336Samurai  int tries;
90824939Sbrian  char *dot;
90911336Samurai
91031343Sbrian  if (arg->argc == 1 || arg->argc == 2) {
91131343Sbrian    if (strncasecmp(arg->argv[0], "random", 6) == 0 &&
91231343Sbrian	(arg->argv[0][6] == '\0' || arg->argv[0][6] == '.')) {
91311336Samurai      VarRedialTimeout = -1;
91430715Sbrian      randinit();
91526516Sbrian    } else {
91631343Sbrian      timeout = atoi(arg->argv[0]);
91711336Samurai
91826516Sbrian      if (timeout >= 0)
91911336Samurai	VarRedialTimeout = timeout;
92011336Samurai      else {
92126516Sbrian	LogPrintf(LogWARN, "Invalid redial timeout\n");
92228679Sbrian	return -1;
92311336Samurai      }
92411336Samurai    }
92524939Sbrian
92631343Sbrian    dot = strchr(arg->argv[0], '.');
92724939Sbrian    if (dot) {
92824939Sbrian      if (strcasecmp(++dot, "random") == 0) {
92928679Sbrian	VarRedialNextTimeout = -1;
93030715Sbrian	randinit();
93128679Sbrian      } else {
93228679Sbrian	timeout = atoi(dot);
93328679Sbrian	if (timeout >= 0)
93428679Sbrian	  VarRedialNextTimeout = timeout;
93528679Sbrian	else {
93628679Sbrian	  LogPrintf(LogWARN, "Invalid next redial timeout\n");
93726516Sbrian	  return -1;
93828679Sbrian	}
93924939Sbrian      }
94028679Sbrian    } else
94128679Sbrian      VarRedialNextTimeout = NEXT_REDIAL_PERIOD;	/* Default next timeout */
94224939Sbrian
94331343Sbrian    if (arg->argc == 2) {
94431343Sbrian      tries = atoi(arg->argv[1]);
94511336Samurai
94611336Samurai      if (tries >= 0) {
94726516Sbrian	VarDialTries = tries;
94826516Sbrian      } else {
94926516Sbrian	LogPrintf(LogWARN, "Invalid retry value\n");
95026516Sbrian	return 1;
95111336Samurai      }
95211336Samurai    }
95326516Sbrian    return 0;
95411336Samurai  }
95526516Sbrian  return -1;
95611336Samurai}
95711336Samurai
95825067Sbrianstatic int
95931343SbrianSetStoppedTimeout(struct cmdargs const *arg)
96028327Sbrian{
96128461Sbrian  LcpFsm.StoppedTimer.load = 0;
96228461Sbrian  IpcpFsm.StoppedTimer.load = 0;
96328461Sbrian  CcpFsm.StoppedTimer.load = 0;
96431343Sbrian  if (arg->argc <= 3) {
96531343Sbrian    if (arg->argc > 0) {
96631343Sbrian      LcpFsm.StoppedTimer.load = atoi(arg->argv[0]) * SECTICKS;
96731343Sbrian      if (arg->argc > 1) {
96831343Sbrian	IpcpFsm.StoppedTimer.load = atoi(arg->argv[1]) * SECTICKS;
96931343Sbrian	if (arg->argc > 2)
97031343Sbrian	  CcpFsm.StoppedTimer.load = atoi(arg->argv[2]) * SECTICKS;
97128461Sbrian      }
97228461Sbrian    }
97328327Sbrian    return 0;
97428327Sbrian  }
97528327Sbrian  return -1;
97628327Sbrian}
97728327Sbrian
97831081Sbrian#define ismask(x) \
97931081Sbrian  (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3)
98031081Sbrian
98128327Sbrianstatic int
98231343SbrianSetServer(struct cmdargs const *arg)
98326940Sbrian{
98426940Sbrian  int res = -1;
98526940Sbrian
98631343Sbrian  if (arg->argc > 0 && arg->argc < 4) {
98731081Sbrian    const char *port, *passwd, *mask;
98831081Sbrian
98931081Sbrian    /* What's what ? */
99031343Sbrian    port = arg->argv[0];
99131343Sbrian    if (arg->argc == 2)
99231343Sbrian      if (ismask(arg->argv[1])) {
99331081Sbrian        passwd = NULL;
99431343Sbrian        mask = arg->argv[1];
99531081Sbrian      } else {
99631343Sbrian        passwd = arg->argv[1];
99731081Sbrian        mask = NULL;
99831081Sbrian      }
99931343Sbrian    else if (arg->argc == 3) {
100031343Sbrian      passwd = arg->argv[1];
100131343Sbrian      mask = arg->argv[2];
100231081Sbrian      if (!ismask(mask))
100331081Sbrian        return -1;
100431081Sbrian    } else
100531081Sbrian      passwd = mask = NULL;
100631081Sbrian
100731081Sbrian    if (passwd == NULL)
100831081Sbrian      VarHaveLocalAuthKey = 0;
100931081Sbrian    else {
101031962Sbrian      strncpy(VarLocalAuthKey, passwd, sizeof VarLocalAuthKey - 1);
101131081Sbrian      VarLocalAuthKey[sizeof VarLocalAuthKey - 1] = '\0';
101231081Sbrian      VarHaveLocalAuthKey = 1;
101331081Sbrian    }
101431081Sbrian    LocalAuthInit();
101531081Sbrian
101631081Sbrian    if (strcasecmp(port, "none") == 0) {
101731081Sbrian      int oserver;
101831081Sbrian
101931081Sbrian      if (mask != NULL || passwd != NULL)
102031081Sbrian        return -1;
102131081Sbrian      oserver = server;
102226940Sbrian      ServerClose();
102331081Sbrian      if (oserver != -1)
102431081Sbrian        LogPrintf(LogPHASE, "Disabling server port.\n");
102526940Sbrian      res = 0;
102631081Sbrian    } else if (*port == '/') {
102731081Sbrian      mode_t imask;
102828679Sbrian
102931081Sbrian      if (mask != NULL) {
103028679Sbrian	unsigned m;
103128679Sbrian
103231081Sbrian	if (sscanf(mask, "%o", &m) == 1)
103331081Sbrian	  imask = m;
103431081Sbrian        else
103531081Sbrian          return -1;
103631081Sbrian      } else
103731081Sbrian        imask = (mode_t)-1;
103831081Sbrian      res = ServerLocalOpen(port, imask);
103927346Sbrian    } else {
104031081Sbrian      int iport;
104128679Sbrian
104231081Sbrian      if (mask != NULL)
104331081Sbrian        return -1;
104428679Sbrian
104531081Sbrian      if (strspn(port, "0123456789") != strlen(port)) {
104631081Sbrian        struct servent *s;
104731081Sbrian
104831081Sbrian        if ((s = getservbyname(port, "tcp")) == NULL) {
104931081Sbrian	  iport = 0;
105031081Sbrian	  LogPrintf(LogWARN, "%s: Invalid port or service\n", port);
105128679Sbrian	} else
105231081Sbrian	  iport = ntohs(s->s_port);
105327346Sbrian      } else
105431081Sbrian        iport = atoi(port);
105531081Sbrian      res = iport ? ServerTcpOpen(iport) : -1;
105627346Sbrian    }
105731081Sbrian  }
105826940Sbrian
105926940Sbrian  return res;
106026940Sbrian}
106126940Sbrian
106226940Sbrianstatic int
106331343SbrianSetModemParity(struct cmdargs const *arg)
10646059Samurai{
106531343Sbrian  return arg->argc > 0 ? ChangeParity(*arg->argv) : -1;
10666059Samurai}
10676059Samurai
10686059Samuraistatic int
106931343SbrianSetLogLevel(struct cmdargs const *arg)
10706059Samurai{
107126516Sbrian  int i;
107226516Sbrian  int res;
107331343Sbrian  int argc;
107431343Sbrian  char const *const *argv, *argp;
107530913Sbrian  void (*Discard)(int), (*Keep)(int);
107630913Sbrian  void (*DiscardAll)(void);
10776059Samurai
107831343Sbrian  argc = arg->argc;
107931343Sbrian  argv = arg->argv;
108026516Sbrian  res = 0;
108131288Sbrian  if (argc == 0 || strcasecmp(argv[0], "local")) {
108230913Sbrian    Discard = LogDiscard;
108330913Sbrian    Keep = LogKeep;
108430913Sbrian    DiscardAll = LogDiscardAll;
108530913Sbrian  } else {
108630913Sbrian    argc--;
108730913Sbrian    argv++;
108830913Sbrian    Discard = LogDiscardLocal;
108930913Sbrian    Keep = LogKeepLocal;
109030913Sbrian    DiscardAll = LogDiscardAllLocal;
109130913Sbrian  }
109230913Sbrian
109326516Sbrian  if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-'))
109431343Sbrian    DiscardAll();
109526516Sbrian  while (argc--) {
109631343Sbrian    argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
109726516Sbrian    for (i = LogMIN; i <= LogMAX; i++)
109831343Sbrian      if (strcasecmp(argp, LogName(i)) == 0) {
109928679Sbrian	if (**argv == '-')
110030913Sbrian	  (*Discard)(i);
110128679Sbrian	else
110230913Sbrian	  (*Keep)(i);
11036059Samurai	break;
11046059Samurai      }
110526516Sbrian    if (i > LogMAX) {
110631343Sbrian      LogPrintf(LogWARN, "%s: Invalid log value\n", argp);
110726516Sbrian      res = -1;
11086059Samurai    }
110926516Sbrian    argv++;
11106059Samurai  }
111126516Sbrian  return res;
11126059Samurai}
11136059Samurai
11146059Samuraistatic int
111531343SbrianSetEscape(struct cmdargs const *arg)
11166059Samurai{
11176059Samurai  int code;
111831343Sbrian  int argc = arg->argc;
111931343Sbrian  char const *const *argv = arg->argv;
11206059Samurai
11216059Samurai  for (code = 0; code < 33; code++)
11226059Samurai    EscMap[code] = 0;
112331343Sbrian
11246059Samurai  while (argc-- > 0) {
11256059Samurai    sscanf(*argv++, "%x", &code);
11266059Samurai    code &= 0xff;
112728679Sbrian    EscMap[code >> 3] |= (1 << (code & 7));
11286059Samurai    EscMap[32] = 1;
11296059Samurai  }
113026516Sbrian  return 0;
11316059Samurai}
11326059Samurai
11336059Samuraistatic int
113431343SbrianSetInitialMRU(struct cmdargs const *arg)
11356059Samurai{
113626326Sbrian  long mru;
113731343Sbrian  const char *err;
11386059Samurai
113931343Sbrian  if (arg->argc > 0) {
114031343Sbrian    mru = atol(*arg->argv);
114126326Sbrian    if (mru < MIN_MRU)
114226516Sbrian      err = "Given MRU value (%ld) is too small.\n";
11436059Samurai    else if (mru > MAX_MRU)
114426516Sbrian      err = "Given MRU value (%ld) is too big.\n";
114526516Sbrian    else {
11466059Samurai      VarMRU = mru;
114726516Sbrian      return 0;
114826516Sbrian    }
114926516Sbrian    LogPrintf(LogWARN, err, mru);
115026516Sbrian  }
115126516Sbrian  return -1;
11526059Samurai}
11536059Samurai
11546059Samuraistatic int
115531343SbrianSetPreferredMTU(struct cmdargs const *arg)
115626326Sbrian{
115726326Sbrian  long mtu;
115831343Sbrian  const char *err;
115926326Sbrian
116031343Sbrian  if (arg->argc > 0) {
116131343Sbrian    mtu = atol(*arg->argv);
116226516Sbrian    if (mtu == 0) {
116326326Sbrian      VarPrefMTU = 0;
116426516Sbrian      return 0;
116526516Sbrian    } else if (mtu < MIN_MTU)
116626516Sbrian      err = "Given MTU value (%ld) is too small.\n";
116726326Sbrian    else if (mtu > MAX_MTU)
116826516Sbrian      err = "Given MTU value (%ld) is too big.\n";
116926516Sbrian    else {
117026326Sbrian      VarPrefMTU = mtu;
117126516Sbrian      return 0;
117226516Sbrian    }
117326516Sbrian    LogPrintf(LogWARN, err, mtu);
117426516Sbrian  }
117526516Sbrian  return -1;
117626326Sbrian}
117726326Sbrian
117826326Sbrianstatic int
117931343SbrianSetIdleTimeout(struct cmdargs const *arg)
11806059Samurai{
118131343Sbrian  if (arg->argc > 0) {
118231343Sbrian    VarIdleTimeout = atoi(arg->argv[0]);
118328679Sbrian    UpdateIdleTimer();		/* If we're connected, restart the idle timer */
118431343Sbrian    if (arg->argc > 1) {
118531343Sbrian      VarLqrTimeout = atoi(arg->argv[1]);
11866735Samurai      if (VarLqrTimeout < 1)
11876735Samurai	VarLqrTimeout = 30;
118831343Sbrian      if (arg->argc > 2) {
118931343Sbrian	VarRetryTimeout = atoi(arg->argv[2]);
11906735Samurai	if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
11916735Samurai	  VarRetryTimeout = 3;
11926735Samurai      }
11936735Samurai    }
119426516Sbrian    return 0;
11956059Samurai  }
119626516Sbrian  return -1;
11976059Samurai}
11986059Samurai
119930715Sbrianstatic struct in_addr
120031343SbrianGetIpAddr(const char *cp)
12016059Samurai{
12026059Samurai  struct hostent *hp;
12036059Samurai  struct in_addr ipaddr;
12046059Samurai
120532124Sbrian  if (inet_aton(cp, &ipaddr) == 0) {
120632124Sbrian    hp = gethostbyname(cp);
120732124Sbrian    if (hp && hp->h_addrtype == AF_INET)
120832124Sbrian      memcpy(&ipaddr, hp->h_addr, hp->h_length);
120932124Sbrian    else
121032124Sbrian      ipaddr.s_addr = 0;
121132124Sbrian  }
121228679Sbrian  return (ipaddr);
12136059Samurai}
12146059Samurai
12156059Samuraistatic int
121631343SbrianSetInterfaceAddr(struct cmdargs const *arg)
12176059Samurai{
121832267Sbrian  const char *hisaddr;
121932267Sbrian
122032267Sbrian  hisaddr = NULL;
122128394Sbrian  DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
12226059Samurai
122331343Sbrian  if (arg->argc > 4)
122428679Sbrian    return -1;
122526516Sbrian
122628394Sbrian  HaveTriggerAddress = 0;
122728394Sbrian  ifnetmask.s_addr = 0;
122831690Sbrian  iplist_reset(&DefHisChoice);
122928394Sbrian
123031343Sbrian  if (arg->argc > 0) {
123131690Sbrian    if (!ParseAddr(arg->argc, arg->argv, &DefMyAddress.ipaddr,
123231690Sbrian		   &DefMyAddress.mask, &DefMyAddress.width))
123328679Sbrian      return 1;
123431343Sbrian    if (arg->argc > 1) {
123532267Sbrian      hisaddr = arg->argv[1];
123631343Sbrian      if (arg->argc > 2) {
123731343Sbrian	ifnetmask = GetIpAddr(arg->argv[2]);
123831343Sbrian	if (arg->argc > 3) {
123931343Sbrian	  TriggerAddress = GetIpAddr(arg->argv[3]);
124028679Sbrian	  HaveTriggerAddress = 1;
12419440Samurai	}
12426059Samurai      }
12436059Samurai    }
12446059Samurai  }
124528394Sbrian
12466059Samurai  /*
12476059Samurai   * For backwards compatibility, 0.0.0.0 means any address.
12486059Samurai   */
12496059Samurai  if (DefMyAddress.ipaddr.s_addr == 0) {
12506059Samurai    DefMyAddress.mask.s_addr = 0;
12516059Samurai    DefMyAddress.width = 0;
12526059Samurai  }
125332267Sbrian  IpcpInfo.want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
12546059Samurai  if (DefHisAddress.ipaddr.s_addr == 0) {
12556059Samurai    DefHisAddress.mask.s_addr = 0;
12566059Samurai    DefHisAddress.width = 0;
12576059Samurai  }
125828537Sbrian
125932267Sbrian  if (hisaddr && !UseHisaddr(hisaddr, mode & MODE_AUTO))
126032267Sbrian    return 4;
126131121Sbrian
126226516Sbrian  return 0;
12636059Samurai}
12646059Samurai
126526516Sbrian#ifndef NOMSEXT
12666059Samurai
126730715Sbrianstatic void
126828679SbrianSetMSEXT(struct in_addr * pri_addr,
126928679Sbrian	 struct in_addr * sec_addr,
127028679Sbrian	 int argc,
127131343Sbrian	 char const *const *argv)
127218752Sjkh{
127318752Sjkh  int dummyint;
127418752Sjkh  struct in_addr dummyaddr;
127518752Sjkh
127618752Sjkh  pri_addr->s_addr = sec_addr->s_addr = 0L;
127718752Sjkh
127828679Sbrian  if (argc > 0) {
127918752Sjkh    ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
128028679Sbrian    if (--argc > 0)
128118752Sjkh      ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
128218752Sjkh    else
128318752Sjkh      sec_addr->s_addr = pri_addr->s_addr;
128418752Sjkh  }
128518752Sjkh
128628679Sbrian  /*
128728679Sbrian   * if the primary/secondary ns entries are 0.0.0.0 we should set them to
128828679Sbrian   * either the localhost's ip, or the values in /etc/resolv.conf ??
128928679Sbrian   *
129028679Sbrian   * up to you if you want to implement this...
129128679Sbrian   */
129218752Sjkh
129318752Sjkh}
129418752Sjkh
129518752Sjkhstatic int
129631343SbrianSetNS(struct cmdargs const *arg)
129718752Sjkh{
129831343Sbrian  SetMSEXT(&ns_entries[0], &ns_entries[1], arg->argc, arg->argv);
129926516Sbrian  return 0;
130018752Sjkh}
130118752Sjkh
130218752Sjkhstatic int
130331343SbrianSetNBNS(struct cmdargs const *arg)
130418752Sjkh{
130531343Sbrian  SetMSEXT(&nbns_entries[0], &nbns_entries[1], arg->argc, arg->argv);
130626516Sbrian  return 0;
130718752Sjkh}
130818752Sjkh
130928679Sbrian#endif				/* MS_EXT */
131018752Sjkh
131129696Sbrianint
131231343SbrianSetVariable(struct cmdargs const *arg)
13136059Samurai{
13146059Samurai  u_long map;
131531343Sbrian  const char *argp;
131631343Sbrian  int param = (int)arg->data;
13176059Samurai
131831343Sbrian  if (arg->argc > 0)
131931343Sbrian    argp = *arg->argv;
132026551Sbrian  else
132131343Sbrian    argp = "";
132226551Sbrian
132326551Sbrian  switch (param) {
132428679Sbrian  case VAR_AUTHKEY:
132531962Sbrian    strncpy(VarAuthKey, argp, sizeof VarAuthKey - 1);
132631962Sbrian    VarAuthKey[sizeof VarAuthKey - 1] = '\0';
132728679Sbrian    break;
132828679Sbrian  case VAR_AUTHNAME:
132931962Sbrian    strncpy(VarAuthName, argp, sizeof VarAuthName - 1);
133031962Sbrian    VarAuthName[sizeof VarAuthName - 1] = '\0';
133128679Sbrian    break;
133228679Sbrian  case VAR_DIAL:
133331962Sbrian    strncpy(VarDialScript, argp, sizeof VarDialScript - 1);
133431962Sbrian    VarDialScript[sizeof VarDialScript - 1] = '\0';
133528679Sbrian    break;
133628679Sbrian  case VAR_LOGIN:
133731962Sbrian    strncpy(VarLoginScript, argp, sizeof VarLoginScript - 1);
133831962Sbrian    VarLoginScript[sizeof VarLoginScript - 1] = '\0';
133928679Sbrian    break;
134028679Sbrian  case VAR_DEVICE:
134132129Sbrian    if (mode & MODE_INTER)
134232129Sbrian      HangupModem(0);
134329696Sbrian    if (modem != -1)
134429696Sbrian      LogPrintf(LogWARN, "Cannot change device to \"%s\" when \"%s\" is open\n",
134531343Sbrian                argp, VarDevice);
134629696Sbrian    else {
134731962Sbrian      strncpy(VarDeviceList, argp, sizeof VarDeviceList - 1);
134831962Sbrian      VarDeviceList[sizeof VarDeviceList - 1] = '\0';
134929696Sbrian    }
135028679Sbrian    break;
135128679Sbrian  case VAR_ACCMAP:
135231343Sbrian    sscanf(argp, "%lx", &map);
135328679Sbrian    VarAccmap = map;
135428679Sbrian    break;
135528679Sbrian  case VAR_PHONE:
135631962Sbrian    strncpy(VarPhoneList, argp, sizeof VarPhoneList - 1);
135731962Sbrian    VarPhoneList[sizeof VarPhoneList - 1] = '\0';
135831962Sbrian    strncpy(VarPhoneCopy, VarPhoneList, sizeof VarPhoneCopy - 1);
135931962Sbrian    VarPhoneCopy[sizeof VarPhoneCopy - 1] = '\0';
136028679Sbrian    VarNextPhone = VarPhoneCopy;
136131082Sbrian    VarAltPhone = NULL;
136228679Sbrian    break;
136328679Sbrian  case VAR_HANGUP:
136431962Sbrian    strncpy(VarHangupScript, argp, sizeof VarHangupScript - 1);
136531962Sbrian    VarHangupScript[sizeof VarHangupScript - 1] = '\0';
136628679Sbrian    break;
136729840Sbrian#ifdef HAVE_DES
136829549Sbrian  case VAR_ENC:
136931343Sbrian    VarMSChap = !strcasecmp(argp, "mschap");
137029549Sbrian    break;
137129840Sbrian#endif
13726059Samurai  }
137326516Sbrian  return 0;
13746059Samurai}
13756059Samurai
137628679Sbrianstatic int
137731343SbrianSetCtsRts(struct cmdargs const *arg)
137820812Sjkh{
137931343Sbrian  if (arg->argc > 0) {
138031343Sbrian    if (strcmp(*arg->argv, "on") == 0)
138130715Sbrian      VarCtsRts = 1;
138231343Sbrian    else if (strcmp(*arg->argv, "off") == 0)
138330715Sbrian      VarCtsRts = 0;
138420812Sjkh    else
138526516Sbrian      return -1;
138626516Sbrian    return 0;
138720812Sjkh  }
138826516Sbrian  return -1;
138920812Sjkh}
139020812Sjkh
139120812Sjkh
139228679Sbrianstatic int
139331343SbrianSetOpenMode(struct cmdargs const *arg)
13946059Samurai{
139531343Sbrian  if (arg->argc > 0) {
139631343Sbrian    if (strcmp(*arg->argv, "active") == 0)
13976059Samurai      VarOpenMode = OPEN_ACTIVE;
139831343Sbrian    else if (strcmp(*arg->argv, "passive") == 0)
13996059Samurai      VarOpenMode = OPEN_PASSIVE;
14006059Samurai    else
140126516Sbrian      return -1;
140226516Sbrian    return 0;
14036059Samurai  }
140426516Sbrian  return -1;
14056059Samurai}
14066059Samurai
140730715Sbrianstatic struct cmdtab const SetCommands[] = {
140828679Sbrian  {"accmap", NULL, SetVariable, LOCAL_AUTH,
140931343Sbrian  "Set accmap value", "set accmap hex-value", (const void *) VAR_ACCMAP},
141028679Sbrian  {"afilter", NULL, SetAfilter, LOCAL_AUTH,
141128679Sbrian  "Set keep Alive filter", "set afilter ..."},
141228679Sbrian  {"authkey", "key", SetVariable, LOCAL_AUTH,
141331343Sbrian  "Set authentication key", "set authkey|key key", (const void *) VAR_AUTHKEY},
141428679Sbrian  {"authname", NULL, SetVariable, LOCAL_AUTH,
141531343Sbrian  "Set authentication name", "set authname name", (const void *) VAR_AUTHNAME},
141628679Sbrian  {"ctsrts", NULL, SetCtsRts, LOCAL_AUTH,
141728679Sbrian  "Use CTS/RTS modem signalling", "set ctsrts [on|off]"},
141831343Sbrian  {"device", "line", SetVariable, LOCAL_AUTH, "Set modem device name",
141931917Sbrian  "set device|line device-name[,device-name]", (const void *) VAR_DEVICE},
142028679Sbrian  {"dfilter", NULL, SetDfilter, LOCAL_AUTH,
142128679Sbrian  "Set demand filter", "set dfilter ..."},
142228679Sbrian  {"dial", NULL, SetVariable, LOCAL_AUTH,
142331343Sbrian  "Set dialing script", "set dial chat-script", (const void *) VAR_DIAL},
142429840Sbrian#ifdef HAVE_DES
142531343Sbrian  {"encrypt", NULL, SetVariable, LOCAL_AUTH, "Set CHAP encryption algorithm",
142631343Sbrian  "set encrypt MSChap|MD5", (const void *) VAR_ENC},
142729840Sbrian#endif
142828679Sbrian  {"escape", NULL, SetEscape, LOCAL_AUTH,
142928679Sbrian  "Set escape characters", "set escape hex-digit ..."},
143028679Sbrian  {"hangup", NULL, SetVariable, LOCAL_AUTH,
143131343Sbrian  "Set hangup script", "set hangup chat-script", (const void *) VAR_HANGUP},
143231343Sbrian  {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "Set destination address",
143331343Sbrian  "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
143428679Sbrian  {"ifilter", NULL, SetIfilter, LOCAL_AUTH,
143528679Sbrian  "Set input filter", "set ifilter ..."},
143628679Sbrian  {"loopback", NULL, SetLoopback, LOCAL_AUTH,
143728679Sbrian  "Set loopback facility", "set loopback on|off"},
143828679Sbrian  {"log", NULL, SetLogLevel, LOCAL_AUTH,
143930913Sbrian  "Set log level", "set log [local] [+|-]value..."},
144028679Sbrian  {"login", NULL, SetVariable, LOCAL_AUTH,
144131343Sbrian  "Set login script", "set login chat-script", (const void *) VAR_LOGIN},
144228679Sbrian  {"mru", NULL, SetInitialMRU, LOCAL_AUTH,
144328679Sbrian  "Set Initial MRU value", "set mru value"},
144428679Sbrian  {"mtu", NULL, SetPreferredMTU, LOCAL_AUTH,
144528679Sbrian  "Set Preferred MTU value", "set mtu value"},
144628679Sbrian  {"ofilter", NULL, SetOfilter, LOCAL_AUTH,
144728679Sbrian  "Set output filter", "set ofilter ..."},
144828679Sbrian  {"openmode", NULL, SetOpenMode, LOCAL_AUTH,
144928679Sbrian  "Set open mode", "set openmode [active|passive]"},
145028679Sbrian  {"parity", NULL, SetModemParity, LOCAL_AUTH,
145128679Sbrian  "Set modem parity", "set parity [odd|even|none]"},
145231343Sbrian  {"phone", NULL, SetVariable, LOCAL_AUTH, "Set telephone number(s)",
145331343Sbrian  "set phone phone1[:phone2[...]]", (const void *) VAR_PHONE},
145428679Sbrian  {"reconnect", NULL, SetReconnect, LOCAL_AUTH,
145528679Sbrian  "Set Reconnect timeout", "set reconnect value ntries"},
145631343Sbrian  {"redial", NULL, SetRedialTimeout, LOCAL_AUTH, "Set Redial timeout",
145731343Sbrian  "set redial value|random[.value|random] [dial_attempts]"},
145831343Sbrian  {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH, "Set STOPPED timeouts",
145931343Sbrian  "set stopped [LCPseconds [IPCPseconds [CCPseconds]]]"},
146028679Sbrian  {"server", "socket", SetServer, LOCAL_AUTH,
146128679Sbrian  "Set server port", "set server|socket TcpPort|LocalName|none [mask]"},
146228679Sbrian  {"speed", NULL, SetModemSpeed, LOCAL_AUTH,
146328679Sbrian  "Set modem speed", "set speed value"},
146428679Sbrian  {"timeout", NULL, SetIdleTimeout, LOCAL_AUTH,
146528679Sbrian  "Set Idle timeout", "set timeout value"},
146626516Sbrian#ifndef NOMSEXT
146728679Sbrian  {"ns", NULL, SetNS, LOCAL_AUTH,
146828679Sbrian  "Set NameServer", "set ns pri-addr [sec-addr]"},
146928679Sbrian  {"nbns", NULL, SetNBNS, LOCAL_AUTH,
147028679Sbrian  "Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"},
147126516Sbrian#endif
147228679Sbrian  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
147331343Sbrian  "Display this message", "set help|? [command]", SetCommands},
147428679Sbrian  {NULL, NULL, NULL},
14756059Samurai};
14766059Samurai
14776059Samuraistatic int
147831343SbrianSetCommand(struct cmdargs const *arg)
14796059Samurai{
148031343Sbrian  if (arg->argc > 0)
148131822Sbrian    FindExec(SetCommands, arg->argc, arg->argv, "set ");
148226516Sbrian  else if (VarTerm)
148331343Sbrian    fprintf(VarTerm, "Use `set ?' to get a arg->cmd or `set ? <var>' for"
148426516Sbrian	    " syntax help.\n");
14856059Samurai  else
148626516Sbrian    LogPrintf(LogWARN, "set command must have arguments\n");
148726516Sbrian
148826516Sbrian  return 0;
14896059Samurai}
14906059Samurai
14916059Samurai
14926059Samuraistatic int
149331343SbrianAddCommand(struct cmdargs const *arg)
14946059Samurai{
14956059Samurai  struct in_addr dest, gateway, netmask;
149631598Sbrian  int gw;
14976059Samurai
149831598Sbrian  if (arg->argc != 3 && arg->argc != 2)
149931598Sbrian    return -1;
150031598Sbrian
150131598Sbrian  if (arg->argc == 2)
150231598Sbrian    if (strcasecmp(arg->argv[0], "default"))
150331598Sbrian      return -1;
150431598Sbrian    else {
150531598Sbrian      dest.s_addr = netmask.s_addr = INADDR_ANY;
150631598Sbrian      gw = 1;
150731598Sbrian    }
150831598Sbrian  else {
150931343Sbrian    if (strcasecmp(arg->argv[0], "MYADDR") == 0)
151027011Sbrian      dest = IpcpInfo.want_ipaddr;
151132267Sbrian    else if (strcasecmp(arg->argv[0], "HISADDR") == 0)
151232267Sbrian      dest = IpcpInfo.his_ipaddr;
151327011Sbrian    else
151431343Sbrian      dest = GetIpAddr(arg->argv[0]);
151531343Sbrian    netmask = GetIpAddr(arg->argv[1]);
151631598Sbrian    gw = 2;
15176059Samurai  }
151831598Sbrian  if (strcasecmp(arg->argv[gw], "HISADDR") == 0)
151931598Sbrian    gateway = IpcpInfo.his_ipaddr;
152031598Sbrian  else if (strcasecmp(arg->argv[gw], "INTERFACE") == 0)
152131598Sbrian    gateway.s_addr = INADDR_ANY;
152231598Sbrian  else
152331598Sbrian    gateway = GetIpAddr(arg->argv[gw]);
152432109Sbrian  OsSetRoute(RTM_ADD, dest, gateway, netmask, arg->data ? 1 : 0);
152531598Sbrian  return 0;
15266059Samurai}
15276059Samurai
15286059Samuraistatic int
152931343SbrianDeleteCommand(struct cmdargs const *arg)
15306059Samurai{
153131598Sbrian  struct in_addr dest, none;
15326059Samurai
153331598Sbrian  if (arg->argc == 1)
153431598Sbrian    if(strcasecmp(arg->argv[0], "all") == 0)
153531598Sbrian      DeleteIfRoutes(0);
153631598Sbrian    else {
153731598Sbrian      if (strcasecmp(arg->argv[0], "MYADDR") == 0)
153831598Sbrian        dest = IpcpInfo.want_ipaddr;
153931598Sbrian      else if (strcasecmp(arg->argv[0], "default") == 0)
154031598Sbrian        dest.s_addr = INADDR_ANY;
154126591Sbrian      else
154231598Sbrian        dest = GetIpAddr(arg->argv[0]);
154331598Sbrian      none.s_addr = INADDR_ANY;
154432109Sbrian      OsSetRoute(RTM_DELETE, dest, none, none, arg->data ? 1 : 0);
154531598Sbrian    }
154631598Sbrian  else
154726516Sbrian    return -1;
154826516Sbrian
154926516Sbrian  return 0;
15506059Samurai}
15516059Samurai
155231343Sbrian#ifndef NOALIAS
155326031Sbrianstatic struct cmdtab const AliasCommands[] =
155426031Sbrian{
155528679Sbrian  {"enable", NULL, AliasEnable, LOCAL_AUTH,
155628679Sbrian  "enable IP aliasing", "alias enable [yes|no]"},
155728679Sbrian  {"port", NULL, AliasRedirectPort, LOCAL_AUTH,
155828679Sbrian  "port redirection", "alias port [proto addr_local:port_local  port_alias]"},
155928679Sbrian  {"addr", NULL, AliasRedirectAddr, LOCAL_AUTH,
156028679Sbrian  "static address translation", "alias addr [addr_local addr_alias]"},
156128679Sbrian  {"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
156228679Sbrian    "stop incoming connections", "alias deny_incoming [yes|no]",
156331343Sbrian  (const void *) PKT_ALIAS_DENY_INCOMING},
156428679Sbrian  {"log", NULL, AliasOption, LOCAL_AUTH,
156528679Sbrian    "log aliasing link creation", "alias log [yes|no]",
156631343Sbrian  (const void *) PKT_ALIAS_LOG},
156728679Sbrian  {"same_ports", NULL, AliasOption, LOCAL_AUTH,
156828679Sbrian    "try to leave port numbers unchanged", "alias same_ports [yes|no]",
156931343Sbrian  (const void *) PKT_ALIAS_SAME_PORTS},
157028679Sbrian  {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
157128679Sbrian    "allocate host sockets", "alias use_sockets [yes|no]",
157231343Sbrian  (const void *) PKT_ALIAS_USE_SOCKETS},
157328679Sbrian  {"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
157428679Sbrian    "alias unregistered (private) IP address space only",
157528679Sbrian    "alias unregistered_only [yes|no]",
157631343Sbrian  (const void *) PKT_ALIAS_UNREGISTERED_ONLY},
157728679Sbrian  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
157831343Sbrian    "Display this message", "alias help|? [command]", AliasCommands},
157928679Sbrian  {NULL, NULL, NULL},
158026031Sbrian};
158126031Sbrian
158226031Sbrian
158326031Sbrianstatic int
158431343SbrianAliasCommand(struct cmdargs const *arg)
158526031Sbrian{
158631343Sbrian  if (arg->argc > 0)
158731822Sbrian    FindExec(AliasCommands, arg->argc, arg->argv, "alias ");
158826516Sbrian  else if (VarTerm)
158931343Sbrian    fprintf(VarTerm, "Use `alias help' to get a arg->cmd or `alias help <option>'"
159026516Sbrian	    " for syntax help.\n");
159126031Sbrian  else
159226516Sbrian    LogPrintf(LogWARN, "alias command must have arguments\n");
159326516Sbrian
159426516Sbrian  return 0;
159526031Sbrian}
159626031Sbrian
159726031Sbrianstatic int
159831343SbrianAliasEnable(struct cmdargs const *arg)
159926031Sbrian{
160031343Sbrian  if (arg->argc == 1)
160131343Sbrian    if (strcasecmp(arg->argv[0], "yes") == 0) {
160226516Sbrian      if (!(mode & MODE_ALIAS)) {
160328679Sbrian	if (loadAliasHandlers(&VarAliasHandlers) == 0) {
160428679Sbrian	  mode |= MODE_ALIAS;
160528679Sbrian	  return 0;
160628679Sbrian	}
160728679Sbrian	LogPrintf(LogWARN, "Cannot load alias library\n");
160828679Sbrian	return 1;
160926516Sbrian      }
161026516Sbrian      return 0;
161131343Sbrian    } else if (strcasecmp(arg->argv[0], "no") == 0) {
161226516Sbrian      if (mode & MODE_ALIAS) {
161328679Sbrian	unloadAliasHandlers();
161428679Sbrian	mode &= ~MODE_ALIAS;
161526516Sbrian      }
161626516Sbrian      return 0;
161726142Sbrian    }
161826516Sbrian  return -1;
161926031Sbrian}
162026031Sbrian
162126031Sbrian
162226031Sbrianstatic int
162331343SbrianAliasOption(struct cmdargs const *arg)
162426031Sbrian{
162531343Sbrian  unsigned param = (unsigned)arg->data;
162631343Sbrian  if (arg->argc == 1)
162731343Sbrian    if (strcasecmp(arg->argv[0], "yes") == 0) {
162828679Sbrian      if (mode & MODE_ALIAS) {
162931343Sbrian	VarPacketAliasSetMode(param, param);
163028679Sbrian	return 0;
163128679Sbrian      }
163228679Sbrian      LogPrintf(LogWARN, "alias not enabled\n");
163331343Sbrian    } else if (strcmp(arg->argv[0], "no") == 0) {
163428679Sbrian      if (mode & MODE_ALIAS) {
163531343Sbrian	VarPacketAliasSetMode(0, param);
163628679Sbrian	return 0;
163728679Sbrian      }
163828679Sbrian      LogPrintf(LogWARN, "alias not enabled\n");
163928679Sbrian    }
164028679Sbrian  return -1;
164126031Sbrian}
164231343Sbrian#endif /* #ifndef NOALIAS */
164331121Sbrian
164431121Sbrianstatic struct cmdtab const AllowCommands[] = {
164531121Sbrian  {"users", "user", AllowUsers, LOCAL_AUTH,
164631121Sbrian  "Allow users access to ppp", "allow users logname..."},
164731121Sbrian  {"modes", "mode", AllowModes, LOCAL_AUTH,
164831121Sbrian  "Only allow certain ppp modes", "allow modes mode..."},
164931121Sbrian  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
165031343Sbrian  "Display this message", "allow help|? [command]", AllowCommands},
165131121Sbrian  {NULL, NULL, NULL},
165231121Sbrian};
165331121Sbrian
165431121Sbrianstatic int
165531343SbrianAllowCommand(struct cmdargs const *arg)
165631121Sbrian{
165731343Sbrian  if (arg->argc > 0)
165831822Sbrian    FindExec(AllowCommands, arg->argc, arg->argv, "allow ");
165931121Sbrian  else if (VarTerm)
166031343Sbrian    fprintf(VarTerm, "Use `allow ?' to get a arg->cmd or `allow ? <cmd>' for"
166131121Sbrian	    " syntax help.\n");
166231121Sbrian  else
166331121Sbrian    LogPrintf(LogWARN, "allow command must have arguments\n");
166431121Sbrian
166531121Sbrian  return 0;
166631121Sbrian}
1667