command.c revision 37210
16059Samurai/* 26059Samurai * PPP User command processing module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2037210Sbrian * $Id: command.c,v 1.151 1998/06/27 14:18:02 brian Exp $ 218857Srgrimes * 226059Samurai */ 2336285Sbrian#include <sys/types.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3331343Sbrian#ifndef NOALIAS 3426031Sbrian#include <alias.h> 3531343Sbrian#endif 3630715Sbrian#include <errno.h> 3726516Sbrian#include <fcntl.h> 3830715Sbrian#include <paths.h> 3930715Sbrian#include <stdio.h> 4030715Sbrian#include <stdlib.h> 4130715Sbrian#include <string.h> 4230715Sbrian#include <sys/wait.h> 4330715Sbrian#include <termios.h> 4430715Sbrian#include <unistd.h> 4530715Sbrian 4637009Sbrian#include "defs.h" 4731343Sbrian#include "command.h" 4830715Sbrian#include "mbuf.h" 4930715Sbrian#include "log.h" 5030715Sbrian#include "timer.h" 516059Samurai#include "fsm.h" 526059Samurai#include "lcp.h" 5331690Sbrian#include "iplist.h" 5436285Sbrian#include "throughput.h" 5536285Sbrian#include "slcompress.h" 566059Samurai#include "ipcp.h" 576059Samurai#include "modem.h" 5831343Sbrian#ifndef NOALIAS 5926031Sbrian#include "alias_cmd.h" 6031343Sbrian#endif 6136285Sbrian#include "lqr.h" 626059Samurai#include "hdlc.h" 6325630Sbrian#include "systems.h" 6436285Sbrian#include "filter.h" 6536285Sbrian#include "descriptor.h" 6630715Sbrian#include "main.h" 6730715Sbrian#include "route.h" 6830715Sbrian#include "ccp.h" 6931080Sbrian#include "auth.h" 7036285Sbrian#include "async.h" 7136285Sbrian#include "link.h" 7236285Sbrian#include "physical.h" 7336285Sbrian#include "mp.h" 7436285Sbrian#include "bundle.h" 7536285Sbrian#include "server.h" 7636285Sbrian#include "prompt.h" 7736285Sbrian#include "chat.h" 7836285Sbrian#include "chap.h" 7936285Sbrian#include "datalink.h" 806059Samurai 8136285Sbrian/* ``set'' values */ 8236285Sbrian#define VAR_AUTHKEY 0 8336285Sbrian#define VAR_DIAL 1 8436285Sbrian#define VAR_LOGIN 2 8536285Sbrian#define VAR_AUTHNAME 3 8636285Sbrian#define VAR_AUTOLOAD 4 8736285Sbrian#define VAR_WINSIZE 5 8836285Sbrian#define VAR_DEVICE 6 8936285Sbrian#define VAR_ACCMAP 7 9036285Sbrian#define VAR_MRRU 8 9136285Sbrian#define VAR_MRU 9 9236285Sbrian#define VAR_MTU 10 9336285Sbrian#define VAR_OPENMODE 11 9436285Sbrian#define VAR_PHONE 12 9536285Sbrian#define VAR_HANGUP 13 9636285Sbrian#define VAR_IDLETIMEOUT 14 9736285Sbrian#define VAR_LQRPERIOD 15 9836285Sbrian#define VAR_LCPRETRY 16 9936285Sbrian#define VAR_CHAPRETRY 17 10036285Sbrian#define VAR_PAPRETRY 18 10136285Sbrian#define VAR_CCPRETRY 19 10236285Sbrian#define VAR_IPCPRETRY 20 10336285Sbrian#define VAR_DNS 21 10436285Sbrian#define VAR_NBNS 22 10536285Sbrian#define VAR_MODE 23 1066059Samurai 10736285Sbrian/* ``accept|deny|disable|enable'' masks */ 10836285Sbrian#define NEG_HISMASK (1) 10936285Sbrian#define NEG_MYMASK (2) 11036285Sbrian 11136285Sbrian/* ``accept|deny|disable|enable'' values */ 11236285Sbrian#define NEG_ACFCOMP 40 11336285Sbrian#define NEG_CHAP 41 11436285Sbrian#define NEG_DEFLATE 42 11536285Sbrian#define NEG_LQR 43 11636285Sbrian#define NEG_PAP 44 11736285Sbrian#define NEG_PPPDDEFLATE 45 11836285Sbrian#define NEG_PRED1 46 11936285Sbrian#define NEG_PROTOCOMP 47 12036285Sbrian#define NEG_SHORTSEQ 48 12136285Sbrian#define NEG_VJCOMP 49 12236285Sbrian#define NEG_DNS 50 12336285Sbrian 12436285Sbrianconst char Version[] = "2.0-beta"; 12537210Sbrianconst char VersionDate[] = "$Date: 1998/06/27 14:18:02 $"; 12636285Sbrian 12736285Sbrianstatic int ShowCommand(struct cmdargs const *); 12836285Sbrianstatic int TerminalCommand(struct cmdargs const *); 12936285Sbrianstatic int QuitCommand(struct cmdargs const *); 13036285Sbrianstatic int OpenCommand(struct cmdargs const *); 13136285Sbrianstatic int CloseCommand(struct cmdargs const *); 13236285Sbrianstatic int DownCommand(struct cmdargs const *); 13336285Sbrianstatic int AllowCommand(struct cmdargs const *); 13436285Sbrianstatic int SetCommand(struct cmdargs const *); 13536285Sbrianstatic int LinkCommand(struct cmdargs const *); 13636285Sbrianstatic int AddCommand(struct cmdargs const *); 13736285Sbrianstatic int DeleteCommand(struct cmdargs const *); 13836285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 13936934Sbrianstatic int ClearCommand(struct cmdargs const *); 14031343Sbrian#ifndef NOALIAS 14136285Sbrianstatic int AliasCommand(struct cmdargs const *); 14236285Sbrianstatic int AliasEnable(struct cmdargs const *); 14336285Sbrianstatic int AliasOption(struct cmdargs const *); 14431343Sbrian#endif 1456059Samurai 14636285Sbrianstatic const char * 14736285Sbrianshowcx(struct cmdtab const *cmd) 14836285Sbrian{ 14936285Sbrian if (cmd->lauth & LOCAL_CX) 15036285Sbrian return "(c)"; 15136285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 15236285Sbrian return "(o)"; 15336285Sbrian 15436285Sbrian return ""; 15536285Sbrian} 15636285Sbrian 1576059Samuraistatic int 15831343SbrianHelpCommand(struct cmdargs const *arg) 1596059Samurai{ 16028679Sbrian struct cmdtab const *cmd; 16136285Sbrian int n, cmax, dmax, cols, cxlen; 16236285Sbrian const char *cx; 1636059Samurai 16436285Sbrian if (!arg->prompt) { 16536285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 16626516Sbrian return 0; 16736285Sbrian } 16826516Sbrian 16936285Sbrian if (arg->argc > arg->argn) { 17036285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 17136285Sbrian if ((cmd->lauth & arg->prompt->auth) && 17236285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 17336285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 17436285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 17528679Sbrian return 0; 1766059Samurai } 17726516Sbrian return -1; 1786059Samurai } 17936285Sbrian 18031372Sbrian cmax = dmax = 0; 18136285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 18236285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 18336285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 18431372Sbrian cmax = n; 18531372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 18631372Sbrian dmax = n; 18731372Sbrian } 18831372Sbrian 18931372Sbrian cols = 80 / (dmax + cmax + 3); 1906059Samurai n = 0; 19136285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 19236285Sbrian " (c) = Context required\n"); 19336285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 19436285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 19536285Sbrian cx = showcx(cmd); 19636285Sbrian cxlen = cmax - strlen(cmd->name); 19736285Sbrian prompt_Printf(arg->prompt, " %s%-*.*s: %-*.*s", 19836285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 19931372Sbrian if (++n % cols == 0) 20036285Sbrian prompt_Printf(arg->prompt, "\n"); 2016059Samurai } 20231372Sbrian if (n % cols != 0) 20336285Sbrian prompt_Printf(arg->prompt, "\n"); 20426516Sbrian 20526516Sbrian return 0; 2066059Samurai} 2076059Samurai 20836285Sbrianstatic int 20936285SbrianCloneCommand(struct cmdargs const *arg) 2106059Samurai{ 21136285Sbrian char namelist[LINE_LEN]; 21236285Sbrian char *name; 21336285Sbrian int f; 2146059Samurai 21536285Sbrian if (arg->argc == arg->argn) 21636285Sbrian return -1; 21736285Sbrian 21836285Sbrian namelist[sizeof namelist - 1] = '\0'; 21936285Sbrian for (f = arg->argn; f < arg->argc; f++) { 22036285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 22136285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 22236285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2236059Samurai } 22436285Sbrian 22536285Sbrian return 0; 2266059Samurai} 2276059Samurai 2286059Samuraistatic int 22936285SbrianRemoveCommand(struct cmdargs const *arg) 2306059Samurai{ 23136285Sbrian if (arg->argc != arg->argn) 23236285Sbrian return -1; 23311336Samurai 23436285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 23536285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 23636285Sbrian return 2; 2376059Samurai } 23826516Sbrian 23936285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 24036285Sbrian return 0; 24136285Sbrian} 24232711Sbrian 24336285Sbrianstatic int 24436285SbrianRenameCommand(struct cmdargs const *arg) 24536285Sbrian{ 24636285Sbrian if (arg->argc != arg->argn + 1) 24736285Sbrian return -1; 24831121Sbrian 24936285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 25036285Sbrian return 0; 25136285Sbrian 25236285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 25336285Sbrian arg->cx->name, arg->argv[arg->argn]); 25436285Sbrian return 1; 25536285Sbrian} 25636285Sbrian 25736285Sbrianint 25836285SbrianLoadCommand(struct cmdargs const *arg) 25936285Sbrian{ 26036285Sbrian const char *name; 26136285Sbrian 26236285Sbrian if (arg->argc > arg->argn) 26336285Sbrian name = arg->argv[arg->argn]; 26436285Sbrian else 26536285Sbrian name = "default"; 26636285Sbrian 26736928Sbrian if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type.all)) { 26837019Sbrian log_Printf(LogWARN, "%s: Label not allowed\n", name); 26936285Sbrian return 1; 27036285Sbrian } else { 27136285Sbrian /* 27236285Sbrian * Set the label before & after so that `set enddisc' works and 27336285Sbrian * we handle nested `load' commands. 27436285Sbrian */ 27536285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 27637008Sbrian if (system_Select(arg->bundle, name, CONFFILE, arg->prompt, arg->cx) < 0) { 27736285Sbrian bundle_SetLabel(arg->bundle, NULL); 27836285Sbrian log_Printf(LogWARN, "%s: label not found.\n", name); 27936285Sbrian return -1; 28032403Sbrian } 28136285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28236285Sbrian } 28326516Sbrian return 0; 2846059Samurai} 2856059Samurai 28636285Sbrianint 28736285SbrianSaveCommand(struct cmdargs const *arg) 28836285Sbrian{ 28936285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 29036285Sbrian return 1; 29136285Sbrian} 29236285Sbrian 29310528Samuraistatic int 29436285SbrianDialCommand(struct cmdargs const *arg) 29528536Sbrian{ 29636285Sbrian int res; 29736285Sbrian 29836465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 29936465Sbrian || (!arg->cx && 30036928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 30136285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 30236285Sbrian " interactive links\n"); 30336285Sbrian return 1; 30434536Sbrian } 30536285Sbrian 30636285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 30736285Sbrian return res; 30836285Sbrian 30936285Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 31036285Sbrian 31136285Sbrian return 0; 31228536Sbrian} 31328536Sbrian 31428536Sbrianstatic int 31531343SbrianShellCommand(struct cmdargs const *arg, int bg) 31610528Samurai{ 31710528Samurai const char *shell; 31810528Samurai pid_t shpid; 31931343Sbrian int argc; 32031343Sbrian char *argv[MAXARGS]; 32120813Sjkh 32218856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 32326911Sbrian /* we're only allowed to shell when we run ppp interactively */ 32436285Sbrian if (arg->prompt && arg->prompt->owner) { 32536285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 32626516Sbrian return 1; 32710528Samurai } 32826911Sbrian#endif 32928679Sbrian 33036285Sbrian if (arg->argc == arg->argn) { 33136285Sbrian if (!arg->prompt) { 33236285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 33336285Sbrian " a config file\n"); 33428381Sbrian return 1; 33536285Sbrian } else if (arg->prompt->owner) { 33636285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 33736285Sbrian " a socket connection\n"); 33836285Sbrian return 1; 33928381Sbrian } else if (bg) { 34036285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 34128679Sbrian " the foreground mode\n"); 34228381Sbrian return 1; 34328381Sbrian } 34434536Sbrian } 34534536Sbrian 34628679Sbrian if ((shpid = fork()) == 0) { 34736285Sbrian int i, fd; 34818531Sbde 34936285Sbrian if ((shell = getenv("SHELL")) == 0) 35036285Sbrian shell = _PATH_BSHELL; 35132017Sbrian 35236285Sbrian timer_TermService(); 35336285Sbrian 35436285Sbrian if (arg->prompt) 35536285Sbrian fd = arg->prompt->fd_out; 35636285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 35736285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 35836285Sbrian _PATH_DEVNULL, strerror(errno)); 35928679Sbrian exit(1); 36028679Sbrian } 36128679Sbrian for (i = 0; i < 3; i++) 36228679Sbrian dup2(fd, i); 36326516Sbrian 36436285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 36526516Sbrian 36631061Sbrian setuid(geteuid()); 36736285Sbrian if (arg->argc > arg->argn) { 36828679Sbrian /* substitute pseudo args */ 36936285Sbrian argv[0] = strdup(arg->argv[arg->argn]); 37036285Sbrian for (argc = 1; argc < arg->argc - arg->argn; argc++) { 37136285Sbrian if (strcasecmp(arg->argv[argc + arg->argn], "HISADDR") == 0) 37236285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.peer_ip)); 37336285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "INTERFACE") == 0) 37436285Sbrian argv[argc] = strdup(arg->bundle->ifp.Name); 37536285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "MYADDR") == 0) 37636285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.my_ip)); 37731343Sbrian else 37836285Sbrian argv[argc] = strdup(arg->argv[argc + arg->argn]); 37931343Sbrian } 38031343Sbrian argv[argc] = NULL; 38128679Sbrian if (bg) { 38228679Sbrian pid_t p; 38310528Samurai 38428679Sbrian p = getpid(); 38528679Sbrian if (daemon(1, 1) == -1) { 38636832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 38728679Sbrian exit(1); 38828679Sbrian } 38936285Sbrian } else if (arg->prompt) 39036285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 39131343Sbrian execvp(argv[0], argv); 39230316Sbrian } else { 39336285Sbrian if (arg->prompt) 39432017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 39536285Sbrian prompt_TtyOldMode(arg->prompt); 39631343Sbrian execl(shell, shell, NULL); 39730316Sbrian } 39820813Sjkh 39936285Sbrian log_Printf(LogWARN, "exec() of %s failed\n", 40036285Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell); 40128679Sbrian exit(255); 40210528Samurai } 40336285Sbrian 40436285Sbrian if (shpid == (pid_t) - 1) 40536285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 40636285Sbrian else { 40710528Samurai int status; 40831343Sbrian waitpid(shpid, &status, 0); 40910528Samurai } 41020813Sjkh 41136285Sbrian if (arg->prompt && !arg->prompt->owner) 41236285Sbrian prompt_TtyCommandMode(arg->prompt); 41320813Sjkh 41436285Sbrian return 0; 41510528Samurai} 41610528Samurai 41731343Sbrianstatic int 41831343SbrianBgShellCommand(struct cmdargs const *arg) 41931343Sbrian{ 42036285Sbrian if (arg->argc == arg->argn) 42131343Sbrian return -1; 42231343Sbrian return ShellCommand(arg, 1); 42331343Sbrian} 42431343Sbrian 42531343Sbrianstatic int 42631343SbrianFgShellCommand(struct cmdargs const *arg) 42731343Sbrian{ 42831343Sbrian return ShellCommand(arg, 0); 42931343Sbrian} 43031343Sbrian 43130715Sbrianstatic struct cmdtab const Commands[] = { 43236285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 43328679Sbrian "accept option request", "accept option .."}, 43428679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 43532109Sbrian "add route", "add dest mask gateway", NULL}, 43636285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 43732109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 43836285Sbrian#ifndef NOALIAS 43936285Sbrian {"alias", NULL, AliasCommand, LOCAL_AUTH, 44036285Sbrian "alias control", "alias option [yes|no]"}, 44136285Sbrian#endif 44231121Sbrian {"allow", "auth", AllowCommand, LOCAL_AUTH, 44331121Sbrian "Allow ppp access", "allow users|modes ...."}, 44428679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 44531372Sbrian "Run a background command", "[!]bg command"}, 44636934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 44736934Sbrian "Clear throughput statistics", "clear ipcp|modem [current|overall|peak]..."}, 44836285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 44936285Sbrian "Clone a link", "clone newname..."}, 45036285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45136285Sbrian "Close an FSM", "close [lcp|ccp]"}, 45228679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 45332109Sbrian "delete route", "delete dest", NULL}, 45436285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 45532109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 45636285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45728679Sbrian "Deny option request", "deny option .."}, 45836285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45928679Sbrian "Dial and login", "dial|call [remote]"}, 46036285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46128679Sbrian "Disable option", "disable option .."}, 46236285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46336285Sbrian "Generate a down event", "down"}, 46436285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46528679Sbrian "Enable option", "enable option .."}, 46636285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 46736285Sbrian "Link specific commands", "link name command ..."}, 46837008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46928679Sbrian "Load settings", "load [remote]"}, 47036285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 47137160Sbrian "Open an FSM", "open [lcp|ccp|ipcp]"}, 47236285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 47336285Sbrian "Password for manipulation", "passwd LocalPassword"}, 47436285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 47536285Sbrian "Quit PPP program", "quit|bye [all]"}, 47636285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 47736285Sbrian "Remove a link", "remove"}, 47836285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 47936285Sbrian "Rename a link", "rename name"}, 48028679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 48128679Sbrian "Save settings", "save"}, 48236285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 48328679Sbrian "Set parameters", "set[up] var value"}, 48428679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 48528679Sbrian "Run a subshell", "shell|! [sh command]"}, 48636285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 48731372Sbrian "Show status and stats", "show var"}, 48836285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 48931372Sbrian "Enter terminal mode", "term"}, 49028679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 49131343Sbrian "Display this message", "help|? [command]", Commands}, 49228679Sbrian {NULL, NULL, NULL}, 4936059Samurai}; 4946059Samurai 49528536Sbrianstatic int 49631343SbrianShowEscape(struct cmdargs const *arg) 4976059Samurai{ 49836285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 49936285Sbrian int code, bit; 50036285Sbrian const char *sep = ""; 5016059Samurai 50226516Sbrian for (code = 0; code < 32; code++) 50336285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 50428679Sbrian for (bit = 0; bit < 8; bit++) 50536285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 50636285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 50736285Sbrian sep = ", "; 50836285Sbrian } 50936285Sbrian prompt_Printf(arg->prompt, "\n"); 5106059Samurai } 51131077Sbrian return 0; 5126059Samurai} 5136059Samurai 51428679Sbrianstatic int 51536285SbrianShowTimerList(struct cmdargs const *arg) 5166059Samurai{ 51736285Sbrian timer_Show(0, arg->prompt); 51831077Sbrian return 0; 5196059Samurai} 5206059Samurai 52128679Sbrianstatic int 52231343SbrianShowStopped(struct cmdargs const *arg) 52328327Sbrian{ 52436285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 52536285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 52636285Sbrian prompt_Printf(arg->prompt, "Disabled"); 52728327Sbrian else 52836285Sbrian prompt_Printf(arg->prompt, "%ld secs", 52936285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 53028461Sbrian 53136285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 53236285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 53336285Sbrian prompt_Printf(arg->prompt, "Disabled"); 53428461Sbrian else 53536285Sbrian prompt_Printf(arg->prompt, "%ld secs", 53636285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 53728461Sbrian 53836285Sbrian prompt_Printf(arg->prompt, "\n"); 53928461Sbrian 54031077Sbrian return 0; 54128327Sbrian} 54228327Sbrian 54328679Sbrianstatic int 54431343SbrianShowVersion(struct cmdargs const *arg) 5456059Samurai{ 54636285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 54731077Sbrian return 0; 5486059Samurai} 5496059Samurai 55028679Sbrianstatic int 55136285SbrianShowProtocolStats(struct cmdargs const *arg) 55226326Sbrian{ 55336285Sbrian struct link *l = command_ChooseLink(arg); 55426326Sbrian 55536285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 55636285Sbrian link_ReportProtocolStatus(l, arg->prompt); 55731077Sbrian return 0; 55826326Sbrian} 55926326Sbrian 56030715Sbrianstatic struct cmdtab const ShowCommands[] = { 56136285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 56236285Sbrian "bundle details", "show bundle"}, 56336285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 56436285Sbrian "CCP status", "show cpp"}, 56536285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 56636285Sbrian "VJ compression stats", "show compress"}, 56736285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 56836285Sbrian "escape characters", "show escape"}, 56936285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 57036285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 57136285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 57236285Sbrian "HDLC errors", "show hdlc"}, 57336285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 57436285Sbrian "IPCP status", "show ipcp"}, 57536285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 57636285Sbrian "LCP status", "show lcp"}, 57736285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 57836285Sbrian "(high-level) link info", "show link"}, 57936285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 58036285Sbrian "available link names", "show links"}, 58136285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 58236285Sbrian "log levels", "show log"}, 58336285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 58436285Sbrian "mbuf allocations", "show mem"}, 58536285Sbrian {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 58636285Sbrian "(low-level) link info", "show modem"}, 58736285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 58836285Sbrian "multilink setup", "show mp"}, 58936285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 59036285Sbrian "protocol summary", "show proto"}, 59136285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 59236285Sbrian "routing table", "show route"}, 59336285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 59436285Sbrian "STOPPED timeout", "show stopped"}, 59536285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 59636285Sbrian "alarm timers", "show timers"}, 59728679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 59836285Sbrian "version string", "show version"}, 59936285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 60036285Sbrian "client list", "show who"}, 60128679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 60231343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 60328679Sbrian {NULL, NULL, NULL}, 6046059Samurai}; 6056059Samurai 60630715Sbrianstatic struct cmdtab const * 60731343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 6086059Samurai{ 60926516Sbrian int nmatch; 61026516Sbrian int len; 61128679Sbrian struct cmdtab const *found; 6126059Samurai 61326516Sbrian found = NULL; 61426516Sbrian len = strlen(str); 61526516Sbrian nmatch = 0; 6166059Samurai while (cmds->func) { 61725566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 61826516Sbrian if (cmds->name[len] == '\0') { 61928679Sbrian *pmatch = 1; 62028679Sbrian return cmds; 62126516Sbrian } 6226059Samurai nmatch++; 6236059Samurai found = cmds; 62428679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 62526516Sbrian if (cmds->alias[len] == '\0') { 62628679Sbrian *pmatch = 1; 62728679Sbrian return cmds; 62826516Sbrian } 6296059Samurai nmatch++; 6306059Samurai found = cmds; 6316059Samurai } 6326059Samurai cmds++; 6336059Samurai } 6346059Samurai *pmatch = nmatch; 63526516Sbrian return found; 6366059Samurai} 6376059Samurai 63836285Sbrianstatic const char * 63936285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 64036285Sbrian{ 64136285Sbrian int f, tlen, len; 64236285Sbrian 64336285Sbrian tlen = 0; 64436285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 64536285Sbrian if (f) 64636285Sbrian tgt[tlen++] = ' '; 64736285Sbrian len = strlen(argv[f]); 64836285Sbrian if (len > sz - tlen - 1) 64936285Sbrian len = sz - tlen - 1; 65036285Sbrian strncpy(tgt+tlen, argv[f], len); 65136285Sbrian tlen += len; 65236285Sbrian } 65336285Sbrian tgt[tlen] = '\0'; 65436285Sbrian return tgt; 65536285Sbrian} 65636285Sbrian 65730715Sbrianstatic int 65836285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 65936285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 6606059Samurai{ 66128679Sbrian struct cmdtab const *cmd; 6626059Samurai int val = 1; 6636059Samurai int nmatch; 66431343Sbrian struct cmdargs arg; 66536285Sbrian char prefix[100]; 6666059Samurai 66736285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 6686059Samurai if (nmatch > 1) 66936285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 67036285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 67136285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 67236285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 67336285Sbrian /* We've got no context, but we require it */ 67436285Sbrian cx = bundle2datalink(bundle, NULL); 67536285Sbrian 67636285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 67736285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 67836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 67936285Sbrian else { 68036285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 68136285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 68236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 68336285Sbrian cx = NULL; 68436285Sbrian } 68536285Sbrian arg.cmdtab = cmds; 68636285Sbrian arg.cmd = cmd; 68736285Sbrian arg.argc = argc; 68836285Sbrian arg.argn = argn+1; 68936285Sbrian arg.argv = argv; 69036285Sbrian arg.bundle = bundle; 69136285Sbrian arg.cx = cx; 69236285Sbrian arg.prompt = prompt; 69336285Sbrian val = (*cmd->func) (&arg); 69436285Sbrian } 69531343Sbrian } else 69636285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 69736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 69826516Sbrian 69926516Sbrian if (val == -1) 70036285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 70128679Sbrian else if (val) 70236285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 70336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 70426516Sbrian 70526516Sbrian return val; 7066059Samurai} 7076059Samurai 70837009Sbrianint 70937009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 7106059Samurai{ 7116059Samurai char *cp; 7126059Samurai 7136059Samurai if (nb > 0) { 7146059Samurai cp = buff + strcspn(buff, "\r\n"); 7156059Samurai if (cp) 7166059Samurai *cp = '\0'; 71737009Sbrian return MakeArgs(buff, argv, MAXARGS); 71837009Sbrian } 71937009Sbrian return 0; 72031121Sbrian} 7216059Samurai 72231822Sbrianstatic int 72331822Sbrianarghidden(int argc, char const *const *argv, int n) 72431822Sbrian{ 72531822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 72631828Sbrian 72731828Sbrian /* set authkey xxxxx */ 72831828Sbrian /* set key xxxxx */ 72931822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 73031822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 73131822Sbrian return 1; 73231822Sbrian 73331828Sbrian /* passwd xxxxx */ 73431828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 73531828Sbrian return 1; 73631828Sbrian 73736285Sbrian /* set server port xxxxx .... */ 73836285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 73936285Sbrian !strncasecmp(argv[1], "se", 2)) 74036285Sbrian return 1; 74136285Sbrian 74231822Sbrian return 0; 74331822Sbrian} 74431822Sbrian 74531121Sbrianvoid 74636285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 74737008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 74831121Sbrian{ 74931156Sbrian if (argc > 0) { 75036285Sbrian if (log_IsKept(LogCOMMAND)) { 75131156Sbrian static char buf[LINE_LEN]; 75231156Sbrian int f, n; 75331156Sbrian 75431156Sbrian *buf = '\0'; 75531156Sbrian if (label) { 75631962Sbrian strncpy(buf, label, sizeof buf - 3); 75731962Sbrian buf[sizeof buf - 3] = '\0'; 75831156Sbrian strcat(buf, ": "); 75931156Sbrian } 76031156Sbrian n = strlen(buf); 76131156Sbrian for (f = 0; f < argc; f++) { 76231962Sbrian if (n < sizeof buf - 1 && f) 76331156Sbrian buf[n++] = ' '; 76431822Sbrian if (arghidden(argc, argv, f)) 76536285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 76631822Sbrian else 76731962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 76831156Sbrian n += strlen(buf+n); 76931156Sbrian } 77036285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 77131156Sbrian } 77237008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 77331156Sbrian } 7746059Samurai} 7756059Samurai 77631121Sbrianvoid 77736285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 77836285Sbrian const char *label) 77931121Sbrian{ 78031121Sbrian int argc; 78137009Sbrian char *argv[MAXARGS]; 78231121Sbrian 78337009Sbrian argc = command_Interpret(buff, nb, argv); 78437008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 78531121Sbrian} 78631121Sbrian 7876059Samuraistatic int 78831343SbrianShowCommand(struct cmdargs const *arg) 7896059Samurai{ 79036285Sbrian if (!arg->prompt) 79136285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 79236285Sbrian else if (arg->argc > arg->argn) 79336285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 79436285Sbrian arg->prompt, arg->cx); 7956059Samurai else 79636285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 79726516Sbrian 79826516Sbrian return 0; 7996059Samurai} 8006059Samurai 8016059Samuraistatic int 80231343SbrianTerminalCommand(struct cmdargs const *arg) 8036059Samurai{ 80436285Sbrian if (!arg->prompt) { 80536285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 80626516Sbrian return 1; 8076059Samurai } 80836285Sbrian 80936285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 81036285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 81136285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 81236285Sbrian return 1; 8136059Samurai } 81436285Sbrian 81536285Sbrian datalink_Up(arg->cx, 0, 0); 81636285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 81736285Sbrian return 0; 8186059Samurai} 8196059Samurai 8206059Samuraistatic int 82131343SbrianQuitCommand(struct cmdargs const *arg) 8226059Samurai{ 82336285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 82436285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 82536285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 82636285Sbrian Cleanup(EX_NORMAL); 82736285Sbrian if (arg->prompt) 82836285Sbrian prompt_Destroy(arg->prompt, 1); 82926516Sbrian 83026516Sbrian return 0; 8316059Samurai} 8326059Samurai 8336059Samuraistatic int 83436285SbrianOpenCommand(struct cmdargs const *arg) 8356059Samurai{ 83637160Sbrian if (arg->argc == arg->argn) 83736285Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 83837160Sbrian else if (arg->argc == arg->argn + 1) { 83937160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 84037160Sbrian if (arg->cx) { 84137160Sbrian if (arg->cx->physical->link.lcp.fsm.state == ST_OPENED) 84237160Sbrian fsm_Reopen(&arg->cx->physical->link.lcp.fsm); 84337160Sbrian else 84437160Sbrian bundle_Open(arg->bundle, arg->cx->name, PHYS_ALL); 84537160Sbrian } else 84637160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 84737160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 84837160Sbrian struct fsm *fp; 8496059Samurai 85037210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 85137160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 85237160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 85337160Sbrian else if (fp->state == ST_OPENED) 85437160Sbrian fsm_Reopen(fp); 85537160Sbrian else { 85637160Sbrian fp->open_mode = 0; /* Not passive any more */ 85737160Sbrian if (fp->state == ST_STOPPED) { 85837160Sbrian fsm_Down(fp); 85937160Sbrian fsm_Up(fp); 86037160Sbrian } else { 86137160Sbrian fsm_Up(fp); 86237160Sbrian fsm_Open(fp); 86337160Sbrian } 86436285Sbrian } 86537160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 86637160Sbrian if (arg->cx) 86737160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 86837160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 86937160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 87037160Sbrian else 87137160Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL); 87237160Sbrian } else 87337160Sbrian return -1; 87436285Sbrian } else 87536285Sbrian return -1; 87636285Sbrian 87726516Sbrian return 0; 8786059Samurai} 8796059Samurai 88025067Sbrianstatic int 88136285SbrianCloseCommand(struct cmdargs const *arg) 8826059Samurai{ 88337007Sbrian if (arg->argc == arg->argn) 88437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 88537007Sbrian else if (arg->argc == arg->argn + 1) { 88637007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 88737007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 88837007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 88937007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 89037007Sbrian struct fsm *fp; 8916059Samurai 89237210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 89337007Sbrian if (fp->state == ST_OPENED) { 89437007Sbrian fsm_Close(fp); 89537007Sbrian if (arg->argv[arg->argn][3] == '!') 89637007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 89737007Sbrian else 89837007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 89937007Sbrian } 90037007Sbrian } else 90136285Sbrian return -1; 90236285Sbrian } else 90336285Sbrian return -1; 90436285Sbrian 90536285Sbrian return 0; 9066059Samurai} 9076059Samurai 90825067Sbrianstatic int 90936285SbrianDownCommand(struct cmdargs const *arg) 91011336Samurai{ 91137018Sbrian if (arg->argc == arg->argn) { 91237018Sbrian if (arg->cx) 91337018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 91437018Sbrian else 91537018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 91637018Sbrian } else if (arg->argc == arg->argn + 1) { 91737018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 91837018Sbrian if (arg->cx) 91937018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 92037018Sbrian else 92137018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 92237018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 92337018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 92437018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 92537060Sbrian fsm2initial(fp); 92637018Sbrian } else 92737018Sbrian return -1; 92836285Sbrian } else 92936285Sbrian return -1; 93036285Sbrian 93136285Sbrian return 0; 93225067Sbrian} 93325067Sbrian 93425067Sbrianstatic int 93536285SbrianSetModemSpeed(struct cmdargs const *arg) 93625067Sbrian{ 93736285Sbrian long speed; 93836285Sbrian char *end; 93911336Samurai 94036285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 94136285Sbrian if (arg->argc > arg->argn+1) { 94236285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 94336285Sbrian return -1; 94411336Samurai } 94536285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 94636285Sbrian physical_SetSync(arg->cx->physical); 94736285Sbrian return 0; 94836285Sbrian } 94936285Sbrian end = NULL; 95036285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 95136285Sbrian if (*end) { 95236285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 95336285Sbrian arg->argv[arg->argn]); 95436285Sbrian return -1; 95536285Sbrian } 95636285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 95736285Sbrian return 0; 95836285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 95936285Sbrian } else 96036285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 96124939Sbrian 96226516Sbrian return -1; 96311336Samurai} 96411336Samurai 96525067Sbrianstatic int 96631343SbrianSetStoppedTimeout(struct cmdargs const *arg) 96728327Sbrian{ 96836285Sbrian struct link *l = &arg->cx->physical->link; 96936285Sbrian 97036285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 97136285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 97236285Sbrian if (arg->argc <= arg->argn+2) { 97336285Sbrian if (arg->argc > arg->argn) { 97436285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 97536285Sbrian if (arg->argc > arg->argn+1) 97636285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 97728461Sbrian } 97828327Sbrian return 0; 97928327Sbrian } 98028327Sbrian return -1; 98128327Sbrian} 98228327Sbrian 98331081Sbrian#define ismask(x) \ 98431081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 98531081Sbrian 98628327Sbrianstatic int 98731343SbrianSetServer(struct cmdargs const *arg) 98826940Sbrian{ 98926940Sbrian int res = -1; 99026940Sbrian 99136285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 99231081Sbrian const char *port, *passwd, *mask; 99331081Sbrian 99431081Sbrian /* What's what ? */ 99536285Sbrian port = arg->argv[arg->argn]; 99636285Sbrian if (arg->argc == arg->argn + 2) { 99736285Sbrian passwd = arg->argv[arg->argn+1]; 99836285Sbrian mask = NULL; 99936285Sbrian } else if (arg->argc == arg->argn + 3) { 100036285Sbrian passwd = arg->argv[arg->argn+1]; 100136285Sbrian mask = arg->argv[arg->argn+2]; 100231081Sbrian if (!ismask(mask)) 100331081Sbrian return -1; 100436285Sbrian } else if (strcasecmp(port, "none") == 0) { 100536285Sbrian if (server_Close(arg->bundle)) 100636285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 100736285Sbrian return 0; 100831081Sbrian } else 100936285Sbrian return -1; 101031081Sbrian 101136285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 101236285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 101331081Sbrian 101436285Sbrian if (*port == '/') { 101531081Sbrian mode_t imask; 101636285Sbrian char *ptr, name[LINE_LEN + 12]; 101728679Sbrian 101831081Sbrian if (mask != NULL) { 101928679Sbrian unsigned m; 102028679Sbrian 102131081Sbrian if (sscanf(mask, "%o", &m) == 1) 102231081Sbrian imask = m; 102331081Sbrian else 102431081Sbrian return -1; 102531081Sbrian } else 102631081Sbrian imask = (mode_t)-1; 102736285Sbrian 102836285Sbrian ptr = strstr(port, "%d"); 102936285Sbrian if (ptr) { 103036285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 103137210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 103236285Sbrian port = name; 103336285Sbrian } 103436285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 103527346Sbrian } else { 103636285Sbrian int iport, add = 0; 103728679Sbrian 103831081Sbrian if (mask != NULL) 103931081Sbrian return -1; 104028679Sbrian 104136285Sbrian if (*port == '+') { 104236285Sbrian port++; 104336285Sbrian add = 1; 104436285Sbrian } 104531081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 104631081Sbrian struct servent *s; 104731081Sbrian 104831081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 104931081Sbrian iport = 0; 105036285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 105128679Sbrian } else 105231081Sbrian iport = ntohs(s->s_port); 105327346Sbrian } else 105431081Sbrian iport = atoi(port); 105536285Sbrian 105636285Sbrian if (iport) { 105736285Sbrian if (add) 105836285Sbrian iport += arg->bundle->unit; 105936285Sbrian res = server_TcpOpen(arg->bundle, iport); 106036285Sbrian } else 106136285Sbrian res = -1; 106227346Sbrian } 106331081Sbrian } 106426940Sbrian 106526940Sbrian return res; 106626940Sbrian} 106726940Sbrian 106826940Sbrianstatic int 106931343SbrianSetModemParity(struct cmdargs const *arg) 10706059Samurai{ 107136285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 107236285Sbrian arg->argv[arg->argn]) : -1; 10736059Samurai} 10746059Samurai 10756059Samuraistatic int 107631343SbrianSetEscape(struct cmdargs const *arg) 10776059Samurai{ 10786059Samurai int code; 107936285Sbrian int argc = arg->argc - arg->argn; 108036285Sbrian char const *const *argv = arg->argv + arg->argn; 10816059Samurai 10826059Samurai for (code = 0; code < 33; code++) 108336285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 108431343Sbrian 10856059Samurai while (argc-- > 0) { 10866059Samurai sscanf(*argv++, "%x", &code); 10876059Samurai code &= 0xff; 108836285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 108936285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 10906059Samurai } 109126516Sbrian return 0; 10926059Samurai} 10936059Samurai 109430715Sbrianstatic struct in_addr 109531343SbrianGetIpAddr(const char *cp) 10966059Samurai{ 10976059Samurai struct hostent *hp; 10986059Samurai struct in_addr ipaddr; 10996059Samurai 110032124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 110132124Sbrian hp = gethostbyname(cp); 110232124Sbrian if (hp && hp->h_addrtype == AF_INET) 110332124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 110432124Sbrian else 110532124Sbrian ipaddr.s_addr = 0; 110632124Sbrian } 110728679Sbrian return (ipaddr); 11086059Samurai} 11096059Samurai 11106059Samuraistatic int 111131343SbrianSetInterfaceAddr(struct cmdargs const *arg) 11126059Samurai{ 111336285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 111432267Sbrian const char *hisaddr; 111532267Sbrian 111632267Sbrian hisaddr = NULL; 111736285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 111836285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 11196059Samurai 112036285Sbrian if (arg->argc > arg->argn + 4) 112128679Sbrian return -1; 112226516Sbrian 112336285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 112436285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 112536285Sbrian iplist_reset(&ipcp->cfg.peer_list); 112628394Sbrian 112736285Sbrian if (arg->argc > arg->argn) { 112836285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 112936285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 113036285Sbrian &ipcp->cfg.my_range.width)) 113128679Sbrian return 1; 113236285Sbrian if (arg->argc > arg->argn+1) { 113336285Sbrian hisaddr = arg->argv[arg->argn+1]; 113436285Sbrian if (arg->argc > arg->argn+2) { 113536285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 113636285Sbrian if (arg->argc > arg->argn+3) { 113736285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 113836285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 11399440Samurai } 11406059Samurai } 11416059Samurai } 11426059Samurai } 114328394Sbrian 11446059Samurai /* 11456059Samurai * For backwards compatibility, 0.0.0.0 means any address. 11466059Samurai */ 114736285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 114836285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 114936285Sbrian ipcp->cfg.my_range.width = 0; 11506059Samurai } 115136285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 115236285Sbrian 115336285Sbrian if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 115436285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 115536285Sbrian ipcp->cfg.peer_range.width = 0; 11566059Samurai } 115728537Sbrian 115836285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 115936928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 116032267Sbrian return 4; 116131121Sbrian 116226516Sbrian return 0; 11636059Samurai} 11646059Samurai 116518752Sjkhstatic int 116631343SbrianSetVariable(struct cmdargs const *arg) 11676059Samurai{ 116837210Sbrian long long_val, param = (long)arg->cmd->args; 116937210Sbrian int mode, dummyint; 117031343Sbrian const char *argp; 117136285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 117236285Sbrian const char *err = NULL; 117336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 117436285Sbrian struct in_addr dummyaddr, *addr; 11756059Samurai 117636285Sbrian if (arg->argc > arg->argn) 117736285Sbrian argp = arg->argv[arg->argn]; 117826551Sbrian else 117931343Sbrian argp = ""; 118026551Sbrian 118136285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 118236285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 118336285Sbrian arg->cmd->name); 118436285Sbrian return 1; 118536285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 118636285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 118736285Sbrian arg->cmd->name, cx->name); 118836285Sbrian cx = NULL; 118936285Sbrian } 119036285Sbrian 119126551Sbrian switch (param) { 119228679Sbrian case VAR_AUTHKEY: 119336285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 119436285Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 119536285Sbrian sizeof arg->bundle->cfg.auth.key - 1); 119636285Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 119736285Sbrian } else { 119836285Sbrian err = "set authkey: Only available at phase DEAD\n"; 119936285Sbrian log_Printf(LogWARN, err); 120036285Sbrian } 120128679Sbrian break; 120237210Sbrian 120328679Sbrian case VAR_AUTHNAME: 120436285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 120536285Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 120636285Sbrian sizeof arg->bundle->cfg.auth.name - 1); 120736285Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 120836285Sbrian } else { 120936285Sbrian err = "set authname: Only available at phase DEAD\n"; 121036285Sbrian log_Printf(LogWARN, err); 121136285Sbrian } 121228679Sbrian break; 121337210Sbrian 121436285Sbrian case VAR_AUTOLOAD: 121536285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 121636285Sbrian arg->bundle->autoload.running = 1; 121736285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 121836285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 121936285Sbrian if (arg->argc == arg->argn + 4) { 122036285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 122136285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 122236285Sbrian } else { 122336285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 122436285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 122536285Sbrian } 122636285Sbrian } else { 122736285Sbrian err = "Set autoload requires two or four arguments\n"; 122836285Sbrian log_Printf(LogWARN, err); 122936285Sbrian } 123036285Sbrian break; 123137210Sbrian 123228679Sbrian case VAR_DIAL: 123336285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 123436285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 123528679Sbrian break; 123637210Sbrian 123728679Sbrian case VAR_LOGIN: 123836285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 123936285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 124028679Sbrian break; 124137210Sbrian 124236285Sbrian case VAR_WINSIZE: 124336285Sbrian if (arg->argc > arg->argn) { 124436285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 124536285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 124636285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 124736285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 124836285Sbrian l->ccp.cfg.deflate.out.winsize); 124936285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 125036285Sbrian } 125136285Sbrian if (arg->argc > arg->argn+1) { 125236285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 125336285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 125436285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 125536285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 125636285Sbrian l->ccp.cfg.deflate.in.winsize); 125736285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 125836285Sbrian } 125936285Sbrian } else 126036285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 126136285Sbrian } else { 126236285Sbrian err = "No window size specified\n"; 126336285Sbrian log_Printf(LogWARN, err); 126436285Sbrian } 126536285Sbrian break; 126637210Sbrian 126728679Sbrian case VAR_DEVICE: 126836285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 126936285Sbrian arg->argv + arg->argn); 127036285Sbrian break; 127137210Sbrian 127236285Sbrian case VAR_ACCMAP: 127336285Sbrian if (arg->argc > arg->argn) { 127437210Sbrian u_long ulong_val; 127536285Sbrian sscanf(argp, "%lx", &ulong_val); 127637210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 127736285Sbrian } else { 127836285Sbrian err = "No accmap specified\n"; 127936285Sbrian log_Printf(LogWARN, err); 128036285Sbrian } 128136285Sbrian break; 128237210Sbrian 128336285Sbrian case VAR_MODE: 128436285Sbrian mode = Nam2mode(argp); 128536285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 128636285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 128736285Sbrian return -1; 128836285Sbrian } 128936285Sbrian bundle_SetMode(arg->bundle, cx, mode); 129036285Sbrian break; 129137210Sbrian 129236285Sbrian case VAR_MRRU: 129337210Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) { 129436285Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); 129537210Sbrian return 1; 129629696Sbrian } 129737210Sbrian long_val = atol(argp); 129837210Sbrian if (long_val && long_val < MIN_MRU) { 129937210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 130037210Sbrian return 1; 130137210Sbrian } else if (long_val > MAX_MRU) { 130237210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 130337210Sbrian return 1; 130437210Sbrian } else 130537210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 130628679Sbrian break; 130737210Sbrian 130836285Sbrian case VAR_MRU: 130937210Sbrian long_val = atol(argp); 131037210Sbrian if (long_val == 0) 131137210Sbrian l->lcp.cfg.mru = DEF_MRU; 131237210Sbrian else if (long_val < MIN_MRU) { 131337210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 131437210Sbrian return 1; 131537210Sbrian } else if (long_val > MAX_MRU) { 131637210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 131737210Sbrian return 1; 131837210Sbrian } else 131937210Sbrian l->lcp.cfg.mru = long_val; 132028679Sbrian break; 132137210Sbrian 132236285Sbrian case VAR_MTU: 132337210Sbrian long_val = atol(argp); 132437210Sbrian if (long_val && long_val < MIN_MTU) { 132537210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 132637210Sbrian return 1; 132737210Sbrian } else if (long_val > MAX_MTU) { 132837210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 132937210Sbrian return 1; 133037210Sbrian } else 133137210Sbrian arg->bundle->cfg.mtu = long_val; 133236285Sbrian break; 133337210Sbrian 133436285Sbrian case VAR_OPENMODE: 133536285Sbrian if (strcasecmp(argp, "active") == 0) 133636285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 133736285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 133836285Sbrian else if (strcasecmp(argp, "passive") == 0) 133936285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 134036285Sbrian else { 134136285Sbrian err = "%s: Invalid openmode\n"; 134236285Sbrian log_Printf(LogWARN, err, argp); 134336285Sbrian } 134436285Sbrian break; 134537210Sbrian 134628679Sbrian case VAR_PHONE: 134736285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 134836285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 134928679Sbrian break; 135037210Sbrian 135128679Sbrian case VAR_HANGUP: 135236285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 135336285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 135428679Sbrian break; 135537210Sbrian 135636285Sbrian case VAR_IDLETIMEOUT: 135736285Sbrian if (arg->argc > arg->argn+1) 135836285Sbrian err = "Too many idle timeout values\n"; 135936285Sbrian else if (arg->argc == arg->argn+1) 136036285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 136136285Sbrian if (err) 136236285Sbrian log_Printf(LogWARN, err); 136329549Sbrian break; 136437210Sbrian 136536285Sbrian case VAR_LQRPERIOD: 136637210Sbrian long_val = atol(argp); 136737210Sbrian if (long_val < MIN_LQRPERIOD) { 136837210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 136937210Sbrian long_val, MIN_LQRPERIOD); 137037210Sbrian return 1; 137136285Sbrian } else 137237210Sbrian l->lcp.cfg.lqrperiod = long_val; 137336285Sbrian break; 137437210Sbrian 137536285Sbrian case VAR_LCPRETRY: 137637210Sbrian long_val = atol(argp); 137737210Sbrian if (long_val < MIN_FSMRETRY) { 137837210Sbrian log_Printf(LogWARN, "%ld: Invalid LCP FSM retry period - min %d\n", 137937210Sbrian long_val, MIN_FSMRETRY); 138037210Sbrian return 1; 138136285Sbrian } else 138237210Sbrian cx->physical->link.lcp.cfg.fsmretry = long_val; 138336285Sbrian break; 138437210Sbrian 138536285Sbrian case VAR_CHAPRETRY: 138637210Sbrian long_val = atol(argp); 138737210Sbrian if (long_val < MIN_FSMRETRY) { 138837210Sbrian log_Printf(LogWARN, "%ld: Invalid CHAP FSM retry period - min %d\n", 138937210Sbrian long_val, MIN_FSMRETRY); 139037210Sbrian return 1; 139136285Sbrian } else 139237210Sbrian cx->chap.auth.cfg.fsmretry = long_val; 139336285Sbrian break; 139437210Sbrian 139536285Sbrian case VAR_PAPRETRY: 139637210Sbrian long_val = atol(argp); 139737210Sbrian if (long_val < MIN_FSMRETRY) { 139837210Sbrian log_Printf(LogWARN, "%ld: Invalid PAP FSM retry period - min %d\n", 139937210Sbrian long_val, MIN_FSMRETRY); 140037210Sbrian return 1; 140136285Sbrian } else 140237210Sbrian cx->pap.cfg.fsmretry = long_val; 140336285Sbrian break; 140437210Sbrian 140536285Sbrian case VAR_CCPRETRY: 140637210Sbrian long_val = atol(argp); 140737210Sbrian if (long_val < MIN_FSMRETRY) { 140837210Sbrian log_Printf(LogWARN, "%ld: Invalid CCP FSM retry period - min %d\n", 140937210Sbrian long_val, MIN_FSMRETRY); 141037210Sbrian return 1; 141136285Sbrian } else 141237210Sbrian l->ccp.cfg.fsmretry = long_val; 141336285Sbrian break; 141437210Sbrian 141536285Sbrian case VAR_IPCPRETRY: 141637210Sbrian long_val = atol(argp); 141737210Sbrian if (long_val < MIN_FSMRETRY) { 141837210Sbrian log_Printf(LogWARN, "%ld: Invalid IPCP FSM retry period - min %d\n", 141937210Sbrian long_val, MIN_FSMRETRY); 142037210Sbrian return 1; 142136285Sbrian } else 142237210Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = long_val; 142336285Sbrian break; 142437210Sbrian 142536285Sbrian case VAR_NBNS: 142636285Sbrian case VAR_DNS: 142736285Sbrian if (param == VAR_DNS) 142836285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 142936285Sbrian else 143036285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 143136285Sbrian 143236285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 143336285Sbrian 143436285Sbrian if (arg->argc > arg->argn) { 143536285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 143636285Sbrian addr, &dummyaddr, &dummyint); 143736285Sbrian if (arg->argc > arg->argn+1) 143836285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 143936285Sbrian addr + 1, &dummyaddr, &dummyint); 144036285Sbrian 144136285Sbrian if (addr[1].s_addr == INADDR_ANY) 144236285Sbrian addr[1].s_addr = addr[0].s_addr; 144336285Sbrian if (addr[0].s_addr == INADDR_ANY) 144436285Sbrian addr[0].s_addr = addr[1].s_addr; 144536285Sbrian } 144636285Sbrian break; 14476059Samurai } 144836285Sbrian 144936285Sbrian return err ? 1 : 0; 14506059Samurai} 14516059Samurai 145228679Sbrianstatic int 145331343SbrianSetCtsRts(struct cmdargs const *arg) 145420812Sjkh{ 145536285Sbrian if (arg->argc == arg->argn+1) { 145636285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 145736285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 145836285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 145936285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 146020812Sjkh else 146126516Sbrian return -1; 146226516Sbrian return 0; 146320812Sjkh } 146426516Sbrian return -1; 146520812Sjkh} 146620812Sjkh 146730715Sbrianstatic struct cmdtab const SetCommands[] = { 146836285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 146936285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 147028679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 147136285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 147228679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 147336285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 147436285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 147536285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 147636285Sbrian (const void *)VAR_AUTOLOAD}, 147736285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 147836285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 147936285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 148036285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 148136285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 148236285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 148336285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 148436285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 148536285Sbrian (const void *) VAR_WINSIZE}, 148636285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 148736285Sbrian "modem device name", "set device|line device-name[,device-name]", 148836285Sbrian (const void *) VAR_DEVICE}, 148936285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 149036285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 149136285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 149236285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 149336285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 149436285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 149536285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 149636285Sbrian "escape characters", "set escape hex-digit ..."}, 149736285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 149836285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 149936285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 150036285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 150136285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 150236285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 150336285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 150431343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 150536285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 150636285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 150736285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 150836285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 150936712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 151036712Sbrian "set log [local] [+|-]async|ccp|chat|command|connect|debug|hdlc|id0|ipcp|" 151136712Sbrian "lcp|lqm|phase|tcp/ip|timer|tun..."}, 151236285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 151336285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 151436285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 151536285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 151636285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 151736285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 151836285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 151936285Sbrian "set mrru value", (const void *)VAR_MRRU}, 152036285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 152136285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 152236285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 152336285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 152436285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 152536285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 152636285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 152736285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 152836285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 152936285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 153036285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 153136285Sbrian "modem parity", "set parity [odd|even|none]"}, 153236285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 153336285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 153436285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 153536285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 153636285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 153736285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 153828679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 153936774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 154036285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 154136285Sbrian "modem speed", "set speed value"}, 154236285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 154336285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 154436285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 154536285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 154636285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 154736285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 154836285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 154936285Sbrian "datalink weighting", "set weight n"}, 155028679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 155131343Sbrian "Display this message", "set help|? [command]", SetCommands}, 155228679Sbrian {NULL, NULL, NULL}, 15536059Samurai}; 15546059Samurai 15556059Samuraistatic int 155631343SbrianSetCommand(struct cmdargs const *arg) 15576059Samurai{ 155836285Sbrian if (arg->argc > arg->argn) 155936285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 156036285Sbrian arg->prompt, arg->cx); 156136285Sbrian else if (arg->prompt) 156236285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 156326516Sbrian " syntax help.\n"); 15646059Samurai else 156536285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 156626516Sbrian 156726516Sbrian return 0; 15686059Samurai} 15696059Samurai 15706059Samurai 15716059Samuraistatic int 157231343SbrianAddCommand(struct cmdargs const *arg) 15736059Samurai{ 15746059Samurai struct in_addr dest, gateway, netmask; 157536285Sbrian int gw, addrs; 15766059Samurai 157736285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 157831598Sbrian return -1; 157931598Sbrian 158036285Sbrian addrs = 0; 158136285Sbrian if (arg->argc == arg->argn+2) { 158236285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 158336285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 158431598Sbrian else { 158536285Sbrian int width; 158636285Sbrian 158736285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 158836285Sbrian &dest, &netmask, &width)) 158936285Sbrian return -1; 159036285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 159136285Sbrian addrs = ROUTE_DSTMYADDR; 159236285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 159336285Sbrian addrs = ROUTE_DSTHISADDR; 159431598Sbrian } 159536285Sbrian gw = 1; 159634536Sbrian } else { 159736285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 159836285Sbrian addrs = ROUTE_DSTMYADDR; 159936285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 160036285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 160136285Sbrian addrs = ROUTE_DSTHISADDR; 160236285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 160336285Sbrian } else 160436285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 160536285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 160631598Sbrian gw = 2; 16076059Samurai } 160836285Sbrian 160936285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 161036285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 161136285Sbrian addrs |= ROUTE_GWHISADDR; 161236285Sbrian } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0) 161331598Sbrian gateway.s_addr = INADDR_ANY; 161431598Sbrian else 161536285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 161636285Sbrian 161736285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 161836285Sbrian arg->cmd->args ? 1 : 0)) 161936285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 162036285Sbrian 162131598Sbrian return 0; 16226059Samurai} 16236059Samurai 16246059Samuraistatic int 162531343SbrianDeleteCommand(struct cmdargs const *arg) 16266059Samurai{ 162731598Sbrian struct in_addr dest, none; 162836285Sbrian int addrs; 16296059Samurai 163036285Sbrian if (arg->argc == arg->argn+1) { 163136285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 163236285Sbrian route_IfDelete(arg->bundle, 0); 163336285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 163436285Sbrian } else { 163536285Sbrian addrs = 0; 163636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 163736285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 163836285Sbrian addrs = ROUTE_DSTMYADDR; 163936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 164036285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 164136285Sbrian addrs = ROUTE_DSTHISADDR; 164236285Sbrian } else { 164336285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 164436285Sbrian dest.s_addr = INADDR_ANY; 164536285Sbrian else 164636285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 164736285Sbrian addrs = ROUTE_STATIC; 164836285Sbrian } 164931598Sbrian none.s_addr = INADDR_ANY; 165036285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 165136285Sbrian arg->cmd->args ? 1 : 0); 165236285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 165331598Sbrian } 165434536Sbrian } else 165526516Sbrian return -1; 165626516Sbrian 165726516Sbrian return 0; 16586059Samurai} 16596059Samurai 166031343Sbrian#ifndef NOALIAS 166126031Sbrianstatic struct cmdtab const AliasCommands[] = 166226031Sbrian{ 166336285Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 166436285Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 166536285Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 166636285Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 166736285Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 166828679Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 166936285Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 167028679Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 167136285Sbrian "log aliasing link creation", "alias log [yes|no]", 167236285Sbrian (const void *) PKT_ALIAS_LOG}, 167336285Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 167436285Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 167528679Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 167636285Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 167736285Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 167836285Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 167936285Sbrian "alias unregistered (private) IP address space only", 168036285Sbrian "alias unregistered_only [yes|no]", 168136285Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 168228679Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 168336285Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 168436285Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 168528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 168636285Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 168728679Sbrian {NULL, NULL, NULL}, 168826031Sbrian}; 168926031Sbrian 169026031Sbrian 169126031Sbrianstatic int 169231343SbrianAliasCommand(struct cmdargs const *arg) 169326031Sbrian{ 169436285Sbrian if (arg->argc > arg->argn) 169536285Sbrian FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv, 169636285Sbrian arg->prompt, arg->cx); 169736285Sbrian else if (arg->prompt) 169836285Sbrian prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 169936285Sbrian " <option>' for syntax help.\n"); 170026031Sbrian else 170136285Sbrian log_Printf(LogWARN, "alias command must have arguments\n"); 170226516Sbrian 170326516Sbrian return 0; 170426031Sbrian} 170526031Sbrian 170626031Sbrianstatic int 170731343SbrianAliasEnable(struct cmdargs const *arg) 170826031Sbrian{ 170936285Sbrian if (arg->argc == arg->argn+1) { 171036285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 171137191Sbrian arg->bundle->AliasEnabled = 1; 171237191Sbrian return 0; 171336285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 171437191Sbrian arg->bundle->AliasEnabled = 0; 171526516Sbrian return 0; 171626142Sbrian } 171735449Sbrian } 171836285Sbrian 171926516Sbrian return -1; 172026031Sbrian} 172126031Sbrian 172226031Sbrian 172326031Sbrianstatic int 172431343SbrianAliasOption(struct cmdargs const *arg) 172526031Sbrian{ 172636285Sbrian unsigned param = (unsigned)arg->cmd->args; 172736285Sbrian if (arg->argc == arg->argn+1) { 172836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 172937191Sbrian if (arg->bundle->AliasEnabled) { 173037191Sbrian PacketAliasSetMode(param, param); 173128679Sbrian return 0; 173228679Sbrian } 173336285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 173436285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 173537191Sbrian if (arg->bundle->AliasEnabled) { 173637191Sbrian PacketAliasSetMode(0, param); 173728679Sbrian return 0; 173828679Sbrian } 173936285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 174028679Sbrian } 174135449Sbrian } 174228679Sbrian return -1; 174326031Sbrian} 174431343Sbrian#endif /* #ifndef NOALIAS */ 174531121Sbrian 174631121Sbrianstatic struct cmdtab const AllowCommands[] = { 174736285Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 174836285Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 174931121Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 175031121Sbrian "Allow users access to ppp", "allow users logname..."}, 175131121Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 175231343Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 175331121Sbrian {NULL, NULL, NULL}, 175431121Sbrian}; 175531121Sbrian 175631121Sbrianstatic int 175731343SbrianAllowCommand(struct cmdargs const *arg) 175831121Sbrian{ 175936285Sbrian /* arg->bundle may be NULL (see system_IsValid()) ! */ 176036285Sbrian if (arg->argc > arg->argn) 176136285Sbrian FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv, 176236285Sbrian arg->prompt, arg->cx); 176336285Sbrian else if (arg->prompt) 176436285Sbrian prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 176536285Sbrian " for syntax help.\n"); 176631121Sbrian else 176736285Sbrian log_Printf(LogWARN, "allow command must have arguments\n"); 176831121Sbrian 176931121Sbrian return 0; 177031121Sbrian} 177136285Sbrian 177236285Sbrianstatic int 177336285SbrianLinkCommand(struct cmdargs const *arg) 177436285Sbrian{ 177536285Sbrian if (arg->argc > arg->argn+1) { 177636285Sbrian char namelist[LINE_LEN]; 177736285Sbrian struct datalink *cx; 177836285Sbrian char *name; 177936285Sbrian int result = 0; 178036285Sbrian 178136285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 178236285Sbrian struct datalink *dl; 178336285Sbrian 178436285Sbrian cx = arg->bundle->links; 178536285Sbrian while (cx) { 178636285Sbrian /* Watch it, the command could be a ``remove'' */ 178736285Sbrian dl = cx->next; 178836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 178936285Sbrian arg->prompt, cx); 179036285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 179136285Sbrian if (cx == dl) 179236285Sbrian break; /* Pointer's still valid ! */ 179336285Sbrian } 179436285Sbrian } else { 179536285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 179636285Sbrian namelist[sizeof namelist - 1] = '\0'; 179736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 179836285Sbrian if (!bundle2datalink(arg->bundle, name)) { 179936285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 180036285Sbrian return 1; 180136285Sbrian } 180236285Sbrian 180336285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 180436285Sbrian namelist[sizeof namelist - 1] = '\0'; 180536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 180636285Sbrian cx = bundle2datalink(arg->bundle, name); 180736285Sbrian if (cx) 180836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 180936285Sbrian arg->prompt, cx); 181036285Sbrian else { 181136285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 181236285Sbrian result++; 181336285Sbrian } 181436285Sbrian } 181536285Sbrian } 181636285Sbrian return result; 181736285Sbrian } 181836285Sbrian 181936285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 182036285Sbrian return 2; 182136285Sbrian} 182236285Sbrian 182336285Sbrianstruct link * 182436285Sbriancommand_ChooseLink(struct cmdargs const *arg) 182536285Sbrian{ 182636285Sbrian if (arg->cx) 182736285Sbrian return &arg->cx->physical->link; 182837210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 182936285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 183037210Sbrian if (dl) 183137210Sbrian return &dl->physical->link; 183236285Sbrian } 183337210Sbrian return &arg->bundle->ncp.mp.link; 183436285Sbrian} 183536285Sbrian 183636285Sbrianstatic const char * 183736285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 183836285Sbrian{ 183936285Sbrian const char *result; 184036285Sbrian 184136285Sbrian switch (*cmd) { 184236285Sbrian case 'A': 184336285Sbrian case 'a': 184436285Sbrian result = "accept"; 184536285Sbrian *keep = NEG_MYMASK; 184636285Sbrian *add = NEG_ACCEPTED; 184736285Sbrian break; 184836285Sbrian case 'D': 184936285Sbrian case 'd': 185036285Sbrian switch (cmd[1]) { 185136285Sbrian case 'E': 185236285Sbrian case 'e': 185336285Sbrian result = "deny"; 185436285Sbrian *keep = NEG_MYMASK; 185536285Sbrian *add = 0; 185636285Sbrian break; 185736285Sbrian case 'I': 185836285Sbrian case 'i': 185936285Sbrian result = "disable"; 186036285Sbrian *keep = NEG_HISMASK; 186136285Sbrian *add = 0; 186236285Sbrian break; 186336285Sbrian default: 186436285Sbrian return NULL; 186536285Sbrian } 186636285Sbrian break; 186736285Sbrian case 'E': 186836285Sbrian case 'e': 186936285Sbrian result = "enable"; 187036285Sbrian *keep = NEG_HISMASK; 187136285Sbrian *add = NEG_ENABLED; 187236285Sbrian break; 187336285Sbrian default: 187436285Sbrian return NULL; 187536285Sbrian } 187636285Sbrian 187736285Sbrian return result; 187836285Sbrian} 187936285Sbrian 188036285Sbrianstatic int 188136285SbrianOptSet(struct cmdargs const *arg) 188236285Sbrian{ 188337210Sbrian int bit = (long)arg->cmd->args ? 1 : 0; 188436285Sbrian const char *cmd; 188536285Sbrian unsigned keep; /* Keep these bits */ 188636285Sbrian unsigned add; /* Add these bits */ 188736285Sbrian 188836285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 188936285Sbrian return 1; 189036285Sbrian 189136285Sbrian if (add) 189236285Sbrian arg->bundle->cfg.opt |= bit; 189336285Sbrian else 189436285Sbrian arg->bundle->cfg.opt &= ~bit; 189536285Sbrian return 0; 189636285Sbrian} 189736285Sbrian 189836285Sbrianstatic int 189936285SbrianNegotiateSet(struct cmdargs const *arg) 190036285Sbrian{ 190137210Sbrian long param = (long)arg->cmd->args; 190236285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 190336285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 190436285Sbrian const char *cmd; 190536285Sbrian unsigned keep; /* Keep these bits */ 190636285Sbrian unsigned add; /* Add these bits */ 190736285Sbrian 190836285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 190936285Sbrian return 1; 191036285Sbrian 191136285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 191236285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 191336285Sbrian cmd, arg->cmd->name); 191436285Sbrian return 2; 191536285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 191636285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 191736285Sbrian cmd, arg->cmd->name, cx->name); 191836285Sbrian cx = NULL; 191936285Sbrian } 192036285Sbrian 192136285Sbrian switch (param) { 192236285Sbrian case NEG_ACFCOMP: 192336285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 192436285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 192536285Sbrian break; 192636285Sbrian case NEG_CHAP: 192736285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 192836285Sbrian cx->physical->link.lcp.cfg.chap |= add; 192936285Sbrian break; 193036285Sbrian case NEG_DEFLATE: 193136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 193236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 193336285Sbrian break; 193436285Sbrian case NEG_DNS: 193536285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 193636285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 193736285Sbrian break; 193836285Sbrian case NEG_LQR: 193936285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 194036285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 194136285Sbrian break; 194236285Sbrian case NEG_PAP: 194336285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 194436285Sbrian cx->physical->link.lcp.cfg.pap |= add; 194536285Sbrian break; 194636285Sbrian case NEG_PPPDDEFLATE: 194736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 194836285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 194936285Sbrian break; 195036285Sbrian case NEG_PRED1: 195136285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 195236285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 195336285Sbrian break; 195436285Sbrian case NEG_PROTOCOMP: 195536285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 195636285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 195736285Sbrian break; 195836285Sbrian case NEG_SHORTSEQ: 195936285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 196036285Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); 196136285Sbrian else { 196236285Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 196336285Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 196436285Sbrian } 196536285Sbrian break; 196636285Sbrian case NEG_VJCOMP: 196736285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 196836285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 196936285Sbrian break; 197036285Sbrian } 197136285Sbrian 197236285Sbrian return 0; 197336285Sbrian} 197436285Sbrian 197536285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 197636285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 197736285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 197836285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 197936285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 198036285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 198136285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 198236285Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", 198336285Sbrian "disable|enable", (const void *)OPT_PROXY}, 198436285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 198536285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 198636285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 198736285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 198836285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 198936285Sbrian "disable|enable", (const void *)OPT_UTMP}, 199036285Sbrian 199136285Sbrian#define OPT_MAX 7 /* accept/deny allowed below and not above */ 199236285Sbrian 199336285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 199436285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 199536285Sbrian (const void *)NEG_ACFCOMP}, 199636285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 199736285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 199836285Sbrian (const void *)NEG_CHAP}, 199936285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 200036285Sbrian "Deflate compression", "accept|deny|disable|enable", 200136285Sbrian (const void *)NEG_DEFLATE}, 200236285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 200336285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 200436285Sbrian (const void *)NEG_PPPDDEFLATE}, 200536285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 200636285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 200736285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 200836285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 200936285Sbrian (const void *)NEG_LQR}, 201036285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 201136285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 201236285Sbrian (const void *)NEG_PAP}, 201336285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 201436285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 201536285Sbrian (const void *)NEG_PRED1}, 201636285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 201736285Sbrian "Protocol field compression", "accept|deny|disable|enable", 201836285Sbrian (const void *)NEG_PROTOCOMP}, 201936285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 202036285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 202136285Sbrian (const void *)NEG_SHORTSEQ}, 202236285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 202336285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 202436285Sbrian (const void *)NEG_VJCOMP}, 202536285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 202636285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 202736285Sbrian NegotiateCommands}, 202836285Sbrian {NULL, NULL, NULL}, 202936285Sbrian}; 203036285Sbrian 203136285Sbrianstatic int 203236285SbrianNegotiateCommand(struct cmdargs const *arg) 203336285Sbrian{ 203436285Sbrian if (arg->argc > arg->argn) { 203536285Sbrian char const *argv[3]; 203636285Sbrian unsigned keep, add; 203736285Sbrian int n; 203836285Sbrian 203936285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 204036285Sbrian return -1; 204136285Sbrian argv[2] = NULL; 204236285Sbrian 204336285Sbrian for (n = arg->argn; n < arg->argc; n++) { 204436285Sbrian argv[1] = arg->argv[n]; 204536285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 204636285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 204736285Sbrian } 204836285Sbrian } else if (arg->prompt) 204936285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 205036285Sbrian arg->argv[arg->argn-1]); 205136285Sbrian else 205236285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 205336285Sbrian arg->argv[arg->argn] ); 205436285Sbrian 205536285Sbrian return 0; 205636285Sbrian} 205736285Sbrian 205836285Sbrianconst char * 205936285Sbriancommand_ShowNegval(unsigned val) 206036285Sbrian{ 206136285Sbrian switch (val&3) { 206236285Sbrian case 1: return "disabled & accepted"; 206336285Sbrian case 2: return "enabled & denied"; 206436285Sbrian case 3: return "enabled & accepted"; 206536285Sbrian } 206636285Sbrian return "disabled & denied"; 206736285Sbrian} 206836934Sbrian 206936934Sbrianstatic int 207036934SbrianClearCommand(struct cmdargs const *arg) 207136934Sbrian{ 207236934Sbrian struct pppThroughput *t; 207336934Sbrian struct datalink *cx; 207436934Sbrian int i, clear_type; 207536934Sbrian 207636934Sbrian if (arg->argc < arg->argn + 1) 207736934Sbrian return -1; 207836934Sbrian 207936934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 208036934Sbrian cx = arg->cx; 208136934Sbrian if (!cx) 208236934Sbrian cx = bundle2datalink(arg->bundle, NULL); 208336934Sbrian if (!cx) { 208436934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 208536934Sbrian return 1; 208636934Sbrian } 208736934Sbrian t = &cx->physical->link.throughput; 208836934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 208936934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 209036934Sbrian else 209136934Sbrian return -1; 209236934Sbrian 209336934Sbrian if (arg->argc > arg->argn + 1) { 209436934Sbrian clear_type = 0; 209536934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 209636934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 209736934Sbrian clear_type |= THROUGHPUT_OVERALL; 209836934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 209936934Sbrian clear_type |= THROUGHPUT_CURRENT; 210036934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 210136934Sbrian clear_type |= THROUGHPUT_PEAK; 210236934Sbrian else 210336934Sbrian return -1; 210436934Sbrian } else 210536934Sbrian clear_type = THROUGHPUT_ALL; 210636934Sbrian 210736934Sbrian throughput_clear(t, clear_type, arg->prompt); 210836934Sbrian return 0; 210936934Sbrian} 2110