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