command.c revision 29521
1/*
2 *		PPP User command processing module
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: command.c,v 1.80 1997/09/09 23:56:29 brian Exp $
21 *
22 */
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <ctype.h>
26#include <termios.h>
27#include <sys/wait.h>
28#include <time.h>
29#include <netdb.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#include <net/route.h>
34#include <paths.h>
35#include <alias.h>
36#include <fcntl.h>
37#include <errno.h>
38#include "fsm.h"
39#include "phase.h"
40#include "lcp.h"
41#include "ipcp.h"
42#include "modem.h"
43#include "filter.h"
44#include "command.h"
45#include "alias_cmd.h"
46#include "hdlc.h"
47#include "loadalias.h"
48#include "vars.h"
49#include "systems.h"
50#include "chat.h"
51#include "os.h"
52#include "timeout.h"
53#include "server.h"
54
55extern void Cleanup(), TtyTermMode(), PacketMode();
56extern int EnableCommand(), DisableCommand(), DisplayCommand();
57extern int AcceptCommand(), DenyCommand();
58static int AliasCommand();
59extern int LocalAuthCommand();
60extern int LoadCommand(), SaveCommand();
61extern int ChangeParity(char *);
62extern int SelectSystem();
63extern int ShowRoute();
64extern void TtyOldMode(), TtyCommandMode();
65extern struct pppvars pppVars;
66extern struct cmdtab const SetCommands[];
67
68extern char *IfDevName;
69
70struct in_addr ifnetmask;
71int randinit;
72
73static int ShowCommand(struct cmdtab const *, int, char **);
74static int TerminalCommand(struct cmdtab const *, int, char **);
75static int QuitCommand(struct cmdtab const *, int, char **);
76static int CloseCommand(struct cmdtab const *, int, char **);
77static int DialCommand(struct cmdtab const *, int, char **);
78static int DownCommand(struct cmdtab const *, int, char **);
79static int SetCommand(struct cmdtab const *, int, char **);
80static int AddCommand(struct cmdtab const *, int, char **);
81static int DeleteCommand(struct cmdtab const *, int, char **);
82static int BgShellCommand(struct cmdtab const *, int, char **);
83static int FgShellCommand(struct cmdtab const *, int, char **);
84static int ShellCommand(struct cmdtab const *, int, char **, int);
85
86static int
87HelpCommand(struct cmdtab const * list,
88	    int argc,
89	    char **argv,
90	    struct cmdtab const * plist)
91{
92  struct cmdtab const *cmd;
93  int n;
94
95  if (!VarTerm)
96    return 0;
97
98  if (argc > 0) {
99    for (cmd = plist; cmd->name; cmd++)
100      if (strcasecmp(cmd->name, *argv) == 0 && (cmd->lauth & VarLocalAuth)) {
101	fprintf(VarTerm, "%s\n", cmd->syntax);
102	return 0;
103      }
104    return -1;
105  }
106  n = 0;
107  for (cmd = plist; cmd->func; cmd++)
108    if (cmd->name && (cmd->lauth & VarLocalAuth)) {
109      fprintf(VarTerm, "  %-9s: %-20s\n", cmd->name, cmd->helpmes);
110      n++;
111    }
112  if (n & 1)
113    fprintf(VarTerm, "\n");
114
115  return 0;
116}
117
118int
119IsInteractive()
120{
121  char *mes = NULL;
122
123  if (mode & MODE_DDIAL)
124    mes = "Working in dedicated dial mode.";
125  else if (mode & MODE_BACKGROUND)
126    mes = "Working in background mode.";
127  else if (mode & MODE_AUTO)
128    mes = "Working in auto mode.";
129  else if (mode & MODE_DIRECT)
130    mes = "Working in direct mode.";
131  else if (mode & MODE_DEDICATED)
132    mes = "Working in dedicated mode.";
133  if (mes) {
134    if (VarTerm)
135      fprintf(VarTerm, "%s\n", mes);
136    return 0;
137  }
138  return 1;
139}
140
141static int
142DialCommand(struct cmdtab const * cmdlist, int argc, char **argv)
143{
144  int tries;
145  int res;
146
147  if (LcpFsm.state > ST_CLOSED) {
148    if (VarTerm)
149      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
150    return 0;
151  }
152
153  if (argc > 0) {
154    if (SelectSystem(*argv, CONFFILE) < 0) {
155      if (VarTerm)
156	fprintf(VarTerm, "%s: not found.\n", *argv);
157      return -1;
158    }
159  }
160  tries = 0;
161  do {
162    if (VarTerm)
163      fprintf(VarTerm, "Dial attempt %u of %d\n", ++tries, VarDialTries);
164    if (OpenModem(mode) < 0) {
165      if (VarTerm)
166	fprintf(VarTerm, "Failed to open modem.\n");
167      break;
168    }
169    if ((res = DialModem()) == EX_DONE) {
170      sleep(1);
171      ModemTimeout();
172      PacketMode();
173      break;
174    } else if (res == EX_SIG)
175      return 1;
176  } while (VarDialTries == 0 || tries < VarDialTries);
177
178  return 0;
179}
180
181static int
182SetLoopback(struct cmdtab const * cmdlist, int argc, char **argv)
183{
184  if (argc == 1)
185    if (!strcasecmp(*argv, "on"))
186      VarLoopback = 1;
187    else if (!strcasecmp(*argv, "off"))
188      VarLoopback = 0;
189  return -1;
190}
191
192static int
193BgShellCommand(struct cmdtab const * cmdlist, int argc, char **argv)
194{
195  if (argc == 0)
196    return -1;
197  return ShellCommand(cmdlist, argc, argv, 1);
198}
199
200static int
201FgShellCommand(struct cmdtab const * cmdlist, int argc, char **argv)
202{
203  return ShellCommand(cmdlist, argc, argv, 0);
204}
205
206static int
207ShellCommand(struct cmdtab const * cmdlist, int argc, char **argv, int bg)
208{
209  const char *shell;
210  pid_t shpid;
211  FILE *oVarTerm;
212
213#ifdef SHELL_ONLY_INTERACTIVELY
214  /* we're only allowed to shell when we run ppp interactively */
215  if (mode != MODE_INTER) {
216    LogPrintf(LogWARN, "Can only start a shell in interactive mode\n");
217    return 1;
218  }
219#endif
220#ifdef NO_SHELL_IN_AUTO_INTERACTIVE
221
222  /*
223   * we want to stop shell commands when we've got a telnet connection to an
224   * auto mode ppp
225   */
226  if ((mode & (MODE_AUTO | MODE_INTER)) == (MODE_AUTO | MODE_INTER)) {
227    LogPrintf(LogWARN, "Shell is not allowed interactively in auto mode\n");
228    return 1;
229  }
230#endif
231
232  if (argc == 0)
233    if (!(mode & MODE_INTER)) {
234      LogPrintf(LogWARN, "Can only start an interactive shell in"
235		" interactive mode\n");
236      return 1;
237    } else if (bg) {
238      LogPrintf(LogWARN, "Can only start an interactive shell in"
239		" the foreground mode\n");
240      return 1;
241    } else if (mode&(MODE_AUTO|MODE_DEDICATED|MODE_DIRECT)) {
242      LogPrintf(LogWARN, "Can't start an interactive shell from"
243		" a telnet session\n");
244      return 1;
245    }
246  if ((shell = getenv("SHELL")) == 0)
247    shell = _PATH_BSHELL;
248
249  if ((shpid = fork()) == 0) {
250    int dtablesize, i, fd;
251
252    if (VarTerm)
253      fd = fileno(VarTerm);
254    else if ((fd = open("/dev/null", O_RDWR)) == -1) {
255      LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno));
256      exit(1);
257    }
258    for (i = 0; i < 3; i++)
259      dup2(fd, i);
260
261    if (fd > 2)
262      if (VarTerm) {
263	oVarTerm = VarTerm;
264	VarTerm = 0;
265	if (oVarTerm && oVarTerm != stdout)
266	  fclose(oVarTerm);
267      } else
268	close(fd);
269
270    for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++)
271      (void) close(i);
272
273    /*
274     * We are running setuid, we should change to real user for avoiding
275     * security problems.
276     */
277    if (setgid(getgid()) < 0) {
278      LogPrintf(LogERROR, "setgid: %s\n", strerror(errno));
279      exit(1);
280    }
281    if (setuid(getuid()) < 0) {
282      LogPrintf(LogERROR, "setuid: %s\n", strerror(errno));
283      exit(1);
284    }
285    TtyOldMode();
286    if (argc > 0) {
287      /* substitute pseudo args */
288      for (i = 1; i < argc; i++)
289	if (strcasecmp(argv[i], "HISADDR") == 0)
290	  argv[i] = strdup(inet_ntoa(IpcpInfo.his_ipaddr));
291	else if (strcasecmp(argv[i], "INTERFACE") == 0)
292	  argv[i] = strdup(IfDevName);
293	else if (strcasecmp(argv[i], "MYADDR") == 0)
294	  argv[i] = strdup(inet_ntoa(IpcpInfo.want_ipaddr));
295      if (bg) {
296	pid_t p;
297
298	p = getpid();
299	if (daemon(1, 1) == -1) {
300	  LogPrintf(LogERROR, "%d: daemon: %s\n", p, strerror(errno));
301	  exit(1);
302	}
303      }
304      (void) execvp(argv[0], argv);
305    } else
306      (void) execl(shell, shell, NULL);
307
308    LogPrintf(LogWARN, "exec() of %s failed\n", argc > 0 ? argv[0] : shell);
309    exit(255);
310  }
311  if (shpid == (pid_t) - 1) {
312    LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno));
313  } else {
314    int status;
315
316    (void) waitpid(shpid, &status, 0);
317  }
318
319  TtyCommandMode(1);
320
321  return (0);
322}
323
324struct cmdtab const Commands[] = {
325  {"accept", NULL, AcceptCommand, LOCAL_AUTH,
326  "accept option request", "accept option .."},
327  {"add", NULL, AddCommand, LOCAL_AUTH,
328  "add route", "add dest mask gateway"},
329  {"bg", "!bg", BgShellCommand, LOCAL_AUTH,
330  "Run a command in the background", "[!]bg command"},
331  {"close", NULL, CloseCommand, LOCAL_AUTH,
332  "Close connection", "close"},
333  {"delete", NULL, DeleteCommand, LOCAL_AUTH,
334  "delete route", "delete ALL | dest [gateway [mask]]"},
335  {"deny", NULL, DenyCommand, LOCAL_AUTH,
336  "Deny option request", "deny option .."},
337  {"dial", "call", DialCommand, LOCAL_AUTH,
338  "Dial and login", "dial|call [remote]"},
339  {"disable", NULL, DisableCommand, LOCAL_AUTH,
340  "Disable option", "disable option .."},
341  {"display", NULL, DisplayCommand, LOCAL_AUTH,
342  "Display option configs", "display"},
343  {"enable", NULL, EnableCommand, LOCAL_AUTH,
344  "Enable option", "enable option .."},
345  {"passwd", NULL, LocalAuthCommand, LOCAL_NO_AUTH,
346  "Password for manipulation", "passwd LocalPassword"},
347  {"load", NULL, LoadCommand, LOCAL_AUTH,
348  "Load settings", "load [remote]"},
349  {"save", NULL, SaveCommand, LOCAL_AUTH,
350  "Save settings", "save"},
351  {"set", "setup", SetCommand, LOCAL_AUTH,
352  "Set parameters", "set[up] var value"},
353  {"shell", "!", FgShellCommand, LOCAL_AUTH,
354  "Run a subshell", "shell|! [sh command]"},
355  {"show", NULL, ShowCommand, LOCAL_AUTH,
356  "Show status and statictics", "show var"},
357  {"term", NULL, TerminalCommand, LOCAL_AUTH,
358  "Enter to terminal mode", "term"},
359  {"alias", NULL, AliasCommand, LOCAL_AUTH,
360  "alias control", "alias option [yes|no]"},
361  {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
362  "Quit PPP program", "quit|bye [all]"},
363  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
364  "Display this message", "help|? [command]", (void *) Commands},
365  {NULL, "down", DownCommand, LOCAL_AUTH,
366  "Generate down event", "down"},
367  {NULL, NULL, NULL},
368};
369
370extern int ReportCcpStatus();
371extern int ReportLcpStatus();
372extern int ReportIpcpStatus();
373extern int ReportProtStatus();
374extern int ReportCompress();
375extern int ShowModemStatus();
376extern int ReportHdlcStatus();
377extern int ShowMemMap();
378
379static int
380ShowLoopback()
381{
382  if (VarTerm)
383    fprintf(VarTerm, "Local loopback is %s\n", VarLoopback ? "on" : "off");
384
385  return 0;
386}
387
388static int
389ShowLogLevel()
390{
391  int i;
392
393  if (!VarTerm)
394    return 0;
395  fprintf(VarTerm, "Log:");
396  for (i = LogMIN; i < LogMAXCONF; i++) {
397    if (LogIsKept(i))
398      fprintf(VarTerm, " %s", LogName(i));
399  }
400  fprintf(VarTerm, "\n");
401
402  return 0;
403}
404
405static int
406ShowEscape()
407{
408  int code, bit;
409
410  if (!VarTerm)
411    return 0;
412  if (EscMap[32]) {
413    for (code = 0; code < 32; code++)
414      if (EscMap[code])
415	for (bit = 0; bit < 8; bit++)
416	  if (EscMap[code] & (1 << bit))
417	    fprintf(VarTerm, " 0x%02x", (code << 3) + bit);
418    fprintf(VarTerm, "\n");
419  }
420  return 1;
421}
422
423static int
424ShowTimeout()
425{
426  if (!VarTerm)
427    return 0;
428  fprintf(VarTerm, " Idle Timer: %d secs   LQR Timer: %d secs"
429	  "   Retry Timer: %d secs\n", VarIdleTimeout, VarLqrTimeout,
430	  VarRetryTimeout);
431  return 1;
432}
433
434static int
435ShowStopped()
436{
437  if (!VarTerm)
438    return 0;
439
440  fprintf(VarTerm, " Stopped Timer:  LCP: ");
441  if (!LcpFsm.StoppedTimer.load)
442    fprintf(VarTerm, "Disabled");
443  else
444    fprintf(VarTerm, "%ld secs", LcpFsm.StoppedTimer.load / SECTICKS);
445
446  fprintf(VarTerm, ", IPCP: ");
447  if (!IpcpFsm.StoppedTimer.load)
448    fprintf(VarTerm, "Disabled");
449  else
450    fprintf(VarTerm, "%ld secs", IpcpFsm.StoppedTimer.load / SECTICKS);
451
452  fprintf(VarTerm, ", CCP: ");
453  if (!CcpFsm.StoppedTimer.load)
454    fprintf(VarTerm, "Disabled");
455  else
456    fprintf(VarTerm, "%ld secs", CcpFsm.StoppedTimer.load / SECTICKS);
457
458  fprintf(VarTerm, "\n");
459
460  return 1;
461}
462
463static int
464ShowAuthKey()
465{
466  if (!VarTerm)
467    return 0;
468  fprintf(VarTerm, "AuthName = %s\n", VarAuthName);
469  fprintf(VarTerm, "AuthKey  = %s\n", VarAuthKey);
470  return 1;
471}
472
473static int
474ShowVersion()
475{
476  extern char VarVersion[];
477  extern char VarLocalVersion[];
478
479  if (!VarTerm)
480    return 0;
481  fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
482  return 1;
483}
484
485static int
486ShowInitialMRU()
487{
488  if (!VarTerm)
489    return 0;
490  fprintf(VarTerm, " Initial MRU: %ld\n", VarMRU);
491  return 1;
492}
493
494static int
495ShowPreferredMTU()
496{
497  if (!VarTerm)
498    return 0;
499  if (VarPrefMTU)
500    fprintf(VarTerm, " Preferred MTU: %ld\n", VarPrefMTU);
501  else
502    fprintf(VarTerm, " Preferred MTU: unspecified\n");
503  return 1;
504}
505
506static int
507ShowReconnect()
508{
509  if (!VarTerm)
510    return 0;
511  fprintf(VarTerm, " Reconnect Timer:  %d,  %d tries\n",
512	  VarReconnectTimer, VarReconnectTries);
513  return 1;
514}
515
516static int
517ShowRedial()
518{
519  if (!VarTerm)
520    return 0;
521  fprintf(VarTerm, " Redial Timer: ");
522
523  if (VarRedialTimeout >= 0) {
524    fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
525  } else {
526    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
527  }
528
529  fprintf(VarTerm, " Redial Next Timer: ");
530
531  if (VarRedialNextTimeout >= 0) {
532    fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
533  } else {
534    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
535  }
536
537  if (VarDialTries)
538    fprintf(VarTerm, "%d dial tries", VarDialTries);
539
540  fprintf(VarTerm, "\n");
541
542  return 1;
543}
544
545#ifndef NOMSEXT
546static int
547ShowMSExt()
548{
549  if (!VarTerm)
550    return 0;
551  fprintf(VarTerm, " MS PPP extention values \n");
552  fprintf(VarTerm, "   Primary NS     : %s\n", inet_ntoa(ns_entries[0]));
553  fprintf(VarTerm, "   Secondary NS   : %s\n", inet_ntoa(ns_entries[1]));
554  fprintf(VarTerm, "   Primary NBNS   : %s\n", inet_ntoa(nbns_entries[0]));
555  fprintf(VarTerm, "   Secondary NBNS : %s\n", inet_ntoa(nbns_entries[1]));
556  return 1;
557}
558
559#endif
560
561extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
562
563struct cmdtab const ShowCommands[] = {
564  {"afilter", NULL, ShowAfilter, LOCAL_AUTH,
565  "Show keep Alive filters", "show afilter option .."},
566  {"auth", NULL, ShowAuthKey, LOCAL_AUTH,
567  "Show auth name/key", "show auth"},
568  {"ccp", NULL, ReportCcpStatus, LOCAL_AUTH,
569  "Show CCP status", "show cpp"},
570  {"compress", NULL, ReportCompress, LOCAL_AUTH,
571  "Show compression statictics", "show compress"},
572  {"dfilter", NULL, ShowDfilter, LOCAL_AUTH,
573  "Show Demand filters", "show dfilteroption .."},
574  {"escape", NULL, ShowEscape, LOCAL_AUTH,
575  "Show escape characters", "show escape"},
576  {"hdlc", NULL, ReportHdlcStatus, LOCAL_AUTH,
577  "Show HDLC error summary", "show hdlc"},
578  {"ifilter", NULL, ShowIfilter, LOCAL_AUTH,
579  "Show Input filters", "show ifilter option .."},
580  {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH,
581  "Show IPCP status", "show ipcp"},
582  {"lcp", NULL, ReportLcpStatus, LOCAL_AUTH,
583  "Show LCP status", "show lcp"},
584  {"loopback", NULL, ShowLoopback, LOCAL_AUTH,
585  "Show current loopback setting", "show loopback"},
586  {"log", NULL, ShowLogLevel, LOCAL_AUTH,
587  "Show current log level", "show log"},
588  {"mem", NULL, ShowMemMap, LOCAL_AUTH,
589  "Show memory map", "show mem"},
590  {"modem", NULL, ShowModemStatus, LOCAL_AUTH,
591  "Show modem setups", "show modem"},
592  {"mru", NULL, ShowInitialMRU, LOCAL_AUTH,
593  "Show Initial MRU", "show mru"},
594  {"mtu", NULL, ShowPreferredMTU, LOCAL_AUTH,
595  "Show Preferred MTU", "show mtu"},
596  {"ofilter", NULL, ShowOfilter, LOCAL_AUTH,
597  "Show Output filters", "show ofilter option .."},
598  {"proto", NULL, ReportProtStatus, LOCAL_AUTH,
599  "Show protocol summary", "show proto"},
600  {"reconnect", NULL, ShowReconnect, LOCAL_AUTH,
601  "Show Reconnect timer,tries", "show reconnect"},
602  {"redial", NULL, ShowRedial, LOCAL_AUTH,
603  "Show Redial timeout value", "show redial"},
604  {"route", NULL, ShowRoute, LOCAL_AUTH,
605  "Show routing table", "show route"},
606  {"timeout", NULL, ShowTimeout, LOCAL_AUTH,
607  "Show Idle timeout value", "show timeout"},
608  {"stopped", NULL, ShowStopped, LOCAL_AUTH,
609  "Show STOPPED timeout value", "show stopped"},
610#ifndef NOMSEXT
611  {"msext", NULL, ShowMSExt, LOCAL_AUTH,
612  "Show MS PPP extentions", "show msext"},
613#endif
614  {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
615  "Show version string", "show version"},
616  {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
617  "Display this message", "show help|? [command]", (void *) ShowCommands},
618  {NULL, NULL, NULL},
619};
620
621struct cmdtab const *
622FindCommand(struct cmdtab const * cmds, char *str, int *pmatch)
623{
624  int nmatch;
625  int len;
626  struct cmdtab const *found;
627
628  found = NULL;
629  len = strlen(str);
630  nmatch = 0;
631  while (cmds->func) {
632    if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
633      if (cmds->name[len] == '\0') {
634	*pmatch = 1;
635	return cmds;
636      }
637      nmatch++;
638      found = cmds;
639    } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
640      if (cmds->alias[len] == '\0') {
641	*pmatch = 1;
642	return cmds;
643      }
644      nmatch++;
645      found = cmds;
646    }
647    cmds++;
648  }
649  *pmatch = nmatch;
650  return found;
651}
652
653int
654FindExec(struct cmdtab const * cmdlist, int argc, char **argv)
655{
656  struct cmdtab const *cmd;
657  int val = 1;
658  int nmatch;
659
660  cmd = FindCommand(cmdlist, *argv, &nmatch);
661  if (nmatch > 1)
662    LogPrintf(LogWARN, "%s: Ambiguous command\n", *argv);
663  else if (cmd && (cmd->lauth & VarLocalAuth))
664    val = (cmd->func) (cmd, argc-1, argv+1, cmd->args);
665  else
666    LogPrintf(LogWARN, "%s: Invalid command\n", *argv);
667
668  if (val == -1)
669    LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
670  else if (val)
671    LogPrintf(LogCOMMAND, "%s: Failed %d\n", *argv, val);
672
673  return val;
674}
675
676int aft_cmd = 1;
677extern int TermMode;
678
679void
680Prompt()
681{
682  char *pconnect, *pauth;
683
684  if (!(mode & MODE_INTER) || !VarTerm || TermMode)
685    return;
686
687  if (!aft_cmd)
688    fprintf(VarTerm, "\n");
689  else
690    aft_cmd = 0;
691
692  if (VarLocalAuth == LOCAL_AUTH)
693    pauth = " ON ";
694  else
695    pauth = " on ";
696  if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
697    pconnect = "PPP";
698  else
699    pconnect = "ppp";
700  fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
701  fflush(VarTerm);
702}
703
704void
705DecodeCommand(char *buff, int nb, int prompt)
706{
707  char *vector[20];
708  char **argv;
709  int argc;
710  char *cp;
711
712  if (nb > 0) {
713    cp = buff + strcspn(buff, "\r\n");
714    if (cp)
715      *cp = '\0';
716    argc = MakeArgs(buff, vector, VECSIZE(vector));
717    argv = vector;
718
719    if (argc > 0)
720      FindExec(Commands, argc, argv);
721  }
722  if (prompt)
723    Prompt();
724}
725
726static int
727ShowCommand(struct cmdtab const * list, int argc, char **argv)
728{
729  if (argc > 0)
730    FindExec(ShowCommands, argc, argv);
731  else if (VarTerm)
732    fprintf(VarTerm, "Use ``show ?'' to get a list.\n");
733  else
734    LogPrintf(LogWARN, "show command must have arguments\n");
735
736  return 0;
737}
738
739static int
740TerminalCommand(struct cmdtab const * list, int argc, char **argv)
741{
742  if (LcpFsm.state > ST_CLOSED) {
743    if (VarTerm)
744      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
745    return 1;
746  }
747  if (!IsInteractive())
748    return (1);
749  if (OpenModem(mode) < 0) {
750    if (VarTerm)
751      fprintf(VarTerm, "Failed to open modem.\n");
752    return (1);
753  }
754  if (VarTerm) {
755    fprintf(VarTerm, "Enter to terminal mode.\n");
756    fprintf(VarTerm, "Type `~?' for help.\n");
757  }
758  TtyTermMode();
759  return (0);
760}
761
762static int
763QuitCommand(struct cmdtab const * list, int argc, char **argv)
764{
765  FILE *oVarTerm;
766
767  if (mode & (MODE_DIRECT | MODE_DEDICATED | MODE_AUTO)) {
768    if (argc > 0 && !strcasecmp(*argv, "all") && (VarLocalAuth & LOCAL_AUTH)) {
769      mode &= ~MODE_INTER;
770      oVarTerm = VarTerm;
771      VarTerm = 0;
772      if (oVarTerm && oVarTerm != stdout)
773	fclose(oVarTerm);
774      Cleanup(EX_NORMAL);
775    } else if (VarTerm) {
776      LogPrintf(LogPHASE, "Client connection closed.\n");
777      VarLocalAuth = LOCAL_NO_AUTH;
778      mode &= ~MODE_INTER;
779      oVarTerm = VarTerm;
780      VarTerm = 0;
781      if (oVarTerm && oVarTerm != stdout)
782	fclose(oVarTerm);
783      close(netfd);
784      netfd = -1;
785    }
786  } else
787    Cleanup(EX_NORMAL);
788
789  return 0;
790}
791
792static int
793CloseCommand(struct cmdtab const * list, int argc, char **argv)
794{
795  reconnect(RECON_FALSE);
796  LcpClose();
797  if (mode & MODE_BACKGROUND)
798    Cleanup(EX_NORMAL);
799  return 0;
800}
801
802static int
803DownCommand(struct cmdtab const * list, int argc, char **argv)
804{
805  LcpDown();
806  return 0;
807}
808
809static int
810SetModemSpeed(struct cmdtab const * list, int argc, char **argv)
811{
812  int speed;
813
814  if (argc > 0) {
815    if (strcasecmp(*argv, "sync") == 0) {
816      VarSpeed = 0;
817      return 0;
818    }
819    speed = atoi(*argv);
820    if (IntToSpeed(speed) != B0) {
821      VarSpeed = speed;
822      return 0;
823    }
824    LogPrintf(LogWARN, "%s: Invalid speed\n", *argv);
825  }
826  return -1;
827}
828
829static int
830SetReconnect(struct cmdtab const * list, int argc, char **argv)
831{
832  if (argc == 2) {
833    VarReconnectTimer = atoi(argv[0]);
834    VarReconnectTries = atoi(argv[1]);
835    return 0;
836  }
837  return -1;
838}
839
840static int
841SetRedialTimeout(struct cmdtab const * list, int argc, char **argv)
842{
843  int timeout;
844  int tries;
845  char *dot;
846
847  if (argc == 1 || argc == 2) {
848    if (strncasecmp(argv[0], "random", 6) == 0 &&
849	(argv[0][6] == '\0' || argv[0][6] == '.')) {
850      VarRedialTimeout = -1;
851      if (!randinit) {
852	randinit = 1;
853	srandomdev();
854      }
855    } else {
856      timeout = atoi(argv[0]);
857
858      if (timeout >= 0)
859	VarRedialTimeout = timeout;
860      else {
861	LogPrintf(LogWARN, "Invalid redial timeout\n");
862	return -1;
863      }
864    }
865
866    dot = index(argv[0], '.');
867    if (dot) {
868      if (strcasecmp(++dot, "random") == 0) {
869	VarRedialNextTimeout = -1;
870	if (!randinit) {
871	  randinit = 1;
872	  srandomdev();
873	}
874      } else {
875	timeout = atoi(dot);
876	if (timeout >= 0)
877	  VarRedialNextTimeout = timeout;
878	else {
879	  LogPrintf(LogWARN, "Invalid next redial timeout\n");
880	  return -1;
881	}
882      }
883    } else
884      VarRedialNextTimeout = NEXT_REDIAL_PERIOD;	/* Default next timeout */
885
886    if (argc == 2) {
887      tries = atoi(argv[1]);
888
889      if (tries >= 0) {
890	VarDialTries = tries;
891      } else {
892	LogPrintf(LogWARN, "Invalid retry value\n");
893	return 1;
894      }
895    }
896    return 0;
897  }
898  return -1;
899}
900
901static int
902SetStoppedTimeout(struct cmdtab const * list, int argc, char **argv)
903{
904  LcpFsm.StoppedTimer.load = 0;
905  IpcpFsm.StoppedTimer.load = 0;
906  CcpFsm.StoppedTimer.load = 0;
907  if (argc <= 3) {
908    if (argc > 0) {
909      LcpFsm.StoppedTimer.load = atoi(argv[0]) * SECTICKS;
910      if (argc > 1) {
911	IpcpFsm.StoppedTimer.load = atoi(argv[1]) * SECTICKS;
912	if (argc > 2)
913	  CcpFsm.StoppedTimer.load = atoi(argv[2]) * SECTICKS;
914      }
915    }
916    return 0;
917  }
918  return -1;
919}
920
921static int
922SetServer(struct cmdtab const * list, int argc, char **argv)
923{
924  int res = -1;
925
926  if (argc > 0 && argc < 3)
927    if (strcasecmp(argv[0], "none") == 0) {
928      ServerClose();
929      LogPrintf(LogPHASE, "Disabling server port.\n");
930      res = 0;
931    } else if (*argv[0] == '/') {
932      mode_t mask;
933
934      umask(mask = umask(0));
935      if (argc == 2) {
936	unsigned m;
937
938	if (sscanf(argv[1], "%o", &m) == 1)
939	  mask = m;
940      }
941      res = ServerLocalOpen(argv[0], mask);
942    } else {
943      int port;
944
945      if (strspn(argv[0], "0123456789") != strlen(argv[0])) {
946	struct servent *s;
947
948	if ((s = getservbyname(argv[0], "tcp")) == NULL) {
949	  port = 0;
950	  LogPrintf(LogWARN, "%s: Invalid port or service\n", argv[0]);
951	} else
952	  port = ntohs(s->s_port);
953      } else
954	port = atoi(argv[0]);
955      if (port)
956	res = ServerTcpOpen(port);
957    }
958
959  return res;
960}
961
962static int
963SetModemParity(struct cmdtab const * list, int argc, char **argv)
964{
965  return argc > 0 ? ChangeParity(*argv) : -1;
966}
967
968static int
969SetLogLevel(struct cmdtab const * list, int argc, char **argv)
970{
971  int i;
972  int res;
973  char *arg;
974
975  res = 0;
976  if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-'))
977    LogDiscardAll();
978  while (argc--) {
979    arg = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
980    for (i = LogMIN; i <= LogMAX; i++)
981      if (strcasecmp(arg, LogName(i)) == 0) {
982	if (**argv == '-')
983	  LogDiscard(i);
984	else
985	  LogKeep(i);
986	break;
987      }
988    if (i > LogMAX) {
989      LogPrintf(LogWARN, "%s: Invalid log value\n", arg);
990      res = -1;
991    }
992    argv++;
993  }
994  return res;
995}
996
997static int
998SetEscape(struct cmdtab const * list, int argc, char **argv)
999{
1000  int code;
1001
1002  for (code = 0; code < 33; code++)
1003    EscMap[code] = 0;
1004  while (argc-- > 0) {
1005    sscanf(*argv++, "%x", &code);
1006    code &= 0xff;
1007    EscMap[code >> 3] |= (1 << (code & 7));
1008    EscMap[32] = 1;
1009  }
1010  return 0;
1011}
1012
1013static int
1014SetInitialMRU(struct cmdtab const * list, int argc, char **argv)
1015{
1016  long mru;
1017  char *err;
1018
1019  if (argc > 0) {
1020    mru = atol(*argv);
1021    if (mru < MIN_MRU)
1022      err = "Given MRU value (%ld) is too small.\n";
1023    else if (mru > MAX_MRU)
1024      err = "Given MRU value (%ld) is too big.\n";
1025    else {
1026      VarMRU = mru;
1027      return 0;
1028    }
1029    LogPrintf(LogWARN, err, mru);
1030  }
1031  return -1;
1032}
1033
1034static int
1035SetPreferredMTU(struct cmdtab const * list, int argc, char **argv)
1036{
1037  long mtu;
1038  char *err;
1039
1040  if (argc > 0) {
1041    mtu = atol(*argv);
1042    if (mtu == 0) {
1043      VarPrefMTU = 0;
1044      return 0;
1045    } else if (mtu < MIN_MTU)
1046      err = "Given MTU value (%ld) is too small.\n";
1047    else if (mtu > MAX_MTU)
1048      err = "Given MTU value (%ld) is too big.\n";
1049    else {
1050      VarPrefMTU = mtu;
1051      return 0;
1052    }
1053    LogPrintf(LogWARN, err, mtu);
1054  }
1055  return -1;
1056}
1057
1058static int
1059SetIdleTimeout(struct cmdtab const * list, int argc, char **argv)
1060{
1061  if (argc-- > 0) {
1062    VarIdleTimeout = atoi(*argv++);
1063    UpdateIdleTimer();		/* If we're connected, restart the idle timer */
1064    if (argc-- > 0) {
1065      VarLqrTimeout = atoi(*argv++);
1066      if (VarLqrTimeout < 1)
1067	VarLqrTimeout = 30;
1068      if (argc > 0) {
1069	VarRetryTimeout = atoi(*argv);
1070	if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
1071	  VarRetryTimeout = 3;
1072      }
1073    }
1074    return 0;
1075  }
1076  return -1;
1077}
1078
1079struct in_addr
1080GetIpAddr(char *cp)
1081{
1082  struct hostent *hp;
1083  struct in_addr ipaddr;
1084
1085  hp = gethostbyname(cp);
1086  if (hp && hp->h_addrtype == AF_INET)
1087    bcopy(hp->h_addr, &ipaddr, hp->h_length);
1088  else if (inet_aton(cp, &ipaddr) == 0)
1089    ipaddr.s_addr = 0;
1090  return (ipaddr);
1091}
1092
1093static int
1094SetInterfaceAddr(struct cmdtab const * list, int argc, char **argv)
1095{
1096  DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
1097
1098  if (argc > 4)
1099    return -1;
1100
1101  HaveTriggerAddress = 0;
1102  ifnetmask.s_addr = 0;
1103
1104  if (argc > 0) {
1105    if (ParseAddr(argc, argv++,
1106		  &DefMyAddress.ipaddr,
1107		  &DefMyAddress.mask,
1108		  &DefMyAddress.width) == 0)
1109      return 1;
1110    if (--argc > 0) {
1111      if (ParseAddr(argc, argv++,
1112		    &DefHisAddress.ipaddr,
1113		    &DefHisAddress.mask,
1114		    &DefHisAddress.width) == 0)
1115	return 2;
1116      if (--argc > 0) {
1117	ifnetmask = GetIpAddr(*argv);
1118	if (--argc > 0) {
1119	  TriggerAddress = GetIpAddr(*argv);
1120	  HaveTriggerAddress = 1;
1121	}
1122      }
1123    }
1124  }
1125
1126  /*
1127   * For backwards compatibility, 0.0.0.0 means any address.
1128   */
1129  if (DefMyAddress.ipaddr.s_addr == 0) {
1130    DefMyAddress.mask.s_addr = 0;
1131    DefMyAddress.width = 0;
1132  }
1133  if (DefHisAddress.ipaddr.s_addr == 0) {
1134    DefHisAddress.mask.s_addr = 0;
1135    DefHisAddress.width = 0;
1136  }
1137  IpcpInfo.want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
1138  IpcpInfo.his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
1139
1140  if ((mode & MODE_AUTO) ||
1141      ((mode & MODE_DEDICATED) && dstsystem)) {
1142    if (OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask) < 0)
1143      return 4;
1144  }
1145  return 0;
1146}
1147
1148#ifndef NOMSEXT
1149
1150void
1151SetMSEXT(struct in_addr * pri_addr,
1152	 struct in_addr * sec_addr,
1153	 int argc,
1154	 char **argv)
1155{
1156  int dummyint;
1157  struct in_addr dummyaddr;
1158
1159  pri_addr->s_addr = sec_addr->s_addr = 0L;
1160
1161  if (argc > 0) {
1162    ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
1163    if (--argc > 0)
1164      ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
1165    else
1166      sec_addr->s_addr = pri_addr->s_addr;
1167  }
1168
1169  /*
1170   * if the primary/secondary ns entries are 0.0.0.0 we should set them to
1171   * either the localhost's ip, or the values in /etc/resolv.conf ??
1172   *
1173   * up to you if you want to implement this...
1174   */
1175
1176}
1177
1178static int
1179SetNS(struct cmdtab const * list, int argc, char **argv)
1180{
1181  SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv);
1182  return 0;
1183}
1184
1185static int
1186SetNBNS(struct cmdtab const * list, int argc, char **argv)
1187{
1188  SetMSEXT(&nbns_entries[0], &nbns_entries[1], argc, argv);
1189  return 0;
1190}
1191
1192#endif				/* MS_EXT */
1193
1194#define	VAR_AUTHKEY	0
1195#define	VAR_DIAL	1
1196#define	VAR_LOGIN	2
1197#define	VAR_AUTHNAME	3
1198#define	VAR_DEVICE	4
1199#define	VAR_ACCMAP	5
1200#define	VAR_PHONE	6
1201#define	VAR_HANGUP	7
1202
1203static int
1204SetVariable(struct cmdtab const * list, int argc, char **argv, int param)
1205{
1206  u_long map;
1207  char *arg;
1208
1209  if (argc > 0)
1210    arg = *argv;
1211  else
1212    arg = "";
1213
1214  switch (param) {
1215  case VAR_AUTHKEY:
1216    strncpy(VarAuthKey, arg, sizeof(VarAuthKey) - 1);
1217    VarAuthKey[sizeof(VarAuthKey) - 1] = '\0';
1218    break;
1219  case VAR_AUTHNAME:
1220    strncpy(VarAuthName, arg, sizeof(VarAuthName) - 1);
1221    VarAuthName[sizeof(VarAuthName) - 1] = '\0';
1222    break;
1223  case VAR_DIAL:
1224    strncpy(VarDialScript, arg, sizeof(VarDialScript) - 1);
1225    VarDialScript[sizeof(VarDialScript) - 1] = '\0';
1226    break;
1227  case VAR_LOGIN:
1228    strncpy(VarLoginScript, arg, sizeof(VarLoginScript) - 1);
1229    VarLoginScript[sizeof(VarLoginScript) - 1] = '\0';
1230    break;
1231  case VAR_DEVICE:
1232    CloseModem();
1233    strncpy(VarDevice, arg, sizeof(VarDevice) - 1);
1234    VarDevice[sizeof(VarDevice) - 1] = '\0';
1235    VarBaseDevice = rindex(VarDevice, '/');
1236    VarBaseDevice = VarBaseDevice ? VarBaseDevice + 1 : "";
1237    break;
1238  case VAR_ACCMAP:
1239    sscanf(arg, "%lx", &map);
1240    VarAccmap = map;
1241    break;
1242  case VAR_PHONE:
1243    strncpy(VarPhoneList, arg, sizeof(VarPhoneList) - 1);
1244    VarPhoneList[sizeof(VarPhoneList) - 1] = '\0';
1245    strcpy(VarPhoneCopy, VarPhoneList);
1246    VarNextPhone = VarPhoneCopy;
1247    break;
1248  case VAR_HANGUP:
1249    strncpy(VarHangupScript, arg, sizeof(VarHangupScript) - 1);
1250    VarHangupScript[sizeof(VarHangupScript) - 1] = '\0';
1251    break;
1252  }
1253  return 0;
1254}
1255
1256static int
1257SetCtsRts(struct cmdtab const * list, int argc, char **argv)
1258{
1259  if (argc > 0) {
1260    if (strcmp(*argv, "on") == 0)
1261      VarCtsRts = TRUE;
1262    else if (strcmp(*argv, "off") == 0)
1263      VarCtsRts = FALSE;
1264    else
1265      return -1;
1266    return 0;
1267  }
1268  return -1;
1269}
1270
1271
1272static int
1273SetOpenMode(struct cmdtab const * list, int argc, char **argv)
1274{
1275  if (argc > 0) {
1276    if (strcmp(*argv, "active") == 0)
1277      VarOpenMode = OPEN_ACTIVE;
1278    else if (strcmp(*argv, "passive") == 0)
1279      VarOpenMode = OPEN_PASSIVE;
1280    else
1281      return -1;
1282    return 0;
1283  }
1284  return -1;
1285}
1286
1287extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
1288
1289struct cmdtab const SetCommands[] = {
1290  {"accmap", NULL, SetVariable, LOCAL_AUTH,
1291  "Set accmap value", "set accmap hex-value", (void *) VAR_ACCMAP},
1292  {"afilter", NULL, SetAfilter, LOCAL_AUTH,
1293  "Set keep Alive filter", "set afilter ..."},
1294  {"authkey", "key", SetVariable, LOCAL_AUTH,
1295  "Set authentication key", "set authkey|key key", (void *) VAR_AUTHKEY},
1296  {"authname", NULL, SetVariable, LOCAL_AUTH,
1297  "Set authentication name", "set authname name", (void *) VAR_AUTHNAME},
1298  {"ctsrts", NULL, SetCtsRts, LOCAL_AUTH,
1299  "Use CTS/RTS modem signalling", "set ctsrts [on|off]"},
1300  {"device", "line", SetVariable, LOCAL_AUTH,
1301  "Set modem device name", "set device|line device-name", (void *) VAR_DEVICE},
1302  {"dfilter", NULL, SetDfilter, LOCAL_AUTH,
1303  "Set demand filter", "set dfilter ..."},
1304  {"dial", NULL, SetVariable, LOCAL_AUTH,
1305  "Set dialing script", "set dial chat-script", (void *) VAR_DIAL},
1306  {"escape", NULL, SetEscape, LOCAL_AUTH,
1307  "Set escape characters", "set escape hex-digit ..."},
1308  {"hangup", NULL, SetVariable, LOCAL_AUTH,
1309  "Set hangup script", "set hangup chat-script", (void *) VAR_HANGUP},
1310  {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH,
1311  "Set destination address", "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
1312  {"ifilter", NULL, SetIfilter, LOCAL_AUTH,
1313  "Set input filter", "set ifilter ..."},
1314  {"loopback", NULL, SetLoopback, LOCAL_AUTH,
1315  "Set loopback facility", "set loopback on|off"},
1316  {"log", NULL, SetLogLevel, LOCAL_AUTH,
1317  "Set log level", "set log [+|-]value..."},
1318  {"login", NULL, SetVariable, LOCAL_AUTH,
1319  "Set login script", "set login chat-script", (void *) VAR_LOGIN},
1320  {"mru", NULL, SetInitialMRU, LOCAL_AUTH,
1321  "Set Initial MRU value", "set mru value"},
1322  {"mtu", NULL, SetPreferredMTU, LOCAL_AUTH,
1323  "Set Preferred MTU value", "set mtu value"},
1324  {"ofilter", NULL, SetOfilter, LOCAL_AUTH,
1325  "Set output filter", "set ofilter ..."},
1326  {"openmode", NULL, SetOpenMode, LOCAL_AUTH,
1327  "Set open mode", "set openmode [active|passive]"},
1328  {"parity", NULL, SetModemParity, LOCAL_AUTH,
1329  "Set modem parity", "set parity [odd|even|none]"},
1330  {"phone", NULL, SetVariable, LOCAL_AUTH,
1331  "Set telephone number(s)", "set phone phone1[:phone2[...]]", (void *) VAR_PHONE},
1332  {"reconnect", NULL, SetReconnect, LOCAL_AUTH,
1333  "Set Reconnect timeout", "set reconnect value ntries"},
1334  {"redial", NULL, SetRedialTimeout, LOCAL_AUTH,
1335  "Set Redial timeout", "set redial value|random[.value|random] [dial_attempts]"},
1336  {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH,
1337  "Set STOPPED timeouts", "set stopped [LCPseconds [IPCPseconds [CCPseconds]]]"},
1338  {"server", "socket", SetServer, LOCAL_AUTH,
1339  "Set server port", "set server|socket TcpPort|LocalName|none [mask]"},
1340  {"speed", NULL, SetModemSpeed, LOCAL_AUTH,
1341  "Set modem speed", "set speed value"},
1342  {"timeout", NULL, SetIdleTimeout, LOCAL_AUTH,
1343  "Set Idle timeout", "set timeout value"},
1344#ifndef NOMSEXT
1345  {"ns", NULL, SetNS, LOCAL_AUTH,
1346  "Set NameServer", "set ns pri-addr [sec-addr]"},
1347  {"nbns", NULL, SetNBNS, LOCAL_AUTH,
1348  "Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"},
1349#endif
1350  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
1351  "Display this message", "set help|? [command]", (void *) SetCommands},
1352  {NULL, NULL, NULL},
1353};
1354
1355static int
1356SetCommand(struct cmdtab const * list, int argc, char **argv)
1357{
1358  if (argc > 0)
1359    FindExec(SetCommands, argc, argv);
1360  else if (VarTerm)
1361    fprintf(VarTerm, "Use `set ?' to get a list or `set ? <var>' for"
1362	    " syntax help.\n");
1363  else
1364    LogPrintf(LogWARN, "set command must have arguments\n");
1365
1366  return 0;
1367}
1368
1369
1370static int
1371AddCommand(struct cmdtab const * list, int argc, char **argv)
1372{
1373  struct in_addr dest, gateway, netmask;
1374
1375  if (argc == 3) {
1376    if (strcasecmp(argv[0], "MYADDR") == 0)
1377      dest = IpcpInfo.want_ipaddr;
1378    else
1379      dest = GetIpAddr(argv[0]);
1380    netmask = GetIpAddr(argv[1]);
1381    if (strcasecmp(argv[2], "HISADDR") == 0)
1382      gateway = IpcpInfo.his_ipaddr;
1383    else
1384      gateway = GetIpAddr(argv[2]);
1385    OsSetRoute(RTM_ADD, dest, gateway, netmask);
1386    return 0;
1387  }
1388  return -1;
1389}
1390
1391static int
1392DeleteCommand(struct cmdtab const * list, int argc, char **argv)
1393{
1394  struct in_addr dest, gateway, netmask;
1395
1396  if (argc == 1 && strcasecmp(argv[0], "all") == 0)
1397    DeleteIfRoutes(0);
1398  else if (argc > 0 && argc < 4) {
1399    if (strcasecmp(argv[0], "MYADDR") == 0)
1400      dest = IpcpInfo.want_ipaddr;
1401    else
1402      dest = GetIpAddr(argv[0]);
1403    netmask.s_addr = INADDR_ANY;
1404    if (argc > 1) {
1405      if (strcasecmp(argv[1], "HISADDR") == 0)
1406	gateway = IpcpInfo.his_ipaddr;
1407      else
1408	gateway = GetIpAddr(argv[1]);
1409      if (argc == 3) {
1410	if (inet_aton(argv[2], &netmask) == 0) {
1411	  LogPrintf(LogWARN, "Bad netmask value.\n");
1412	  return -1;
1413	}
1414      }
1415    } else
1416      gateway.s_addr = INADDR_ANY;
1417    OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1418  } else
1419    return -1;
1420
1421  return 0;
1422}
1423
1424static int AliasEnable();
1425static int AliasOption();
1426
1427static struct cmdtab const AliasCommands[] =
1428{
1429  {"enable", NULL, AliasEnable, LOCAL_AUTH,
1430  "enable IP aliasing", "alias enable [yes|no]"},
1431  {"port", NULL, AliasRedirectPort, LOCAL_AUTH,
1432  "port redirection", "alias port [proto addr_local:port_local  port_alias]"},
1433  {"addr", NULL, AliasRedirectAddr, LOCAL_AUTH,
1434  "static address translation", "alias addr [addr_local addr_alias]"},
1435  {"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
1436    "stop incoming connections", "alias deny_incoming [yes|no]",
1437  (void *) PKT_ALIAS_DENY_INCOMING},
1438  {"log", NULL, AliasOption, LOCAL_AUTH,
1439    "log aliasing link creation", "alias log [yes|no]",
1440  (void *) PKT_ALIAS_LOG},
1441  {"same_ports", NULL, AliasOption, LOCAL_AUTH,
1442    "try to leave port numbers unchanged", "alias same_ports [yes|no]",
1443  (void *) PKT_ALIAS_SAME_PORTS},
1444  {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
1445    "allocate host sockets", "alias use_sockets [yes|no]",
1446  (void *) PKT_ALIAS_USE_SOCKETS},
1447  {"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
1448    "alias unregistered (private) IP address space only",
1449    "alias unregistered_only [yes|no]",
1450  (void *) PKT_ALIAS_UNREGISTERED_ONLY},
1451  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
1452    "Display this message", "alias help|? [command]",
1453  (void *) AliasCommands},
1454  {NULL, NULL, NULL},
1455};
1456
1457
1458static int
1459AliasCommand(struct cmdtab const * list, int argc, char **argv)
1460{
1461  if (argc > 0)
1462    FindExec(AliasCommands, argc, argv);
1463  else if (VarTerm)
1464    fprintf(VarTerm, "Use `alias help' to get a list or `alias help <option>'"
1465	    " for syntax help.\n");
1466  else
1467    LogPrintf(LogWARN, "alias command must have arguments\n");
1468
1469  return 0;
1470}
1471
1472static int
1473AliasEnable(struct cmdtab const * list, int argc, char **argv)
1474{
1475  if (argc == 1)
1476    if (strcasecmp(argv[0], "yes") == 0) {
1477      if (!(mode & MODE_ALIAS)) {
1478	if (loadAliasHandlers(&VarAliasHandlers) == 0) {
1479	  mode |= MODE_ALIAS;
1480	  return 0;
1481	}
1482	LogPrintf(LogWARN, "Cannot load alias library\n");
1483	return 1;
1484      }
1485      return 0;
1486    } else if (strcasecmp(argv[0], "no") == 0) {
1487      if (mode & MODE_ALIAS) {
1488	unloadAliasHandlers();
1489	mode &= ~MODE_ALIAS;
1490      }
1491      return 0;
1492    }
1493  return -1;
1494}
1495
1496
1497static int
1498AliasOption(struct cmdtab const * list, int argc, char **argv, void *param)
1499{
1500  if (argc == 1)
1501    if (strcasecmp(argv[0], "yes") == 0) {
1502      if (mode & MODE_ALIAS) {
1503	VarPacketAliasSetMode((unsigned) param, (unsigned) param);
1504	return 0;
1505      }
1506      LogPrintf(LogWARN, "alias not enabled\n");
1507    } else if (strcmp(argv[0], "no") == 0) {
1508      if (mode & MODE_ALIAS) {
1509	VarPacketAliasSetMode(0, (unsigned) param);
1510	return 0;
1511      }
1512      LogPrintf(LogWARN, "alias not enabled\n");
1513    }
1514  return -1;
1515}
1516