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