xref: /freebsd/usr.sbin/ppp/command.c (revision 230f8c40e55e3462e90151e30f61bd0fdd4dcda3)
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 extern char *IfDevName;
59 
60 struct in_addr ifnetmask;
61 
62 static int ShowCommand(), TerminalCommand(), QuitCommand();
63 static int CloseCommand(), DialCommand(), DownCommand();
64 static int SetCommand(), AddCommand(), DeleteCommand();
65 static int ShellCommand();
66 
67 static int
68 HelpCommand(list, argc, argv, plist)
69 struct cmdtab *list;
70 int argc;
71 char **argv;
72 struct cmdtab *plist;
73 {
74   struct cmdtab *cmd;
75   int n;
76   char c;
77 
78   if (argc > 0) {
79     for (cmd = plist; cmd->name; cmd++) {
80       if (strcmp(cmd->name, *argv) == 0 && (cmd->lauth & VarLocalAuth)) {
81 	if (plist == SetCommands)
82 		printf("set ");
83         printf("%s %s\n", cmd->name, cmd->syntax);
84         return(1);
85       }
86     }
87     return(1);
88   }
89   n = 0;
90   for (cmd = plist; cmd->func; cmd++) {
91     if (cmd->name && (cmd->lauth & VarLocalAuth)) {
92       c = (n & 1)? '\n' : '\t';
93       printf("  %-8s: %-20s%c", cmd->name, cmd->helpmes, c);
94       n++;
95     }
96   }
97   if (n & 1)
98     printf("\n");
99   return(1);
100 }
101 
102 int
103 IsInteractive()
104 {
105   char *mes = NULL;
106 
107   if (mode & MODE_DDIAL)
108     mes = "Working in dedicated dial mode.";
109   else if (mode & MODE_AUTO)
110     mes = "Working in auto mode.";
111   else if (mode & MODE_DIRECT)
112     mes = "Working in direct mode.";
113   else if (mode & MODE_DEDICATED)
114     mes = "Working in dedicated mode.";
115   if (mes) {
116     printf("%s\n", mes);
117     return(0);
118   }
119   return(1);
120 }
121 
122 static int
123 DialCommand(cmdlist, argc, argv)
124 struct cmdtab *cmdlist;
125 int argc;
126 char **argv;
127 {
128   int tries;
129 
130   if (LcpFsm.state > ST_CLOSED) {
131     printf("LCP state is [%s]\n", StateNames[LcpFsm.state]);
132     return(1);
133   }
134   if (!IsInteractive())
135     return(1);
136   if (argc > 0) {
137     if (SelectSystem(*argv, CONFFILE) < 0) {
138       printf("%s: not found.\n", *argv);
139       return(1);
140     }
141   }
142   tries = 0;
143   do {
144     printf("Dial attempt %u\n", ++tries);
145     modem = OpenModem(mode);
146     if (modem < 0) {
147       printf("failed to open modem.\n");
148       modem = 0;
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 extention values", 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     modem = 0;
579     return(1);
580   }
581   printf("Enter to terminal mode.\n");
582   printf("Type `~?' for help.\n");
583   TtyTermMode();
584   return(0);
585 }
586 
587 static int
588 QuitCommand(list, argc, argv)
589 struct cmdtab *list;
590 int argc;
591 char **argv;
592 {
593   if (mode & (MODE_DIRECT|MODE_DEDICATED|MODE_AUTO)) {
594     if (argc > 0 && (VarLocalAuth & LOCAL_AUTH)) {
595       Cleanup(EX_NORMAL);
596       mode &= ~MODE_INTER;
597     } else {
598       VarLocalAuth = LOCAL_NO_AUTH;
599       close(netfd);
600       close(1);
601       dup2(2, 1);     /* Have to have something here or the modem will be 1 */
602       netfd = -1;
603       mode &= ~MODE_INTER;
604     }
605   } else
606     Cleanup(EX_NORMAL);
607   return(1);
608 }
609 
610 static int
611 CloseCommand()
612 {
613   LcpClose();
614   return(1);
615 }
616 
617 static int
618 DownCommand()
619 {
620   LcpDown();
621   return(1);
622 }
623 
624 static int SetModemSpeed(list, argc, argv)
625 struct cmdtab *list;
626 int argc;
627 char **argv;
628 {
629   int speed;
630 
631   if (argc > 0) {
632     if (strcmp(*argv, "sync") == 0) {
633       VarSpeed = 0;
634       return(1);
635     }
636     speed = atoi(*argv);
637     if (IntToSpeed(speed) != B0) {
638       VarSpeed = speed;
639       return(1);
640     }
641     printf("invalid speed.\n");
642   }
643   return(1);
644 }
645 
646 static int SetRedialTimeout(list, argc, argv)
647 struct cmdtab *list;
648 int argc;
649 char **argv;
650 {
651   int timeout;
652   int tries;
653 
654   if (argc == 1 || argc == 2 ) {
655     if (strcasecmp(argv[0], "random") == 0) {
656       VarRedialTimeout = -1;
657       printf("Using random redial timeout.\n");
658       srandom(time(0));
659     }
660     else {
661       timeout = atoi(argv[0]);
662 
663       if (timeout >= 0) {
664 	VarRedialTimeout = timeout;
665       }
666       else {
667 	printf("invalid redial timeout\n");
668 	printf("Usage: %s %s\n", list->name, list->syntax);
669       }
670     }
671     if (argc == 2) {
672       tries = atoi(argv[1]);
673 
674       if (tries >= 0) {
675 	  VarDialTries = tries;
676       }
677       else {
678 	printf("invalid retry value\n");
679 	printf("Usage: %s %s\n", list->name, list->syntax);
680       }
681     }
682   }
683   else {
684     printf("Usage: %s %s\n", list->name, list->syntax);
685   }
686   return(1);
687 }
688 
689 static int SetModemParity(list, argc, argv)
690 struct cmdtab *list;
691 int argc;
692 char **argv;
693 {
694   int parity;
695 
696   if (argc > 0) {
697     parity = ChangeParity(*argv);
698     if (parity < 0)
699       printf("Invalid parity.\n");
700     else
701       VarParity = parity;
702   }
703   return(1);
704 }
705 
706 static int
707 SetDebugLevel(list, argc, argv)
708 struct cmdtab *list;
709 int argc;
710 char **argv;
711 {
712   int level, w;
713 
714   for (level = 0; argc-- > 0; argv++) {
715     if (isdigit(**argv)) {
716       w = atoi(*argv);
717       if (w < 0 || w >= MAXLOGLEVEL) {
718 	printf("invalid log level.\n");
719 	break;
720       } else
721 	level |= (1 << w);
722     } else {
723       for (w = 0; w < MAXLOGLEVEL; w++) {
724 	if (strcasecmp(*argv, LogLevelName[w]) == 0) {
725 	  level |= (1 << w);
726 	  continue;
727 	}
728       }
729     }
730   }
731   loglevel = level;
732   return(1);
733 }
734 
735 static int
736 SetEscape(list, argc, argv)
737 struct cmdtab *list;
738 int argc;
739 char **argv;
740 {
741   int code;
742 
743   for (code = 0; code < 33; code++)
744     EscMap[code] = 0;
745   while (argc-- > 0) {
746     sscanf(*argv++, "%x", &code);
747     code &= 0xff;
748     EscMap[code >> 3] |= (1 << (code&7));
749     EscMap[32] = 1;
750   }
751   return(1);
752 }
753 
754 static int
755 SetInitialMRU(list, argc, argv)
756 struct cmdtab *list;
757 int argc;
758 char **argv;
759 {
760   int mru;
761 
762   if (argc > 0) {
763     mru = atoi(*argv);
764     if (mru < 100)
765       printf("given value is too small.\n");
766     else if (mru > MAX_MRU)
767       printf("given value is too big.\n");
768     else
769       VarMRU = mru;
770   }
771   return(1);
772 }
773 
774 static int
775 SetIdleTimeout(list, argc, argv)
776 struct cmdtab *list;
777 int argc;
778 char **argv;
779 {
780   if (argc-- > 0) {
781     VarIdleTimeout = atoi(*argv++);
782     if (argc-- > 0) {
783       VarLqrTimeout = atoi(*argv++);
784       if (VarLqrTimeout < 1)
785 	VarLqrTimeout = 30;
786       if (argc > 0) {
787 	VarRetryTimeout = atoi(*argv);
788 	if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
789 	  VarRetryTimeout = 3;
790       }
791     }
792   }
793   return(1);
794 }
795 
796 struct in_addr
797 GetIpAddr(cp)
798 char *cp;
799 {
800   struct hostent *hp;
801   struct in_addr ipaddr;
802 
803   hp = gethostbyname(cp);
804   if (hp && hp->h_addrtype == AF_INET)
805     bcopy(hp->h_addr, &ipaddr, hp->h_length);
806   else if (inet_aton(cp, &ipaddr) == 0)
807     ipaddr.s_addr = 0;
808   return(ipaddr);
809 }
810 
811 static int
812 SetInterfaceAddr(list, argc, argv)
813 struct cmdtab *list;
814 int argc;
815 char **argv;
816 {
817 
818   DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
819   if (argc > 0) {
820     ParseAddr(argc, argv++,
821       &DefMyAddress.ipaddr, &DefMyAddress.mask, &DefMyAddress.width);
822     if (--argc > 0) {
823       ParseAddr(argc, argv++,
824 	&DefHisAddress.ipaddr, &DefHisAddress.mask, &DefHisAddress.width);
825       if (--argc > 0) {
826         ifnetmask = GetIpAddr(*argv);
827     	if (--argc > 0) {
828       		ParseAddr(argc, argv++,
829 		        &DefTriggerAddress.ipaddr,
830 			&DefTriggerAddress.mask,
831 			&DefTriggerAddress.width);
832 	}
833       }
834     }
835   }
836   /*
837    * For backwards compatibility, 0.0.0.0 means any address.
838    */
839   if (DefMyAddress.ipaddr.s_addr == 0) {
840     DefMyAddress.mask.s_addr = 0;
841     DefMyAddress.width = 0;
842   }
843   if (DefHisAddress.ipaddr.s_addr == 0) {
844     DefHisAddress.mask.s_addr = 0;
845     DefHisAddress.width = 0;
846   }
847 
848   if ((mode & MODE_AUTO) ||
849 	((mode & MODE_DEDICATED) && dstsystem)) {
850     OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask);
851   }
852   return(1);
853 }
854 
855 #ifdef MSEXT
856 
857 void
858 SetMSEXT(pri_addr, sec_addr, argc, argv)
859 struct in_addr *pri_addr;
860 struct in_addr *sec_addr;
861 int argc;
862 char **argv;
863 {
864   int dummyint;
865   struct in_addr dummyaddr;
866 
867   pri_addr->s_addr = sec_addr->s_addr = 0L;
868 
869   if( argc > 0 ) {
870     ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
871     if( --argc > 0 )
872       ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
873     else
874       sec_addr->s_addr = pri_addr->s_addr;
875   }
876 
877  /*
878   * if the primary/secondary ns entries are 0.0.0.0 we should
879   * set them to either the localhost's ip, or the values in
880   * /etc/resolv.conf ??
881   *
882   * up to you if you want to implement this...
883   */
884 
885 }
886 
887 static int
888 SetNS(list, argc, argv)
889 struct cmdtab *list;
890 int argc;
891 char **argv;
892 {
893   SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv);
894   return(1);
895 }
896 
897 static int
898 SetNBNS(list, argc, argv)
899 struct cmdtab *list;
900 int argc;
901 char **argv;
902 {
903   SetMSEXT(&nbns_entries[0], &nbns_entries[1], argc, argv);
904   return(1);
905 }
906 
907 #endif /* MS_EXT */
908 
909 #define	VAR_AUTHKEY	0
910 #define	VAR_DIAL	1
911 #define	VAR_LOGIN	2
912 #define	VAR_AUTHNAME	3
913 #define	VAR_DEVICE	4
914 #define	VAR_ACCMAP	5
915 #define	VAR_PHONE	6
916 
917 static int
918 SetVariable(list, argc, argv, param)
919 struct cmdtab *list;
920 int argc;
921 char **argv;
922 int param;
923 {
924   u_long map;
925 
926   if (argc > 0) {
927     switch (param) {
928     case VAR_AUTHKEY:
929       strncpy(VarAuthKey, *argv, sizeof(VarAuthKey)-1);
930       VarAuthKey[sizeof(VarAuthKey)-1] = '\0';
931       break;
932     case VAR_AUTHNAME:
933       strncpy(VarAuthName, *argv, sizeof(VarAuthName)-1);
934       VarAuthName[sizeof(VarAuthName)-1] = '\0';
935       break;
936     case VAR_DIAL:
937       strncpy(VarDialScript, *argv, sizeof(VarDialScript)-1);
938       VarDialScript[sizeof(VarDialScript)-1] = '\0';
939       break;
940     case VAR_LOGIN:
941       strncpy(VarLoginScript, *argv, sizeof(VarLoginScript)-1);
942       VarLoginScript[sizeof(VarLoginScript)-1] = '\0';
943       break;
944     case VAR_DEVICE:
945       strncpy(VarDevice, *argv, sizeof(VarDevice)-1);
946       VarDevice[sizeof(VarDevice)-1] = '\0';
947       break;
948     case VAR_ACCMAP:
949       sscanf(*argv, "%lx", &map);
950       VarAccmap = map;
951       break;
952     case VAR_PHONE:
953       strncpy(VarPhoneList, *argv, sizeof(VarPhoneList)-1);
954       VarPhoneList[sizeof(VarPhoneList)-1] = '\0';
955       strcpy(VarPhoneCopy, VarPhoneList);
956       VarNextPhone = VarPhoneCopy;
957       break;
958     }
959   }
960   return(1);
961 }
962 
963 static int SetCtsRts(list, argc, argv)
964 struct cmdtab *list;
965 int argc;
966 char **argv;
967 {
968   if (argc > 0) {
969     if (strcmp(*argv, "on") == 0)
970       VarCtsRts = TRUE;
971     else if (strcmp(*argv, "off") == 0)
972       VarCtsRts = FALSE;
973     else
974       printf("usage: set ctsrts [on|off].\n");
975   }
976   return(1);
977 }
978 
979 
980 static int SetOpenMode(list, argc, argv)
981 struct cmdtab *list;
982 int argc;
983 char **argv;
984 {
985   if (argc > 0) {
986     if (strcmp(*argv, "active") == 0)
987       VarOpenMode = OPEN_ACTIVE;
988     else if (strcmp(*argv, "passive") == 0)
989       VarOpenMode = OPEN_PASSIVE;
990     else
991       printf("Invalid mode.\n");
992   }
993   return(1);
994 }
995 static char StrChatStr[] = "chat-script";
996 static char StrValue[] = "value";
997 
998 extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
999 
1000 struct cmdtab const SetCommands[] = {
1001   { "accmap",   NULL,	  SetVariable,		LOCAL_AUTH,
1002 	"Set accmap value", "hex-value", (void *)VAR_ACCMAP},
1003   { "afilter",  NULL,     SetAfilter, 		LOCAL_AUTH,
1004 	"Set keep Alive filter", "..."},
1005   { "authkey",  "key",     SetVariable,		LOCAL_AUTH,
1006 	"Set authentication key", "key", (void *)VAR_AUTHKEY},
1007   { "authname", NULL,     SetVariable,		LOCAL_AUTH,
1008 	"Set authentication name", "name", (void *)VAR_AUTHNAME},
1009   { "ctsrts", NULL,	  SetCtsRts,		LOCAL_AUTH,
1010 	"Use CTS/RTS modem signalling", "[on|off]"},
1011   { "debug",    NULL,	  SetDebugLevel,	LOCAL_AUTH,
1012 	"Set debug level", StrValue},
1013   { "device",     "line", SetVariable, 		LOCAL_AUTH,
1014 	"Set modem device name", "device-name",	(void *)VAR_DEVICE},
1015   { "dfilter",  NULL,     SetDfilter,		 LOCAL_AUTH,
1016 	"Set demand filter", "..."},
1017   { "dial",     NULL,     SetVariable, 		LOCAL_AUTH,
1018 	"Set dialing script", StrChatStr, (void *)VAR_DIAL},
1019   { "escape",   NULL,	  SetEscape, 		LOCAL_AUTH,
1020 	"Set escape characters", "hex-digit ..."},
1021   { "ifaddr",   NULL,   SetInterfaceAddr,	LOCAL_AUTH,
1022 	"Set destination address", "[src-addr [dst-addr [netmask [trg-addr]]]]"},
1023   { "ifilter",  NULL,     SetIfilter, 		LOCAL_AUTH,
1024 	"Set input filter", "..."},
1025   { "login",    NULL,     SetVariable,		LOCAL_AUTH,
1026 	"Set login script", StrChatStr,	(void *)VAR_LOGIN },
1027   { "mru",      "mtu",    SetInitialMRU,	LOCAL_AUTH,
1028 	"Set Initial MRU value", StrValue },
1029   { "ofilter",  NULL,	  SetOfilter,		LOCAL_AUTH,
1030 	"Set output filter", "..." },
1031   { "openmode", NULL,	  SetOpenMode,		LOCAL_AUTH,
1032 	"Set open mode", "[active|passive]"},
1033   { "parity",   NULL,     SetModemParity,	LOCAL_AUTH,
1034 	"Set modem parity", "[odd|even|none]"},
1035   { "phone",    NULL,     SetVariable,		LOCAL_AUTH,
1036 	"Set telephone number(s)", "phone1[:phone2[...]]", (void *)VAR_PHONE },
1037   { "speed",    NULL,     SetModemSpeed,	LOCAL_AUTH,
1038 	"Set modem speed", "speed"},
1039   { "timeout",  NULL,     SetIdleTimeout,	LOCAL_AUTH,
1040 	"Set Idle timeout", StrValue},
1041   { "redial",   NULL,     SetRedialTimeout,	LOCAL_AUTH,
1042 	"Set Redial timeout", "value|random [dial_attempts]"},
1043 #ifdef MSEXT
1044   { "ns",	NULL,	  SetNS,		LOCAL_AUTH,
1045 	"Set NameServer", "pri-addr [sec-addr]"},
1046   { "nbns",	NULL,	  SetNBNS,		LOCAL_AUTH,
1047 	"Set NetBIOS NameServer", "pri-addr [sec-addr]"},
1048 #endif /* MSEXT */
1049   { "help",     "?",      HelpCommand,		LOCAL_AUTH | LOCAL_NO_AUTH,
1050 	"Display this message", StrNull, (void *)SetCommands},
1051   { NULL,       NULL,     NULL },
1052 };
1053 
1054 static int
1055 SetCommand(list, argc, argv)
1056 struct cmdtab *list;
1057 int argc;
1058 char **argv;
1059 {
1060   int val = 1;
1061 
1062   if (argc > 0)
1063     val = FindExec(SetCommands, argc, argv);
1064   else
1065     printf("Use `set ?' to get a list or `set ? <var>' for syntax help.\n");
1066   return(val);
1067 }
1068 
1069 
1070 static int
1071 AddCommand(list, argc, argv)
1072 struct cmdtab *list;
1073 int argc;
1074 char **argv;
1075 {
1076   struct in_addr dest, gateway, netmask;
1077 
1078   if (argc == 3) {
1079     dest = GetIpAddr(argv[0]);
1080     netmask = GetIpAddr(argv[1]);
1081     if (strcmp(argv[2], "HISADDR") == 0)
1082       gateway = IpcpInfo.his_ipaddr;
1083     else
1084       gateway = GetIpAddr(argv[2]);
1085     OsSetRoute(RTM_ADD, dest, gateway, netmask);
1086   } else {
1087     printf("Usage: %s %s\n", list->name, list->syntax);
1088   }
1089   return(1);
1090 }
1091 
1092 static int
1093 DeleteCommand(list, argc, argv)
1094 struct cmdtab *list;
1095 int argc;
1096 char **argv;
1097 {
1098   struct in_addr dest, gateway, netmask;
1099 
1100   if (argc >= 2) {
1101     dest = GetIpAddr(argv[0]);
1102     if (strcmp(argv[1], "HISADDR") == 0)
1103       gateway = IpcpInfo.his_ipaddr;
1104     else
1105       gateway = GetIpAddr(argv[1]);
1106     netmask.s_addr = 0;
1107     if (argc == 3) {
1108       if (inet_aton(argv[1], &netmask) == 0) {
1109 	printf("bad netmask value.\n");
1110 	return(1);
1111       }
1112     }
1113     OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1114   } else if (argc == 1 && strcmp(argv[0], "ALL") == 0) {
1115     DeleteIfRoutes(0);
1116   } else {
1117     printf("Usage: %s %s\n", list->name, list->syntax);
1118   }
1119   return(1);
1120 }
1121 
1122