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