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