command.c revision 29696
1230557Sjimharris/*
2230557Sjimharris *		PPP User command processing module
3230557Sjimharris *
4230557Sjimharris *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5230557Sjimharris *
6230557Sjimharris *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7230557Sjimharris *
8230557Sjimharris * Redistribution and use in source and binary forms are permitted
9230557Sjimharris * provided that the above copyright notice and this paragraph are
10230557Sjimharris * duplicated in all such forms and that any documentation,
11230557Sjimharris * advertising materials, and other materials related to such
12230557Sjimharris * distribution and use acknowledge that the software was developed
13230557Sjimharris * by the Internet Initiative Japan, Inc.  The name of the
14230557Sjimharris * IIJ may not be used to endorse or promote products derived
15230557Sjimharris * from this software without specific prior written permission.
16230557Sjimharris * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17230557Sjimharris * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18230557Sjimharris * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19230557Sjimharris *
20230557Sjimharris * $Id: command.c,v 1.83 1997/09/21 13:07:57 brian Exp $
21230557Sjimharris *
22230557Sjimharris */
23230557Sjimharris#include <sys/types.h>
24230557Sjimharris#include <sys/stat.h>
25230557Sjimharris#include <ctype.h>
26230557Sjimharris#include <termios.h>
27230557Sjimharris#include <sys/wait.h>
28230557Sjimharris#include <time.h>
29230557Sjimharris#include <netdb.h>
30230557Sjimharris#include <sys/socket.h>
31230557Sjimharris#include <netinet/in.h>
32230557Sjimharris#include <arpa/inet.h>
33230557Sjimharris#include <net/route.h>
34230557Sjimharris#include <paths.h>
35230557Sjimharris#include <alias.h>
36230557Sjimharris#include <fcntl.h>
37230557Sjimharris#include <errno.h>
38230557Sjimharris#include "fsm.h"
39230557Sjimharris#include "phase.h"
40230557Sjimharris#include "lcp.h"
41230557Sjimharris#include "ipcp.h"
42230557Sjimharris#include "modem.h"
43230557Sjimharris#include "filter.h"
44230557Sjimharris#include "command.h"
45230557Sjimharris#include "alias_cmd.h"
46230557Sjimharris#include "hdlc.h"
47230557Sjimharris#include "loadalias.h"
48230557Sjimharris#include "vars.h"
49230557Sjimharris#include "systems.h"
50230557Sjimharris#include "chat.h"
51230557Sjimharris#include "os.h"
52230557Sjimharris#include "timeout.h"
53230557Sjimharris#include "server.h"
54230557Sjimharris
55230557Sjimharrisextern void Cleanup(), TtyTermMode(), PacketMode();
56230557Sjimharrisextern int EnableCommand(), DisableCommand(), DisplayCommand();
57230557Sjimharrisextern int AcceptCommand(), DenyCommand();
58230557Sjimharrisstatic int AliasCommand();
59230557Sjimharrisextern int LocalAuthCommand();
60230557Sjimharrisextern int LoadCommand(), SaveCommand();
61230557Sjimharrisextern int ChangeParity(char *);
62230557Sjimharrisextern int SelectSystem();
63230557Sjimharrisextern int ShowRoute();
64230557Sjimharrisextern void TtyOldMode(), TtyCommandMode();
65230557Sjimharrisextern struct pppvars pppVars;
66230557Sjimharrisextern struct cmdtab const SetCommands[];
67230557Sjimharris
68230557Sjimharrisextern char *IfDevName;
69230557Sjimharris
70230557Sjimharrisstruct in_addr ifnetmask;
71230557Sjimharrisint randinit;
72230557Sjimharris
73230557Sjimharrisstatic int ShowCommand(struct cmdtab const *, int, char **);
74230557Sjimharrisstatic int TerminalCommand(struct cmdtab const *, int, char **);
75230557Sjimharrisstatic int QuitCommand(struct cmdtab const *, int, char **);
76230557Sjimharrisstatic int CloseCommand(struct cmdtab const *, int, char **);
77230557Sjimharrisstatic int DialCommand(struct cmdtab const *, int, char **);
78230557Sjimharrisstatic int DownCommand(struct cmdtab const *, int, char **);
79230557Sjimharrisstatic int SetCommand(struct cmdtab const *, int, char **);
80230557Sjimharrisstatic int AddCommand(struct cmdtab const *, int, char **);
81230557Sjimharrisstatic int DeleteCommand(struct cmdtab const *, int, char **);
82230557Sjimharrisstatic int BgShellCommand(struct cmdtab const *, int, char **);
83230557Sjimharrisstatic int FgShellCommand(struct cmdtab const *, int, char **);
84230557Sjimharrisstatic int ShellCommand(struct cmdtab const *, int, char **, int);
85230557Sjimharris
86230557Sjimharrisstatic int
87230557SjimharrisHelpCommand(struct cmdtab const * list,
88230557Sjimharris	    int argc,
89230557Sjimharris	    char **argv,
90230557Sjimharris	    struct cmdtab const * plist)
91230557Sjimharris{
92230557Sjimharris  struct cmdtab const *cmd;
93230557Sjimharris  int n;
94230557Sjimharris
95230557Sjimharris  if (!VarTerm)
96230557Sjimharris    return 0;
97230557Sjimharris
98230557Sjimharris  if (argc > 0) {
99230557Sjimharris    for (cmd = plist; cmd->name; cmd++)
100230557Sjimharris      if (strcasecmp(cmd->name, *argv) == 0 && (cmd->lauth & VarLocalAuth)) {
101230557Sjimharris	fprintf(VarTerm, "%s\n", cmd->syntax);
102230557Sjimharris	return 0;
103230557Sjimharris      }
104230557Sjimharris    return -1;
105230557Sjimharris  }
106230557Sjimharris  n = 0;
107230557Sjimharris  for (cmd = plist; cmd->func; cmd++)
108230557Sjimharris    if (cmd->name && (cmd->lauth & VarLocalAuth)) {
109230557Sjimharris      fprintf(VarTerm, "  %-9s: %-20s\n", cmd->name, cmd->helpmes);
110230557Sjimharris      n++;
111230557Sjimharris    }
112230557Sjimharris  if (n & 1)
113230557Sjimharris    fprintf(VarTerm, "\n");
114230557Sjimharris
115230557Sjimharris  return 0;
116230557Sjimharris}
117230557Sjimharris
118230557Sjimharrisint
119230557SjimharrisIsInteractive()
120230557Sjimharris{
121230557Sjimharris  char *mes = NULL;
122230557Sjimharris
123230557Sjimharris  if (mode & MODE_DDIAL)
124230557Sjimharris    mes = "Working in dedicated dial mode.";
125230557Sjimharris  else if (mode & MODE_BACKGROUND)
126230557Sjimharris    mes = "Working in background mode.";
127230557Sjimharris  else if (mode & MODE_AUTO)
128230557Sjimharris    mes = "Working in auto mode.";
129230557Sjimharris  else if (mode & MODE_DIRECT)
130230557Sjimharris    mes = "Working in direct mode.";
131230557Sjimharris  else if (mode & MODE_DEDICATED)
132230557Sjimharris    mes = "Working in dedicated mode.";
133230557Sjimharris  if (mes) {
134230557Sjimharris    if (VarTerm)
135230557Sjimharris      fprintf(VarTerm, "%s\n", mes);
136230557Sjimharris    return 0;
137230557Sjimharris  }
138230557Sjimharris  return 1;
139230557Sjimharris}
140230557Sjimharris
141230557Sjimharrisstatic int
142230557SjimharrisDialCommand(struct cmdtab const * cmdlist, int argc, char **argv)
143230557Sjimharris{
144230557Sjimharris  int tries;
145230557Sjimharris  int res;
146230557Sjimharris
147230557Sjimharris  if (LcpFsm.state > ST_CLOSED) {
148230557Sjimharris    if (VarTerm)
149230557Sjimharris      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
150230557Sjimharris    return 0;
151230557Sjimharris  }
152230557Sjimharris
153230557Sjimharris  if (argc > 0) {
154230557Sjimharris    if (SelectSystem(*argv, CONFFILE) < 0) {
155230557Sjimharris      if (VarTerm)
156230557Sjimharris	fprintf(VarTerm, "%s: not found.\n", *argv);
157230557Sjimharris      return -1;
158230557Sjimharris    }
159230557Sjimharris  }
160230557Sjimharris  tries = 0;
161230557Sjimharris  do {
162230557Sjimharris    if (VarTerm)
163230557Sjimharris      fprintf(VarTerm, "Dial attempt %u of %d\n", ++tries, VarDialTries);
164230557Sjimharris    if (OpenModem(mode) < 0) {
165230557Sjimharris      if (VarTerm)
166230557Sjimharris	fprintf(VarTerm, "Failed to open modem.\n");
167230557Sjimharris      break;
168230557Sjimharris    }
169230557Sjimharris    if ((res = DialModem()) == EX_DONE) {
170230557Sjimharris      sleep(1);
171230557Sjimharris      ModemTimeout();
172230557Sjimharris      PacketMode();
173230557Sjimharris      break;
174230557Sjimharris    } else if (res == EX_SIG)
175230557Sjimharris      return 1;
176230557Sjimharris  } while (VarDialTries == 0 || tries < VarDialTries);
177230557Sjimharris
178230557Sjimharris  return 0;
179230557Sjimharris}
180230557Sjimharris
181230557Sjimharrisstatic int
182230557SjimharrisSetLoopback(struct cmdtab const * cmdlist, int argc, char **argv)
183230557Sjimharris{
184230557Sjimharris  if (argc == 1)
185230557Sjimharris    if (!strcasecmp(*argv, "on"))
186230557Sjimharris      VarLoopback = 1;
187230557Sjimharris    else if (!strcasecmp(*argv, "off"))
188230557Sjimharris      VarLoopback = 0;
189230557Sjimharris  return -1;
190230557Sjimharris}
191230557Sjimharris
192230557Sjimharrisstatic int
193230557SjimharrisBgShellCommand(struct cmdtab const * cmdlist, int argc, char **argv)
194230557Sjimharris{
195230557Sjimharris  if (argc == 0)
196230557Sjimharris    return -1;
197230557Sjimharris  return ShellCommand(cmdlist, argc, argv, 1);
198230557Sjimharris}
199230557Sjimharris
200230557Sjimharrisstatic int
201230557SjimharrisFgShellCommand(struct cmdtab const * cmdlist, int argc, char **argv)
202230557Sjimharris{
203230557Sjimharris  return ShellCommand(cmdlist, argc, argv, 0);
204230557Sjimharris}
205230557Sjimharris
206230557Sjimharrisstatic int
207230557SjimharrisShellCommand(struct cmdtab const * cmdlist, int argc, char **argv, int bg)
208230557Sjimharris{
209230557Sjimharris  const char *shell;
210230557Sjimharris  pid_t shpid;
211230557Sjimharris  FILE *oVarTerm;
212230557Sjimharris
213230557Sjimharris#ifdef SHELL_ONLY_INTERACTIVELY
214230557Sjimharris  /* we're only allowed to shell when we run ppp interactively */
215230557Sjimharris  if (mode != MODE_INTER) {
216230557Sjimharris    LogPrintf(LogWARN, "Can only start a shell in interactive mode\n");
217230557Sjimharris    return 1;
218230557Sjimharris  }
219230557Sjimharris#endif
220230557Sjimharris#ifdef NO_SHELL_IN_AUTO_INTERACTIVE
221230557Sjimharris
222230557Sjimharris  /*
223230557Sjimharris   * we want to stop shell commands when we've got a telnet connection to an
224230557Sjimharris   * auto mode ppp
225230557Sjimharris   */
226230557Sjimharris  if ((mode & (MODE_AUTO | MODE_INTER)) == (MODE_AUTO | MODE_INTER)) {
227230557Sjimharris    LogPrintf(LogWARN, "Shell is not allowed interactively in auto mode\n");
228230557Sjimharris    return 1;
229230557Sjimharris  }
230230557Sjimharris#endif
231230557Sjimharris
232230557Sjimharris  if (argc == 0)
233230557Sjimharris    if (!(mode & MODE_INTER)) {
234230557Sjimharris      LogPrintf(LogWARN, "Can only start an interactive shell in"
235230557Sjimharris		" interactive mode\n");
236230557Sjimharris      return 1;
237230557Sjimharris    } else if (bg) {
238230557Sjimharris      LogPrintf(LogWARN, "Can only start an interactive shell in"
239230557Sjimharris		" the foreground mode\n");
240230557Sjimharris      return 1;
241230557Sjimharris    } else if (mode&(MODE_AUTO|MODE_DEDICATED|MODE_DIRECT)) {
242230557Sjimharris      LogPrintf(LogWARN, "Can't start an interactive shell from"
243230557Sjimharris		" a telnet session\n");
244230557Sjimharris      return 1;
245230557Sjimharris    }
246230557Sjimharris  if ((shell = getenv("SHELL")) == 0)
247230557Sjimharris    shell = _PATH_BSHELL;
248230557Sjimharris
249230557Sjimharris  if ((shpid = fork()) == 0) {
250230557Sjimharris    int dtablesize, i, fd;
251230557Sjimharris
252230557Sjimharris    if (VarTerm)
253230557Sjimharris      fd = fileno(VarTerm);
254230557Sjimharris    else if ((fd = open("/dev/null", O_RDWR)) == -1) {
255230557Sjimharris      LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno));
256230557Sjimharris      exit(1);
257230557Sjimharris    }
258230557Sjimharris    for (i = 0; i < 3; i++)
259230557Sjimharris      dup2(fd, i);
260230557Sjimharris
261230557Sjimharris    if (fd > 2)
262230557Sjimharris      if (VarTerm) {
263230557Sjimharris	oVarTerm = VarTerm;
264230557Sjimharris	VarTerm = 0;
265230557Sjimharris	if (oVarTerm && oVarTerm != stdout)
266230557Sjimharris	  fclose(oVarTerm);
267230557Sjimharris      } else
268230557Sjimharris	close(fd);
269230557Sjimharris
270230557Sjimharris    for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++)
271230557Sjimharris      (void) close(i);
272230557Sjimharris
273230557Sjimharris    /*
274230557Sjimharris     * We are running setuid, we should change to real user for avoiding
275230557Sjimharris     * security problems.
276230557Sjimharris     */
277230557Sjimharris    if (setgid(getgid()) < 0) {
278230557Sjimharris      LogPrintf(LogERROR, "setgid: %s\n", strerror(errno));
279230557Sjimharris      exit(1);
280230557Sjimharris    }
281230557Sjimharris    if (setuid(getuid()) < 0) {
282230557Sjimharris      LogPrintf(LogERROR, "setuid: %s\n", strerror(errno));
283230557Sjimharris      exit(1);
284230557Sjimharris    }
285230557Sjimharris    TtyOldMode();
286230557Sjimharris    if (argc > 0) {
287230557Sjimharris      /* substitute pseudo args */
288230557Sjimharris      for (i = 1; i < argc; i++)
289230557Sjimharris	if (strcasecmp(argv[i], "HISADDR") == 0)
290230557Sjimharris	  argv[i] = strdup(inet_ntoa(IpcpInfo.his_ipaddr));
291230557Sjimharris	else if (strcasecmp(argv[i], "INTERFACE") == 0)
292230557Sjimharris	  argv[i] = strdup(IfDevName);
293230557Sjimharris	else if (strcasecmp(argv[i], "MYADDR") == 0)
294230557Sjimharris	  argv[i] = strdup(inet_ntoa(IpcpInfo.want_ipaddr));
295230557Sjimharris      if (bg) {
296230557Sjimharris	pid_t p;
297230557Sjimharris
298230557Sjimharris	p = getpid();
299230557Sjimharris	if (daemon(1, 1) == -1) {
300230557Sjimharris	  LogPrintf(LogERROR, "%d: daemon: %s\n", p, strerror(errno));
301230557Sjimharris	  exit(1);
302230557Sjimharris	}
303230557Sjimharris      }
304230557Sjimharris      (void) execvp(argv[0], argv);
305230557Sjimharris    } else
306230557Sjimharris      (void) execl(shell, shell, NULL);
307230557Sjimharris
308230557Sjimharris    LogPrintf(LogWARN, "exec() of %s failed\n", argc > 0 ? argv[0] : shell);
309230557Sjimharris    exit(255);
310230557Sjimharris  }
311230557Sjimharris  if (shpid == (pid_t) - 1) {
312230557Sjimharris    LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno));
313230557Sjimharris  } else {
314230557Sjimharris    int status;
315230557Sjimharris
316230557Sjimharris    (void) waitpid(shpid, &status, 0);
317230557Sjimharris  }
318230557Sjimharris
319230557Sjimharris  TtyCommandMode(1);
320230557Sjimharris
321230557Sjimharris  return (0);
322230557Sjimharris}
323230557Sjimharris
324230557Sjimharrisstruct cmdtab const Commands[] = {
325230557Sjimharris  {"accept", NULL, AcceptCommand, LOCAL_AUTH,
326230557Sjimharris  "accept option request", "accept option .."},
327230557Sjimharris  {"add", NULL, AddCommand, LOCAL_AUTH,
328230557Sjimharris  "add route", "add dest mask gateway"},
329230557Sjimharris  {"bg", "!bg", BgShellCommand, LOCAL_AUTH,
330230557Sjimharris  "Run a command in the background", "[!]bg command"},
331230557Sjimharris  {"close", NULL, CloseCommand, LOCAL_AUTH,
332230557Sjimharris  "Close connection", "close"},
333230557Sjimharris  {"delete", NULL, DeleteCommand, LOCAL_AUTH,
334230557Sjimharris  "delete route", "delete ALL | dest [gateway [mask]]"},
335230557Sjimharris  {"deny", NULL, DenyCommand, LOCAL_AUTH,
336230557Sjimharris  "Deny option request", "deny option .."},
337230557Sjimharris  {"dial", "call", DialCommand, LOCAL_AUTH,
338230557Sjimharris  "Dial and login", "dial|call [remote]"},
339230557Sjimharris  {"disable", NULL, DisableCommand, LOCAL_AUTH,
340230557Sjimharris  "Disable option", "disable option .."},
341230557Sjimharris  {"display", NULL, DisplayCommand, LOCAL_AUTH,
342230557Sjimharris  "Display option configs", "display"},
343230557Sjimharris  {"enable", NULL, EnableCommand, LOCAL_AUTH,
344230557Sjimharris  "Enable option", "enable option .."},
345230557Sjimharris  {"passwd", NULL, LocalAuthCommand, LOCAL_NO_AUTH,
346230557Sjimharris  "Password for manipulation", "passwd LocalPassword"},
347230557Sjimharris  {"load", NULL, LoadCommand, LOCAL_AUTH,
348230557Sjimharris  "Load settings", "load [remote]"},
349230557Sjimharris  {"save", NULL, SaveCommand, LOCAL_AUTH,
350230557Sjimharris  "Save settings", "save"},
351230557Sjimharris  {"set", "setup", SetCommand, LOCAL_AUTH,
352230557Sjimharris  "Set parameters", "set[up] var value"},
353230557Sjimharris  {"shell", "!", FgShellCommand, LOCAL_AUTH,
354230557Sjimharris  "Run a subshell", "shell|! [sh command]"},
355230557Sjimharris  {"show", NULL, ShowCommand, LOCAL_AUTH,
356230557Sjimharris  "Show status and statistics", "show var"},
357230557Sjimharris  {"term", NULL, TerminalCommand, LOCAL_AUTH,
358230557Sjimharris  "Enter to terminal mode", "term"},
359230557Sjimharris  {"alias", NULL, AliasCommand, LOCAL_AUTH,
360230557Sjimharris  "alias control", "alias option [yes|no]"},
361230557Sjimharris  {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
362230557Sjimharris  "Quit PPP program", "quit|bye [all]"},
363230557Sjimharris  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
364230557Sjimharris  "Display this message", "help|? [command]", (void *) Commands},
365231137Sjimharris  {NULL, "down", DownCommand, LOCAL_AUTH,
366231137Sjimharris  "Generate down event", "down"},
367230557Sjimharris  {NULL, NULL, NULL},
368230557Sjimharris};
369230557Sjimharris
370230557Sjimharrisextern int ReportCcpStatus();
371230557Sjimharrisextern int ReportLcpStatus();
372230557Sjimharrisextern int ReportIpcpStatus();
373230557Sjimharrisextern int ReportProtStatus();
374230557Sjimharrisextern int ReportCompress();
375231137Sjimharrisextern int ShowModemStatus();
376230557Sjimharrisextern int ReportHdlcStatus();
377230557Sjimharrisextern int ShowMemMap();
378230557Sjimharris
379230557Sjimharrisstatic int
380230557SjimharrisShowLoopback()
381230557Sjimharris{
382230557Sjimharris  if (VarTerm)
383230557Sjimharris    fprintf(VarTerm, "Local loopback is %s\n", VarLoopback ? "on" : "off");
384230557Sjimharris
385230557Sjimharris  return 0;
386230557Sjimharris}
387230557Sjimharris
388230557Sjimharrisstatic int
389230557SjimharrisShowLogLevel()
390230557Sjimharris{
391230557Sjimharris  int i;
392230557Sjimharris
393230557Sjimharris  if (!VarTerm)
394230557Sjimharris    return 0;
395230557Sjimharris  fprintf(VarTerm, "Log:");
396230557Sjimharris  for (i = LogMIN; i < LogMAXCONF; i++) {
397230557Sjimharris    if (LogIsKept(i))
398230557Sjimharris      fprintf(VarTerm, " %s", LogName(i));
399230557Sjimharris  }
400230557Sjimharris  fprintf(VarTerm, "\n");
401230557Sjimharris
402230557Sjimharris  return 0;
403230557Sjimharris}
404230557Sjimharris
405230557Sjimharrisstatic int
406230557SjimharrisShowEscape()
407230557Sjimharris{
408230557Sjimharris  int code, bit;
409230557Sjimharris
410230557Sjimharris  if (!VarTerm)
411230557Sjimharris    return 0;
412230557Sjimharris  if (EscMap[32]) {
413230557Sjimharris    for (code = 0; code < 32; code++)
414230557Sjimharris      if (EscMap[code])
415230557Sjimharris	for (bit = 0; bit < 8; bit++)
416230557Sjimharris	  if (EscMap[code] & (1 << bit))
417230557Sjimharris	    fprintf(VarTerm, " 0x%02x", (code << 3) + bit);
418230557Sjimharris    fprintf(VarTerm, "\n");
419230557Sjimharris  }
420230557Sjimharris  return 1;
421230557Sjimharris}
422230557Sjimharris
423230557Sjimharrisstatic int
424230557SjimharrisShowTimeout()
425230557Sjimharris{
426230557Sjimharris  if (!VarTerm)
427230557Sjimharris    return 0;
428230557Sjimharris  fprintf(VarTerm, " Idle Timer: %d secs   LQR Timer: %d secs"
429230557Sjimharris	  "   Retry Timer: %d secs\n", VarIdleTimeout, VarLqrTimeout,
430230557Sjimharris	  VarRetryTimeout);
431230557Sjimharris  return 1;
432230557Sjimharris}
433230557Sjimharris
434230557Sjimharrisstatic int
435230557SjimharrisShowStopped()
436230557Sjimharris{
437230557Sjimharris  if (!VarTerm)
438230557Sjimharris    return 0;
439230557Sjimharris
440230557Sjimharris  fprintf(VarTerm, " Stopped Timer:  LCP: ");
441230557Sjimharris  if (!LcpFsm.StoppedTimer.load)
442230557Sjimharris    fprintf(VarTerm, "Disabled");
443230557Sjimharris  else
444230557Sjimharris    fprintf(VarTerm, "%ld secs", LcpFsm.StoppedTimer.load / SECTICKS);
445230557Sjimharris
446230557Sjimharris  fprintf(VarTerm, ", IPCP: ");
447230557Sjimharris  if (!IpcpFsm.StoppedTimer.load)
448230557Sjimharris    fprintf(VarTerm, "Disabled");
449230557Sjimharris  else
450230557Sjimharris    fprintf(VarTerm, "%ld secs", IpcpFsm.StoppedTimer.load / SECTICKS);
451230557Sjimharris
452230557Sjimharris  fprintf(VarTerm, ", CCP: ");
453230557Sjimharris  if (!CcpFsm.StoppedTimer.load)
454230557Sjimharris    fprintf(VarTerm, "Disabled");
455230557Sjimharris  else
456230557Sjimharris    fprintf(VarTerm, "%ld secs", CcpFsm.StoppedTimer.load / SECTICKS);
457230557Sjimharris
458230557Sjimharris  fprintf(VarTerm, "\n");
459230557Sjimharris
460230557Sjimharris  return 1;
461230557Sjimharris}
462230557Sjimharris
463230557Sjimharrisstatic int
464230557SjimharrisShowAuthKey()
465230557Sjimharris{
466230557Sjimharris  if (!VarTerm)
467230557Sjimharris    return 0;
468230557Sjimharris  fprintf(VarTerm, "AuthName = %s\n", VarAuthName);
469230557Sjimharris  fprintf(VarTerm, "AuthKey  = %s\n", VarAuthKey);
470230557Sjimharris  fprintf(VarTerm, "Encrypt  = %s\n", VarEncMD4 ? "MD4" : "MD5" );
471230557Sjimharris  return 1;
472230557Sjimharris}
473230557Sjimharris
474230557Sjimharrisstatic int
475230557SjimharrisShowVersion()
476230557Sjimharris{
477230557Sjimharris  extern char VarVersion[];
478230557Sjimharris  extern char VarLocalVersion[];
479230557Sjimharris
480230557Sjimharris  if (!VarTerm)
481230557Sjimharris    return 0;
482230557Sjimharris  fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
483230557Sjimharris  return 1;
484230557Sjimharris}
485230557Sjimharris
486230557Sjimharrisstatic int
487230557SjimharrisShowInitialMRU()
488230557Sjimharris{
489230557Sjimharris  if (!VarTerm)
490230557Sjimharris    return 0;
491230557Sjimharris  fprintf(VarTerm, " Initial MRU: %ld\n", VarMRU);
492230557Sjimharris  return 1;
493230557Sjimharris}
494230557Sjimharris
495230557Sjimharrisstatic int
496230557SjimharrisShowPreferredMTU()
497230557Sjimharris{
498230557Sjimharris  if (!VarTerm)
499230557Sjimharris    return 0;
500230557Sjimharris  if (VarPrefMTU)
501230557Sjimharris    fprintf(VarTerm, " Preferred MTU: %ld\n", VarPrefMTU);
502230557Sjimharris  else
503230557Sjimharris    fprintf(VarTerm, " Preferred MTU: unspecified\n");
504230557Sjimharris  return 1;
505230557Sjimharris}
506230557Sjimharris
507230557Sjimharrisstatic int
508230557SjimharrisShowReconnect()
509230557Sjimharris{
510230557Sjimharris  if (!VarTerm)
511230557Sjimharris    return 0;
512230557Sjimharris  fprintf(VarTerm, " Reconnect Timer:  %d,  %d tries\n",
513230557Sjimharris	  VarReconnectTimer, VarReconnectTries);
514230557Sjimharris  return 1;
515230557Sjimharris}
516230557Sjimharris
517230557Sjimharrisstatic int
518230557SjimharrisShowRedial()
519230557Sjimharris{
520230557Sjimharris  if (!VarTerm)
521230557Sjimharris    return 0;
522230557Sjimharris  fprintf(VarTerm, " Redial Timer: ");
523230557Sjimharris
524230557Sjimharris  if (VarRedialTimeout >= 0) {
525230557Sjimharris    fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
526230557Sjimharris  } else {
527230557Sjimharris    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
528230557Sjimharris  }
529230557Sjimharris
530230557Sjimharris  fprintf(VarTerm, " Redial Next Timer: ");
531230557Sjimharris
532230557Sjimharris  if (VarRedialNextTimeout >= 0) {
533230557Sjimharris    fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
534230557Sjimharris  } else {
535230557Sjimharris    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
536230557Sjimharris  }
537230557Sjimharris
538230557Sjimharris  if (VarDialTries)
539230557Sjimharris    fprintf(VarTerm, "%d dial tries", VarDialTries);
540230557Sjimharris
541230557Sjimharris  fprintf(VarTerm, "\n");
542230557Sjimharris
543230557Sjimharris  return 1;
544230557Sjimharris}
545230557Sjimharris
546230557Sjimharris#ifndef NOMSEXT
547230557Sjimharrisstatic int
548230557SjimharrisShowMSExt()
549230557Sjimharris{
550230557Sjimharris  if (!VarTerm)
551230557Sjimharris    return 0;
552230557Sjimharris  fprintf(VarTerm, " MS PPP extention values \n");
553230557Sjimharris  fprintf(VarTerm, "   Primary NS     : %s\n", inet_ntoa(ns_entries[0]));
554230557Sjimharris  fprintf(VarTerm, "   Secondary NS   : %s\n", inet_ntoa(ns_entries[1]));
555230557Sjimharris  fprintf(VarTerm, "   Primary NBNS   : %s\n", inet_ntoa(nbns_entries[0]));
556230557Sjimharris  fprintf(VarTerm, "   Secondary NBNS : %s\n", inet_ntoa(nbns_entries[1]));
557230557Sjimharris  return 1;
558230557Sjimharris}
559230557Sjimharris
560230557Sjimharris#endif
561230557Sjimharris
562230557Sjimharrisextern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
563230557Sjimharris
564230557Sjimharrisstruct cmdtab const ShowCommands[] = {
565230557Sjimharris  {"afilter", NULL, ShowAfilter, LOCAL_AUTH,
566230557Sjimharris  "Show keep Alive filters", "show afilter option .."},
567230557Sjimharris  {"auth", NULL, ShowAuthKey, LOCAL_AUTH,
568230557Sjimharris  "Show auth name, key and algorithm", "show auth"},
569230557Sjimharris  {"ccp", NULL, ReportCcpStatus, LOCAL_AUTH,
570230557Sjimharris  "Show CCP status", "show cpp"},
571230557Sjimharris  {"compress", NULL, ReportCompress, LOCAL_AUTH,
572230557Sjimharris  "Show compression statistics", "show compress"},
573230557Sjimharris  {"dfilter", NULL, ShowDfilter, LOCAL_AUTH,
574230557Sjimharris  "Show Demand filters", "show dfilteroption .."},
575230557Sjimharris  {"escape", NULL, ShowEscape, LOCAL_AUTH,
576230557Sjimharris  "Show escape characters", "show escape"},
577230557Sjimharris  {"hdlc", NULL, ReportHdlcStatus, LOCAL_AUTH,
578230557Sjimharris  "Show HDLC error summary", "show hdlc"},
579230557Sjimharris  {"ifilter", NULL, ShowIfilter, LOCAL_AUTH,
580230557Sjimharris  "Show Input filters", "show ifilter option .."},
581230557Sjimharris  {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH,
582230557Sjimharris  "Show IPCP status", "show ipcp"},
583230557Sjimharris  {"lcp", NULL, ReportLcpStatus, LOCAL_AUTH,
584230557Sjimharris  "Show LCP status", "show lcp"},
585230557Sjimharris  {"loopback", NULL, ShowLoopback, LOCAL_AUTH,
586230557Sjimharris  "Show current loopback setting", "show loopback"},
587230557Sjimharris  {"log", NULL, ShowLogLevel, LOCAL_AUTH,
588230557Sjimharris  "Show current log level", "show log"},
589230557Sjimharris  {"mem", NULL, ShowMemMap, LOCAL_AUTH,
590230557Sjimharris  "Show memory map", "show mem"},
591230557Sjimharris  {"modem", NULL, ShowModemStatus, LOCAL_AUTH,
592230557Sjimharris  "Show modem setups", "show modem"},
593230557Sjimharris  {"mru", NULL, ShowInitialMRU, LOCAL_AUTH,
594230557Sjimharris  "Show Initial MRU", "show mru"},
595230557Sjimharris  {"mtu", NULL, ShowPreferredMTU, LOCAL_AUTH,
596230557Sjimharris  "Show Preferred MTU", "show mtu"},
597230557Sjimharris  {"ofilter", NULL, ShowOfilter, LOCAL_AUTH,
598230557Sjimharris  "Show Output filters", "show ofilter option .."},
599230557Sjimharris  {"proto", NULL, ReportProtStatus, LOCAL_AUTH,
600230557Sjimharris  "Show protocol summary", "show proto"},
601230557Sjimharris  {"reconnect", NULL, ShowReconnect, LOCAL_AUTH,
602230557Sjimharris  "Show Reconnect timer,tries", "show reconnect"},
603230557Sjimharris  {"redial", NULL, ShowRedial, LOCAL_AUTH,
604230557Sjimharris  "Show Redial timeout value", "show redial"},
605230557Sjimharris  {"route", NULL, ShowRoute, LOCAL_AUTH,
606230557Sjimharris  "Show routing table", "show route"},
607230557Sjimharris  {"timeout", NULL, ShowTimeout, LOCAL_AUTH,
608230557Sjimharris  "Show Idle timeout value", "show timeout"},
609230557Sjimharris  {"stopped", NULL, ShowStopped, LOCAL_AUTH,
610230557Sjimharris  "Show STOPPED timeout value", "show stopped"},
611230557Sjimharris#ifndef NOMSEXT
612230557Sjimharris  {"msext", NULL, ShowMSExt, LOCAL_AUTH,
613230557Sjimharris  "Show MS PPP extentions", "show msext"},
614230557Sjimharris#endif
615230557Sjimharris  {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
616230557Sjimharris  "Show version string", "show version"},
617230557Sjimharris  {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
618230557Sjimharris  "Display this message", "show help|? [command]", (void *) ShowCommands},
619230557Sjimharris  {NULL, NULL, NULL},
620230557Sjimharris};
621230557Sjimharris
622230557Sjimharrisstruct cmdtab const *
623230557SjimharrisFindCommand(struct cmdtab const * cmds, char *str, int *pmatch)
624230557Sjimharris{
625230557Sjimharris  int nmatch;
626230557Sjimharris  int len;
627230557Sjimharris  struct cmdtab const *found;
628230557Sjimharris
629230557Sjimharris  found = NULL;
630230557Sjimharris  len = strlen(str);
631230557Sjimharris  nmatch = 0;
632230557Sjimharris  while (cmds->func) {
633230557Sjimharris    if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
634230557Sjimharris      if (cmds->name[len] == '\0') {
635230557Sjimharris	*pmatch = 1;
636230557Sjimharris	return cmds;
637230557Sjimharris      }
638230557Sjimharris      nmatch++;
639230557Sjimharris      found = cmds;
640230557Sjimharris    } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
641230557Sjimharris      if (cmds->alias[len] == '\0') {
642230557Sjimharris	*pmatch = 1;
643230557Sjimharris	return cmds;
644230557Sjimharris      }
645230557Sjimharris      nmatch++;
646230557Sjimharris      found = cmds;
647230557Sjimharris    }
648230557Sjimharris    cmds++;
649230557Sjimharris  }
650230557Sjimharris  *pmatch = nmatch;
651230557Sjimharris  return found;
652230557Sjimharris}
653230557Sjimharris
654230557Sjimharrisint
655230557SjimharrisFindExec(struct cmdtab const * cmdlist, int argc, char **argv)
656230557Sjimharris{
657230557Sjimharris  struct cmdtab const *cmd;
658230557Sjimharris  int val = 1;
659230557Sjimharris  int nmatch;
660230557Sjimharris
661230557Sjimharris  cmd = FindCommand(cmdlist, *argv, &nmatch);
662230557Sjimharris  if (nmatch > 1)
663230557Sjimharris    LogPrintf(LogWARN, "%s: Ambiguous command\n", *argv);
664230557Sjimharris  else if (cmd && (cmd->lauth & VarLocalAuth))
665230557Sjimharris    val = (cmd->func) (cmd, argc-1, argv+1, cmd->args);
666230557Sjimharris  else
667230557Sjimharris    LogPrintf(LogWARN, "%s: Invalid command\n", *argv);
668230557Sjimharris
669230557Sjimharris  if (val == -1)
670230557Sjimharris    LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
671230557Sjimharris  else if (val)
672230557Sjimharris    LogPrintf(LogCOMMAND, "%s: Failed %d\n", *argv, val);
673230557Sjimharris
674230557Sjimharris  return val;
675230557Sjimharris}
676230557Sjimharris
677230557Sjimharrisint aft_cmd = 1;
678230557Sjimharrisextern int TermMode;
679230557Sjimharris
680230557Sjimharrisvoid
681230557SjimharrisPrompt()
682230557Sjimharris{
683230557Sjimharris  char *pconnect, *pauth;
684230557Sjimharris
685230557Sjimharris  if (!(mode & MODE_INTER) || !VarTerm || TermMode)
686230557Sjimharris    return;
687230557Sjimharris
688230557Sjimharris  if (!aft_cmd)
689230557Sjimharris    fprintf(VarTerm, "\n");
690230557Sjimharris  else
691230557Sjimharris    aft_cmd = 0;
692230557Sjimharris
693230557Sjimharris  if (VarLocalAuth == LOCAL_AUTH)
694230557Sjimharris    pauth = " ON ";
695230557Sjimharris  else
696230557Sjimharris    pauth = " on ";
697230557Sjimharris  if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
698230557Sjimharris    pconnect = "PPP";
699230557Sjimharris  else
700230557Sjimharris    pconnect = "ppp";
701230557Sjimharris  fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
702230557Sjimharris  fflush(VarTerm);
703230557Sjimharris}
704230557Sjimharris
705230557Sjimharrisvoid
706230557SjimharrisDecodeCommand(char *buff, int nb, int prompt)
707230557Sjimharris{
708230557Sjimharris  char *vector[20];
709230557Sjimharris  char **argv;
710230557Sjimharris  int argc;
711230557Sjimharris  char *cp;
712230557Sjimharris
713230557Sjimharris  if (nb > 0) {
714230557Sjimharris    cp = buff + strcspn(buff, "\r\n");
715230557Sjimharris    if (cp)
716230557Sjimharris      *cp = '\0';
717230557Sjimharris    argc = MakeArgs(buff, vector, VECSIZE(vector));
718230557Sjimharris    argv = vector;
719230557Sjimharris
720230557Sjimharris    if (argc > 0)
721230557Sjimharris      FindExec(Commands, argc, argv);
722230557Sjimharris  }
723230557Sjimharris  if (prompt)
724230557Sjimharris    Prompt();
725230557Sjimharris}
726230557Sjimharris
727230557Sjimharrisstatic int
728230557SjimharrisShowCommand(struct cmdtab const * list, int argc, char **argv)
729230557Sjimharris{
730230557Sjimharris  if (argc > 0)
731230557Sjimharris    FindExec(ShowCommands, argc, argv);
732230557Sjimharris  else if (VarTerm)
733230557Sjimharris    fprintf(VarTerm, "Use ``show ?'' to get a list.\n");
734230557Sjimharris  else
735230557Sjimharris    LogPrintf(LogWARN, "show command must have arguments\n");
736230557Sjimharris
737230557Sjimharris  return 0;
738230557Sjimharris}
739230557Sjimharris
740230557Sjimharrisstatic int
741230557SjimharrisTerminalCommand(struct cmdtab const * list, int argc, char **argv)
742230557Sjimharris{
743230557Sjimharris  if (LcpFsm.state > ST_CLOSED) {
744230557Sjimharris    if (VarTerm)
745230557Sjimharris      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
746230557Sjimharris    return 1;
747230557Sjimharris  }
748230557Sjimharris  if (!IsInteractive())
749230557Sjimharris    return (1);
750230557Sjimharris  if (OpenModem(mode) < 0) {
751230557Sjimharris    if (VarTerm)
752230557Sjimharris      fprintf(VarTerm, "Failed to open modem.\n");
753230557Sjimharris    return (1);
754230557Sjimharris  }
755230557Sjimharris  if (VarTerm) {
756230557Sjimharris    fprintf(VarTerm, "Enter to terminal mode.\n");
757230557Sjimharris    fprintf(VarTerm, "Type `~?' for help.\n");
758230557Sjimharris  }
759230557Sjimharris  TtyTermMode();
760230557Sjimharris  return (0);
761230557Sjimharris}
762230557Sjimharris
763230557Sjimharrisstatic int
764230557SjimharrisQuitCommand(struct cmdtab const * list, int argc, char **argv)
765230557Sjimharris{
766230557Sjimharris  FILE *oVarTerm;
767230557Sjimharris
768230557Sjimharris  if (mode & (MODE_DIRECT | MODE_DEDICATED | MODE_AUTO)) {
769230557Sjimharris    if (argc > 0 && !strcasecmp(*argv, "all") && (VarLocalAuth & LOCAL_AUTH)) {
770230557Sjimharris      mode &= ~MODE_INTER;
771230557Sjimharris      oVarTerm = VarTerm;
772230557Sjimharris      VarTerm = 0;
773230557Sjimharris      if (oVarTerm && oVarTerm != stdout)
774230557Sjimharris	fclose(oVarTerm);
775230557Sjimharris      Cleanup(EX_NORMAL);
776230557Sjimharris    } else if (VarTerm) {
777230557Sjimharris      LogPrintf(LogPHASE, "Client connection closed.\n");
778230557Sjimharris      VarLocalAuth = LOCAL_NO_AUTH;
779230557Sjimharris      mode &= ~MODE_INTER;
780230557Sjimharris      oVarTerm = VarTerm;
781230557Sjimharris      VarTerm = 0;
782230557Sjimharris      if (oVarTerm && oVarTerm != stdout)
783230557Sjimharris	fclose(oVarTerm);
784230557Sjimharris      close(netfd);
785230557Sjimharris      netfd = -1;
786230557Sjimharris    }
787230557Sjimharris  } else
788230557Sjimharris    Cleanup(EX_NORMAL);
789230557Sjimharris
790230557Sjimharris  return 0;
791230557Sjimharris}
792230557Sjimharris
793230557Sjimharrisstatic int
794230557SjimharrisCloseCommand(struct cmdtab const * list, int argc, char **argv)
795{
796  reconnect(RECON_FALSE);
797  LcpClose();
798  if (mode & MODE_BACKGROUND)
799    Cleanup(EX_NORMAL);
800  return 0;
801}
802
803static int
804DownCommand(struct cmdtab const * list, int argc, char **argv)
805{
806  LcpDown();
807  return 0;
808}
809
810static int
811SetModemSpeed(struct cmdtab const * list, int argc, char **argv)
812{
813  int speed;
814
815  if (argc > 0) {
816    if (strcasecmp(*argv, "sync") == 0) {
817      VarSpeed = 0;
818      return 0;
819    }
820    speed = atoi(*argv);
821    if (IntToSpeed(speed) != B0) {
822      VarSpeed = speed;
823      return 0;
824    }
825    LogPrintf(LogWARN, "%s: Invalid speed\n", *argv);
826  }
827  return -1;
828}
829
830static int
831SetReconnect(struct cmdtab const * list, int argc, char **argv)
832{
833  if (argc == 2) {
834    VarReconnectTimer = atoi(argv[0]);
835    VarReconnectTries = atoi(argv[1]);
836    return 0;
837  }
838  return -1;
839}
840
841static int
842SetRedialTimeout(struct cmdtab const * list, int argc, char **argv)
843{
844  int timeout;
845  int tries;
846  char *dot;
847
848  if (argc == 1 || argc == 2) {
849    if (strncasecmp(argv[0], "random", 6) == 0 &&
850	(argv[0][6] == '\0' || argv[0][6] == '.')) {
851      VarRedialTimeout = -1;
852      if (!randinit) {
853	randinit = 1;
854	srandomdev();
855      }
856    } else {
857      timeout = atoi(argv[0]);
858
859      if (timeout >= 0)
860	VarRedialTimeout = timeout;
861      else {
862	LogPrintf(LogWARN, "Invalid redial timeout\n");
863	return -1;
864      }
865    }
866
867    dot = index(argv[0], '.');
868    if (dot) {
869      if (strcasecmp(++dot, "random") == 0) {
870	VarRedialNextTimeout = -1;
871	if (!randinit) {
872	  randinit = 1;
873	  srandomdev();
874	}
875      } else {
876	timeout = atoi(dot);
877	if (timeout >= 0)
878	  VarRedialNextTimeout = timeout;
879	else {
880	  LogPrintf(LogWARN, "Invalid next redial timeout\n");
881	  return -1;
882	}
883      }
884    } else
885      VarRedialNextTimeout = NEXT_REDIAL_PERIOD;	/* Default next timeout */
886
887    if (argc == 2) {
888      tries = atoi(argv[1]);
889
890      if (tries >= 0) {
891	VarDialTries = tries;
892      } else {
893	LogPrintf(LogWARN, "Invalid retry value\n");
894	return 1;
895      }
896    }
897    return 0;
898  }
899  return -1;
900}
901
902static int
903SetStoppedTimeout(struct cmdtab const * list, int argc, char **argv)
904{
905  LcpFsm.StoppedTimer.load = 0;
906  IpcpFsm.StoppedTimer.load = 0;
907  CcpFsm.StoppedTimer.load = 0;
908  if (argc <= 3) {
909    if (argc > 0) {
910      LcpFsm.StoppedTimer.load = atoi(argv[0]) * SECTICKS;
911      if (argc > 1) {
912	IpcpFsm.StoppedTimer.load = atoi(argv[1]) * SECTICKS;
913	if (argc > 2)
914	  CcpFsm.StoppedTimer.load = atoi(argv[2]) * SECTICKS;
915      }
916    }
917    return 0;
918  }
919  return -1;
920}
921
922static int
923SetServer(struct cmdtab const * list, int argc, char **argv)
924{
925  int res = -1;
926
927  if (argc > 0 && argc < 3)
928    if (strcasecmp(argv[0], "none") == 0) {
929      ServerClose();
930      LogPrintf(LogPHASE, "Disabling server port.\n");
931      res = 0;
932    } else if (*argv[0] == '/') {
933      mode_t mask;
934
935      umask(mask = umask(0));
936      if (argc == 2) {
937	unsigned m;
938
939	if (sscanf(argv[1], "%o", &m) == 1)
940	  mask = m;
941      }
942      res = ServerLocalOpen(argv[0], mask);
943    } else {
944      int port;
945
946      if (strspn(argv[0], "0123456789") != strlen(argv[0])) {
947	struct servent *s;
948
949	if ((s = getservbyname(argv[0], "tcp")) == NULL) {
950	  port = 0;
951	  LogPrintf(LogWARN, "%s: Invalid port or service\n", argv[0]);
952	} else
953	  port = ntohs(s->s_port);
954      } else
955	port = atoi(argv[0]);
956      if (port)
957	res = ServerTcpOpen(port);
958    }
959
960  return res;
961}
962
963static int
964SetModemParity(struct cmdtab const * list, int argc, char **argv)
965{
966  return argc > 0 ? ChangeParity(*argv) : -1;
967}
968
969static int
970SetLogLevel(struct cmdtab const * list, int argc, char **argv)
971{
972  int i;
973  int res;
974  char *arg;
975
976  res = 0;
977  if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-'))
978    LogDiscardAll();
979  while (argc--) {
980    arg = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
981    for (i = LogMIN; i <= LogMAX; i++)
982      if (strcasecmp(arg, LogName(i)) == 0) {
983	if (**argv == '-')
984	  LogDiscard(i);
985	else
986	  LogKeep(i);
987	break;
988      }
989    if (i > LogMAX) {
990      LogPrintf(LogWARN, "%s: Invalid log value\n", arg);
991      res = -1;
992    }
993    argv++;
994  }
995  return res;
996}
997
998static int
999SetEscape(struct cmdtab const * list, int argc, char **argv)
1000{
1001  int code;
1002
1003  for (code = 0; code < 33; code++)
1004    EscMap[code] = 0;
1005  while (argc-- > 0) {
1006    sscanf(*argv++, "%x", &code);
1007    code &= 0xff;
1008    EscMap[code >> 3] |= (1 << (code & 7));
1009    EscMap[32] = 1;
1010  }
1011  return 0;
1012}
1013
1014static int
1015SetInitialMRU(struct cmdtab const * list, int argc, char **argv)
1016{
1017  long mru;
1018  char *err;
1019
1020  if (argc > 0) {
1021    mru = atol(*argv);
1022    if (mru < MIN_MRU)
1023      err = "Given MRU value (%ld) is too small.\n";
1024    else if (mru > MAX_MRU)
1025      err = "Given MRU value (%ld) is too big.\n";
1026    else {
1027      VarMRU = mru;
1028      return 0;
1029    }
1030    LogPrintf(LogWARN, err, mru);
1031  }
1032  return -1;
1033}
1034
1035static int
1036SetPreferredMTU(struct cmdtab const * list, int argc, char **argv)
1037{
1038  long mtu;
1039  char *err;
1040
1041  if (argc > 0) {
1042    mtu = atol(*argv);
1043    if (mtu == 0) {
1044      VarPrefMTU = 0;
1045      return 0;
1046    } else if (mtu < MIN_MTU)
1047      err = "Given MTU value (%ld) is too small.\n";
1048    else if (mtu > MAX_MTU)
1049      err = "Given MTU value (%ld) is too big.\n";
1050    else {
1051      VarPrefMTU = mtu;
1052      return 0;
1053    }
1054    LogPrintf(LogWARN, err, mtu);
1055  }
1056  return -1;
1057}
1058
1059static int
1060SetIdleTimeout(struct cmdtab const * list, int argc, char **argv)
1061{
1062  if (argc-- > 0) {
1063    VarIdleTimeout = atoi(*argv++);
1064    UpdateIdleTimer();		/* If we're connected, restart the idle timer */
1065    if (argc-- > 0) {
1066      VarLqrTimeout = atoi(*argv++);
1067      if (VarLqrTimeout < 1)
1068	VarLqrTimeout = 30;
1069      if (argc > 0) {
1070	VarRetryTimeout = atoi(*argv);
1071	if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
1072	  VarRetryTimeout = 3;
1073      }
1074    }
1075    return 0;
1076  }
1077  return -1;
1078}
1079
1080struct in_addr
1081GetIpAddr(char *cp)
1082{
1083  struct hostent *hp;
1084  struct in_addr ipaddr;
1085
1086  hp = gethostbyname(cp);
1087  if (hp && hp->h_addrtype == AF_INET)
1088    bcopy(hp->h_addr, &ipaddr, hp->h_length);
1089  else if (inet_aton(cp, &ipaddr) == 0)
1090    ipaddr.s_addr = 0;
1091  return (ipaddr);
1092}
1093
1094static int
1095SetInterfaceAddr(struct cmdtab const * list, int argc, char **argv)
1096{
1097  DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
1098
1099  if (argc > 4)
1100    return -1;
1101
1102  HaveTriggerAddress = 0;
1103  ifnetmask.s_addr = 0;
1104
1105  if (argc > 0) {
1106    if (ParseAddr(argc, argv++,
1107		  &DefMyAddress.ipaddr,
1108		  &DefMyAddress.mask,
1109		  &DefMyAddress.width) == 0)
1110      return 1;
1111    if (--argc > 0) {
1112      if (ParseAddr(argc, argv++,
1113		    &DefHisAddress.ipaddr,
1114		    &DefHisAddress.mask,
1115		    &DefHisAddress.width) == 0)
1116	return 2;
1117      if (--argc > 0) {
1118	ifnetmask = GetIpAddr(*argv);
1119	if (--argc > 0) {
1120	  TriggerAddress = GetIpAddr(*argv);
1121	  HaveTriggerAddress = 1;
1122	}
1123      }
1124    }
1125  }
1126
1127  /*
1128   * For backwards compatibility, 0.0.0.0 means any address.
1129   */
1130  if (DefMyAddress.ipaddr.s_addr == 0) {
1131    DefMyAddress.mask.s_addr = 0;
1132    DefMyAddress.width = 0;
1133  }
1134  if (DefHisAddress.ipaddr.s_addr == 0) {
1135    DefHisAddress.mask.s_addr = 0;
1136    DefHisAddress.width = 0;
1137  }
1138  IpcpInfo.want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
1139  IpcpInfo.his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
1140
1141  if ((mode & MODE_AUTO) ||
1142      ((mode & MODE_DEDICATED) && dstsystem)) {
1143    if (OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask) < 0)
1144      return 4;
1145  }
1146  return 0;
1147}
1148
1149#ifndef NOMSEXT
1150
1151void
1152SetMSEXT(struct in_addr * pri_addr,
1153	 struct in_addr * sec_addr,
1154	 int argc,
1155	 char **argv)
1156{
1157  int dummyint;
1158  struct in_addr dummyaddr;
1159
1160  pri_addr->s_addr = sec_addr->s_addr = 0L;
1161
1162  if (argc > 0) {
1163    ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
1164    if (--argc > 0)
1165      ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
1166    else
1167      sec_addr->s_addr = pri_addr->s_addr;
1168  }
1169
1170  /*
1171   * if the primary/secondary ns entries are 0.0.0.0 we should set them to
1172   * either the localhost's ip, or the values in /etc/resolv.conf ??
1173   *
1174   * up to you if you want to implement this...
1175   */
1176
1177}
1178
1179static int
1180SetNS(struct cmdtab const * list, int argc, char **argv)
1181{
1182  SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv);
1183  return 0;
1184}
1185
1186static int
1187SetNBNS(struct cmdtab const * list, int argc, char **argv)
1188{
1189  SetMSEXT(&nbns_entries[0], &nbns_entries[1], argc, argv);
1190  return 0;
1191}
1192
1193#endif				/* MS_EXT */
1194
1195int
1196SetVariable(struct cmdtab const * list, int argc, char **argv, int param)
1197{
1198  u_long map;
1199  char *arg;
1200
1201  if (argc > 0)
1202    arg = *argv;
1203  else
1204    arg = "";
1205
1206  switch (param) {
1207  case VAR_AUTHKEY:
1208    strncpy(VarAuthKey, arg, sizeof(VarAuthKey) - 1);
1209    VarAuthKey[sizeof(VarAuthKey) - 1] = '\0';
1210    break;
1211  case VAR_AUTHNAME:
1212    strncpy(VarAuthName, arg, sizeof(VarAuthName) - 1);
1213    VarAuthName[sizeof(VarAuthName) - 1] = '\0';
1214    break;
1215  case VAR_DIAL:
1216    strncpy(VarDialScript, arg, sizeof(VarDialScript) - 1);
1217    VarDialScript[sizeof(VarDialScript) - 1] = '\0';
1218    break;
1219  case VAR_LOGIN:
1220    strncpy(VarLoginScript, arg, sizeof(VarLoginScript) - 1);
1221    VarLoginScript[sizeof(VarLoginScript) - 1] = '\0';
1222    break;
1223  case VAR_DEVICE:
1224    if (modem != -1)
1225      LogPrintf(LogWARN, "Cannot change device to \"%s\" when \"%s\" is open\n",
1226                arg, VarDevice);
1227    else {
1228      strncpy(VarDevice, arg, sizeof(VarDevice) - 1);
1229      VarDevice[sizeof(VarDevice) - 1] = '\0';
1230      VarBaseDevice = rindex(VarDevice, '/');
1231      VarBaseDevice = VarBaseDevice ? VarBaseDevice + 1 : "";
1232    }
1233    break;
1234  case VAR_ACCMAP:
1235    sscanf(arg, "%lx", &map);
1236    VarAccmap = map;
1237    break;
1238  case VAR_PHONE:
1239    strncpy(VarPhoneList, arg, sizeof(VarPhoneList) - 1);
1240    VarPhoneList[sizeof(VarPhoneList) - 1] = '\0';
1241    strcpy(VarPhoneCopy, VarPhoneList);
1242    VarNextPhone = VarPhoneCopy;
1243    break;
1244  case VAR_HANGUP:
1245    strncpy(VarHangupScript, arg, sizeof(VarHangupScript) - 1);
1246    VarHangupScript[sizeof(VarHangupScript) - 1] = '\0';
1247    break;
1248  case VAR_ENC:
1249    VarEncMD4 = !strcasecmp(arg, "md4");
1250    break;
1251  }
1252  return 0;
1253}
1254
1255static int
1256SetCtsRts(struct cmdtab const * list, int argc, char **argv)
1257{
1258  if (argc > 0) {
1259    if (strcmp(*argv, "on") == 0)
1260      VarCtsRts = TRUE;
1261    else if (strcmp(*argv, "off") == 0)
1262      VarCtsRts = FALSE;
1263    else
1264      return -1;
1265    return 0;
1266  }
1267  return -1;
1268}
1269
1270
1271static int
1272SetOpenMode(struct cmdtab const * list, int argc, char **argv)
1273{
1274  if (argc > 0) {
1275    if (strcmp(*argv, "active") == 0)
1276      VarOpenMode = OPEN_ACTIVE;
1277    else if (strcmp(*argv, "passive") == 0)
1278      VarOpenMode = OPEN_PASSIVE;
1279    else
1280      return -1;
1281    return 0;
1282  }
1283  return -1;
1284}
1285
1286extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
1287
1288struct cmdtab const SetCommands[] = {
1289  {"accmap", NULL, SetVariable, LOCAL_AUTH,
1290  "Set accmap value", "set accmap hex-value", (void *) VAR_ACCMAP},
1291  {"afilter", NULL, SetAfilter, LOCAL_AUTH,
1292  "Set keep Alive filter", "set afilter ..."},
1293  {"authkey", "key", SetVariable, LOCAL_AUTH,
1294  "Set authentication key", "set authkey|key key", (void *) VAR_AUTHKEY},
1295  {"authname", NULL, SetVariable, LOCAL_AUTH,
1296  "Set authentication name", "set authname name", (void *) VAR_AUTHNAME},
1297  {"ctsrts", NULL, SetCtsRts, LOCAL_AUTH,
1298  "Use CTS/RTS modem signalling", "set ctsrts [on|off]"},
1299  {"device", "line", SetVariable, LOCAL_AUTH,
1300  "Set modem device name", "set device|line device-name", (void *) VAR_DEVICE},
1301  {"dfilter", NULL, SetDfilter, LOCAL_AUTH,
1302  "Set demand filter", "set dfilter ..."},
1303  {"dial", NULL, SetVariable, LOCAL_AUTH,
1304  "Set dialing script", "set dial chat-script", (void *) VAR_DIAL},
1305  {"encrypt", NULL, SetVariable, LOCAL_AUTH,
1306  "Set CHAP encryption algorithm", "set encrypt MD4|MD5", (void *) VAR_ENC},
1307  {"escape", NULL, SetEscape, LOCAL_AUTH,
1308  "Set escape characters", "set escape hex-digit ..."},
1309  {"hangup", NULL, SetVariable, LOCAL_AUTH,
1310  "Set hangup script", "set hangup chat-script", (void *) VAR_HANGUP},
1311  {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH,
1312  "Set destination address", "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
1313  {"ifilter", NULL, SetIfilter, LOCAL_AUTH,
1314  "Set input filter", "set ifilter ..."},
1315  {"loopback", NULL, SetLoopback, LOCAL_AUTH,
1316  "Set loopback facility", "set loopback on|off"},
1317  {"log", NULL, SetLogLevel, LOCAL_AUTH,
1318  "Set log level", "set log [+|-]value..."},
1319  {"login", NULL, SetVariable, LOCAL_AUTH,
1320  "Set login script", "set login chat-script", (void *) VAR_LOGIN},
1321  {"mru", NULL, SetInitialMRU, LOCAL_AUTH,
1322  "Set Initial MRU value", "set mru value"},
1323  {"mtu", NULL, SetPreferredMTU, LOCAL_AUTH,
1324  "Set Preferred MTU value", "set mtu value"},
1325  {"ofilter", NULL, SetOfilter, LOCAL_AUTH,
1326  "Set output filter", "set ofilter ..."},
1327  {"openmode", NULL, SetOpenMode, LOCAL_AUTH,
1328  "Set open mode", "set openmode [active|passive]"},
1329  {"parity", NULL, SetModemParity, LOCAL_AUTH,
1330  "Set modem parity", "set parity [odd|even|none]"},
1331  {"phone", NULL, SetVariable, LOCAL_AUTH,
1332  "Set telephone number(s)", "set phone phone1[:phone2[...]]", (void *) VAR_PHONE},
1333  {"reconnect", NULL, SetReconnect, LOCAL_AUTH,
1334  "Set Reconnect timeout", "set reconnect value ntries"},
1335  {"redial", NULL, SetRedialTimeout, LOCAL_AUTH,
1336  "Set Redial timeout", "set redial value|random[.value|random] [dial_attempts]"},
1337  {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH,
1338  "Set STOPPED timeouts", "set stopped [LCPseconds [IPCPseconds [CCPseconds]]]"},
1339  {"server", "socket", SetServer, LOCAL_AUTH,
1340  "Set server port", "set server|socket TcpPort|LocalName|none [mask]"},
1341  {"speed", NULL, SetModemSpeed, LOCAL_AUTH,
1342  "Set modem speed", "set speed value"},
1343  {"timeout", NULL, SetIdleTimeout, LOCAL_AUTH,
1344  "Set Idle timeout", "set timeout value"},
1345#ifndef NOMSEXT
1346  {"ns", NULL, SetNS, LOCAL_AUTH,
1347  "Set NameServer", "set ns pri-addr [sec-addr]"},
1348  {"nbns", NULL, SetNBNS, LOCAL_AUTH,
1349  "Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"},
1350#endif
1351  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
1352  "Display this message", "set help|? [command]", (void *) SetCommands},
1353  {NULL, NULL, NULL},
1354};
1355
1356static int
1357SetCommand(struct cmdtab const * list, int argc, char **argv)
1358{
1359  if (argc > 0)
1360    FindExec(SetCommands, argc, argv);
1361  else if (VarTerm)
1362    fprintf(VarTerm, "Use `set ?' to get a list or `set ? <var>' for"
1363	    " syntax help.\n");
1364  else
1365    LogPrintf(LogWARN, "set command must have arguments\n");
1366
1367  return 0;
1368}
1369
1370
1371static int
1372AddCommand(struct cmdtab const * list, int argc, char **argv)
1373{
1374  struct in_addr dest, gateway, netmask;
1375
1376  if (argc == 3) {
1377    if (strcasecmp(argv[0], "MYADDR") == 0)
1378      dest = IpcpInfo.want_ipaddr;
1379    else
1380      dest = GetIpAddr(argv[0]);
1381    netmask = GetIpAddr(argv[1]);
1382    if (strcasecmp(argv[2], "HISADDR") == 0)
1383      gateway = IpcpInfo.his_ipaddr;
1384    else
1385      gateway = GetIpAddr(argv[2]);
1386    OsSetRoute(RTM_ADD, dest, gateway, netmask);
1387    return 0;
1388  }
1389  return -1;
1390}
1391
1392static int
1393DeleteCommand(struct cmdtab const * list, int argc, char **argv)
1394{
1395  struct in_addr dest, gateway, netmask;
1396
1397  if (argc == 1 && strcasecmp(argv[0], "all") == 0)
1398    DeleteIfRoutes(0);
1399  else if (argc > 0 && argc < 4) {
1400    if (strcasecmp(argv[0], "MYADDR") == 0)
1401      dest = IpcpInfo.want_ipaddr;
1402    else
1403      dest = GetIpAddr(argv[0]);
1404    netmask.s_addr = INADDR_ANY;
1405    if (argc > 1) {
1406      if (strcasecmp(argv[1], "HISADDR") == 0)
1407	gateway = IpcpInfo.his_ipaddr;
1408      else
1409	gateway = GetIpAddr(argv[1]);
1410      if (argc == 3) {
1411	if (inet_aton(argv[2], &netmask) == 0) {
1412	  LogPrintf(LogWARN, "Bad netmask value.\n");
1413	  return -1;
1414	}
1415      }
1416    } else
1417      gateway.s_addr = INADDR_ANY;
1418    OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1419  } else
1420    return -1;
1421
1422  return 0;
1423}
1424
1425static int AliasEnable();
1426static int AliasOption();
1427
1428static struct cmdtab const AliasCommands[] =
1429{
1430  {"enable", NULL, AliasEnable, LOCAL_AUTH,
1431  "enable IP aliasing", "alias enable [yes|no]"},
1432  {"port", NULL, AliasRedirectPort, LOCAL_AUTH,
1433  "port redirection", "alias port [proto addr_local:port_local  port_alias]"},
1434  {"addr", NULL, AliasRedirectAddr, LOCAL_AUTH,
1435  "static address translation", "alias addr [addr_local addr_alias]"},
1436  {"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
1437    "stop incoming connections", "alias deny_incoming [yes|no]",
1438  (void *) PKT_ALIAS_DENY_INCOMING},
1439  {"log", NULL, AliasOption, LOCAL_AUTH,
1440    "log aliasing link creation", "alias log [yes|no]",
1441  (void *) PKT_ALIAS_LOG},
1442  {"same_ports", NULL, AliasOption, LOCAL_AUTH,
1443    "try to leave port numbers unchanged", "alias same_ports [yes|no]",
1444  (void *) PKT_ALIAS_SAME_PORTS},
1445  {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
1446    "allocate host sockets", "alias use_sockets [yes|no]",
1447  (void *) PKT_ALIAS_USE_SOCKETS},
1448  {"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
1449    "alias unregistered (private) IP address space only",
1450    "alias unregistered_only [yes|no]",
1451  (void *) PKT_ALIAS_UNREGISTERED_ONLY},
1452  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
1453    "Display this message", "alias help|? [command]",
1454  (void *) AliasCommands},
1455  {NULL, NULL, NULL},
1456};
1457
1458
1459static int
1460AliasCommand(struct cmdtab const * list, int argc, char **argv)
1461{
1462  if (argc > 0)
1463    FindExec(AliasCommands, argc, argv);
1464  else if (VarTerm)
1465    fprintf(VarTerm, "Use `alias help' to get a list or `alias help <option>'"
1466	    " for syntax help.\n");
1467  else
1468    LogPrintf(LogWARN, "alias command must have arguments\n");
1469
1470  return 0;
1471}
1472
1473static int
1474AliasEnable(struct cmdtab const * list, int argc, char **argv)
1475{
1476  if (argc == 1)
1477    if (strcasecmp(argv[0], "yes") == 0) {
1478      if (!(mode & MODE_ALIAS)) {
1479	if (loadAliasHandlers(&VarAliasHandlers) == 0) {
1480	  mode |= MODE_ALIAS;
1481	  return 0;
1482	}
1483	LogPrintf(LogWARN, "Cannot load alias library\n");
1484	return 1;
1485      }
1486      return 0;
1487    } else if (strcasecmp(argv[0], "no") == 0) {
1488      if (mode & MODE_ALIAS) {
1489	unloadAliasHandlers();
1490	mode &= ~MODE_ALIAS;
1491      }
1492      return 0;
1493    }
1494  return -1;
1495}
1496
1497
1498static int
1499AliasOption(struct cmdtab const * list, int argc, char **argv, void *param)
1500{
1501  if (argc == 1)
1502    if (strcasecmp(argv[0], "yes") == 0) {
1503      if (mode & MODE_ALIAS) {
1504	VarPacketAliasSetMode((unsigned) param, (unsigned) param);
1505	return 0;
1506      }
1507      LogPrintf(LogWARN, "alias not enabled\n");
1508    } else if (strcmp(argv[0], "no") == 0) {
1509      if (mode & MODE_ALIAS) {
1510	VarPacketAliasSetMode(0, (unsigned) param);
1511	return 0;
1512      }
1513      LogPrintf(LogWARN, "alias not enabled\n");
1514    }
1515  return -1;
1516}
1517