xref: /freebsd/usr.sbin/ppp/command.c (revision df7f5d4de4592a8948a25ce01e5bddfbb7ce39dc)
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.34 1997/03/10 08:04:15 ache 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 
45 extern int  MakeArgs();
46 extern void Cleanup(), TtyTermMode(), PacketMode();
47 extern int  EnableCommand(), DisableCommand(), DisplayCommand();
48 extern int  AcceptCommand(), DenyCommand();
49 extern int  LocalAuthCommand();
50 extern int  LoadCommand(), SaveCommand();
51 extern int  ChangeParity(char *);
52 extern int  SelectSystem();
53 extern int  ShowRoute();
54 extern void TtyOldMode(), TtyCommandMode();
55 extern struct pppvars pppVars;
56 extern struct cmdtab const SetCommands[];
57 
58 extern char *IfDevName;
59 
60 struct in_addr ifnetmask;
61 int randinit;
62 
63 static int ShowCommand(), TerminalCommand(), QuitCommand();
64 static int CloseCommand(), DialCommand(), DownCommand();
65 static int SetCommand(), AddCommand(), DeleteCommand();
66 static int ShellCommand();
67 
68 static int
69 HelpCommand(list, argc, argv, plist)
70 struct cmdtab *list;
71 int argc;
72 char **argv;
73 struct 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 
103 int
104 IsInteractive()
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 
123 static int
124 DialCommand(cmdlist, argc, argv)
125 struct cmdtab *cmdlist;
126 int argc;
127 char **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 
161 static int
162 ShellCommand(cmdlist, argc, argv)
163 struct cmdtab *cmdlist;
164 int argc;
165 char **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 
246 static char StrOption[] = "option ..";
247 static char StrRemote[] = "[remote]";
248 char StrNull[] = "";
249 
250 struct 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 
292 extern int ReportCcpStatus();
293 extern int ReportLcpStatus();
294 extern int ReportIpcpStatus();
295 extern int ReportProtStatus();
296 extern int ReportCompress();
297 extern int ShowModemStatus();
298 extern int ReportHdlcStatus();
299 extern int ShowMemMap();
300 
301 static 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 
307 static 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 
320 static 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 
339 static 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 
346 static int ShowAuthKey()
347 {
348   printf("AuthName = %s\n", VarAuthName);
349   printf("AuthKey  = %s\n", VarAuthKey);
350   return(1);
351 }
352 
353 static int ShowVersion()
354 {
355   extern char VarVersion[];
356   extern char VarLocalVersion[];
357 
358   printf("%s - %s \n", VarVersion, VarLocalVersion);
359   return(1);
360 }
361 
362 static int ShowLogList()
363 {
364   ListLog();
365   return(1);
366 }
367 
368 static int ShowRedial()
369 {
370   printf(" Redial Timer: ");
371 
372   if (VarRedialTimeout >= 0) {
373     printf(" %d seconds, ", VarRedialTimeout);
374   }
375   else {
376     printf(" Random 0 - %d seconds, ", REDIAL_PERIOD);
377   }
378 
379   if (VarDialTries)
380       printf("%d dial tries", VarDialTries);
381 
382   printf("\n");
383 
384   return(1);
385 }
386 
387 #ifdef MSEXT
388 static int ShowMSExt()
389 {
390   printf(" MS PPP extention values \n" );
391   printf("   Primary NS     : %s\n", inet_ntoa( ns_entries[0] ));
392   printf("   Secondary NS   : %s\n", inet_ntoa( ns_entries[1] ));
393   printf("   Primary NBNS   : %s\n", inet_ntoa( nbns_entries[0] ));
394   printf("   Secondary NBNS : %s\n", inet_ntoa( nbns_entries[1] ));
395 
396   return(1);
397 }
398 #endif /* MSEXT */
399 
400 extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
401 
402 struct cmdtab const ShowCommands[] = {
403   { "afilter",  NULL,     ShowAfilter,		LOCAL_AUTH,
404 	"Show keep Alive filters", StrOption},
405   { "auth",     NULL,     ShowAuthKey,		LOCAL_AUTH,
406 	"Show auth name/key", StrNull},
407   { "ccp",      NULL,     ReportCcpStatus,	LOCAL_AUTH,
408 	"Show CCP status", StrNull},
409   { "compress", NULL,     ReportCompress,	LOCAL_AUTH,
410 	"Show compression statictics", StrNull},
411   { "debug",	NULL,	  ShowDebugLevel,	LOCAL_AUTH,
412 	"Show current debug level", StrNull},
413   { "dfilter",  NULL,     ShowDfilter,		LOCAL_AUTH,
414 	"Show Demand filters", StrOption},
415   { "escape",   NULL,     ShowEscape,		LOCAL_AUTH,
416 	"Show escape characters", StrNull},
417   { "hdlc",	NULL,	  ReportHdlcStatus,	LOCAL_AUTH,
418 	"Show HDLC error summary", StrNull},
419   { "ifilter",  NULL,     ShowIfilter,		LOCAL_AUTH,
420 	"Show Input filters", StrOption},
421   { "ipcp",     NULL,     ReportIpcpStatus,	LOCAL_AUTH,
422 	"Show IPCP status", StrNull},
423   { "lcp",      NULL,     ReportLcpStatus,	LOCAL_AUTH,
424 	"Show LCP status", StrNull},
425   { "log",      NULL,     ShowLogList,		LOCAL_AUTH,
426 	"Show log records", StrNull},
427   { "mem",      NULL,     ShowMemMap,		LOCAL_AUTH,
428 	"Show memory map", StrNull},
429   { "modem",    NULL,     ShowModemStatus,	LOCAL_AUTH,
430 	"Show modem setups", StrNull},
431   { "ofilter",  NULL,     ShowOfilter,		LOCAL_AUTH,
432 	"Show Output filters", StrOption},
433   { "proto",    NULL,     ReportProtStatus,	LOCAL_AUTH,
434 	"Show protocol summary", StrNull},
435   { "route",    NULL,     ShowRoute,		LOCAL_AUTH,
436 	"Show routing table", StrNull},
437   { "timeout",  NULL,	  ShowTimeout,		LOCAL_AUTH,
438 	"Show Idle timeout value", StrNull},
439   { "redial",   NULL,	  ShowRedial,		LOCAL_AUTH,
440 	"Show Redial timeout value", StrNull},
441 #ifdef MSEXT
442   { "msext", 	NULL,	  ShowMSExt,		LOCAL_AUTH,
443 	"Show MS PPP extentions", StrNull},
444 #endif /* MSEXT */
445   { "version",  NULL,	  ShowVersion,		LOCAL_NO_AUTH | LOCAL_AUTH,
446 	"Show version string", StrNull},
447   { "help",     "?",      HelpCommand,		LOCAL_NO_AUTH | LOCAL_AUTH,
448 	"Display this message", StrNull, (void *)ShowCommands},
449   { NULL,       NULL,     NULL },
450 };
451 
452 struct cmdtab *
453 FindCommand(cmds, str, pmatch)
454 struct cmdtab *cmds;
455 char *str;
456 int *pmatch;
457 {
458   int nmatch = 0;
459   int len = strlen(str);
460   struct cmdtab *found = NULL;
461 
462   while (cmds->func) {
463     if (cmds->name && strncmp(str, cmds->name, len) == 0) {
464       nmatch++;
465       found = cmds;
466     } else if (cmds->alias && strncmp(str, cmds->alias, len) == 0) {
467       nmatch++;
468       found = cmds;
469     }
470     cmds++;
471   }
472   *pmatch = nmatch;
473   return(found);
474 }
475 
476 int
477 FindExec(cmdlist, argc, argv)
478 struct cmdtab *cmdlist;
479 int argc;
480 char **argv;
481 {
482   struct cmdtab *cmd;
483   int val = 1;
484   int nmatch;
485 
486   cmd = FindCommand(cmdlist, *argv, &nmatch);
487   if (nmatch > 1)
488     printf("Ambiguous.\n");
489   else if (cmd && ( cmd->lauth & VarLocalAuth ) )
490     val = (cmd->func)(cmd, --argc, ++argv, cmd->args);
491   else
492     printf("what?\n");
493   return(val);
494 }
495 
496 int aft_cmd = 1;
497 
498 void
499 Prompt()
500 {
501   char *pconnect, *pauth;
502 
503   if (!(mode & MODE_INTER))
504     return;
505 
506   if (!aft_cmd)
507     printf("\n");
508   else
509     aft_cmd = 0;
510 
511   if ( VarLocalAuth == LOCAL_AUTH )
512     pauth = " ON ";
513   else
514     pauth = " on ";
515   if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
516     pconnect = "PPP";
517   else
518     pconnect = "ppp";
519   printf("%s%s%s> ", pconnect, pauth, VarShortHost);
520   fflush(stdout);
521 }
522 
523 void
524 DecodeCommand(buff, nb, prompt)
525 char *buff;
526 int nb;
527 int prompt;
528 {
529   char *vector[20];
530   char **argv;
531   int argc, val;
532   char *cp;
533 
534   val = 1;
535   if (nb > 0) {
536     cp = buff + strcspn(buff, "\r\n");
537     if (cp)
538       *cp = '\0';
539     {
540       argc = MakeArgs(buff, &vector);
541       argv = vector;
542 
543       if (argc > 0)
544         val = FindExec(Commands, argc, argv);
545     }
546   }
547   if (val && prompt)
548     Prompt(0);
549 }
550 
551 static int
552 ShowCommand(list, argc, argv)
553 struct cmdtab *list;
554 int argc;
555 char **argv;
556 {
557   int val = 1;
558 
559   if (argc > 0)
560     val = FindExec(ShowCommands, argc, argv);
561   else
562     printf("Use ``show ?'' to get a list.\n");
563   return(val);
564 }
565 
566 static int
567 TerminalCommand()
568 {
569   if (LcpFsm.state > ST_CLOSED) {
570     printf("LCP state is [%s]\n", StateNames[LcpFsm.state]);
571     return(1);
572   }
573   if (!IsInteractive())
574     return(1);
575   modem = OpenModem(mode);
576   if (modem < 0) {
577     printf("failed to open modem.\n");
578     return(1);
579   }
580   printf("Enter to terminal mode.\n");
581   printf("Type `~?' for help.\n");
582   TtyTermMode();
583   return(0);
584 }
585 
586 static int
587 QuitCommand(list, argc, argv)
588 struct cmdtab *list;
589 int argc;
590 char **argv;
591 {
592   if (mode & (MODE_DIRECT|MODE_DEDICATED|MODE_AUTO)) {
593     if (argc > 0 && (VarLocalAuth & LOCAL_AUTH)) {
594       Cleanup(EX_NORMAL);
595       mode &= ~MODE_INTER;
596     } else {
597       VarLocalAuth = LOCAL_NO_AUTH;
598       close(netfd);
599       close(1);
600       dup2(2, 1);     /* Have to have something here or the modem will be 1 */
601       netfd = -1;
602       mode &= ~MODE_INTER;
603     }
604   } else
605     Cleanup(EX_NORMAL);
606   return(1);
607 }
608 
609 static int
610 CloseCommand()
611 {
612   LcpClose();
613   return(1);
614 }
615 
616 static int
617 DownCommand()
618 {
619   LcpDown();
620   return(1);
621 }
622 
623 static int SetModemSpeed(list, argc, argv)
624 struct cmdtab *list;
625 int argc;
626 char **argv;
627 {
628   int speed;
629 
630   if (argc > 0) {
631     if (strcmp(*argv, "sync") == 0) {
632       VarSpeed = 0;
633       return(1);
634     }
635     speed = atoi(*argv);
636     if (IntToSpeed(speed) != B0) {
637       VarSpeed = speed;
638       return(1);
639     }
640     printf("invalid speed.\n");
641   }
642   return(1);
643 }
644 
645 static int SetRedialTimeout(list, argc, argv)
646 struct cmdtab *list;
647 int argc;
648 char **argv;
649 {
650   int timeout;
651   int tries;
652 
653   if (argc == 1 || argc == 2 ) {
654     if (strcasecmp(argv[0], "random") == 0) {
655       VarRedialTimeout = -1;
656       printf("Using random redial timeout.\n");
657       if (!randinit) {
658 	srandom((unsigned long)(time(NULL) ^ getpid()));
659 	randinit = 1;
660       }
661     }
662     else {
663       timeout = atoi(argv[0]);
664 
665       if (timeout >= 0) {
666 	VarRedialTimeout = timeout;
667       }
668       else {
669 	printf("invalid redial timeout\n");
670 	printf("Usage: %s %s\n", list->name, list->syntax);
671       }
672     }
673     if (argc == 2) {
674       tries = atoi(argv[1]);
675 
676       if (tries >= 0) {
677 	  VarDialTries = tries;
678       }
679       else {
680 	printf("invalid retry value\n");
681 	printf("Usage: %s %s\n", list->name, list->syntax);
682       }
683     }
684   }
685   else {
686     printf("Usage: %s %s\n", list->name, list->syntax);
687   }
688   return(1);
689 }
690 
691 static int SetModemParity(list, argc, argv)
692 struct cmdtab *list;
693 int argc;
694 char **argv;
695 {
696   int parity;
697 
698   if (argc > 0) {
699     parity = ChangeParity(*argv);
700     if (parity < 0)
701       printf("Invalid parity.\n");
702     else
703       VarParity = parity;
704   }
705   return(1);
706 }
707 
708 static int
709 SetDebugLevel(list, argc, argv)
710 struct cmdtab *list;
711 int argc;
712 char **argv;
713 {
714   int level, w;
715 
716   for (level = 0; argc-- > 0; argv++) {
717     if (isdigit(**argv)) {
718       w = atoi(*argv);
719       if (w < 0 || w >= MAXLOGLEVEL) {
720 	printf("invalid log level.\n");
721 	break;
722       } else
723 	level |= (1 << w);
724     } else {
725       for (w = 0; w < MAXLOGLEVEL; w++) {
726 	if (strcasecmp(*argv, LogLevelName[w]) == 0) {
727 	  level |= (1 << w);
728 	  continue;
729 	}
730       }
731     }
732   }
733   loglevel = level;
734   return(1);
735 }
736 
737 static int
738 SetEscape(list, argc, argv)
739 struct cmdtab *list;
740 int argc;
741 char **argv;
742 {
743   int code;
744 
745   for (code = 0; code < 33; code++)
746     EscMap[code] = 0;
747   while (argc-- > 0) {
748     sscanf(*argv++, "%x", &code);
749     code &= 0xff;
750     EscMap[code >> 3] |= (1 << (code&7));
751     EscMap[32] = 1;
752   }
753   return(1);
754 }
755 
756 static int
757 SetInitialMRU(list, argc, argv)
758 struct cmdtab *list;
759 int argc;
760 char **argv;
761 {
762   int mru;
763 
764   if (argc > 0) {
765     mru = atoi(*argv);
766     if (mru < 100)
767       printf("given value is too small.\n");
768     else if (mru > MAX_MRU)
769       printf("given value is too big.\n");
770     else
771       VarMRU = mru;
772   }
773   return(1);
774 }
775 
776 static int
777 SetIdleTimeout(list, argc, argv)
778 struct cmdtab *list;
779 int argc;
780 char **argv;
781 {
782   if (argc-- > 0) {
783     VarIdleTimeout = atoi(*argv++);
784     if (argc-- > 0) {
785       VarLqrTimeout = atoi(*argv++);
786       if (VarLqrTimeout < 1)
787 	VarLqrTimeout = 30;
788       if (argc > 0) {
789 	VarRetryTimeout = atoi(*argv);
790 	if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
791 	  VarRetryTimeout = 3;
792       }
793     }
794   }
795   return(1);
796 }
797 
798 struct in_addr
799 GetIpAddr(cp)
800 char *cp;
801 {
802   struct hostent *hp;
803   struct in_addr ipaddr;
804 
805   hp = gethostbyname(cp);
806   if (hp && hp->h_addrtype == AF_INET)
807     bcopy(hp->h_addr, &ipaddr, hp->h_length);
808   else if (inet_aton(cp, &ipaddr) == 0)
809     ipaddr.s_addr = 0;
810   return(ipaddr);
811 }
812 
813 static int
814 SetInterfaceAddr(list, argc, argv)
815 struct cmdtab *list;
816 int argc;
817 char **argv;
818 {
819 
820   DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
821   if (argc > 0) {
822     ParseAddr(argc, argv++,
823       &DefMyAddress.ipaddr, &DefMyAddress.mask, &DefMyAddress.width);
824     if (--argc > 0) {
825       ParseAddr(argc, argv++,
826 	&DefHisAddress.ipaddr, &DefHisAddress.mask, &DefHisAddress.width);
827       if (--argc > 0) {
828         ifnetmask = GetIpAddr(*argv);
829     	if (--argc > 0) {
830       		ParseAddr(argc, argv++,
831 		        &DefTriggerAddress.ipaddr,
832 			&DefTriggerAddress.mask,
833 			&DefTriggerAddress.width);
834 	}
835       }
836     }
837   }
838   /*
839    * For backwards compatibility, 0.0.0.0 means any address.
840    */
841   if (DefMyAddress.ipaddr.s_addr == 0) {
842     DefMyAddress.mask.s_addr = 0;
843     DefMyAddress.width = 0;
844   }
845   if (DefHisAddress.ipaddr.s_addr == 0) {
846     DefHisAddress.mask.s_addr = 0;
847     DefHisAddress.width = 0;
848   }
849 
850   if ((mode & MODE_AUTO) ||
851 	((mode & MODE_DEDICATED) && dstsystem)) {
852     OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask);
853   }
854   return(1);
855 }
856 
857 #ifdef MSEXT
858 
859 void
860 SetMSEXT(pri_addr, sec_addr, argc, argv)
861 struct in_addr *pri_addr;
862 struct in_addr *sec_addr;
863 int argc;
864 char **argv;
865 {
866   int dummyint;
867   struct in_addr dummyaddr;
868 
869   pri_addr->s_addr = sec_addr->s_addr = 0L;
870 
871   if( argc > 0 ) {
872     ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
873     if( --argc > 0 )
874       ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
875     else
876       sec_addr->s_addr = pri_addr->s_addr;
877   }
878 
879  /*
880   * if the primary/secondary ns entries are 0.0.0.0 we should
881   * set them to either the localhost's ip, or the values in
882   * /etc/resolv.conf ??
883   *
884   * up to you if you want to implement this...
885   */
886 
887 }
888 
889 static int
890 SetNS(list, argc, argv)
891 struct cmdtab *list;
892 int argc;
893 char **argv;
894 {
895   SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv);
896   return(1);
897 }
898 
899 static int
900 SetNBNS(list, argc, argv)
901 struct cmdtab *list;
902 int argc;
903 char **argv;
904 {
905   SetMSEXT(&nbns_entries[0], &nbns_entries[1], argc, argv);
906   return(1);
907 }
908 
909 #endif /* MS_EXT */
910 
911 #define	VAR_AUTHKEY	0
912 #define	VAR_DIAL	1
913 #define	VAR_LOGIN	2
914 #define	VAR_AUTHNAME	3
915 #define	VAR_DEVICE	4
916 #define	VAR_ACCMAP	5
917 #define	VAR_PHONE	6
918 
919 static int
920 SetVariable(list, argc, argv, param)
921 struct cmdtab *list;
922 int argc;
923 char **argv;
924 int param;
925 {
926   u_long map;
927 
928   if (argc > 0) {
929     switch (param) {
930     case VAR_AUTHKEY:
931       strncpy(VarAuthKey, *argv, sizeof(VarAuthKey)-1);
932       VarAuthKey[sizeof(VarAuthKey)-1] = '\0';
933       break;
934     case VAR_AUTHNAME:
935       strncpy(VarAuthName, *argv, sizeof(VarAuthName)-1);
936       VarAuthName[sizeof(VarAuthName)-1] = '\0';
937       break;
938     case VAR_DIAL:
939       strncpy(VarDialScript, *argv, sizeof(VarDialScript)-1);
940       VarDialScript[sizeof(VarDialScript)-1] = '\0';
941       break;
942     case VAR_LOGIN:
943       strncpy(VarLoginScript, *argv, sizeof(VarLoginScript)-1);
944       VarLoginScript[sizeof(VarLoginScript)-1] = '\0';
945       break;
946     case VAR_DEVICE:
947       strncpy(VarDevice, *argv, sizeof(VarDevice)-1);
948       VarDevice[sizeof(VarDevice)-1] = '\0';
949       break;
950     case VAR_ACCMAP:
951       sscanf(*argv, "%lx", &map);
952       VarAccmap = map;
953       break;
954     case VAR_PHONE:
955       strncpy(VarPhoneList, *argv, sizeof(VarPhoneList)-1);
956       VarPhoneList[sizeof(VarPhoneList)-1] = '\0';
957       strcpy(VarPhoneCopy, VarPhoneList);
958       VarNextPhone = VarPhoneCopy;
959       break;
960     }
961   }
962   return(1);
963 }
964 
965 static int SetCtsRts(list, argc, argv)
966 struct cmdtab *list;
967 int argc;
968 char **argv;
969 {
970   if (argc > 0) {
971     if (strcmp(*argv, "on") == 0)
972       VarCtsRts = TRUE;
973     else if (strcmp(*argv, "off") == 0)
974       VarCtsRts = FALSE;
975     else
976       printf("usage: set ctsrts [on|off].\n");
977   }
978   return(1);
979 }
980 
981 
982 static int SetOpenMode(list, argc, argv)
983 struct cmdtab *list;
984 int argc;
985 char **argv;
986 {
987   if (argc > 0) {
988     if (strcmp(*argv, "active") == 0)
989       VarOpenMode = OPEN_ACTIVE;
990     else if (strcmp(*argv, "passive") == 0)
991       VarOpenMode = OPEN_PASSIVE;
992     else
993       printf("Invalid mode.\n");
994   }
995   return(1);
996 }
997 static char StrChatStr[] = "chat-script";
998 static char StrValue[] = "value";
999 
1000 extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
1001 
1002 struct cmdtab const SetCommands[] = {
1003   { "accmap",   NULL,	  SetVariable,		LOCAL_AUTH,
1004 	"Set accmap value", "hex-value", (void *)VAR_ACCMAP},
1005   { "afilter",  NULL,     SetAfilter, 		LOCAL_AUTH,
1006 	"Set keep Alive filter", "..."},
1007   { "authkey",  "key",     SetVariable,		LOCAL_AUTH,
1008 	"Set authentication key", "key", (void *)VAR_AUTHKEY},
1009   { "authname", NULL,     SetVariable,		LOCAL_AUTH,
1010 	"Set authentication name", "name", (void *)VAR_AUTHNAME},
1011   { "ctsrts", NULL,	  SetCtsRts,		LOCAL_AUTH,
1012 	"Use CTS/RTS modem signalling", "[on|off]"},
1013   { "debug",    NULL,	  SetDebugLevel,	LOCAL_AUTH,
1014 	"Set debug level", StrValue},
1015   { "device",     "line", SetVariable, 		LOCAL_AUTH,
1016 	"Set modem device name", "device-name",	(void *)VAR_DEVICE},
1017   { "dfilter",  NULL,     SetDfilter,		 LOCAL_AUTH,
1018 	"Set demand filter", "..."},
1019   { "dial",     NULL,     SetVariable, 		LOCAL_AUTH,
1020 	"Set dialing script", StrChatStr, (void *)VAR_DIAL},
1021   { "escape",   NULL,	  SetEscape, 		LOCAL_AUTH,
1022 	"Set escape characters", "hex-digit ..."},
1023   { "ifaddr",   NULL,   SetInterfaceAddr,	LOCAL_AUTH,
1024 	"Set destination address", "[src-addr [dst-addr [netmask [trg-addr]]]]"},
1025   { "ifilter",  NULL,     SetIfilter, 		LOCAL_AUTH,
1026 	"Set input filter", "..."},
1027   { "login",    NULL,     SetVariable,		LOCAL_AUTH,
1028 	"Set login script", StrChatStr,	(void *)VAR_LOGIN },
1029   { "mru",      "mtu",    SetInitialMRU,	LOCAL_AUTH,
1030 	"Set Initial MRU value", StrValue },
1031   { "ofilter",  NULL,	  SetOfilter,		LOCAL_AUTH,
1032 	"Set output filter", "..." },
1033   { "openmode", NULL,	  SetOpenMode,		LOCAL_AUTH,
1034 	"Set open mode", "[active|passive]"},
1035   { "parity",   NULL,     SetModemParity,	LOCAL_AUTH,
1036 	"Set modem parity", "[odd|even|none]"},
1037   { "phone",    NULL,     SetVariable,		LOCAL_AUTH,
1038 	"Set telephone number(s)", "phone1[:phone2[...]]", (void *)VAR_PHONE },
1039   { "speed",    NULL,     SetModemSpeed,	LOCAL_AUTH,
1040 	"Set modem speed", "speed"},
1041   { "timeout",  NULL,     SetIdleTimeout,	LOCAL_AUTH,
1042 	"Set Idle timeout", StrValue},
1043   { "redial",   NULL,     SetRedialTimeout,	LOCAL_AUTH,
1044 	"Set Redial timeout", "value|random [dial_attempts]"},
1045 #ifdef MSEXT
1046   { "ns",	NULL,	  SetNS,		LOCAL_AUTH,
1047 	"Set NameServer", "pri-addr [sec-addr]"},
1048   { "nbns",	NULL,	  SetNBNS,		LOCAL_AUTH,
1049 	"Set NetBIOS NameServer", "pri-addr [sec-addr]"},
1050 #endif /* MSEXT */
1051   { "help",     "?",      HelpCommand,		LOCAL_AUTH | LOCAL_NO_AUTH,
1052 	"Display this message", StrNull, (void *)SetCommands},
1053   { NULL,       NULL,     NULL },
1054 };
1055 
1056 static int
1057 SetCommand(list, argc, argv)
1058 struct cmdtab *list;
1059 int argc;
1060 char **argv;
1061 {
1062   int val = 1;
1063 
1064   if (argc > 0)
1065     val = FindExec(SetCommands, argc, argv);
1066   else
1067     printf("Use `set ?' to get a list or `set ? <var>' for syntax help.\n");
1068   return(val);
1069 }
1070 
1071 
1072 static int
1073 AddCommand(list, argc, argv)
1074 struct cmdtab *list;
1075 int argc;
1076 char **argv;
1077 {
1078   struct in_addr dest, gateway, netmask;
1079 
1080   if (argc == 3) {
1081     dest = GetIpAddr(argv[0]);
1082     netmask = GetIpAddr(argv[1]);
1083     if (strcmp(argv[2], "HISADDR") == 0)
1084       gateway = IpcpInfo.his_ipaddr;
1085     else
1086       gateway = GetIpAddr(argv[2]);
1087     OsSetRoute(RTM_ADD, dest, gateway, netmask);
1088   } else {
1089     printf("Usage: %s %s\n", list->name, list->syntax);
1090   }
1091   return(1);
1092 }
1093 
1094 static int
1095 DeleteCommand(list, argc, argv)
1096 struct cmdtab *list;
1097 int argc;
1098 char **argv;
1099 {
1100   struct in_addr dest, gateway, netmask;
1101 
1102   if (argc >= 2) {
1103     dest = GetIpAddr(argv[0]);
1104     if (strcmp(argv[1], "HISADDR") == 0)
1105       gateway = IpcpInfo.his_ipaddr;
1106     else
1107       gateway = GetIpAddr(argv[1]);
1108     netmask.s_addr = 0;
1109     if (argc == 3) {
1110       if (inet_aton(argv[1], &netmask) == 0) {
1111 	printf("bad netmask value.\n");
1112 	return(1);
1113       }
1114     }
1115     OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1116   } else if (argc == 1 && strcmp(argv[0], "ALL") == 0) {
1117     DeleteIfRoutes(0);
1118   } else {
1119     printf("Usage: %s %s\n", list->name, list->syntax);
1120   }
1121   return(1);
1122 }
1123 
1124