xref: /freebsd/usr.sbin/ppp/command.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
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.66 1997/07/12 19:22:34 brian Exp $
21  *
22  */
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <ctype.h>
26 #include <termios.h>
27 #include <sys/wait.h>
28 #include <time.h>
29 #include <netdb.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <net/route.h>
34 #include <paths.h>
35 #include <alias.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include "fsm.h"
39 #include "phase.h"
40 #include "lcp.h"
41 #include "ipcp.h"
42 #include "modem.h"
43 #include "filter.h"
44 #include "command.h"
45 #include "alias_cmd.h"
46 #include "hdlc.h"
47 #include "loadalias.h"
48 #include "vars.h"
49 #include "systems.h"
50 #include "chat.h"
51 #include "os.h"
52 #include "timeout.h"
53 #include "server.h"
54 
55 extern void Cleanup(), TtyTermMode(), PacketMode();
56 extern int  EnableCommand(), DisableCommand(), DisplayCommand();
57 extern int  AcceptCommand(), DenyCommand();
58 static int  AliasCommand();
59 extern int  LocalAuthCommand();
60 extern int  LoadCommand(), SaveCommand();
61 extern int  ChangeParity(char *);
62 extern int  SelectSystem();
63 extern int  ShowRoute();
64 extern void TtyOldMode(), TtyCommandMode();
65 extern struct pppvars pppVars;
66 extern struct cmdtab const SetCommands[];
67 
68 extern char *IfDevName;
69 
70 struct in_addr ifnetmask;
71 int randinit;
72 
73 static int ShowCommand(), TerminalCommand(), QuitCommand();
74 static int CloseCommand(), DialCommand(), DownCommand();
75 static int SetCommand(), AddCommand(), DeleteCommand();
76 static int ShellCommand();
77 
78 static int
79 HelpCommand(list, argc, argv, plist)
80 struct cmdtab *list;
81 int argc;
82 char **argv;
83 struct cmdtab *plist;
84 {
85   struct cmdtab *cmd;
86   int n;
87 
88   if (!VarTerm)
89     return 0;
90 
91   if (argc > 0) {
92     for (cmd = plist; cmd->name; cmd++)
93       if (strcasecmp(cmd->name, *argv) == 0 && (cmd->lauth & VarLocalAuth)) {
94         fprintf(VarTerm, "%s\n", cmd->syntax);
95         return 0;
96       }
97 
98     return -1;
99   }
100 
101   n = 0;
102   for (cmd = plist; cmd->func; cmd++)
103     if (cmd->name && (cmd->lauth & VarLocalAuth)) {
104       fprintf(VarTerm, "  %-9s: %-20s\n", cmd->name, cmd->helpmes);
105       n++;
106     }
107 
108   if (n & 1)
109     fprintf(VarTerm, "\n");
110 
111   return 0;
112 }
113 
114 int
115 IsInteractive()
116 {
117   char *mes = NULL;
118 
119   if (mode & MODE_DDIAL)
120     mes = "Working in dedicated dial mode.";
121   else if (mode & MODE_BACKGROUND)
122     mes = "Working in background mode.";
123   else if (mode & MODE_AUTO)
124     mes = "Working in auto mode.";
125   else if (mode & MODE_DIRECT)
126     mes = "Working in direct mode.";
127   else if (mode & MODE_DEDICATED)
128     mes = "Working in dedicated mode.";
129   if (mes) {
130     if (VarTerm)
131       fprintf(VarTerm, "%s\n", mes);
132     return 0;
133   }
134   return 1;
135 }
136 
137 static int
138 DialCommand(cmdlist, argc, argv)
139 struct cmdtab *cmdlist;
140 int argc;
141 char **argv;
142 {
143   int tries;
144   int res;
145 
146   if (LcpFsm.state > ST_CLOSED) {
147     if (VarTerm)
148       fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
149     return 0;
150   }
151 
152   if (!IsInteractive())
153     return(1);
154 
155   if (argc > 0) {
156     if (SelectSystem(*argv, CONFFILE) < 0) {
157       if (VarTerm)
158         fprintf(VarTerm, "%s: not found.\n", *argv);
159       return -1;
160     }
161   }
162 
163   tries = 0;
164   do {
165     if (VarTerm)
166       fprintf(VarTerm, "Dial attempt %u of %d\n", ++tries, VarDialTries);
167     modem = OpenModem(mode);
168     if (modem < 0) {
169       if (VarTerm)
170         fprintf(VarTerm, "Failed to open modem.\n");
171       break;
172     }
173     if ((res = DialModem()) == EX_DONE) {
174       sleep(1);
175       ModemTimeout();
176       PacketMode();
177       break;
178     } else if (res == EX_SIG)
179       return 1;
180   } while (VarDialTries == 0 || tries < VarDialTries);
181 
182   return 0;
183 }
184 
185 static int
186 ShellCommand(cmdlist, argc, argv)
187 struct cmdtab *cmdlist;
188 int argc;
189 char **argv;
190 {
191   const char *shell;
192   pid_t shpid;
193   FILE *oVarTerm;
194 
195 #ifdef SHELL_ONLY_INTERACTIVELY
196   /* we're only allowed to shell when we run ppp interactively */
197   if (mode != MODE_INTER) {
198     LogPrintf(LogWARN, "Can only start a shell in interactive mode\n");
199     return 1;
200   }
201 #endif
202 #ifdef NO_SHELL_IN_AUTO_INTERACTIVE
203   /*
204    * we want to stop shell commands when we've got a telnet connection
205    * to an auto mode ppp
206    */
207   if ((mode & (MODE_AUTO|MODE_INTER)) == (MODE_AUTO|MODE_INTER)) {
208     LogPrintf(LogWARN,  "Shell is not allowed interactively in auto mode\n");
209     return 1;
210   }
211 #endif
212 
213   if(argc == 0 && !(mode & MODE_INTER)) {
214     LogPrintf(LogWARN, "Can only start an interactive shell in"
215 	      " interactive mode\n");
216     return 1;
217   }
218 
219   if((shell = getenv("SHELL")) == 0)
220     shell = _PATH_BSHELL;
221 
222   if((shpid = fork()) == 0) {
223      int dtablesize, i, fd;
224 
225      if (VarTerm)
226        fd = fileno(VarTerm);
227      else if ((fd = open("/dev/null", O_RDWR)) == -1) {
228        LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno));
229        exit(1);
230      }
231 
232      for (i = 0; i < 3; i++)
233        dup2(fd, i);
234 
235      if (fd > 2)
236        if (VarTerm) {
237 	 oVarTerm = VarTerm;
238 	 VarTerm = 0;
239          if (oVarTerm && oVarTerm != stdout)
240            fclose(oVarTerm);
241        } else
242          close(fd);
243 
244      for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++)
245 	(void)close(i);
246 
247      /*
248       * We are running setuid, we should change to
249       * real user for avoiding security problems.
250       */
251      if (setgid(getgid()) < 0) {
252         LogPrintf(LogERROR, "setgid: %s\n", strerror(errno));
253 	exit(1);
254      }
255      if (setuid(getuid()) < 0) {
256         LogPrintf(LogERROR, "setuid: %s\n", strerror(errno));
257 	exit(1);
258      }
259      TtyOldMode();
260      if(argc > 0) {
261        /* substitute pseudo args */
262        for (i=1; i<argc; i++)
263          if (strcasecmp(argv[i], "HISADDR") == 0)
264            argv[i] = strdup(inet_ntoa(IpcpInfo.his_ipaddr));
265          else if (strcasecmp(argv[i], "INTERFACE") == 0)
266            argv[i] = strdup(IfDevName);
267          else if (strcasecmp(argv[i], "MYADDR") == 0)
268            argv[i] = strdup(inet_ntoa(IpcpInfo.want_ipaddr));
269        (void)execvp(argv[0], argv);
270      }
271      else
272        (void)execl(shell, shell, NULL);
273 
274      LogPrintf(LogWARN, "exec() of %s failed\n", argc > 0 ? argv[0] : shell);
275      exit(255);
276   }
277 
278   if( shpid == (pid_t)-1 ) {
279     LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno));
280   } else {
281     int status;
282     (void)waitpid(shpid, &status, 0);
283   }
284 
285   TtyCommandMode(1);
286 
287   return(0);
288 }
289 
290 struct cmdtab const Commands[] = {
291   { "accept",  NULL,    AcceptCommand,	LOCAL_AUTH,
292   	"accept option request",	"accept option .."},
293   { "add",     NULL,	AddCommand,	LOCAL_AUTH,
294 	"add route",			"add dest mask gateway"},
295   { "close",   NULL,    CloseCommand,	LOCAL_AUTH,
296 	"Close connection",		"close"},
297   { "delete",  NULL,    DeleteCommand,	LOCAL_AUTH,
298 	"delete route",                 "delete ALL | dest [gateway [mask]]"},
299   { "deny",    NULL,    DenyCommand,	LOCAL_AUTH,
300   	"Deny option request",		"deny option .."},
301   { "dial",    "call",  DialCommand,	LOCAL_AUTH,
302   	"Dial and login",		"dial|call [remote]"},
303   { "disable", NULL,    DisableCommand,	LOCAL_AUTH,
304   	"Disable option",		"disable option .."},
305   { "display", NULL,    DisplayCommand,	LOCAL_AUTH,
306   	"Display option configs",	"display"},
307   { "enable",  NULL,    EnableCommand,	LOCAL_AUTH,
308   	"Enable option",		"enable option .."},
309   { "passwd",  NULL,	LocalAuthCommand,LOCAL_NO_AUTH,
310   	"Password for manipulation", "passwd option .."},
311   { "load",    NULL,    LoadCommand,	LOCAL_AUTH,
312   	"Load settings",		"load [remote]"},
313   { "save",    NULL,    SaveCommand,	LOCAL_AUTH,
314   	"Save settings", "save"},
315   { "set",     "setup", SetCommand,	LOCAL_AUTH,
316   	"Set parameters",  "set[up] var value"},
317   { "shell",   "!",     ShellCommand,   LOCAL_AUTH,
318 	"Run a subshell",  "shell|! [sh command]"},
319   { "show",    NULL,    ShowCommand,	LOCAL_AUTH,
320   	"Show status and statictics", "show var"},
321   { "term",    NULL,    TerminalCommand,LOCAL_AUTH,
322   	"Enter to terminal mode", "term"},
323   { "alias",   NULL,    AliasCommand,   LOCAL_AUTH,
324         "alias control",        "alias option [yes|no]"},
325   { "quit",    "bye",   QuitCommand,	LOCAL_AUTH | LOCAL_NO_AUTH,
326 	"Quit PPP program", "quit|bye [all]"},
327   { "help",    "?",     HelpCommand,	LOCAL_AUTH | LOCAL_NO_AUTH,
328 	"Display this message", "help|? [command]", (void *)Commands },
329   { NULL,      "down",  DownCommand,	LOCAL_AUTH,
330   	"Generate down event",		"down"},
331   { NULL,      NULL,    NULL },
332 };
333 
334 extern int ReportCcpStatus();
335 extern int ReportLcpStatus();
336 extern int ReportIpcpStatus();
337 extern int ReportProtStatus();
338 extern int ReportCompress();
339 extern int ShowModemStatus();
340 extern int ReportHdlcStatus();
341 extern int ShowMemMap();
342 
343 static int ShowLogLevel()
344 {
345   int i;
346 
347   if (!VarTerm)
348     return 0;
349   fprintf(VarTerm, "Log:");
350   for (i = LogMIN; i < LogMAXCONF; i++) {
351     if (LogIsKept(i))
352       fprintf(VarTerm, " %s", LogName(i));
353   }
354   fprintf(VarTerm, "\n");
355 
356   return 0;
357 }
358 
359 static int ShowEscape()
360 {
361   int code, bit;
362 
363   if (!VarTerm)
364     return 0;
365   if (EscMap[32]) {
366     for (code = 0; code < 32; code++)
367       if (EscMap[code])
368         for (bit = 0; bit < 8; bit++)
369           if (EscMap[code] & (1<<bit))
370             fprintf(VarTerm, " 0x%02x", (code << 3) + bit);
371     fprintf(VarTerm, "\n");
372   }
373   return 1;
374 }
375 
376 static int ShowTimeout()
377 {
378   if (!VarTerm)
379     return 0;
380   fprintf(VarTerm, " Idle Timer: %d secs   LQR Timer: %d secs"
381           "   Retry Timer: %d secs\n", VarIdleTimeout, VarLqrTimeout,
382           VarRetryTimeout);
383   return 1;
384 }
385 
386 static int ShowAuthKey()
387 {
388   if (!VarTerm)
389     return 0;
390   fprintf(VarTerm, "AuthName = %s\n", VarAuthName);
391   fprintf(VarTerm, "AuthKey  = %s\n", VarAuthKey);
392   return 1;
393 }
394 
395 static int ShowVersion()
396 {
397   extern char VarVersion[];
398   extern char VarLocalVersion[];
399 
400   if (!VarTerm)
401     return 0;
402   fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
403   return 1;
404 }
405 
406 static int ShowInitialMRU()
407 {
408   if (!VarTerm)
409     return 0;
410   fprintf(VarTerm, " Initial MRU: %ld\n", VarMRU);
411   return 1;
412 }
413 
414 static int ShowPreferredMTU()
415 {
416   if (!VarTerm)
417     return 0;
418   if (VarPrefMTU)
419     fprintf(VarTerm, " Preferred MTU: %ld\n", VarPrefMTU);
420   else
421     fprintf(VarTerm, " Preferred MTU: unspecified\n");
422   return 1;
423 }
424 
425 static int ShowReconnect()
426 {
427   if (!VarTerm)
428     return 0;
429   fprintf(VarTerm, " Reconnect Timer:  %d,  %d tries\n",
430          VarReconnectTimer, VarReconnectTries);
431   return 1;
432 }
433 
434 static int ShowRedial()
435 {
436   if (!VarTerm)
437     return 0;
438   fprintf(VarTerm, " Redial Timer: ");
439 
440   if (VarRedialTimeout >= 0) {
441     fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
442   }
443   else {
444     fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
445   }
446 
447   fprintf(VarTerm, " Redial Next Timer: ");
448 
449   if (VarRedialNextTimeout >= 0) {
450     fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
451   }
452   else {
453     fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
454   }
455 
456   if (VarDialTries)
457       fprintf(VarTerm, "%d dial tries", VarDialTries);
458 
459   fprintf(VarTerm, "\n");
460 
461   return 1;
462 }
463 
464 #ifndef NOMSEXT
465 static int ShowMSExt()
466 {
467   if (!VarTerm)
468     return 0;
469   fprintf(VarTerm, " MS PPP extention values \n" );
470   fprintf(VarTerm, "   Primary NS     : %s\n", inet_ntoa( ns_entries[0] ));
471   fprintf(VarTerm, "   Secondary NS   : %s\n", inet_ntoa( ns_entries[1] ));
472   fprintf(VarTerm, "   Primary NBNS   : %s\n", inet_ntoa( nbns_entries[0] ));
473   fprintf(VarTerm, "   Secondary NBNS : %s\n", inet_ntoa( nbns_entries[1] ));
474   return 1;
475 }
476 #endif
477 
478 extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
479 
480 struct cmdtab const ShowCommands[] = {
481   { "afilter",  NULL,     ShowAfilter,		LOCAL_AUTH,
482 	"Show keep Alive filters", "show afilter option .."},
483   { "auth",     NULL,     ShowAuthKey,		LOCAL_AUTH,
484 	"Show auth name/key", "show auth"},
485   { "ccp",      NULL,     ReportCcpStatus,	LOCAL_AUTH,
486 	"Show CCP status", "show cpp"},
487   { "compress", NULL,     ReportCompress,	LOCAL_AUTH,
488 	"Show compression statictics", "show compress"},
489   { "dfilter",  NULL,     ShowDfilter,		LOCAL_AUTH,
490 	"Show Demand filters", "show dfilteroption .."},
491   { "escape",   NULL,     ShowEscape,		LOCAL_AUTH,
492 	"Show escape characters", "show escape"},
493   { "hdlc",	NULL,	  ReportHdlcStatus,	LOCAL_AUTH,
494 	"Show HDLC error summary", "show hdlc"},
495   { "ifilter",  NULL,     ShowIfilter,		LOCAL_AUTH,
496 	"Show Input filters", "show ifilter option .."},
497   { "ipcp",     NULL,     ReportIpcpStatus,	LOCAL_AUTH,
498 	"Show IPCP status", "show ipcp"},
499   { "lcp",      NULL,     ReportLcpStatus,	LOCAL_AUTH,
500 	"Show LCP status", "show lcp"},
501   { "log",	NULL,	  ShowLogLevel,	LOCAL_AUTH,
502 	"Show current log level", "show log"},
503   { "mem",      NULL,     ShowMemMap,		LOCAL_AUTH,
504 	"Show memory map", "show mem"},
505   { "modem",    NULL,     ShowModemStatus,	LOCAL_AUTH,
506 	"Show modem setups", "show modem"},
507   { "mru",      NULL,     ShowInitialMRU,	LOCAL_AUTH,
508 	"Show Initial MRU", "show mru"},
509   { "mtu",      NULL,     ShowPreferredMTU,	LOCAL_AUTH,
510 	"Show Preferred MTU", "show mtu"},
511   { "ofilter",  NULL,     ShowOfilter,		LOCAL_AUTH,
512 	"Show Output filters", "show ofilter option .."},
513   { "proto",    NULL,     ReportProtStatus,	LOCAL_AUTH,
514 	"Show protocol summary", "show proto"},
515   { "reconnect",NULL,	  ShowReconnect,	LOCAL_AUTH,
516 	"Show Reconnect timer,tries", "show reconnect"},
517   { "redial",   NULL,	  ShowRedial,		LOCAL_AUTH,
518 	"Show Redial timeout value", "show redial"},
519   { "route",    NULL,     ShowRoute,		LOCAL_AUTH,
520 	"Show routing table", "show route"},
521   { "timeout",  NULL,	  ShowTimeout,		LOCAL_AUTH,
522 	"Show Idle timeout value", "show timeout"},
523 #ifndef NOMSEXT
524   { "msext", 	NULL,	  ShowMSExt,		LOCAL_AUTH,
525 	"Show MS PPP extentions", "show msext"},
526 #endif
527   { "version",  NULL,	  ShowVersion,		LOCAL_NO_AUTH | LOCAL_AUTH,
528 	"Show version string", "show version"},
529   { "help",     "?",      HelpCommand,		LOCAL_NO_AUTH | LOCAL_AUTH,
530 	"Display this message", "show help|? [command]", (void *)ShowCommands},
531   { NULL,       NULL,     NULL },
532 };
533 
534 struct cmdtab *
535 FindCommand(cmds, str, pmatch)
536 struct cmdtab *cmds;
537 char *str;
538 int *pmatch;
539 {
540   int nmatch;
541   int len;
542   struct cmdtab *found;
543 
544   found = NULL;
545   len = strlen(str);
546   nmatch = 0;
547   while (cmds->func) {
548     if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
549       if (cmds->name[len] == '\0') {
550         *pmatch = 1;
551         return cmds;
552       }
553       nmatch++;
554       found = cmds;
555     } else if(cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
556       if (cmds->alias[len] == '\0') {
557         *pmatch = 1;
558         return cmds;
559       }
560       nmatch++;
561       found = cmds;
562     }
563     cmds++;
564   }
565   *pmatch = nmatch;
566   return found;
567 }
568 
569 int
570 FindExec(cmdlist, argc, argv)
571 struct cmdtab *cmdlist;
572 int argc;
573 char **argv;
574 {
575   struct cmdtab *cmd;
576   int val = 1;
577   int nmatch;
578 
579   cmd = FindCommand(cmdlist, *argv, &nmatch);
580   if (nmatch > 1)
581     LogPrintf(LogWARN, "%s: Ambiguous command\n", *argv);
582   else if (cmd && ( cmd->lauth & VarLocalAuth ) )
583     val = (cmd->func)(cmd, --argc, ++argv, cmd->args);
584   else
585     LogPrintf(LogWARN, "%s: Invalid command\n", *argv);
586 
587   if (val == -1)
588     LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
589   else if(val)
590     LogPrintf(LogCOMMAND, "%s: Failed %d\n", *argv, val);
591 
592   return val;
593 }
594 
595 int aft_cmd = 1;
596 extern int TermMode;
597 
598 void
599 Prompt()
600 {
601   char *pconnect, *pauth;
602 
603   if (!(mode & MODE_INTER) || !VarTerm || TermMode)
604     return;
605 
606   if (!aft_cmd)
607     fprintf(VarTerm, "\n");
608   else
609     aft_cmd = 0;
610 
611   if ( VarLocalAuth == LOCAL_AUTH )
612     pauth = " ON ";
613   else
614     pauth = " on ";
615   if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
616     pconnect = "PPP";
617   else
618     pconnect = "ppp";
619   fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
620   fflush(VarTerm);
621 }
622 
623 void
624 DecodeCommand(buff, nb, prompt)
625 char *buff;
626 int nb;
627 int prompt;
628 {
629   char *vector[20];
630   char **argv;
631   int argc;
632   char *cp;
633 
634   if (nb > 0) {
635     cp = buff + strcspn(buff, "\r\n");
636     if (cp)
637       *cp = '\0';
638     argc = MakeArgs(buff, vector, VECSIZE(vector));
639     argv = vector;
640 
641     if (argc > 0)
642       FindExec(Commands, argc, argv);
643   }
644   if (prompt)
645     Prompt();
646 }
647 
648 static int
649 ShowCommand(list, argc, argv)
650 struct cmdtab *list;
651 int argc;
652 char **argv;
653 {
654   if (argc > 0)
655     FindExec(ShowCommands, argc, argv);
656   else if (VarTerm)
657     fprintf(VarTerm, "Use ``show ?'' to get a list.\n");
658   else
659     LogPrintf(LogWARN, "show command must have arguments\n");
660 
661   return 0;
662 }
663 
664 static int
665 TerminalCommand()
666 {
667   if (LcpFsm.state > ST_CLOSED) {
668     if (VarTerm)
669       fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
670     return 1;
671   }
672   if (!IsInteractive())
673     return(1);
674   modem = OpenModem(mode);
675   if (modem < 0) {
676     if (VarTerm)
677       fprintf(VarTerm, "Failed to open modem.\n");
678     return(1);
679   }
680   if (VarTerm) {
681     fprintf(VarTerm, "Enter to terminal mode.\n");
682     fprintf(VarTerm, "Type `~?' for help.\n");
683   }
684   TtyTermMode();
685   return(0);
686 }
687 
688 static int
689 QuitCommand(list, argc, argv)
690 struct cmdtab *list;
691 int argc;
692 char **argv;
693 {
694   FILE *oVarTerm;
695 
696   if (mode & (MODE_DIRECT|MODE_DEDICATED|MODE_AUTO)) {
697     if (argc > 0 && (VarLocalAuth & LOCAL_AUTH)) {
698       Cleanup(EX_NORMAL);
699       mode &= ~MODE_INTER;
700       oVarTerm = VarTerm;
701       VarTerm = 0;
702       if (oVarTerm && oVarTerm != stdout)
703         fclose(oVarTerm);
704     } else {
705       LogPrintf(LogPHASE, "Client connection closed.\n");
706       VarLocalAuth = LOCAL_NO_AUTH;
707       mode &= ~MODE_INTER;
708       oVarTerm = VarTerm;
709       VarTerm = 0;
710       if (oVarTerm && oVarTerm != stdout)
711         fclose(oVarTerm);
712       close(netfd);
713       netfd = -1;
714     }
715   } else
716     Cleanup(EX_NORMAL);
717 
718   return 0;
719 }
720 
721 static int
722 CloseCommand()
723 {
724   reconnect(RECON_FALSE);
725   LcpClose();
726   if (mode & MODE_BACKGROUND)
727       Cleanup(EX_NORMAL);
728   return 0;
729 }
730 
731 static int
732 DownCommand()
733 {
734   LcpDown();
735   return 0;
736 }
737 
738 static int
739 SetModemSpeed(list, argc, argv)
740 struct cmdtab *list;
741 int argc;
742 char **argv;
743 {
744   int speed;
745 
746   if (argc > 0) {
747     if (strcmp(*argv, "sync") == 0) {
748       VarSpeed = 0;
749       return 0;
750     }
751     speed = atoi(*argv);
752     if (IntToSpeed(speed) != B0) {
753       VarSpeed = speed;
754       return 0;
755     }
756     LogPrintf(LogWARN, "%s: Invalid speed\n", *argv);
757   }
758   return -1;
759 }
760 
761 static int
762 SetReconnect(list, argc, argv)
763 struct cmdtab *list;
764 int argc;
765 char **argv;
766 {
767   if (argc == 2) {
768     VarReconnectTimer = atoi(argv[0]);
769     VarReconnectTries = atoi(argv[1]);
770     return 0;
771   }
772 
773   return -1;
774 }
775 
776 static int
777 SetRedialTimeout(list, argc, argv)
778 struct cmdtab *list;
779 int argc;
780 char **argv;
781 {
782   int timeout;
783   int tries;
784   char *dot;
785 
786   if (argc == 1 || argc == 2 ) {
787     if (strncasecmp(argv[0], "random", 6) == 0 &&
788 	(argv[0][6] == '\0' || argv[0][6] == '.')) {
789       VarRedialTimeout = -1;
790       if (!randinit) {
791 	randinit = 1;
792 	srandomdev();
793       }
794     } else {
795       timeout = atoi(argv[0]);
796 
797       if (timeout >= 0)
798 	VarRedialTimeout = timeout;
799       else {
800 	LogPrintf(LogWARN, "Invalid redial timeout\n");
801         return -1;
802       }
803     }
804 
805     dot = index(argv[0],'.');
806     if (dot) {
807       if (strcasecmp(++dot, "random") == 0) {
808         VarRedialNextTimeout = -1;
809         if (!randinit) {
810           randinit = 1;
811 	  srandomdev();
812         }
813       }
814       else {
815         timeout = atoi(dot);
816         if (timeout >= 0)
817           VarRedialNextTimeout = timeout;
818         else {
819           LogPrintf(LogWARN, "Invalid next redial timeout\n");
820 	  return -1;
821         }
822       }
823     }
824     else
825       VarRedialNextTimeout = NEXT_REDIAL_PERIOD;   /* Default next timeout */
826 
827     if (argc == 2) {
828       tries = atoi(argv[1]);
829 
830       if (tries >= 0) {
831 	VarDialTries = tries;
832       } else {
833 	LogPrintf(LogWARN, "Invalid retry value\n");
834 	return 1;
835       }
836     }
837     return 0;
838   }
839 
840   return -1;
841 }
842 
843 static int
844 SetServer(list, argc, argv)
845 struct cmdtab *list;
846 int argc;
847 char **argv;
848 {
849   int res = -1;
850 
851   if (argc > 0 && argc < 3)
852     if (strcasecmp(argv[0], "none") == 0) {
853       ServerClose();
854       LogPrintf(LogPHASE, "Disabling server port.\n");
855       res = 0;
856     } else if (*argv[0] == '/') {
857       mode_t mask;
858       umask(mask = umask(0));
859       if (argc == 2) {
860         unsigned m;
861         if (sscanf(argv[1], "%o", &m) == 1)
862           mask = m;
863       }
864       res = ServerLocalOpen(argv[0], mask);
865     } else {
866       int port;
867       if (strspn(argv[0], "0123456789") != strlen(argv[0])) {
868         struct servent *s;
869         if ((s = getservbyname(argv[0], "tcp")) == NULL) {
870           port = 0;
871           LogPrintf(LogWARN, "%s: Invalid port or service\n", argv[0]);
872         } else
873           port = ntohs(s->s_port);
874       } else
875         port = atoi(argv[0]);
876       if (port)
877         res = ServerTcpOpen(port);
878     }
879 
880   return res;
881 }
882 
883 static int
884 SetModemParity(list, argc, argv)
885 struct cmdtab *list;
886 int argc;
887 char **argv;
888 {
889   return argc > 0 ? ChangeParity(*argv) : -1;
890 }
891 
892 static int
893 SetLogLevel(list, argc, argv)
894 struct cmdtab *list;
895 int argc;
896 char **argv;
897 {
898   int i;
899   int res;
900   char *arg;
901 
902   res = 0;
903   if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-'))
904     LogDiscardAll();
905   while (argc--) {
906     arg = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
907     for (i = LogMIN; i <= LogMAX; i++)
908       if (strcasecmp(arg, LogName(i)) == 0) {
909         if (**argv == '-')
910           LogDiscard(i);
911         else
912 	  LogKeep(i);
913 	break;
914       }
915     if (i > LogMAX) {
916       LogPrintf(LogWARN, "%s: Invalid log value\n", arg);
917       res = -1;
918     }
919     argv++;
920   }
921   return res;
922 }
923 
924 static int
925 SetEscape(list, argc, argv)
926 struct cmdtab *list;
927 int argc;
928 char **argv;
929 {
930   int code;
931 
932   for (code = 0; code < 33; code++)
933     EscMap[code] = 0;
934   while (argc-- > 0) {
935     sscanf(*argv++, "%x", &code);
936     code &= 0xff;
937     EscMap[code >> 3] |= (1 << (code&7));
938     EscMap[32] = 1;
939   }
940   return 0;
941 }
942 
943 static int
944 SetInitialMRU(list, argc, argv)
945 struct cmdtab *list;
946 int argc;
947 char **argv;
948 {
949   long mru;
950   char *err;
951 
952   if (argc > 0) {
953     mru = atol(*argv);
954     if (mru < MIN_MRU)
955       err = "Given MRU value (%ld) is too small.\n";
956     else if (mru > MAX_MRU)
957       err = "Given MRU value (%ld) is too big.\n";
958     else {
959       VarMRU = mru;
960       return 0;
961     }
962     LogPrintf(LogWARN, err, mru);
963   }
964 
965   return -1;
966 }
967 
968 static int
969 SetPreferredMTU(list, argc, argv)
970 struct cmdtab *list;
971 int argc;
972 char **argv;
973 {
974   long mtu;
975   char *err;
976 
977   if (argc > 0) {
978     mtu = atol(*argv);
979     if (mtu == 0) {
980       VarPrefMTU = 0;
981       return 0;
982     } else if (mtu < MIN_MTU)
983       err = "Given MTU value (%ld) is too small.\n";
984     else if (mtu > MAX_MTU)
985       err = "Given MTU value (%ld) is too big.\n";
986     else {
987       VarPrefMTU = mtu;
988       return 0;
989     }
990     LogPrintf(LogWARN, err, mtu);
991   }
992 
993   return -1;
994 }
995 
996 static int
997 SetIdleTimeout(list, argc, argv)
998 struct cmdtab *list;
999 int argc;
1000 char **argv;
1001 {
1002   if (argc-- > 0) {
1003     VarIdleTimeout = atoi(*argv++);
1004     UpdateIdleTimer();  /* If we're connected, restart the idle timer */
1005     if (argc-- > 0) {
1006       VarLqrTimeout = atoi(*argv++);
1007       if (VarLqrTimeout < 1)
1008 	VarLqrTimeout = 30;
1009       if (argc > 0) {
1010 	VarRetryTimeout = atoi(*argv);
1011 	if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
1012 	  VarRetryTimeout = 3;
1013       }
1014     }
1015     return 0;
1016   }
1017 
1018   return -1;
1019 }
1020 
1021 struct in_addr
1022 GetIpAddr(cp)
1023 char *cp;
1024 {
1025   struct hostent *hp;
1026   struct in_addr ipaddr;
1027 
1028   hp = gethostbyname(cp);
1029   if (hp && hp->h_addrtype == AF_INET)
1030     bcopy(hp->h_addr, &ipaddr, hp->h_length);
1031   else if (inet_aton(cp, &ipaddr) == 0)
1032     ipaddr.s_addr = 0;
1033   return(ipaddr);
1034 }
1035 
1036 static int
1037 SetInterfaceAddr(list, argc, argv)
1038 struct cmdtab *list;
1039 int argc;
1040 char **argv;
1041 {
1042 
1043   DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
1044   if (argc > 4)
1045      return -1;
1046 
1047   if (argc > 0) {
1048     if (ParseAddr(argc, argv++,
1049             &DefMyAddress.ipaddr,
1050 	    &DefMyAddress.mask,
1051 	    &DefMyAddress.width) == 0)
1052        return 1;
1053     if (--argc > 0) {
1054       if (ParseAddr(argc, argv++,
1055 		    &DefHisAddress.ipaddr,
1056 		    &DefHisAddress.mask,
1057 		    &DefHisAddress.width) == 0)
1058 	 return 2;
1059       if (--argc > 0) {
1060         ifnetmask = GetIpAddr(*argv);
1061     	if (--argc > 0) {
1062 	   if (ParseAddr(argc, argv++,
1063 			 &DefTriggerAddress.ipaddr,
1064 			 &DefTriggerAddress.mask,
1065 			 &DefTriggerAddress.width) == 0)
1066 	      return 3;
1067 	}
1068       }
1069     }
1070   }
1071   /*
1072    * For backwards compatibility, 0.0.0.0 means any address.
1073    */
1074   if (DefMyAddress.ipaddr.s_addr == 0) {
1075     DefMyAddress.mask.s_addr = 0;
1076     DefMyAddress.width = 0;
1077   }
1078   if (DefHisAddress.ipaddr.s_addr == 0) {
1079     DefHisAddress.mask.s_addr = 0;
1080     DefHisAddress.width = 0;
1081   }
1082 
1083   if ((mode & MODE_AUTO) ||
1084 	((mode & MODE_DEDICATED) && dstsystem)) {
1085     if (OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask) < 0)
1086        return 4;
1087   }
1088   return 0;
1089 }
1090 
1091 #ifndef NOMSEXT
1092 
1093 void
1094 SetMSEXT(pri_addr, sec_addr, argc, argv)
1095 struct in_addr *pri_addr;
1096 struct in_addr *sec_addr;
1097 int argc;
1098 char **argv;
1099 {
1100   int dummyint;
1101   struct in_addr dummyaddr;
1102 
1103   pri_addr->s_addr = sec_addr->s_addr = 0L;
1104 
1105   if( argc > 0 ) {
1106     ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
1107     if( --argc > 0 )
1108       ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
1109     else
1110       sec_addr->s_addr = pri_addr->s_addr;
1111   }
1112 
1113  /*
1114   * if the primary/secondary ns entries are 0.0.0.0 we should
1115   * set them to either the localhost's ip, or the values in
1116   * /etc/resolv.conf ??
1117   *
1118   * up to you if you want to implement this...
1119   */
1120 
1121 }
1122 
1123 static int
1124 SetNS(list, argc, argv)
1125 struct cmdtab *list;
1126 int argc;
1127 char **argv;
1128 {
1129   SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv);
1130   return 0;
1131 }
1132 
1133 static int
1134 SetNBNS(list, argc, argv)
1135 struct cmdtab *list;
1136 int argc;
1137 char **argv;
1138 {
1139   SetMSEXT(&nbns_entries[0], &nbns_entries[1], argc, argv);
1140   return 0;
1141 }
1142 
1143 #endif /* MS_EXT */
1144 
1145 #define	VAR_AUTHKEY	0
1146 #define	VAR_DIAL	1
1147 #define	VAR_LOGIN	2
1148 #define	VAR_AUTHNAME	3
1149 #define	VAR_DEVICE	4
1150 #define	VAR_ACCMAP	5
1151 #define	VAR_PHONE	6
1152 #define	VAR_HANGUP	7
1153 
1154 static int
1155 SetVariable(list, argc, argv, param)
1156 struct cmdtab *list;
1157 int argc;
1158 char **argv;
1159 int param;
1160 {
1161   u_long map;
1162   char *arg;
1163 
1164   if (argc > 0)
1165     arg = *argv;
1166   else
1167     arg = "";
1168 
1169   switch (param) {
1170     case VAR_AUTHKEY:
1171       strncpy(VarAuthKey, arg, sizeof(VarAuthKey)-1);
1172       VarAuthKey[sizeof(VarAuthKey)-1] = '\0';
1173       break;
1174     case VAR_AUTHNAME:
1175       strncpy(VarAuthName, arg, sizeof(VarAuthName)-1);
1176       VarAuthName[sizeof(VarAuthName)-1] = '\0';
1177       break;
1178     case VAR_DIAL:
1179       strncpy(VarDialScript, arg, sizeof(VarDialScript)-1);
1180       VarDialScript[sizeof(VarDialScript)-1] = '\0';
1181       break;
1182     case VAR_LOGIN:
1183       strncpy(VarLoginScript, arg, sizeof(VarLoginScript)-1);
1184       VarLoginScript[sizeof(VarLoginScript)-1] = '\0';
1185       break;
1186     case VAR_DEVICE:
1187       CloseModem();
1188       strncpy(VarDevice, arg, sizeof(VarDevice)-1);
1189       VarDevice[sizeof(VarDevice)-1] = '\0';
1190       VarBaseDevice = rindex(VarDevice, '/');
1191       VarBaseDevice = VarBaseDevice ? VarBaseDevice + 1 : "";
1192       break;
1193     case VAR_ACCMAP:
1194       sscanf(arg, "%lx", &map);
1195       VarAccmap = map;
1196       break;
1197     case VAR_PHONE:
1198       strncpy(VarPhoneList, arg, sizeof(VarPhoneList)-1);
1199       VarPhoneList[sizeof(VarPhoneList)-1] = '\0';
1200       strcpy(VarPhoneCopy, VarPhoneList);
1201       VarNextPhone = VarPhoneCopy;
1202       break;
1203     case VAR_HANGUP:
1204       strncpy(VarHangupScript, arg, sizeof(VarHangupScript)-1);
1205       VarHangupScript[sizeof(VarHangupScript)-1] = '\0';
1206       break;
1207   }
1208   return 0;
1209 }
1210 
1211 static int SetCtsRts(list, argc, argv)
1212 struct cmdtab *list;
1213 int argc;
1214 char **argv;
1215 {
1216   if (argc > 0) {
1217     if (strcmp(*argv, "on") == 0)
1218       VarCtsRts = TRUE;
1219     else if (strcmp(*argv, "off") == 0)
1220       VarCtsRts = FALSE;
1221     else
1222       return -1;
1223     return 0;
1224   }
1225   return -1;
1226 }
1227 
1228 
1229 static int SetOpenMode(list, argc, argv)
1230 struct cmdtab *list;
1231 int argc;
1232 char **argv;
1233 {
1234   if (argc > 0) {
1235     if (strcmp(*argv, "active") == 0)
1236       VarOpenMode = OPEN_ACTIVE;
1237     else if (strcmp(*argv, "passive") == 0)
1238       VarOpenMode = OPEN_PASSIVE;
1239     else
1240       return -1;
1241     return 0;
1242   }
1243   return -1;
1244 }
1245 
1246 extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
1247 
1248 struct cmdtab const SetCommands[] = {
1249   { "accmap",   NULL,	  SetVariable,		LOCAL_AUTH,
1250 	"Set accmap value", "set accmap hex-value", (void *)VAR_ACCMAP},
1251   { "afilter",  NULL,     SetAfilter, 		LOCAL_AUTH,
1252 	"Set keep Alive filter", "set afilter ..."},
1253   { "authkey",  "key",     SetVariable,		LOCAL_AUTH,
1254 	"Set authentication key", "set authkey|key key", (void *)VAR_AUTHKEY},
1255   { "authname", NULL,     SetVariable,		LOCAL_AUTH,
1256 	"Set authentication name", "set authname name", (void *)VAR_AUTHNAME},
1257   { "ctsrts", NULL,	  SetCtsRts,		LOCAL_AUTH,
1258 	"Use CTS/RTS modem signalling", "set ctsrts [on|off]"},
1259   { "device",     "line", SetVariable, 		LOCAL_AUTH,
1260 	"Set modem device name", "set device|line device-name", (void *)VAR_DEVICE},
1261   { "dfilter",  NULL,     SetDfilter,		 LOCAL_AUTH,
1262 	"Set demand filter", "set dfilter ..."},
1263   { "dial",     NULL,     SetVariable, 		LOCAL_AUTH,
1264 	"Set dialing script", "set dial chat-script", (void *)VAR_DIAL},
1265   { "escape",   NULL,	  SetEscape, 		LOCAL_AUTH,
1266 	"Set escape characters", "set escape hex-digit ..."},
1267   { "hangup",   NULL,     SetVariable,                LOCAL_AUTH,
1268         "Set hangup script", "set hangup chat-script", (void *)VAR_HANGUP},
1269   { "ifaddr",   NULL,   SetInterfaceAddr,	LOCAL_AUTH,
1270 	"Set destination address", "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
1271   { "ifilter",  NULL,     SetIfilter, 		LOCAL_AUTH,
1272 	"Set input filter", "set ifilter ..."},
1273   { "log",    NULL,	  SetLogLevel,	LOCAL_AUTH,
1274 	"Set log level", "set log [+|-]value..."},
1275   { "login",    NULL,     SetVariable,		LOCAL_AUTH,
1276 	"Set login script", "set login chat-script",	(void *)VAR_LOGIN },
1277   { "mru",      NULL,     SetInitialMRU,	LOCAL_AUTH,
1278 	"Set Initial MRU value", "set mru value" },
1279   { "mtu",      NULL,     SetPreferredMTU,	LOCAL_AUTH,
1280 	"Set Preferred MTU value", "set mtu value" },
1281   { "ofilter",  NULL,	  SetOfilter,		LOCAL_AUTH,
1282 	"Set output filter", "set ofilter ..." },
1283   { "openmode", NULL,	  SetOpenMode,		LOCAL_AUTH,
1284 	"Set open mode", "set openmode [active|passive]"},
1285   { "parity",   NULL,     SetModemParity,	LOCAL_AUTH,
1286 	"Set modem parity", "set parity [odd|even|none]"},
1287   { "phone",    NULL,     SetVariable,		LOCAL_AUTH,
1288 	"Set telephone number(s)", "set phone phone1[:phone2[...]]", (void *)VAR_PHONE },
1289   { "reconnect",NULL,     SetReconnect,		LOCAL_AUTH,
1290 	"Set Reconnect timeout", "set reconnect value ntries"},
1291   { "redial",   NULL,     SetRedialTimeout,	LOCAL_AUTH,
1292 	"Set Redial timeout", "set redial value|random[.value|random] [dial_attempts]"},
1293   { "server",    "socket",     SetServer,	LOCAL_AUTH,
1294 	"Set server port", "set server|socket TcpPort|LocalName|none [mask]"},
1295   { "speed",    NULL,     SetModemSpeed,	LOCAL_AUTH,
1296 	"Set modem speed", "set speed value"},
1297   { "timeout",  NULL,     SetIdleTimeout,	LOCAL_AUTH,
1298 	"Set Idle timeout", "set timeout value"},
1299 #ifndef NOMSEXT
1300   { "ns",	NULL,	  SetNS,		LOCAL_AUTH,
1301 	"Set NameServer", "set ns pri-addr [sec-addr]"},
1302   { "nbns",	NULL,	  SetNBNS,		LOCAL_AUTH,
1303 	"Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"},
1304 #endif
1305   { "help",     "?",      HelpCommand,		LOCAL_AUTH | LOCAL_NO_AUTH,
1306 	"Display this message", "set help|? [command]", (void *)SetCommands},
1307   { NULL,       NULL,     NULL },
1308 };
1309 
1310 static int
1311 SetCommand(list, argc, argv)
1312 struct cmdtab *list;
1313 int argc;
1314 char **argv;
1315 {
1316   if (argc > 0)
1317     FindExec(SetCommands, argc, argv);
1318   else if (VarTerm)
1319     fprintf(VarTerm, "Use `set ?' to get a list or `set ? <var>' for"
1320 	    " syntax help.\n");
1321   else
1322     LogPrintf(LogWARN, "set command must have arguments\n");
1323 
1324   return 0;
1325 }
1326 
1327 
1328 static int
1329 AddCommand(list, argc, argv)
1330 struct cmdtab *list;
1331 int argc;
1332 char **argv;
1333 {
1334   struct in_addr dest, gateway, netmask;
1335 
1336   if (argc == 3) {
1337     if (strcasecmp(argv[0], "MYADDR") == 0)
1338       dest = IpcpInfo.want_ipaddr;
1339     else
1340       dest = GetIpAddr(argv[0]);
1341     netmask = GetIpAddr(argv[1]);
1342     if (strcasecmp(argv[2], "HISADDR") == 0)
1343       gateway = IpcpInfo.his_ipaddr;
1344     else
1345       gateway = GetIpAddr(argv[2]);
1346     OsSetRoute(RTM_ADD, dest, gateway, netmask);
1347     return 0;
1348   }
1349 
1350   return -1;
1351 }
1352 
1353 static int
1354 DeleteCommand(list, argc, argv)
1355 struct cmdtab *list;
1356 int argc;
1357 char **argv;
1358 {
1359   struct in_addr dest, gateway, netmask;
1360 
1361   if (argc == 1 && strcasecmp(argv[0], "all") == 0)
1362     DeleteIfRoutes(0);
1363   else if (argc > 0 && argc < 4) {
1364     if (strcasecmp(argv[0], "MYADDR") == 0)
1365       dest = IpcpInfo.want_ipaddr;
1366     else
1367       dest = GetIpAddr(argv[0]);
1368     netmask.s_addr = INADDR_ANY;
1369     if (argc > 1) {
1370       if (strcasecmp(argv[1], "HISADDR") == 0)
1371         gateway = IpcpInfo.his_ipaddr;
1372       else
1373         gateway = GetIpAddr(argv[1]);
1374       if (argc == 3) {
1375         if (inet_aton(argv[2], &netmask) == 0) {
1376 	  LogPrintf(LogWARN, "Bad netmask value.\n");
1377 	  return -1;
1378         }
1379       }
1380     } else
1381       gateway.s_addr = INADDR_ANY;
1382     OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1383   } else
1384     return -1;
1385 
1386   return 0;
1387 }
1388 
1389 static int AliasEnable();
1390 static int AliasOption();
1391 
1392 static struct cmdtab const AliasCommands[] =
1393 {
1394   { "enable",   NULL,     AliasEnable,          LOCAL_AUTH,
1395         "enable IP aliasing", "alias enable [yes|no]"},
1396   { "port",   NULL,     AliasRedirectPort,          LOCAL_AUTH,
1397         "port redirection", "alias port [proto addr_local:port_local  port_alias]"},
1398   { "addr",   NULL,     AliasRedirectAddr,          LOCAL_AUTH,
1399         "static address translation", "alias addr [addr_local addr_alias]"},
1400   { "deny_incoming",  NULL,    AliasOption,     LOCAL_AUTH,
1401         "stop incoming connections",   "alias deny_incoming [yes|no]",
1402         (void*)PKT_ALIAS_DENY_INCOMING},
1403   { "log",  NULL,     AliasOption,              LOCAL_AUTH,
1404         "log aliasing link creation",           "alias log [yes|no]",
1405         (void*)PKT_ALIAS_LOG},
1406   { "same_ports", NULL,     AliasOption,        LOCAL_AUTH,
1407         "try to leave port numbers unchanged", "alias same_ports [yes|no]",
1408         (void*)PKT_ALIAS_SAME_PORTS},
1409   { "use_sockets", NULL,     AliasOption,       LOCAL_AUTH,
1410         "allocate host sockets", "alias use_sockets [yes|no]",
1411         (void*)PKT_ALIAS_USE_SOCKETS },
1412   { "unregistered_only", NULL,     AliasOption, LOCAL_AUTH,
1413         "alias unregistered (private) IP address space only",
1414         "alias unregistered_only [yes|no]",
1415         (void*)PKT_ALIAS_UNREGISTERED_ONLY},
1416   { "help",     "?",      HelpCommand,          LOCAL_AUTH | LOCAL_NO_AUTH,
1417         "Display this message", "alias help|? [command]",
1418         (void *)AliasCommands},
1419   { NULL,       NULL,     NULL },
1420 };
1421 
1422 
1423 static int
1424 AliasCommand(list, argc, argv)
1425 struct cmdtab *list;
1426 int argc;
1427 char **argv;
1428 {
1429   if (argc > 0)
1430     FindExec(AliasCommands, argc, argv);
1431   else if (VarTerm)
1432     fprintf(VarTerm, "Use `alias help' to get a list or `alias help <option>'"
1433 	    " for syntax help.\n");
1434   else
1435     LogPrintf(LogWARN, "alias command must have arguments\n");
1436 
1437   return 0;
1438 }
1439 
1440 static int
1441 AliasEnable(list, argc, argv)
1442 struct cmdtab *list;
1443 int argc;
1444 char **argv;
1445 {
1446   if (argc == 1)
1447     if (strcasecmp(argv[0], "yes") == 0) {
1448       if (!(mode & MODE_ALIAS)) {
1449         if (loadAliasHandlers(&VarAliasHandlers) == 0) {
1450           mode |= MODE_ALIAS;
1451           return 0;
1452         }
1453         LogPrintf(LogWARN, "Cannot load alias library\n");
1454         return 1;
1455       }
1456       return 0;
1457     } else if (strcasecmp(argv[0], "no") == 0) {
1458       if (mode & MODE_ALIAS) {
1459         unloadAliasHandlers();
1460         mode &= ~MODE_ALIAS;
1461       }
1462       return 0;
1463     }
1464 
1465   return -1;
1466 }
1467 
1468 
1469 static int
1470 AliasOption(list, argc, argv, param)
1471 struct cmdtab *list;
1472 int argc;
1473 char **argv;
1474 void* param;
1475 {
1476    if (argc == 1)
1477      if (strcasecmp(argv[0], "yes") == 0) {
1478        if (mode & MODE_ALIAS) {
1479          VarSetPacketAliasMode((unsigned)param, (unsigned)param);
1480          return 0;
1481        }
1482        LogPrintf(LogWARN, "alias not enabled\n");
1483      } else if (strcmp(argv[0], "no") == 0) {
1484        if (mode & MODE_ALIAS) {
1485          VarSetPacketAliasMode(0, (unsigned)param);
1486          return 0;
1487        }
1488        LogPrintf(LogWARN, "alias not enabled\n");
1489      }
1490 
1491    return -1;
1492 }
1493