xref: /freebsd/usr.sbin/ppp/command.c (revision 3e0f6b97b257a96f7275e4442204263e44b16686)
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  * $FreeBSD$
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 struct in_addr ifnetmask;
59 
60 static int ShowCommand(), TerminalCommand(), QuitCommand();
61 static int CloseCommand(), DialCommand(), DownCommand();
62 static int SetCommand(), AddCommand(), DeleteCommand();
63 static int ShellCommand();
64 
65 static int
66 HelpCommand(list, argc, argv, plist)
67 struct cmdtab *list;
68 int argc;
69 char **argv;
70 struct 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 
100 int
101 IsInteractive()
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 
120 static int
121 DialCommand(cmdlist, argc, argv)
122 struct cmdtab *cmdlist;
123 int argc;
124 char **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 
159 static int
160 ShellCommand(cmdlist, argc, argv)
161 struct cmdtab *cmdlist;
162 int argc;
163 char **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 
241 static char StrOption[] = "option ..";
242 static char StrRemote[] = "[remote]";
243 char StrNull[] = "";
244 
245 struct 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 
287 extern int ReportCcpStatus();
288 extern int ReportLcpStatus();
289 extern int ReportIpcpStatus();
290 extern int ReportProtStatus();
291 extern int ReportCompress();
292 extern int ShowModemStatus();
293 extern int ReportHdlcStatus();
294 extern int ShowMemMap();
295 
296 static 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 
302 static 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 
315 static 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 
334 static 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 
341 static int ShowAuthKey()
342 {
343   printf("AuthName = %s\n", VarAuthName);
344   printf("AuthKey  = %s\n", VarAuthKey);
345   return(1);
346 }
347 
348 static int ShowVersion()
349 {
350   extern char VarVersion[];
351   extern char VarLocalVersion[];
352 
353   printf("%s - %s \n", VarVersion, VarLocalVersion);
354   return(1);
355 }
356 
357 static int ShowLogList()
358 {
359   ListLog();
360   return(1);
361 }
362 
363 static 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
383 static 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 
395 extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
396 
397 struct 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 
447 struct cmdtab *
448 FindCommand(cmds, str, pmatch)
449 struct cmdtab *cmds;
450 char *str;
451 int *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 
471 int
472 FindExec(cmdlist, argc, argv)
473 struct cmdtab *cmdlist;
474 int argc;
475 char **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 
491 int aft_cmd = 1;
492 
493 void
494 Prompt()
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 
518 void
519 DecodeCommand(buff, nb, prompt)
520 char *buff;
521 int nb;
522 int 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 
546 static int
547 ShowCommand(list, argc, argv)
548 struct cmdtab *list;
549 int argc;
550 char **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 
561 static int
562 TerminalCommand()
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 
582 static int
583 QuitCommand(list, argc, argv)
584 struct cmdtab *list;
585 int argc;
586 char **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 
605 static int
606 CloseCommand()
607 {
608   LcpClose();
609   return(1);
610 }
611 
612 static int
613 DownCommand()
614 {
615   LcpDown();
616   return(1);
617 }
618 
619 static int SetModemSpeed(list, argc, argv)
620 struct cmdtab *list;
621 int argc;
622 char **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 
641 static int SetRedialTimeout(list, argc, argv)
642 struct cmdtab *list;
643 int argc;
644 char **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 
684 static int SetModemParity(list, argc, argv)
685 struct cmdtab *list;
686 int argc;
687 char **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 
701 static int
702 SetDebugLevel(list, argc, argv)
703 struct cmdtab *list;
704 int argc;
705 char **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 
730 static int
731 SetEscape(list, argc, argv)
732 struct cmdtab *list;
733 int argc;
734 char **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 
749 static int
750 SetInitialMRU(list, argc, argv)
751 struct cmdtab *list;
752 int argc;
753 char **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 
769 static int
770 SetIdleTimeout(list, argc, argv)
771 struct cmdtab *list;
772 int argc;
773 char **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 
791 struct in_addr
792 GetIpAddr(cp)
793 char *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 
806 static int
807 SetInterfaceAddr(list, argc, argv)
808 struct cmdtab *list;
809 int argc;
810 char **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 
852 void
853 SetMSEXT(pri_addr, sec_addr, argc, argv)
854 struct in_addr *pri_addr;
855 struct in_addr *sec_addr;
856 int argc;
857 char **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 
882 static int
883 SetNS(list, argc, argv)
884 struct cmdtab *list;
885 int argc;
886 char **argv;
887 {
888   SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv);
889   return(1);
890 }
891 
892 static int
893 SetNBNS(list, argc, argv)
894 struct cmdtab *list;
895 int argc;
896 char **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 
912 static int
913 SetVariable(list, argc, argv, param)
914 struct cmdtab *list;
915 int argc;
916 char **argv;
917 int 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       VarAuthKey[sizeof(VarAuthKey)-1] = '\0';
926       break;
927     case VAR_AUTHNAME:
928       strncpy(VarAuthName, *argv, sizeof(VarAuthName)-1);
929       VarAuthName[sizeof(VarAuthName)-1] = '\0';
930       break;
931     case VAR_DIAL:
932       strncpy(VarDialScript, *argv, sizeof(VarDialScript)-1);
933       VarDialScript[sizeof(VarDialScript)-1] = '\0';
934       break;
935     case VAR_LOGIN:
936       strncpy(VarLoginScript, *argv, sizeof(VarLoginScript)-1);
937       VarLoginScript[sizeof(VarLoginScript)-1] = '\0';
938       break;
939     case VAR_DEVICE:
940       strncpy(VarDevice, *argv, sizeof(VarDevice)-1);
941       VarDevice[sizeof(VarDevice)-1] = '\0';
942       break;
943     case VAR_ACCMAP:
944       sscanf(*argv, "%lx", &map);
945       VarAccmap = map;
946       break;
947     case VAR_PHONE:
948       strncpy(VarPhoneList, *argv, sizeof(VarPhoneList)-1);
949       VarPhoneList[sizeof(VarPhoneList)-1] = '\0';
950       strcpy(VarPhoneCopy, VarPhoneList);
951       VarNextPhone = VarPhoneCopy;
952       break;
953     }
954   }
955   return(1);
956 }
957 
958 static int SetCtsRts(list, argc, argv)
959 struct cmdtab *list;
960 int argc;
961 char **argv;
962 {
963   if (argc > 0) {
964     if (strcmp(*argv, "on") == 0)
965       VarCtsRts = TRUE;
966     else if (strcmp(*argv, "off") == 0)
967       VarCtsRts = FALSE;
968     else
969       printf("usage: set ctsrts [on|off].\n");
970   }
971   return(1);
972 }
973 
974 
975 static int SetOpenMode(list, argc, argv)
976 struct cmdtab *list;
977 int argc;
978 char **argv;
979 {
980   if (argc > 0) {
981     if (strcmp(*argv, "active") == 0)
982       VarOpenMode = OPEN_ACTIVE;
983     else if (strcmp(*argv, "passive") == 0)
984       VarOpenMode = OPEN_PASSIVE;
985     else
986       printf("Invalid mode.\n");
987   }
988   return(1);
989 }
990 static char StrChatStr[] = "chat-script";
991 static char StrValue[] = "value";
992 
993 extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
994 
995 struct cmdtab const SetCommands[] = {
996   { "accmap",   NULL,	  SetVariable,		LOCAL_AUTH,
997 	"Set accmap value", "hex-value", (void *)VAR_ACCMAP},
998   { "afilter",  NULL,     SetAfilter, 		LOCAL_AUTH,
999 	"Set keep Alive filter", "..."},
1000   { "authkey",  "key",     SetVariable,		LOCAL_AUTH,
1001 	"Set authentication key", "key", (void *)VAR_AUTHKEY},
1002   { "authname", NULL,     SetVariable,		LOCAL_AUTH,
1003 	"Set authentication name", "name", (void *)VAR_AUTHNAME},
1004   { "ctsrts", NULL,	  SetCtsRts,		LOCAL_AUTH,
1005 	"Use CTS/RTS modem signalling", "[on|off]"},
1006   { "debug",    NULL,	  SetDebugLevel,	LOCAL_AUTH,
1007 	"Set debug level", StrValue},
1008   { "device",     "line", SetVariable, 		LOCAL_AUTH,
1009 	"Set modem device name", "device-name",	(void *)VAR_DEVICE},
1010   { "dfilter",  NULL,     SetDfilter,		 LOCAL_AUTH,
1011 	"Set demand filter", "..."},
1012   { "dial",     NULL,     SetVariable, 		LOCAL_AUTH,
1013 	"Set dialing script", StrChatStr, (void *)VAR_DIAL},
1014   { "escape",   NULL,	  SetEscape, 		LOCAL_AUTH,
1015 	"Set escape characters", "hex-digit ..."},
1016   { "ifaddr",   NULL,   SetInterfaceAddr,	LOCAL_AUTH,
1017 	"Set destination address", "[src-addr [dst-addr [netmask [trg-addr]]]]"},
1018   { "ifilter",  NULL,     SetIfilter, 		LOCAL_AUTH,
1019 	"Set input filter", "..."},
1020   { "login",    NULL,     SetVariable,		LOCAL_AUTH,
1021 	"Set login script", StrChatStr,	(void *)VAR_LOGIN },
1022   { "mru",      "mtu",    SetInitialMRU,	LOCAL_AUTH,
1023 	"Set Initial MRU value", StrValue },
1024   { "ofilter",  NULL,	  SetOfilter,		LOCAL_AUTH,
1025 	"Set output filter", "..." },
1026   { "openmode", NULL,	  SetOpenMode,		LOCAL_AUTH,
1027 	"Set open mode", "[active|passive]"},
1028   { "parity",   NULL,     SetModemParity,	LOCAL_AUTH,
1029 	"Set modem parity", "[odd|even|none]"},
1030   { "phone",    NULL,     SetVariable,		LOCAL_AUTH,
1031 	"Set telephone number(s)", "phone1[:phone2[...]]", (void *)VAR_PHONE },
1032   { "speed",    NULL,     SetModemSpeed,	LOCAL_AUTH,
1033 	"Set modem speed", "speed"},
1034   { "timeout",  NULL,     SetIdleTimeout,	LOCAL_AUTH,
1035 	"Set Idle timeout", StrValue},
1036   { "redial",   NULL,     SetRedialTimeout,	LOCAL_AUTH,
1037 	"Set Redial timeout", "value|random [dial_attempts]"},
1038 #ifdef MSEXT
1039   { "ns",	NULL,	  SetNS,		LOCAL_AUTH,
1040 	"Set NameServer", "pri-addr [sec-addr]"},
1041   { "nbns",	NULL,	  SetNBNS,		LOCAL_AUTH,
1042 	"Set NetBIOS NameServer", "pri-addr [sec-addr]"},
1043 #endif /* MSEXT */
1044   { "help",     "?",      HelpCommand,		LOCAL_AUTH | LOCAL_NO_AUTH,
1045 	"Display this message", StrNull, (void *)SetCommands},
1046   { NULL,       NULL,     NULL },
1047 };
1048 
1049 static int
1050 SetCommand(list, argc, argv)
1051 struct cmdtab *list;
1052 int argc;
1053 char **argv;
1054 {
1055   int val = 1;
1056 
1057   if (argc > 0)
1058     val = FindExec(SetCommands, argc, argv);
1059   else
1060     printf("Use `set ?' to get a list or `set ? <var>' for syntax help.\n");
1061   return(val);
1062 }
1063 
1064 
1065 static int
1066 AddCommand(list, argc, argv)
1067 struct cmdtab *list;
1068 int argc;
1069 char **argv;
1070 {
1071   struct in_addr dest, gateway, netmask;
1072 
1073   if (argc == 3) {
1074     dest = GetIpAddr(argv[0]);
1075     netmask = GetIpAddr(argv[1]);
1076     if (strcmp(argv[2], "HISADDR") == 0)
1077       gateway = IpcpInfo.his_ipaddr;
1078     else
1079       gateway = GetIpAddr(argv[2]);
1080     OsSetRoute(RTM_ADD, dest, gateway, netmask);
1081   } else {
1082     printf("Usage: %s %s\n", list->name, list->syntax);
1083   }
1084   return(1);
1085 }
1086 
1087 static int
1088 DeleteCommand(list, argc, argv)
1089 struct cmdtab *list;
1090 int argc;
1091 char **argv;
1092 {
1093   struct in_addr dest, gateway, netmask;
1094 
1095   if (argc >= 2) {
1096     dest = GetIpAddr(argv[0]);
1097     if (strcmp(argv[1], "HISADDR") == 0)
1098       gateway = IpcpInfo.his_ipaddr;
1099     else
1100       gateway = GetIpAddr(argv[1]);
1101     netmask.s_addr = 0;
1102     if (argc == 3) {
1103       if (inet_aton(argv[1], &netmask) == 0) {
1104 	printf("bad netmask value.\n");
1105 	return(1);
1106       }
1107     }
1108     OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1109   } else if (argc == 1 && strcmp(argv[0], "ALL") == 0) {
1110     DeleteIfRoutes(0);
1111   } else {
1112     printf("Usage: %s %s\n", list->name, list->syntax);
1113   }
1114   return(1);
1115 }
1116 
1117