command.c revision 28679
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.74 1997/08/21 17:07:30 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  if (!IsInteractive())
153    return (1);
154
155  if (argc > 0) {
156    if (SelectSystem(*argv, CONFFILE) < 0) {
157      if (VarTerm)
158	fprintf(VarTerm, "%s: not found.\n", *argv);
159      return -1;
160    }
161  }
162  tries = 0;
163  do {
164    if (VarTerm)
165      fprintf(VarTerm, "Dial attempt %u of %d\n", ++tries, VarDialTries);
166    modem = OpenModem(mode);
167    if (modem < 0) {
168      if (VarTerm)
169	fprintf(VarTerm, "Failed to open modem.\n");
170      break;
171    }
172    if ((res = DialModem()) == EX_DONE) {
173      sleep(1);
174      ModemTimeout();
175      PacketMode();
176      break;
177    } else if (res == EX_SIG)
178      return 1;
179  } while (VarDialTries == 0 || tries < VarDialTries);
180
181  return 0;
182}
183
184static int
185SetLoopback(struct cmdtab const * cmdlist, int argc, char **argv)
186{
187  if (argc == 1)
188    if (!strcasecmp(*argv, "on"))
189      VarLoopback = 1;
190    else if (!strcasecmp(*argv, "off"))
191      VarLoopback = 0;
192  return -1;
193}
194
195static int
196BgShellCommand(struct cmdtab const * cmdlist, int argc, char **argv)
197{
198  if (argc == 0)
199    return -1;
200  return ShellCommand(cmdlist, argc, argv, 1);
201}
202
203static int
204FgShellCommand(struct cmdtab const * cmdlist, int argc, char **argv)
205{
206  return ShellCommand(cmdlist, argc, argv, 0);
207}
208
209static int
210ShellCommand(struct cmdtab const * cmdlist, int argc, char **argv, int bg)
211{
212  const char *shell;
213  pid_t shpid;
214  FILE *oVarTerm;
215
216#ifdef SHELL_ONLY_INTERACTIVELY
217  /* we're only allowed to shell when we run ppp interactively */
218  if (mode != MODE_INTER) {
219    LogPrintf(LogWARN, "Can only start a shell in interactive mode\n");
220    return 1;
221  }
222#endif
223#ifdef NO_SHELL_IN_AUTO_INTERACTIVE
224
225  /*
226   * we want to stop shell commands when we've got a telnet connection to an
227   * auto mode ppp
228   */
229  if ((mode & (MODE_AUTO | MODE_INTER)) == (MODE_AUTO | MODE_INTER)) {
230    LogPrintf(LogWARN, "Shell is not allowed interactively in auto mode\n");
231    return 1;
232  }
233#endif
234
235  if (argc == 0)
236    if (!(mode & MODE_INTER)) {
237      LogPrintf(LogWARN, "Can only start an interactive shell in"
238		" interactive mode\n");
239      return 1;
240    } else if (bg) {
241      LogPrintf(LogWARN, "Can only start an interactive shell in"
242		" the foreground mode\n");
243      return 1;
244    }
245  if ((shell = getenv("SHELL")) == 0)
246    shell = _PATH_BSHELL;
247
248  if ((shpid = fork()) == 0) {
249    int dtablesize, i, fd;
250
251    if (VarTerm)
252      fd = fileno(VarTerm);
253    else if ((fd = open("/dev/null", O_RDWR)) == -1) {
254      LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno));
255      exit(1);
256    }
257    for (i = 0; i < 3; i++)
258      dup2(fd, i);
259
260    if (fd > 2)
261      if (VarTerm) {
262	oVarTerm = VarTerm;
263	VarTerm = 0;
264	if (oVarTerm && oVarTerm != stdout)
265	  fclose(oVarTerm);
266      } else
267	close(fd);
268
269    for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++)
270      (void) close(i);
271
272    /*
273     * We are running setuid, we should change to real user for avoiding
274     * security problems.
275     */
276    if (setgid(getgid()) < 0) {
277      LogPrintf(LogERROR, "setgid: %s\n", strerror(errno));
278      exit(1);
279    }
280    if (setuid(getuid()) < 0) {
281      LogPrintf(LogERROR, "setuid: %s\n", strerror(errno));
282      exit(1);
283    }
284    TtyOldMode();
285    if (argc > 0) {
286      /* substitute pseudo args */
287      for (i = 1; i < argc; i++)
288	if (strcasecmp(argv[i], "HISADDR") == 0)
289	  argv[i] = strdup(inet_ntoa(IpcpInfo.his_ipaddr));
290	else if (strcasecmp(argv[i], "INTERFACE") == 0)
291	  argv[i] = strdup(IfDevName);
292	else if (strcasecmp(argv[i], "MYADDR") == 0)
293	  argv[i] = strdup(inet_ntoa(IpcpInfo.want_ipaddr));
294      if (bg) {
295	pid_t p;
296
297	p = getpid();
298	if (daemon(1, 1) == -1) {
299	  LogPrintf(LogERROR, "%d: daemon: %s", p, strerror(errno));
300	  exit(1);
301	}
302      }
303      (void) execvp(argv[0], argv);
304    } else
305      (void) execl(shell, shell, NULL);
306
307    LogPrintf(LogWARN, "exec() of %s failed\n", argc > 0 ? argv[0] : shell);
308    exit(255);
309  }
310  if (shpid == (pid_t) - 1) {
311    LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno));
312  } else {
313    int status;
314
315    (void) waitpid(shpid, &status, 0);
316  }
317
318  TtyCommandMode(1);
319
320  return (0);
321}
322
323struct cmdtab const Commands[] = {
324  {"accept", NULL, AcceptCommand, LOCAL_AUTH,
325  "accept option request", "accept option .."},
326  {"add", NULL, AddCommand, LOCAL_AUTH,
327  "add route", "add dest mask gateway"},
328  {"bg", "!bg", BgShellCommand, LOCAL_AUTH,
329  "Run a command in the background", "[!]bg command"},
330  {"close", NULL, CloseCommand, LOCAL_AUTH,
331  "Close connection", "close"},
332  {"delete", NULL, DeleteCommand, LOCAL_AUTH,
333  "delete route", "delete ALL | dest [gateway [mask]]"},
334  {"deny", NULL, DenyCommand, LOCAL_AUTH,
335  "Deny option request", "deny option .."},
336  {"dial", "call", DialCommand, LOCAL_AUTH,
337  "Dial and login", "dial|call [remote]"},
338  {"disable", NULL, DisableCommand, LOCAL_AUTH,
339  "Disable option", "disable option .."},
340  {"display", NULL, DisplayCommand, LOCAL_AUTH,
341  "Display option configs", "display"},
342  {"enable", NULL, EnableCommand, LOCAL_AUTH,
343  "Enable option", "enable option .."},
344  {"passwd", NULL, LocalAuthCommand, LOCAL_NO_AUTH,
345  "Password for manipulation", "passwd option .."},
346  {"load", NULL, LoadCommand, LOCAL_AUTH,
347  "Load settings", "load [remote]"},
348  {"save", NULL, SaveCommand, LOCAL_AUTH,
349  "Save settings", "save"},
350  {"set", "setup", SetCommand, LOCAL_AUTH,
351  "Set parameters", "set[up] var value"},
352  {"shell", "!", FgShellCommand, LOCAL_AUTH,
353  "Run a subshell", "shell|! [sh command]"},
354  {"show", NULL, ShowCommand, LOCAL_AUTH,
355  "Show status and statictics", "show var"},
356  {"term", NULL, TerminalCommand, LOCAL_AUTH,
357  "Enter to terminal mode", "term"},
358  {"alias", NULL, AliasCommand, LOCAL_AUTH,
359  "alias control", "alias option [yes|no]"},
360  {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
361  "Quit PPP program", "quit|bye [all]"},
362  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
363  "Display this message", "help|? [command]", (void *) Commands},
364  {NULL, "down", DownCommand, LOCAL_AUTH,
365  "Generate down event", "down"},
366  {NULL, NULL, NULL},
367};
368
369extern int ReportCcpStatus();
370extern int ReportLcpStatus();
371extern int ReportIpcpStatus();
372extern int ReportProtStatus();
373extern int ReportCompress();
374extern int ShowModemStatus();
375extern int ReportHdlcStatus();
376extern int ShowMemMap();
377
378static int
379ShowLoopback()
380{
381  if (VarTerm)
382    fprintf(VarTerm, "Local loopback is %s\n", VarLoopback ? "on" : "off");
383
384  return 0;
385}
386
387static int
388ShowLogLevel()
389{
390  int i;
391
392  if (!VarTerm)
393    return 0;
394  fprintf(VarTerm, "Log:");
395  for (i = LogMIN; i < LogMAXCONF; i++) {
396    if (LogIsKept(i))
397      fprintf(VarTerm, " %s", LogName(i));
398  }
399  fprintf(VarTerm, "\n");
400
401  return 0;
402}
403
404static int
405ShowEscape()
406{
407  int code, bit;
408
409  if (!VarTerm)
410    return 0;
411  if (EscMap[32]) {
412    for (code = 0; code < 32; code++)
413      if (EscMap[code])
414	for (bit = 0; bit < 8; bit++)
415	  if (EscMap[code] & (1 << bit))
416	    fprintf(VarTerm, " 0x%02x", (code << 3) + bit);
417    fprintf(VarTerm, "\n");
418  }
419  return 1;
420}
421
422static int
423ShowTimeout()
424{
425  if (!VarTerm)
426    return 0;
427  fprintf(VarTerm, " Idle Timer: %d secs   LQR Timer: %d secs"
428	  "   Retry Timer: %d secs\n", VarIdleTimeout, VarLqrTimeout,
429	  VarRetryTimeout);
430  return 1;
431}
432
433static int
434ShowStopped()
435{
436  if (!VarTerm)
437    return 0;
438
439  fprintf(VarTerm, " Stopped Timer:  LCP: ");
440  if (!LcpFsm.StoppedTimer.load)
441    fprintf(VarTerm, "Disabled");
442  else
443    fprintf(VarTerm, "%ld secs", LcpFsm.StoppedTimer.load / SECTICKS);
444
445  fprintf(VarTerm, ", IPCP: ");
446  if (!IpcpFsm.StoppedTimer.load)
447    fprintf(VarTerm, "Disabled");
448  else
449    fprintf(VarTerm, "%ld secs", IpcpFsm.StoppedTimer.load / SECTICKS);
450
451  fprintf(VarTerm, ", CCP: ");
452  if (!CcpFsm.StoppedTimer.load)
453    fprintf(VarTerm, "Disabled");
454  else
455    fprintf(VarTerm, "%ld secs", CcpFsm.StoppedTimer.load / SECTICKS);
456
457  fprintf(VarTerm, "\n");
458
459  return 1;
460}
461
462static int
463ShowAuthKey()
464{
465  if (!VarTerm)
466    return 0;
467  fprintf(VarTerm, "AuthName = %s\n", VarAuthName);
468  fprintf(VarTerm, "AuthKey  = %s\n", VarAuthKey);
469  return 1;
470}
471
472static int
473ShowVersion()
474{
475  extern char VarVersion[];
476  extern char VarLocalVersion[];
477
478  if (!VarTerm)
479    return 0;
480  fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
481  return 1;
482}
483
484static int
485ShowInitialMRU()
486{
487  if (!VarTerm)
488    return 0;
489  fprintf(VarTerm, " Initial MRU: %ld\n", VarMRU);
490  return 1;
491}
492
493static int
494ShowPreferredMTU()
495{
496  if (!VarTerm)
497    return 0;
498  if (VarPrefMTU)
499    fprintf(VarTerm, " Preferred MTU: %ld\n", VarPrefMTU);
500  else
501    fprintf(VarTerm, " Preferred MTU: unspecified\n");
502  return 1;
503}
504
505static int
506ShowReconnect()
507{
508  if (!VarTerm)
509    return 0;
510  fprintf(VarTerm, " Reconnect Timer:  %d,  %d tries\n",
511	  VarReconnectTimer, VarReconnectTries);
512  return 1;
513}
514
515static int
516ShowRedial()
517{
518  if (!VarTerm)
519    return 0;
520  fprintf(VarTerm, " Redial Timer: ");
521
522  if (VarRedialTimeout >= 0) {
523    fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
524  } else {
525    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
526  }
527
528  fprintf(VarTerm, " Redial Next Timer: ");
529
530  if (VarRedialNextTimeout >= 0) {
531    fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
532  } else {
533    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
534  }
535
536  if (VarDialTries)
537    fprintf(VarTerm, "%d dial tries", VarDialTries);
538
539  fprintf(VarTerm, "\n");
540
541  return 1;
542}
543
544#ifndef NOMSEXT
545static int
546ShowMSExt()
547{
548  if (!VarTerm)
549    return 0;
550  fprintf(VarTerm, " MS PPP extention values \n");
551  fprintf(VarTerm, "   Primary NS     : %s\n", inet_ntoa(ns_entries[0]));
552  fprintf(VarTerm, "   Secondary NS   : %s\n", inet_ntoa(ns_entries[1]));
553  fprintf(VarTerm, "   Primary NBNS   : %s\n", inet_ntoa(nbns_entries[0]));
554  fprintf(VarTerm, "   Secondary NBNS : %s\n", inet_ntoa(nbns_entries[1]));
555  return 1;
556}
557
558#endif
559
560extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
561
562struct cmdtab const ShowCommands[] = {
563  {"afilter", NULL, ShowAfilter, LOCAL_AUTH,
564  "Show keep Alive filters", "show afilter option .."},
565  {"auth", NULL, ShowAuthKey, LOCAL_AUTH,
566  "Show auth name/key", "show auth"},
567  {"ccp", NULL, ReportCcpStatus, LOCAL_AUTH,
568  "Show CCP status", "show cpp"},
569  {"compress", NULL, ReportCompress, LOCAL_AUTH,
570  "Show compression statictics", "show compress"},
571  {"dfilter", NULL, ShowDfilter, LOCAL_AUTH,
572  "Show Demand filters", "show dfilteroption .."},
573  {"escape", NULL, ShowEscape, LOCAL_AUTH,
574  "Show escape characters", "show escape"},
575  {"hdlc", NULL, ReportHdlcStatus, LOCAL_AUTH,
576  "Show HDLC error summary", "show hdlc"},
577  {"ifilter", NULL, ShowIfilter, LOCAL_AUTH,
578  "Show Input filters", "show ifilter option .."},
579  {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH,
580  "Show IPCP status", "show ipcp"},
581  {"lcp", NULL, ReportLcpStatus, LOCAL_AUTH,
582  "Show LCP status", "show lcp"},
583  {"loopback", NULL, ShowLoopback, LOCAL_AUTH,
584  "Show current loopback setting", "show loopback"},
585  {"log", NULL, ShowLogLevel, LOCAL_AUTH,
586  "Show current log level", "show log"},
587  {"mem", NULL, ShowMemMap, LOCAL_AUTH,
588  "Show memory map", "show mem"},
589  {"modem", NULL, ShowModemStatus, LOCAL_AUTH,
590  "Show modem setups", "show modem"},
591  {"mru", NULL, ShowInitialMRU, LOCAL_AUTH,
592  "Show Initial MRU", "show mru"},
593  {"mtu", NULL, ShowPreferredMTU, LOCAL_AUTH,
594  "Show Preferred MTU", "show mtu"},
595  {"ofilter", NULL, ShowOfilter, LOCAL_AUTH,
596  "Show Output filters", "show ofilter option .."},
597  {"proto", NULL, ReportProtStatus, LOCAL_AUTH,
598  "Show protocol summary", "show proto"},
599  {"reconnect", NULL, ShowReconnect, LOCAL_AUTH,
600  "Show Reconnect timer,tries", "show reconnect"},
601  {"redial", NULL, ShowRedial, LOCAL_AUTH,
602  "Show Redial timeout value", "show redial"},
603  {"route", NULL, ShowRoute, LOCAL_AUTH,
604  "Show routing table", "show route"},
605  {"timeout", NULL, ShowTimeout, LOCAL_AUTH,
606  "Show Idle timeout value", "show timeout"},
607  {"stopped", NULL, ShowStopped, LOCAL_AUTH,
608  "Show STOPPED timeout value", "show stopped"},
609#ifndef NOMSEXT
610  {"msext", NULL, ShowMSExt, LOCAL_AUTH,
611  "Show MS PPP extentions", "show msext"},
612#endif
613  {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
614  "Show version string", "show version"},
615  {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
616  "Display this message", "show help|? [command]", (void *) ShowCommands},
617  {NULL, NULL, NULL},
618};
619
620struct cmdtab const *
621FindCommand(struct cmdtab const * cmds, char *str, int *pmatch)
622{
623  int nmatch;
624  int len;
625  struct cmdtab const *found;
626
627  found = NULL;
628  len = strlen(str);
629  nmatch = 0;
630  while (cmds->func) {
631    if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
632      if (cmds->name[len] == '\0') {
633	*pmatch = 1;
634	return cmds;
635      }
636      nmatch++;
637      found = cmds;
638    } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
639      if (cmds->alias[len] == '\0') {
640	*pmatch = 1;
641	return cmds;
642      }
643      nmatch++;
644      found = cmds;
645    }
646    cmds++;
647  }
648  *pmatch = nmatch;
649  return found;
650}
651
652int
653FindExec(struct cmdtab const * cmdlist, int argc, char **argv)
654{
655  struct cmdtab const *cmd;
656  int val = 1;
657  int nmatch;
658
659  cmd = FindCommand(cmdlist, *argv, &nmatch);
660  if (nmatch > 1)
661    LogPrintf(LogWARN, "%s: Ambiguous command\n", *argv);
662  else if (cmd && (cmd->lauth & VarLocalAuth))
663    val = (cmd->func) (cmd, --argc, ++argv, cmd->args);
664  else
665    LogPrintf(LogWARN, "%s: Invalid command\n", *argv);
666
667  if (val == -1)
668    LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
669  else if (val)
670    LogPrintf(LogCOMMAND, "%s: Failed %d\n", *argv, val);
671
672  return val;
673}
674
675int aft_cmd = 1;
676extern int TermMode;
677
678void
679Prompt()
680{
681  char *pconnect, *pauth;
682
683  if (!(mode & MODE_INTER) || !VarTerm || TermMode)
684    return;
685
686  if (!aft_cmd)
687    fprintf(VarTerm, "\n");
688  else
689    aft_cmd = 0;
690
691  if (VarLocalAuth == LOCAL_AUTH)
692    pauth = " ON ";
693  else
694    pauth = " on ";
695  if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
696    pconnect = "PPP";
697  else
698    pconnect = "ppp";
699  fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
700  fflush(VarTerm);
701}
702
703void
704DecodeCommand(char *buff, int nb, int prompt)
705{
706  char *vector[20];
707  char **argv;
708  int argc;
709  char *cp;
710
711  if (nb > 0) {
712    cp = buff + strcspn(buff, "\r\n");
713    if (cp)
714      *cp = '\0';
715    argc = MakeArgs(buff, vector, VECSIZE(vector));
716    argv = vector;
717
718    if (argc > 0)
719      FindExec(Commands, argc, argv);
720  }
721  if (prompt)
722    Prompt();
723}
724
725static int
726ShowCommand(struct cmdtab const * list, int argc, char **argv)
727{
728  if (argc > 0)
729    FindExec(ShowCommands, argc, argv);
730  else if (VarTerm)
731    fprintf(VarTerm, "Use ``show ?'' to get a list.\n");
732  else
733    LogPrintf(LogWARN, "show command must have arguments\n");
734
735  return 0;
736}
737
738static int
739TerminalCommand(struct cmdtab const * list, int argc, char **argv)
740{
741  if (LcpFsm.state > ST_CLOSED) {
742    if (VarTerm)
743      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
744    return 1;
745  }
746  if (!IsInteractive())
747    return (1);
748  modem = OpenModem(mode);
749  if (modem < 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 && (VarLocalAuth & LOCAL_AUTH)) {
769      Cleanup(EX_NORMAL);
770      mode &= ~MODE_INTER;
771      oVarTerm = VarTerm;
772      VarTerm = 0;
773      if (oVarTerm && oVarTerm != stdout)
774	fclose(oVarTerm);
775    } else {
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 (strcmp(*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