command.c revision 29549
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.81 1997/09/16 23:15:11 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  fprintf(VarTerm, "Encrypt  = %s\n", VarEncMD4 ? "MD4" : "MD5" );
471  return 1;
472}
473
474static int
475ShowVersion()
476{
477  extern char VarVersion[];
478  extern char VarLocalVersion[];
479
480  if (!VarTerm)
481    return 0;
482  fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
483  return 1;
484}
485
486static int
487ShowInitialMRU()
488{
489  if (!VarTerm)
490    return 0;
491  fprintf(VarTerm, " Initial MRU: %ld\n", VarMRU);
492  return 1;
493}
494
495static int
496ShowPreferredMTU()
497{
498  if (!VarTerm)
499    return 0;
500  if (VarPrefMTU)
501    fprintf(VarTerm, " Preferred MTU: %ld\n", VarPrefMTU);
502  else
503    fprintf(VarTerm, " Preferred MTU: unspecified\n");
504  return 1;
505}
506
507static int
508ShowReconnect()
509{
510  if (!VarTerm)
511    return 0;
512  fprintf(VarTerm, " Reconnect Timer:  %d,  %d tries\n",
513	  VarReconnectTimer, VarReconnectTries);
514  return 1;
515}
516
517static int
518ShowRedial()
519{
520  if (!VarTerm)
521    return 0;
522  fprintf(VarTerm, " Redial Timer: ");
523
524  if (VarRedialTimeout >= 0) {
525    fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
526  } else {
527    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
528  }
529
530  fprintf(VarTerm, " Redial Next Timer: ");
531
532  if (VarRedialNextTimeout >= 0) {
533    fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
534  } else {
535    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
536  }
537
538  if (VarDialTries)
539    fprintf(VarTerm, "%d dial tries", VarDialTries);
540
541  fprintf(VarTerm, "\n");
542
543  return 1;
544}
545
546#ifndef NOMSEXT
547static int
548ShowMSExt()
549{
550  if (!VarTerm)
551    return 0;
552  fprintf(VarTerm, " MS PPP extention values \n");
553  fprintf(VarTerm, "   Primary NS     : %s\n", inet_ntoa(ns_entries[0]));
554  fprintf(VarTerm, "   Secondary NS   : %s\n", inet_ntoa(ns_entries[1]));
555  fprintf(VarTerm, "   Primary NBNS   : %s\n", inet_ntoa(nbns_entries[0]));
556  fprintf(VarTerm, "   Secondary NBNS : %s\n", inet_ntoa(nbns_entries[1]));
557  return 1;
558}
559
560#endif
561
562extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
563
564struct cmdtab const ShowCommands[] = {
565  {"afilter", NULL, ShowAfilter, LOCAL_AUTH,
566  "Show keep Alive filters", "show afilter option .."},
567  {"auth", NULL, ShowAuthKey, LOCAL_AUTH,
568  "Show auth name, key and algorithm", "show auth"},
569  {"ccp", NULL, ReportCcpStatus, LOCAL_AUTH,
570  "Show CCP status", "show cpp"},
571  {"compress", NULL, ReportCompress, LOCAL_AUTH,
572  "Show compression statictics", "show compress"},
573  {"dfilter", NULL, ShowDfilter, LOCAL_AUTH,
574  "Show Demand filters", "show dfilteroption .."},
575  {"escape", NULL, ShowEscape, LOCAL_AUTH,
576  "Show escape characters", "show escape"},
577  {"hdlc", NULL, ReportHdlcStatus, LOCAL_AUTH,
578  "Show HDLC error summary", "show hdlc"},
579  {"ifilter", NULL, ShowIfilter, LOCAL_AUTH,
580  "Show Input filters", "show ifilter option .."},
581  {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH,
582  "Show IPCP status", "show ipcp"},
583  {"lcp", NULL, ReportLcpStatus, LOCAL_AUTH,
584  "Show LCP status", "show lcp"},
585  {"loopback", NULL, ShowLoopback, LOCAL_AUTH,
586  "Show current loopback setting", "show loopback"},
587  {"log", NULL, ShowLogLevel, LOCAL_AUTH,
588  "Show current log level", "show log"},
589  {"mem", NULL, ShowMemMap, LOCAL_AUTH,
590  "Show memory map", "show mem"},
591  {"modem", NULL, ShowModemStatus, LOCAL_AUTH,
592  "Show modem setups", "show modem"},
593  {"mru", NULL, ShowInitialMRU, LOCAL_AUTH,
594  "Show Initial MRU", "show mru"},
595  {"mtu", NULL, ShowPreferredMTU, LOCAL_AUTH,
596  "Show Preferred MTU", "show mtu"},
597  {"ofilter", NULL, ShowOfilter, LOCAL_AUTH,
598  "Show Output filters", "show ofilter option .."},
599  {"proto", NULL, ReportProtStatus, LOCAL_AUTH,
600  "Show protocol summary", "show proto"},
601  {"reconnect", NULL, ShowReconnect, LOCAL_AUTH,
602  "Show Reconnect timer,tries", "show reconnect"},
603  {"redial", NULL, ShowRedial, LOCAL_AUTH,
604  "Show Redial timeout value", "show redial"},
605  {"route", NULL, ShowRoute, LOCAL_AUTH,
606  "Show routing table", "show route"},
607  {"timeout", NULL, ShowTimeout, LOCAL_AUTH,
608  "Show Idle timeout value", "show timeout"},
609  {"stopped", NULL, ShowStopped, LOCAL_AUTH,
610  "Show STOPPED timeout value", "show stopped"},
611#ifndef NOMSEXT
612  {"msext", NULL, ShowMSExt, LOCAL_AUTH,
613  "Show MS PPP extentions", "show msext"},
614#endif
615  {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
616  "Show version string", "show version"},
617  {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
618  "Display this message", "show help|? [command]", (void *) ShowCommands},
619  {NULL, NULL, NULL},
620};
621
622struct cmdtab const *
623FindCommand(struct cmdtab const * cmds, char *str, int *pmatch)
624{
625  int nmatch;
626  int len;
627  struct cmdtab const *found;
628
629  found = NULL;
630  len = strlen(str);
631  nmatch = 0;
632  while (cmds->func) {
633    if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
634      if (cmds->name[len] == '\0') {
635	*pmatch = 1;
636	return cmds;
637      }
638      nmatch++;
639      found = cmds;
640    } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
641      if (cmds->alias[len] == '\0') {
642	*pmatch = 1;
643	return cmds;
644      }
645      nmatch++;
646      found = cmds;
647    }
648    cmds++;
649  }
650  *pmatch = nmatch;
651  return found;
652}
653
654int
655FindExec(struct cmdtab const * cmdlist, int argc, char **argv)
656{
657  struct cmdtab const *cmd;
658  int val = 1;
659  int nmatch;
660
661  cmd = FindCommand(cmdlist, *argv, &nmatch);
662  if (nmatch > 1)
663    LogPrintf(LogWARN, "%s: Ambiguous command\n", *argv);
664  else if (cmd && (cmd->lauth & VarLocalAuth))
665    val = (cmd->func) (cmd, argc-1, argv+1, cmd->args);
666  else
667    LogPrintf(LogWARN, "%s: Invalid command\n", *argv);
668
669  if (val == -1)
670    LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
671  else if (val)
672    LogPrintf(LogCOMMAND, "%s: Failed %d\n", *argv, val);
673
674  return val;
675}
676
677int aft_cmd = 1;
678extern int TermMode;
679
680void
681Prompt()
682{
683  char *pconnect, *pauth;
684
685  if (!(mode & MODE_INTER) || !VarTerm || TermMode)
686    return;
687
688  if (!aft_cmd)
689    fprintf(VarTerm, "\n");
690  else
691    aft_cmd = 0;
692
693  if (VarLocalAuth == LOCAL_AUTH)
694    pauth = " ON ";
695  else
696    pauth = " on ";
697  if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
698    pconnect = "PPP";
699  else
700    pconnect = "ppp";
701  fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
702  fflush(VarTerm);
703}
704
705void
706DecodeCommand(char *buff, int nb, int prompt)
707{
708  char *vector[20];
709  char **argv;
710  int argc;
711  char *cp;
712
713  if (nb > 0) {
714    cp = buff + strcspn(buff, "\r\n");
715    if (cp)
716      *cp = '\0';
717    argc = MakeArgs(buff, vector, VECSIZE(vector));
718    argv = vector;
719
720    if (argc > 0)
721      FindExec(Commands, argc, argv);
722  }
723  if (prompt)
724    Prompt();
725}
726
727static int
728ShowCommand(struct cmdtab const * list, int argc, char **argv)
729{
730  if (argc > 0)
731    FindExec(ShowCommands, argc, argv);
732  else if (VarTerm)
733    fprintf(VarTerm, "Use ``show ?'' to get a list.\n");
734  else
735    LogPrintf(LogWARN, "show command must have arguments\n");
736
737  return 0;
738}
739
740static int
741TerminalCommand(struct cmdtab const * list, int argc, char **argv)
742{
743  if (LcpFsm.state > ST_CLOSED) {
744    if (VarTerm)
745      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
746    return 1;
747  }
748  if (!IsInteractive())
749    return (1);
750  if (OpenModem(mode) < 0) {
751    if (VarTerm)
752      fprintf(VarTerm, "Failed to open modem.\n");
753    return (1);
754  }
755  if (VarTerm) {
756    fprintf(VarTerm, "Enter to terminal mode.\n");
757    fprintf(VarTerm, "Type `~?' for help.\n");
758  }
759  TtyTermMode();
760  return (0);
761}
762
763static int
764QuitCommand(struct cmdtab const * list, int argc, char **argv)
765{
766  FILE *oVarTerm;
767
768  if (mode & (MODE_DIRECT | MODE_DEDICATED | MODE_AUTO)) {
769    if (argc > 0 && !strcasecmp(*argv, "all") && (VarLocalAuth & LOCAL_AUTH)) {
770      mode &= ~MODE_INTER;
771      oVarTerm = VarTerm;
772      VarTerm = 0;
773      if (oVarTerm && oVarTerm != stdout)
774	fclose(oVarTerm);
775      Cleanup(EX_NORMAL);
776    } else if (VarTerm) {
777      LogPrintf(LogPHASE, "Client connection closed.\n");
778      VarLocalAuth = LOCAL_NO_AUTH;
779      mode &= ~MODE_INTER;
780      oVarTerm = VarTerm;
781      VarTerm = 0;
782      if (oVarTerm && oVarTerm != stdout)
783	fclose(oVarTerm);
784      close(netfd);
785      netfd = -1;
786    }
787  } else
788    Cleanup(EX_NORMAL);
789
790  return 0;
791}
792
793static int
794CloseCommand(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
1195#define	VAR_AUTHKEY	0
1196#define	VAR_DIAL	1
1197#define	VAR_LOGIN	2
1198#define	VAR_AUTHNAME	3
1199#define	VAR_DEVICE	4
1200#define	VAR_ACCMAP	5
1201#define	VAR_PHONE	6
1202#define	VAR_HANGUP	7
1203#define	VAR_ENC		8
1204
1205static int
1206SetVariable(struct cmdtab const * list, int argc, char **argv, int param)
1207{
1208  u_long map;
1209  char *arg;
1210
1211  if (argc > 0)
1212    arg = *argv;
1213  else
1214    arg = "";
1215
1216  switch (param) {
1217  case VAR_AUTHKEY:
1218    strncpy(VarAuthKey, arg, sizeof(VarAuthKey) - 1);
1219    VarAuthKey[sizeof(VarAuthKey) - 1] = '\0';
1220    break;
1221  case VAR_AUTHNAME:
1222    strncpy(VarAuthName, arg, sizeof(VarAuthName) - 1);
1223    VarAuthName[sizeof(VarAuthName) - 1] = '\0';
1224    break;
1225  case VAR_DIAL:
1226    strncpy(VarDialScript, arg, sizeof(VarDialScript) - 1);
1227    VarDialScript[sizeof(VarDialScript) - 1] = '\0';
1228    break;
1229  case VAR_LOGIN:
1230    strncpy(VarLoginScript, arg, sizeof(VarLoginScript) - 1);
1231    VarLoginScript[sizeof(VarLoginScript) - 1] = '\0';
1232    break;
1233  case VAR_DEVICE:
1234    CloseModem();
1235    strncpy(VarDevice, arg, sizeof(VarDevice) - 1);
1236    VarDevice[sizeof(VarDevice) - 1] = '\0';
1237    VarBaseDevice = rindex(VarDevice, '/');
1238    VarBaseDevice = VarBaseDevice ? VarBaseDevice + 1 : "";
1239    break;
1240  case VAR_ACCMAP:
1241    sscanf(arg, "%lx", &map);
1242    VarAccmap = map;
1243    break;
1244  case VAR_PHONE:
1245    strncpy(VarPhoneList, arg, sizeof(VarPhoneList) - 1);
1246    VarPhoneList[sizeof(VarPhoneList) - 1] = '\0';
1247    strcpy(VarPhoneCopy, VarPhoneList);
1248    VarNextPhone = VarPhoneCopy;
1249    break;
1250  case VAR_HANGUP:
1251    strncpy(VarHangupScript, arg, sizeof(VarHangupScript) - 1);
1252    VarHangupScript[sizeof(VarHangupScript) - 1] = '\0';
1253    break;
1254  case VAR_ENC:
1255    VarEncMD4 = !strcasecmp(arg, "md4");
1256    break;
1257  }
1258  return 0;
1259}
1260
1261static int
1262SetCtsRts(struct cmdtab const * list, int argc, char **argv)
1263{
1264  if (argc > 0) {
1265    if (strcmp(*argv, "on") == 0)
1266      VarCtsRts = TRUE;
1267    else if (strcmp(*argv, "off") == 0)
1268      VarCtsRts = FALSE;
1269    else
1270      return -1;
1271    return 0;
1272  }
1273  return -1;
1274}
1275
1276
1277static int
1278SetOpenMode(struct cmdtab const * list, int argc, char **argv)
1279{
1280  if (argc > 0) {
1281    if (strcmp(*argv, "active") == 0)
1282      VarOpenMode = OPEN_ACTIVE;
1283    else if (strcmp(*argv, "passive") == 0)
1284      VarOpenMode = OPEN_PASSIVE;
1285    else
1286      return -1;
1287    return 0;
1288  }
1289  return -1;
1290}
1291
1292extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
1293
1294struct cmdtab const SetCommands[] = {
1295  {"accmap", NULL, SetVariable, LOCAL_AUTH,
1296  "Set accmap value", "set accmap hex-value", (void *) VAR_ACCMAP},
1297  {"afilter", NULL, SetAfilter, LOCAL_AUTH,
1298  "Set keep Alive filter", "set afilter ..."},
1299  {"authkey", "key", SetVariable, LOCAL_AUTH,
1300  "Set authentication key", "set authkey|key key", (void *) VAR_AUTHKEY},
1301  {"authname", NULL, SetVariable, LOCAL_AUTH,
1302  "Set authentication name", "set authname name", (void *) VAR_AUTHNAME},
1303  {"ctsrts", NULL, SetCtsRts, LOCAL_AUTH,
1304  "Use CTS/RTS modem signalling", "set ctsrts [on|off]"},
1305  {"device", "line", SetVariable, LOCAL_AUTH,
1306  "Set modem device name", "set device|line device-name", (void *) VAR_DEVICE},
1307  {"dfilter", NULL, SetDfilter, LOCAL_AUTH,
1308  "Set demand filter", "set dfilter ..."},
1309  {"dial", NULL, SetVariable, LOCAL_AUTH,
1310  "Set dialing script", "set dial chat-script", (void *) VAR_DIAL},
1311  {"encrypt", NULL, SetVariable, LOCAL_AUTH,
1312  "Set CHAP encryption algorithm", "set encrypt MD4|MD5", (void *) VAR_ENC},
1313  {"escape", NULL, SetEscape, LOCAL_AUTH,
1314  "Set escape characters", "set escape hex-digit ..."},
1315  {"hangup", NULL, SetVariable, LOCAL_AUTH,
1316  "Set hangup script", "set hangup chat-script", (void *) VAR_HANGUP},
1317  {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH,
1318  "Set destination address", "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
1319  {"ifilter", NULL, SetIfilter, LOCAL_AUTH,
1320  "Set input filter", "set ifilter ..."},
1321  {"loopback", NULL, SetLoopback, LOCAL_AUTH,
1322  "Set loopback facility", "set loopback on|off"},
1323  {"log", NULL, SetLogLevel, LOCAL_AUTH,
1324  "Set log level", "set log [+|-]value..."},
1325  {"login", NULL, SetVariable, LOCAL_AUTH,
1326  "Set login script", "set login chat-script", (void *) VAR_LOGIN},
1327  {"mru", NULL, SetInitialMRU, LOCAL_AUTH,
1328  "Set Initial MRU value", "set mru value"},
1329  {"mtu", NULL, SetPreferredMTU, LOCAL_AUTH,
1330  "Set Preferred MTU value", "set mtu value"},
1331  {"ofilter", NULL, SetOfilter, LOCAL_AUTH,
1332  "Set output filter", "set ofilter ..."},
1333  {"openmode", NULL, SetOpenMode, LOCAL_AUTH,
1334  "Set open mode", "set openmode [active|passive]"},
1335  {"parity", NULL, SetModemParity, LOCAL_AUTH,
1336  "Set modem parity", "set parity [odd|even|none]"},
1337  {"phone", NULL, SetVariable, LOCAL_AUTH,
1338  "Set telephone number(s)", "set phone phone1[:phone2[...]]", (void *) VAR_PHONE},
1339  {"reconnect", NULL, SetReconnect, LOCAL_AUTH,
1340  "Set Reconnect timeout", "set reconnect value ntries"},
1341  {"redial", NULL, SetRedialTimeout, LOCAL_AUTH,
1342  "Set Redial timeout", "set redial value|random[.value|random] [dial_attempts]"},
1343  {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH,
1344  "Set STOPPED timeouts", "set stopped [LCPseconds [IPCPseconds [CCPseconds]]]"},
1345  {"server", "socket", SetServer, LOCAL_AUTH,
1346  "Set server port", "set server|socket TcpPort|LocalName|none [mask]"},
1347  {"speed", NULL, SetModemSpeed, LOCAL_AUTH,
1348  "Set modem speed", "set speed value"},
1349  {"timeout", NULL, SetIdleTimeout, LOCAL_AUTH,
1350  "Set Idle timeout", "set timeout value"},
1351#ifndef NOMSEXT
1352  {"ns", NULL, SetNS, LOCAL_AUTH,
1353  "Set NameServer", "set ns pri-addr [sec-addr]"},
1354  {"nbns", NULL, SetNBNS, LOCAL_AUTH,
1355  "Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"},
1356#endif
1357  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
1358  "Display this message", "set help|? [command]", (void *) SetCommands},
1359  {NULL, NULL, NULL},
1360};
1361
1362static int
1363SetCommand(struct cmdtab const * list, int argc, char **argv)
1364{
1365  if (argc > 0)
1366    FindExec(SetCommands, argc, argv);
1367  else if (VarTerm)
1368    fprintf(VarTerm, "Use `set ?' to get a list or `set ? <var>' for"
1369	    " syntax help.\n");
1370  else
1371    LogPrintf(LogWARN, "set command must have arguments\n");
1372
1373  return 0;
1374}
1375
1376
1377static int
1378AddCommand(struct cmdtab const * list, int argc, char **argv)
1379{
1380  struct in_addr dest, gateway, netmask;
1381
1382  if (argc == 3) {
1383    if (strcasecmp(argv[0], "MYADDR") == 0)
1384      dest = IpcpInfo.want_ipaddr;
1385    else
1386      dest = GetIpAddr(argv[0]);
1387    netmask = GetIpAddr(argv[1]);
1388    if (strcasecmp(argv[2], "HISADDR") == 0)
1389      gateway = IpcpInfo.his_ipaddr;
1390    else
1391      gateway = GetIpAddr(argv[2]);
1392    OsSetRoute(RTM_ADD, dest, gateway, netmask);
1393    return 0;
1394  }
1395  return -1;
1396}
1397
1398static int
1399DeleteCommand(struct cmdtab const * list, int argc, char **argv)
1400{
1401  struct in_addr dest, gateway, netmask;
1402
1403  if (argc == 1 && strcasecmp(argv[0], "all") == 0)
1404    DeleteIfRoutes(0);
1405  else if (argc > 0 && argc < 4) {
1406    if (strcasecmp(argv[0], "MYADDR") == 0)
1407      dest = IpcpInfo.want_ipaddr;
1408    else
1409      dest = GetIpAddr(argv[0]);
1410    netmask.s_addr = INADDR_ANY;
1411    if (argc > 1) {
1412      if (strcasecmp(argv[1], "HISADDR") == 0)
1413	gateway = IpcpInfo.his_ipaddr;
1414      else
1415	gateway = GetIpAddr(argv[1]);
1416      if (argc == 3) {
1417	if (inet_aton(argv[2], &netmask) == 0) {
1418	  LogPrintf(LogWARN, "Bad netmask value.\n");
1419	  return -1;
1420	}
1421      }
1422    } else
1423      gateway.s_addr = INADDR_ANY;
1424    OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1425  } else
1426    return -1;
1427
1428  return 0;
1429}
1430
1431static int AliasEnable();
1432static int AliasOption();
1433
1434static struct cmdtab const AliasCommands[] =
1435{
1436  {"enable", NULL, AliasEnable, LOCAL_AUTH,
1437  "enable IP aliasing", "alias enable [yes|no]"},
1438  {"port", NULL, AliasRedirectPort, LOCAL_AUTH,
1439  "port redirection", "alias port [proto addr_local:port_local  port_alias]"},
1440  {"addr", NULL, AliasRedirectAddr, LOCAL_AUTH,
1441  "static address translation", "alias addr [addr_local addr_alias]"},
1442  {"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
1443    "stop incoming connections", "alias deny_incoming [yes|no]",
1444  (void *) PKT_ALIAS_DENY_INCOMING},
1445  {"log", NULL, AliasOption, LOCAL_AUTH,
1446    "log aliasing link creation", "alias log [yes|no]",
1447  (void *) PKT_ALIAS_LOG},
1448  {"same_ports", NULL, AliasOption, LOCAL_AUTH,
1449    "try to leave port numbers unchanged", "alias same_ports [yes|no]",
1450  (void *) PKT_ALIAS_SAME_PORTS},
1451  {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
1452    "allocate host sockets", "alias use_sockets [yes|no]",
1453  (void *) PKT_ALIAS_USE_SOCKETS},
1454  {"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
1455    "alias unregistered (private) IP address space only",
1456    "alias unregistered_only [yes|no]",
1457  (void *) PKT_ALIAS_UNREGISTERED_ONLY},
1458  {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
1459    "Display this message", "alias help|? [command]",
1460  (void *) AliasCommands},
1461  {NULL, NULL, NULL},
1462};
1463
1464
1465static int
1466AliasCommand(struct cmdtab const * list, int argc, char **argv)
1467{
1468  if (argc > 0)
1469    FindExec(AliasCommands, argc, argv);
1470  else if (VarTerm)
1471    fprintf(VarTerm, "Use `alias help' to get a list or `alias help <option>'"
1472	    " for syntax help.\n");
1473  else
1474    LogPrintf(LogWARN, "alias command must have arguments\n");
1475
1476  return 0;
1477}
1478
1479static int
1480AliasEnable(struct cmdtab const * list, int argc, char **argv)
1481{
1482  if (argc == 1)
1483    if (strcasecmp(argv[0], "yes") == 0) {
1484      if (!(mode & MODE_ALIAS)) {
1485	if (loadAliasHandlers(&VarAliasHandlers) == 0) {
1486	  mode |= MODE_ALIAS;
1487	  return 0;
1488	}
1489	LogPrintf(LogWARN, "Cannot load alias library\n");
1490	return 1;
1491      }
1492      return 0;
1493    } else if (strcasecmp(argv[0], "no") == 0) {
1494      if (mode & MODE_ALIAS) {
1495	unloadAliasHandlers();
1496	mode &= ~MODE_ALIAS;
1497      }
1498      return 0;
1499    }
1500  return -1;
1501}
1502
1503
1504static int
1505AliasOption(struct cmdtab const * list, int argc, char **argv, void *param)
1506{
1507  if (argc == 1)
1508    if (strcasecmp(argv[0], "yes") == 0) {
1509      if (mode & MODE_ALIAS) {
1510	VarPacketAliasSetMode((unsigned) param, (unsigned) param);
1511	return 0;
1512      }
1513      LogPrintf(LogWARN, "alias not enabled\n");
1514    } else if (strcmp(argv[0], "no") == 0) {
1515      if (mode & MODE_ALIAS) {
1516	VarPacketAliasSetMode(0, (unsigned) param);
1517	return 0;
1518      }
1519      LogPrintf(LogWARN, "alias not enabled\n");
1520    }
1521  return -1;
1522}
1523