command.c revision 36465
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 * 2036465Sbrian * $Id: command.c,v 1.135 1998/05/21 21:44:44 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> 3936285Sbrian#include <signal.h> 4030715Sbrian#include <stdio.h> 4130715Sbrian#include <stdlib.h> 4230715Sbrian#include <string.h> 4330715Sbrian#include <sys/wait.h> 4430715Sbrian#include <termios.h> 4530715Sbrian#include <unistd.h> 4630715Sbrian 4731343Sbrian#include "command.h" 4830715Sbrian#include "mbuf.h" 4930715Sbrian#include "log.h" 5030715Sbrian#include "defs.h" 5130715Sbrian#include "timer.h" 526059Samurai#include "fsm.h" 536059Samurai#include "lcp.h" 5431690Sbrian#include "iplist.h" 5536285Sbrian#include "throughput.h" 5636285Sbrian#include "slcompress.h" 576059Samurai#include "ipcp.h" 586059Samurai#include "modem.h" 5931343Sbrian#ifndef NOALIAS 6026031Sbrian#include "alias_cmd.h" 6131343Sbrian#endif 6236285Sbrian#include "lqr.h" 636059Samurai#include "hdlc.h" 6426142Sbrian#include "loadalias.h" 6525630Sbrian#include "systems.h" 6636285Sbrian#include "filter.h" 6736285Sbrian#include "descriptor.h" 6830715Sbrian#include "main.h" 6930715Sbrian#include "route.h" 7030715Sbrian#include "ccp.h" 7131080Sbrian#include "auth.h" 7236285Sbrian#include "async.h" 7336285Sbrian#include "link.h" 7436285Sbrian#include "physical.h" 7536285Sbrian#include "mp.h" 7636285Sbrian#include "bundle.h" 7736285Sbrian#include "server.h" 7836285Sbrian#include "prompt.h" 7936285Sbrian#include "chat.h" 8036285Sbrian#include "chap.h" 8136285Sbrian#include "datalink.h" 826059Samurai 8336285Sbrian/* ``set'' values */ 8436285Sbrian#define VAR_AUTHKEY 0 8536285Sbrian#define VAR_DIAL 1 8636285Sbrian#define VAR_LOGIN 2 8736285Sbrian#define VAR_AUTHNAME 3 8836285Sbrian#define VAR_AUTOLOAD 4 8936285Sbrian#define VAR_WINSIZE 5 9036285Sbrian#define VAR_DEVICE 6 9136285Sbrian#define VAR_ACCMAP 7 9236285Sbrian#define VAR_MRRU 8 9336285Sbrian#define VAR_MRU 9 9436285Sbrian#define VAR_MTU 10 9536285Sbrian#define VAR_OPENMODE 11 9636285Sbrian#define VAR_PHONE 12 9736285Sbrian#define VAR_HANGUP 13 9836285Sbrian#define VAR_IDLETIMEOUT 14 9936285Sbrian#define VAR_LQRPERIOD 15 10036285Sbrian#define VAR_LCPRETRY 16 10136285Sbrian#define VAR_CHAPRETRY 17 10236285Sbrian#define VAR_PAPRETRY 18 10336285Sbrian#define VAR_CCPRETRY 19 10436285Sbrian#define VAR_IPCPRETRY 20 10536285Sbrian#define VAR_DNS 21 10636285Sbrian#define VAR_NBNS 22 10736285Sbrian#define VAR_MODE 23 1086059Samurai 10936285Sbrian/* ``accept|deny|disable|enable'' masks */ 11036285Sbrian#define NEG_HISMASK (1) 11136285Sbrian#define NEG_MYMASK (2) 11236285Sbrian 11336285Sbrian/* ``accept|deny|disable|enable'' values */ 11436285Sbrian#define NEG_ACFCOMP 40 11536285Sbrian#define NEG_CHAP 41 11636285Sbrian#define NEG_DEFLATE 42 11736285Sbrian#define NEG_LQR 43 11836285Sbrian#define NEG_PAP 44 11936285Sbrian#define NEG_PPPDDEFLATE 45 12036285Sbrian#define NEG_PRED1 46 12136285Sbrian#define NEG_PROTOCOMP 47 12236285Sbrian#define NEG_SHORTSEQ 48 12336285Sbrian#define NEG_VJCOMP 49 12436285Sbrian#define NEG_DNS 50 12536285Sbrian 12636285Sbrianconst char Version[] = "2.0-beta"; 12736465Sbrianconst char VersionDate[] = "$Date: 1998/05/21 21:44:44 $"; 12836285Sbrian 12936285Sbrianstatic int ShowCommand(struct cmdargs const *); 13036285Sbrianstatic int TerminalCommand(struct cmdargs const *); 13136285Sbrianstatic int QuitCommand(struct cmdargs const *); 13236285Sbrianstatic int OpenCommand(struct cmdargs const *); 13336285Sbrianstatic int CloseCommand(struct cmdargs const *); 13436285Sbrianstatic int DownCommand(struct cmdargs const *); 13536285Sbrianstatic int AllowCommand(struct cmdargs const *); 13636285Sbrianstatic int SetCommand(struct cmdargs const *); 13736285Sbrianstatic int LinkCommand(struct cmdargs const *); 13836285Sbrianstatic int AddCommand(struct cmdargs const *); 13936285Sbrianstatic int DeleteCommand(struct cmdargs const *); 14036285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 14131343Sbrian#ifndef NOALIAS 14236285Sbrianstatic int AliasCommand(struct cmdargs const *); 14336285Sbrianstatic int AliasEnable(struct cmdargs const *); 14436285Sbrianstatic int AliasOption(struct cmdargs const *); 14531343Sbrian#endif 1466059Samurai 14736285Sbrianstatic const char * 14836285Sbrianshowcx(struct cmdtab const *cmd) 14936285Sbrian{ 15036285Sbrian if (cmd->lauth & LOCAL_CX) 15136285Sbrian return "(c)"; 15236285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 15336285Sbrian return "(o)"; 15436285Sbrian 15536285Sbrian return ""; 15636285Sbrian} 15736285Sbrian 1586059Samuraistatic int 15931343SbrianHelpCommand(struct cmdargs const *arg) 1606059Samurai{ 16128679Sbrian struct cmdtab const *cmd; 16236285Sbrian int n, cmax, dmax, cols, cxlen; 16336285Sbrian const char *cx; 1646059Samurai 16536285Sbrian if (!arg->prompt) { 16636285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 16726516Sbrian return 0; 16836285Sbrian } 16926516Sbrian 17036285Sbrian if (arg->argc > arg->argn) { 17136285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 17236285Sbrian if ((cmd->lauth & arg->prompt->auth) && 17336285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 17436285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 17536285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 17628679Sbrian return 0; 1776059Samurai } 17826516Sbrian return -1; 1796059Samurai } 18036285Sbrian 18131372Sbrian cmax = dmax = 0; 18236285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 18336285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 18436285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 18531372Sbrian cmax = n; 18631372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 18731372Sbrian dmax = n; 18831372Sbrian } 18931372Sbrian 19031372Sbrian cols = 80 / (dmax + cmax + 3); 1916059Samurai n = 0; 19236285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 19336285Sbrian " (c) = Context required\n"); 19436285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 19536285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 19636285Sbrian cx = showcx(cmd); 19736285Sbrian cxlen = cmax - strlen(cmd->name); 19836285Sbrian prompt_Printf(arg->prompt, " %s%-*.*s: %-*.*s", 19936285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 20031372Sbrian if (++n % cols == 0) 20136285Sbrian prompt_Printf(arg->prompt, "\n"); 2026059Samurai } 20331372Sbrian if (n % cols != 0) 20436285Sbrian prompt_Printf(arg->prompt, "\n"); 20526516Sbrian 20626516Sbrian return 0; 2076059Samurai} 2086059Samurai 20936285Sbrianstatic int 21036285SbrianCloneCommand(struct cmdargs const *arg) 2116059Samurai{ 21236285Sbrian char namelist[LINE_LEN]; 21336285Sbrian char *name; 21436285Sbrian int f; 2156059Samurai 21636285Sbrian if (arg->argc == arg->argn) 21736285Sbrian return -1; 21836285Sbrian 21936285Sbrian namelist[sizeof namelist - 1] = '\0'; 22036285Sbrian for (f = arg->argn; f < arg->argc; f++) { 22136285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 22236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 22336285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2246059Samurai } 22536285Sbrian 22636285Sbrian return 0; 2276059Samurai} 2286059Samurai 2296059Samuraistatic int 23036285SbrianRemoveCommand(struct cmdargs const *arg) 2316059Samurai{ 23236285Sbrian if (arg->argc != arg->argn) 23336285Sbrian return -1; 23411336Samurai 23536285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 23636285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 23736285Sbrian return 2; 2386059Samurai } 23926516Sbrian 24036285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 24136285Sbrian return 0; 24236285Sbrian} 24332711Sbrian 24436285Sbrianstatic int 24536285SbrianRenameCommand(struct cmdargs const *arg) 24636285Sbrian{ 24736285Sbrian if (arg->argc != arg->argn + 1) 24836285Sbrian return -1; 24931121Sbrian 25036285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 25136285Sbrian return 0; 25236285Sbrian 25336285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 25436285Sbrian arg->cx->name, arg->argv[arg->argn]); 25536285Sbrian return 1; 25636285Sbrian} 25736285Sbrian 25836285Sbrianint 25936285SbrianLoadCommand(struct cmdargs const *arg) 26036285Sbrian{ 26136285Sbrian const char *name; 26236285Sbrian 26336285Sbrian if (arg->argc > arg->argn) 26436285Sbrian name = arg->argv[arg->argn]; 26536285Sbrian else 26636285Sbrian name = "default"; 26736285Sbrian 26836285Sbrian if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type)) { 26936285Sbrian log_Printf(LogERROR, "%s: Label not allowed\n", name); 27036285Sbrian return 1; 27136285Sbrian } else { 27236285Sbrian /* 27336285Sbrian * Set the label before & after so that `set enddisc' works and 27436285Sbrian * we handle nested `load' commands. 27536285Sbrian */ 27636285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 27736285Sbrian if (system_Select(arg->bundle, name, CONFFILE, arg->prompt) < 0) { 27836285Sbrian bundle_SetLabel(arg->bundle, NULL); 27936285Sbrian log_Printf(LogWARN, "%s: label not found.\n", name); 28036285Sbrian return -1; 28132403Sbrian } 28236285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28336285Sbrian } 28426516Sbrian return 0; 2856059Samurai} 2866059Samurai 28736285Sbrianint 28836285SbrianSaveCommand(struct cmdargs const *arg) 28936285Sbrian{ 29036285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 29136285Sbrian return 1; 29236285Sbrian} 29336285Sbrian 29410528Samuraistatic int 29536285SbrianDialCommand(struct cmdargs const *arg) 29628536Sbrian{ 29736285Sbrian int res; 29836285Sbrian 29936465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 30036465Sbrian || (!arg->cx && 30136465Sbrian (arg->bundle->phys_type & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 30236285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 30336285Sbrian " interactive links\n"); 30436285Sbrian return 1; 30534536Sbrian } 30636285Sbrian 30736285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 30836285Sbrian return res; 30936285Sbrian 31036285Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 31136285Sbrian 31236285Sbrian return 0; 31328536Sbrian} 31428536Sbrian 31528536Sbrianstatic int 31631343SbrianShellCommand(struct cmdargs const *arg, int bg) 31710528Samurai{ 31810528Samurai const char *shell; 31910528Samurai pid_t shpid; 32031343Sbrian int argc; 32131343Sbrian char *argv[MAXARGS]; 32220813Sjkh 32318856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 32426911Sbrian /* we're only allowed to shell when we run ppp interactively */ 32536285Sbrian if (arg->prompt && arg->prompt->owner) { 32636285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 32726516Sbrian return 1; 32810528Samurai } 32926911Sbrian#endif 33028679Sbrian 33136285Sbrian if (arg->argc == arg->argn) { 33236285Sbrian if (!arg->prompt) { 33336285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 33436285Sbrian " a config file\n"); 33528381Sbrian return 1; 33636285Sbrian } else if (arg->prompt->owner) { 33736285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 33836285Sbrian " a socket connection\n"); 33936285Sbrian return 1; 34028381Sbrian } else if (bg) { 34136285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 34228679Sbrian " the foreground mode\n"); 34328381Sbrian return 1; 34428381Sbrian } 34534536Sbrian } 34634536Sbrian 34728679Sbrian if ((shpid = fork()) == 0) { 34836285Sbrian int i, fd; 34918531Sbde 35036285Sbrian if ((shell = getenv("SHELL")) == 0) 35136285Sbrian shell = _PATH_BSHELL; 35232017Sbrian 35336285Sbrian timer_TermService(); 35436285Sbrian 35536285Sbrian if (arg->prompt) 35636285Sbrian fd = arg->prompt->fd_out; 35736285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 35836285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 35936285Sbrian _PATH_DEVNULL, strerror(errno)); 36028679Sbrian exit(1); 36128679Sbrian } 36228679Sbrian for (i = 0; i < 3; i++) 36328679Sbrian dup2(fd, i); 36426516Sbrian 36536285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 36626516Sbrian 36731061Sbrian setuid(geteuid()); 36836285Sbrian if (arg->argc > arg->argn) { 36928679Sbrian /* substitute pseudo args */ 37036285Sbrian argv[0] = strdup(arg->argv[arg->argn]); 37136285Sbrian for (argc = 1; argc < arg->argc - arg->argn; argc++) { 37236285Sbrian if (strcasecmp(arg->argv[argc + arg->argn], "HISADDR") == 0) 37336285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.peer_ip)); 37436285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "INTERFACE") == 0) 37536285Sbrian argv[argc] = strdup(arg->bundle->ifp.Name); 37636285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "MYADDR") == 0) 37736285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.my_ip)); 37831343Sbrian else 37936285Sbrian argv[argc] = strdup(arg->argv[argc + arg->argn]); 38031343Sbrian } 38131343Sbrian argv[argc] = NULL; 38228679Sbrian if (bg) { 38328679Sbrian pid_t p; 38410528Samurai 38528679Sbrian p = getpid(); 38628679Sbrian if (daemon(1, 1) == -1) { 38736285Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", p, strerror(errno)); 38828679Sbrian exit(1); 38928679Sbrian } 39036285Sbrian } else if (arg->prompt) 39136285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 39231343Sbrian execvp(argv[0], argv); 39330316Sbrian } else { 39436285Sbrian if (arg->prompt) 39532017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 39636285Sbrian prompt_TtyOldMode(arg->prompt); 39731343Sbrian execl(shell, shell, NULL); 39830316Sbrian } 39920813Sjkh 40036285Sbrian log_Printf(LogWARN, "exec() of %s failed\n", 40136285Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell); 40228679Sbrian exit(255); 40310528Samurai } 40436285Sbrian 40536285Sbrian if (shpid == (pid_t) - 1) 40636285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 40736285Sbrian else { 40810528Samurai int status; 40931343Sbrian waitpid(shpid, &status, 0); 41010528Samurai } 41120813Sjkh 41236285Sbrian if (arg->prompt && !arg->prompt->owner) 41336285Sbrian prompt_TtyCommandMode(arg->prompt); 41420813Sjkh 41536285Sbrian return 0; 41610528Samurai} 41710528Samurai 41831343Sbrianstatic int 41931343SbrianBgShellCommand(struct cmdargs const *arg) 42031343Sbrian{ 42136285Sbrian if (arg->argc == arg->argn) 42231343Sbrian return -1; 42331343Sbrian return ShellCommand(arg, 1); 42431343Sbrian} 42531343Sbrian 42631343Sbrianstatic int 42731343SbrianFgShellCommand(struct cmdargs const *arg) 42831343Sbrian{ 42931343Sbrian return ShellCommand(arg, 0); 43031343Sbrian} 43131343Sbrian 43230715Sbrianstatic struct cmdtab const Commands[] = { 43336285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 43428679Sbrian "accept option request", "accept option .."}, 43528679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 43632109Sbrian "add route", "add dest mask gateway", NULL}, 43736285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 43832109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 43936285Sbrian#ifndef NOALIAS 44036285Sbrian {"alias", NULL, AliasCommand, LOCAL_AUTH, 44136285Sbrian "alias control", "alias option [yes|no]"}, 44236285Sbrian#endif 44331121Sbrian {"allow", "auth", AllowCommand, LOCAL_AUTH, 44431121Sbrian "Allow ppp access", "allow users|modes ...."}, 44528679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 44631372Sbrian "Run a background command", "[!]bg command"}, 44736285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 44836285Sbrian "Clone a link", "clone newname..."}, 44936285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45036285Sbrian "Close an FSM", "close [lcp|ccp]"}, 45128679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 45232109Sbrian "delete route", "delete dest", NULL}, 45336285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 45432109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 45536285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45628679Sbrian "Deny option request", "deny option .."}, 45736285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45828679Sbrian "Dial and login", "dial|call [remote]"}, 45936285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46028679Sbrian "Disable option", "disable option .."}, 46136285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46236285Sbrian "Generate a down event", "down"}, 46336285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46428679Sbrian "Enable option", "enable option .."}, 46536285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 46636285Sbrian "Link specific commands", "link name command ..."}, 46728679Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH, 46828679Sbrian "Load settings", "load [remote]"}, 46936285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 47036285Sbrian "Open an FSM", "open [lcp|ccp]"}, 47136285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 47236285Sbrian "Password for manipulation", "passwd LocalPassword"}, 47336285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 47436285Sbrian "Quit PPP program", "quit|bye [all]"}, 47536285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 47636285Sbrian "Remove a link", "remove"}, 47736285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 47836285Sbrian "Rename a link", "rename name"}, 47928679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 48028679Sbrian "Save settings", "save"}, 48136285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 48228679Sbrian "Set parameters", "set[up] var value"}, 48328679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 48428679Sbrian "Run a subshell", "shell|! [sh command]"}, 48536285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 48631372Sbrian "Show status and stats", "show var"}, 48736285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 48831372Sbrian "Enter terminal mode", "term"}, 48928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 49031343Sbrian "Display this message", "help|? [command]", Commands}, 49128679Sbrian {NULL, NULL, NULL}, 4926059Samurai}; 4936059Samurai 49428536Sbrianstatic int 49531343SbrianShowEscape(struct cmdargs const *arg) 4966059Samurai{ 49736285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 49836285Sbrian int code, bit; 49936285Sbrian const char *sep = ""; 5006059Samurai 50126516Sbrian for (code = 0; code < 32; code++) 50236285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 50328679Sbrian for (bit = 0; bit < 8; bit++) 50436285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 50536285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 50636285Sbrian sep = ", "; 50736285Sbrian } 50836285Sbrian prompt_Printf(arg->prompt, "\n"); 5096059Samurai } 51031077Sbrian return 0; 5116059Samurai} 5126059Samurai 51328679Sbrianstatic int 51436285SbrianShowTimerList(struct cmdargs const *arg) 5156059Samurai{ 51636285Sbrian timer_Show(0, arg->prompt); 51731077Sbrian return 0; 5186059Samurai} 5196059Samurai 52028679Sbrianstatic int 52131343SbrianShowStopped(struct cmdargs const *arg) 52228327Sbrian{ 52336285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 52436285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 52536285Sbrian prompt_Printf(arg->prompt, "Disabled"); 52628327Sbrian else 52736285Sbrian prompt_Printf(arg->prompt, "%ld secs", 52836285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 52928461Sbrian 53036285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 53136285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 53236285Sbrian prompt_Printf(arg->prompt, "Disabled"); 53328461Sbrian else 53436285Sbrian prompt_Printf(arg->prompt, "%ld secs", 53536285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 53628461Sbrian 53736285Sbrian prompt_Printf(arg->prompt, "\n"); 53828461Sbrian 53931077Sbrian return 0; 54028327Sbrian} 54128327Sbrian 54228679Sbrianstatic int 54331343SbrianShowVersion(struct cmdargs const *arg) 5446059Samurai{ 54536285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 54631077Sbrian return 0; 5476059Samurai} 5486059Samurai 54928679Sbrianstatic int 55036285SbrianShowProtocolStats(struct cmdargs const *arg) 55126326Sbrian{ 55236285Sbrian struct link *l = command_ChooseLink(arg); 55326326Sbrian 55436285Sbrian if (!l) 55536285Sbrian return -1; 55636285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 55736285Sbrian link_ReportProtocolStatus(l, arg->prompt); 55831077Sbrian return 0; 55926326Sbrian} 56026326Sbrian 56130715Sbrianstatic struct cmdtab const ShowCommands[] = { 56236285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 56336285Sbrian "bundle details", "show bundle"}, 56436285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 56536285Sbrian "CCP status", "show cpp"}, 56636285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 56736285Sbrian "VJ compression stats", "show compress"}, 56836285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 56936285Sbrian "escape characters", "show escape"}, 57036285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 57136285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 57236285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 57336285Sbrian "HDLC errors", "show hdlc"}, 57436285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 57536285Sbrian "IPCP status", "show ipcp"}, 57636285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 57736285Sbrian "LCP status", "show lcp"}, 57836285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 57936285Sbrian "(high-level) link info", "show link"}, 58036285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 58136285Sbrian "available link names", "show links"}, 58236285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 58336285Sbrian "log levels", "show log"}, 58436285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 58536285Sbrian "mbuf allocations", "show mem"}, 58636285Sbrian {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 58736285Sbrian "(low-level) link info", "show modem"}, 58836285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 58936285Sbrian "multilink setup", "show mp"}, 59036285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 59136285Sbrian "protocol summary", "show proto"}, 59236285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 59336285Sbrian "routing table", "show route"}, 59436285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 59536285Sbrian "STOPPED timeout", "show stopped"}, 59636285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 59736285Sbrian "alarm timers", "show timers"}, 59828679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 59936285Sbrian "version string", "show version"}, 60036285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 60136285Sbrian "client list", "show who"}, 60228679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 60331343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 60428679Sbrian {NULL, NULL, NULL}, 6056059Samurai}; 6066059Samurai 60730715Sbrianstatic struct cmdtab const * 60831343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 6096059Samurai{ 61026516Sbrian int nmatch; 61126516Sbrian int len; 61228679Sbrian struct cmdtab const *found; 6136059Samurai 61426516Sbrian found = NULL; 61526516Sbrian len = strlen(str); 61626516Sbrian nmatch = 0; 6176059Samurai while (cmds->func) { 61825566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 61926516Sbrian if (cmds->name[len] == '\0') { 62028679Sbrian *pmatch = 1; 62128679Sbrian return cmds; 62226516Sbrian } 6236059Samurai nmatch++; 6246059Samurai found = cmds; 62528679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 62626516Sbrian if (cmds->alias[len] == '\0') { 62728679Sbrian *pmatch = 1; 62828679Sbrian return cmds; 62926516Sbrian } 6306059Samurai nmatch++; 6316059Samurai found = cmds; 6326059Samurai } 6336059Samurai cmds++; 6346059Samurai } 6356059Samurai *pmatch = nmatch; 63626516Sbrian return found; 6376059Samurai} 6386059Samurai 63936285Sbrianstatic const char * 64036285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 64136285Sbrian{ 64236285Sbrian int f, tlen, len; 64336285Sbrian 64436285Sbrian tlen = 0; 64536285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 64636285Sbrian if (f) 64736285Sbrian tgt[tlen++] = ' '; 64836285Sbrian len = strlen(argv[f]); 64936285Sbrian if (len > sz - tlen - 1) 65036285Sbrian len = sz - tlen - 1; 65136285Sbrian strncpy(tgt+tlen, argv[f], len); 65236285Sbrian tlen += len; 65336285Sbrian } 65436285Sbrian tgt[tlen] = '\0'; 65536285Sbrian return tgt; 65636285Sbrian} 65736285Sbrian 65830715Sbrianstatic int 65936285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 66036285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 6616059Samurai{ 66228679Sbrian struct cmdtab const *cmd; 6636059Samurai int val = 1; 6646059Samurai int nmatch; 66531343Sbrian struct cmdargs arg; 66636285Sbrian char prefix[100]; 6676059Samurai 66836285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 6696059Samurai if (nmatch > 1) 67036285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 67136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 67236285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 67336285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 67436285Sbrian /* We've got no context, but we require it */ 67536285Sbrian cx = bundle2datalink(bundle, NULL); 67636285Sbrian 67736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 67836285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 67936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 68036285Sbrian else { 68136285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 68236285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 68336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 68436285Sbrian cx = NULL; 68536285Sbrian } 68636285Sbrian arg.cmdtab = cmds; 68736285Sbrian arg.cmd = cmd; 68836285Sbrian arg.argc = argc; 68936285Sbrian arg.argn = argn+1; 69036285Sbrian arg.argv = argv; 69136285Sbrian arg.bundle = bundle; 69236285Sbrian arg.cx = cx; 69336285Sbrian arg.prompt = prompt; 69436285Sbrian val = (*cmd->func) (&arg); 69536285Sbrian } 69631343Sbrian } else 69736285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 69836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 69926516Sbrian 70026516Sbrian if (val == -1) 70136285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 70228679Sbrian else if (val) 70336285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 70436285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 70526516Sbrian 70626516Sbrian return val; 7076059Samurai} 7086059Samurai 7096059Samuraivoid 71036285Sbriancommand_Interpret(char *buff, int nb, int *argc, char ***argv) 7116059Samurai{ 71231343Sbrian static char *vector[MAXARGS]; 7136059Samurai char *cp; 7146059Samurai 7156059Samurai if (nb > 0) { 7166059Samurai cp = buff + strcspn(buff, "\r\n"); 7176059Samurai if (cp) 7186059Samurai *cp = '\0'; 71931121Sbrian *argc = MakeArgs(buff, vector, VECSIZE(vector)); 72031121Sbrian *argv = vector; 72131121Sbrian } else 72231121Sbrian *argc = 0; 72331121Sbrian} 7246059Samurai 72531822Sbrianstatic int 72631822Sbrianarghidden(int argc, char const *const *argv, int n) 72731822Sbrian{ 72831822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 72931828Sbrian 73031828Sbrian /* set authkey xxxxx */ 73131828Sbrian /* set key xxxxx */ 73231822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 73331822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 73431822Sbrian return 1; 73531822Sbrian 73631828Sbrian /* passwd xxxxx */ 73731828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 73831828Sbrian return 1; 73931828Sbrian 74036285Sbrian /* set server port xxxxx .... */ 74136285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 74236285Sbrian !strncasecmp(argv[1], "se", 2)) 74336285Sbrian return 1; 74436285Sbrian 74531822Sbrian return 0; 74631822Sbrian} 74731822Sbrian 74831121Sbrianvoid 74936285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 75036285Sbrian struct prompt *prompt, const char *label) 75131121Sbrian{ 75231156Sbrian if (argc > 0) { 75336285Sbrian if (log_IsKept(LogCOMMAND)) { 75431156Sbrian static char buf[LINE_LEN]; 75531156Sbrian int f, n; 75631156Sbrian 75731156Sbrian *buf = '\0'; 75831156Sbrian if (label) { 75931962Sbrian strncpy(buf, label, sizeof buf - 3); 76031962Sbrian buf[sizeof buf - 3] = '\0'; 76131156Sbrian strcat(buf, ": "); 76231156Sbrian } 76331156Sbrian n = strlen(buf); 76431156Sbrian for (f = 0; f < argc; f++) { 76531962Sbrian if (n < sizeof buf - 1 && f) 76631156Sbrian buf[n++] = ' '; 76731822Sbrian if (arghidden(argc, argv, f)) 76836285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 76931822Sbrian else 77031962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 77131156Sbrian n += strlen(buf+n); 77231156Sbrian } 77336285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 77431156Sbrian } 77536285Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, NULL); 77631156Sbrian } 7776059Samurai} 7786059Samurai 77931121Sbrianvoid 78036285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 78136285Sbrian const char *label) 78231121Sbrian{ 78331121Sbrian int argc; 78431121Sbrian char **argv; 78531121Sbrian 78636285Sbrian command_Interpret(buff, nb, &argc, &argv); 78736285Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label); 78831121Sbrian} 78931121Sbrian 7906059Samuraistatic int 79131343SbrianShowCommand(struct cmdargs const *arg) 7926059Samurai{ 79336285Sbrian if (!arg->prompt) 79436285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 79536285Sbrian else if (arg->argc > arg->argn) 79636285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 79736285Sbrian arg->prompt, arg->cx); 7986059Samurai else 79936285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 80026516Sbrian 80126516Sbrian return 0; 8026059Samurai} 8036059Samurai 8046059Samuraistatic int 80531343SbrianTerminalCommand(struct cmdargs const *arg) 8066059Samurai{ 80736285Sbrian if (!arg->prompt) { 80836285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 80926516Sbrian return 1; 8106059Samurai } 81136285Sbrian 81236285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 81336285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 81436285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 81536285Sbrian return 1; 8166059Samurai } 81736285Sbrian 81836285Sbrian datalink_Up(arg->cx, 0, 0); 81936285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 82036285Sbrian return 0; 8216059Samurai} 8226059Samurai 8236059Samuraistatic int 82431343SbrianQuitCommand(struct cmdargs const *arg) 8256059Samurai{ 82636285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 82736285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 82836285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 82936285Sbrian Cleanup(EX_NORMAL); 83036285Sbrian if (arg->prompt) 83136285Sbrian prompt_Destroy(arg->prompt, 1); 83226516Sbrian 83326516Sbrian return 0; 8346059Samurai} 8356059Samurai 8366059Samuraistatic int 83736285SbrianOpenCommand(struct cmdargs const *arg) 8386059Samurai{ 83936285Sbrian if (arg->argc == arg->argn || 84036285Sbrian (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp"))) 84136285Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 84236285Sbrian else if (arg->argc == arg->argn+1 && 84336285Sbrian !strcasecmp(arg->argv[arg->argn], "ccp")) { 84436285Sbrian struct link *l; 84536285Sbrian struct fsm *fp; 8466059Samurai 84736285Sbrian if (!(l = command_ChooseLink(arg))) 84836285Sbrian return -1; 84936285Sbrian fp = &l->ccp.fsm; 85036285Sbrian 85136285Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 85236285Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 85336285Sbrian else if (fp->state != ST_OPENED) { 85436285Sbrian fp->open_mode = 0; /* Not passive any more */ 85536285Sbrian if (fp->state == ST_STOPPED) { 85636285Sbrian fsm_Down(fp); 85736285Sbrian fsm_Up(fp); 85836285Sbrian } else { 85936285Sbrian fsm_Up(fp); 86036285Sbrian fsm_Open(fp); 86136285Sbrian } 86236285Sbrian } 86336285Sbrian } else 86436285Sbrian return -1; 86536285Sbrian 86626516Sbrian return 0; 8676059Samurai} 8686059Samurai 86925067Sbrianstatic int 87036285SbrianCloseCommand(struct cmdargs const *arg) 8716059Samurai{ 87236285Sbrian if (arg->argc == arg->argn || 87336285Sbrian (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp"))) 87436285Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, 1); 87536285Sbrian else if (arg->argc == arg->argn+1 && 87636285Sbrian (!strcasecmp(arg->argv[arg->argn], "ccp") || 87736285Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!"))) { 87836285Sbrian struct link *l; 87936285Sbrian struct fsm *fp; 8806059Samurai 88136285Sbrian if (!(l = command_ChooseLink(arg))) 88236285Sbrian return -1; 88336285Sbrian fp = &l->ccp.fsm; 88436285Sbrian 88536285Sbrian if (fp->state == ST_OPENED) { 88636285Sbrian fsm_Close(fp); 88736285Sbrian if (arg->argv[arg->argn][3] == '!') 88836285Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 88936285Sbrian else 89036285Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 8916735Samurai } 89236285Sbrian } else 89336285Sbrian return -1; 89436285Sbrian 89536285Sbrian return 0; 8966059Samurai} 8976059Samurai 89825067Sbrianstatic int 89936285SbrianDownCommand(struct cmdargs const *arg) 90011336Samurai{ 90136285Sbrian if (arg->argc == arg->argn || 90236285Sbrian (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp"))) { 90336285Sbrian if (arg->cx) 90436285Sbrian datalink_Down(arg->cx, 1); 90536285Sbrian else 90636285Sbrian bundle_Down(arg->bundle); 90736285Sbrian } else if (arg->argc == arg->argn+1 && 90836285Sbrian !strcasecmp(arg->argv[arg->argn], "ccp")) { 90936285Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 91036285Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 91136285Sbrian fsm_Down(fp); 91236285Sbrian fsm_Close(fp); 91336285Sbrian } else 91436285Sbrian return -1; 91536285Sbrian 91636285Sbrian return 0; 91725067Sbrian} 91825067Sbrian 91925067Sbrianstatic int 92036285SbrianSetModemSpeed(struct cmdargs const *arg) 92125067Sbrian{ 92236285Sbrian long speed; 92336285Sbrian char *end; 92411336Samurai 92536285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 92636285Sbrian if (arg->argc > arg->argn+1) { 92736285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 92836285Sbrian return -1; 92911336Samurai } 93036285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 93136285Sbrian physical_SetSync(arg->cx->physical); 93236285Sbrian return 0; 93336285Sbrian } 93436285Sbrian end = NULL; 93536285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 93636285Sbrian if (*end) { 93736285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 93836285Sbrian arg->argv[arg->argn]); 93936285Sbrian return -1; 94036285Sbrian } 94136285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 94236285Sbrian return 0; 94336285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 94436285Sbrian } else 94536285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 94624939Sbrian 94726516Sbrian return -1; 94811336Samurai} 94911336Samurai 95025067Sbrianstatic int 95131343SbrianSetStoppedTimeout(struct cmdargs const *arg) 95228327Sbrian{ 95336285Sbrian struct link *l = &arg->cx->physical->link; 95436285Sbrian 95536285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 95636285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 95736285Sbrian if (arg->argc <= arg->argn+2) { 95836285Sbrian if (arg->argc > arg->argn) { 95936285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 96036285Sbrian if (arg->argc > arg->argn+1) 96136285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 96228461Sbrian } 96328327Sbrian return 0; 96428327Sbrian } 96528327Sbrian return -1; 96628327Sbrian} 96728327Sbrian 96831081Sbrian#define ismask(x) \ 96931081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 97031081Sbrian 97128327Sbrianstatic int 97231343SbrianSetServer(struct cmdargs const *arg) 97326940Sbrian{ 97426940Sbrian int res = -1; 97526940Sbrian 97636285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 97731081Sbrian const char *port, *passwd, *mask; 97831081Sbrian 97931081Sbrian /* What's what ? */ 98036285Sbrian port = arg->argv[arg->argn]; 98136285Sbrian if (arg->argc == arg->argn + 2) { 98236285Sbrian passwd = arg->argv[arg->argn+1]; 98336285Sbrian mask = NULL; 98436285Sbrian } else if (arg->argc == arg->argn + 3) { 98536285Sbrian passwd = arg->argv[arg->argn+1]; 98636285Sbrian mask = arg->argv[arg->argn+2]; 98731081Sbrian if (!ismask(mask)) 98831081Sbrian return -1; 98936285Sbrian } else if (strcasecmp(port, "none") == 0) { 99036285Sbrian if (server_Close(arg->bundle)) 99136285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 99236285Sbrian return 0; 99331081Sbrian } else 99436285Sbrian return -1; 99531081Sbrian 99636285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 99736285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 99831081Sbrian 99936285Sbrian if (*port == '/') { 100031081Sbrian mode_t imask; 100136285Sbrian char *ptr, name[LINE_LEN + 12]; 100228679Sbrian 100331081Sbrian if (mask != NULL) { 100428679Sbrian unsigned m; 100528679Sbrian 100631081Sbrian if (sscanf(mask, "%o", &m) == 1) 100731081Sbrian imask = m; 100831081Sbrian else 100931081Sbrian return -1; 101031081Sbrian } else 101131081Sbrian imask = (mode_t)-1; 101236285Sbrian 101336285Sbrian ptr = strstr(port, "%d"); 101436285Sbrian if (ptr) { 101536285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 101636285Sbrian ptr - port, port, arg->bundle->unit, ptr + 2); 101736285Sbrian port = name; 101836285Sbrian } 101936285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 102027346Sbrian } else { 102136285Sbrian int iport, add = 0; 102228679Sbrian 102331081Sbrian if (mask != NULL) 102431081Sbrian return -1; 102528679Sbrian 102636285Sbrian if (*port == '+') { 102736285Sbrian port++; 102836285Sbrian add = 1; 102936285Sbrian } 103031081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 103131081Sbrian struct servent *s; 103231081Sbrian 103331081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 103431081Sbrian iport = 0; 103536285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 103628679Sbrian } else 103731081Sbrian iport = ntohs(s->s_port); 103827346Sbrian } else 103931081Sbrian iport = atoi(port); 104036285Sbrian 104136285Sbrian if (iport) { 104236285Sbrian if (add) 104336285Sbrian iport += arg->bundle->unit; 104436285Sbrian res = server_TcpOpen(arg->bundle, iport); 104536285Sbrian } else 104636285Sbrian res = -1; 104727346Sbrian } 104831081Sbrian } 104926940Sbrian 105026940Sbrian return res; 105126940Sbrian} 105226940Sbrian 105326940Sbrianstatic int 105431343SbrianSetModemParity(struct cmdargs const *arg) 10556059Samurai{ 105636285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 105736285Sbrian arg->argv[arg->argn]) : -1; 10586059Samurai} 10596059Samurai 10606059Samuraistatic int 106131343SbrianSetEscape(struct cmdargs const *arg) 10626059Samurai{ 10636059Samurai int code; 106436285Sbrian int argc = arg->argc - arg->argn; 106536285Sbrian char const *const *argv = arg->argv + arg->argn; 10666059Samurai 10676059Samurai for (code = 0; code < 33; code++) 106836285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 106931343Sbrian 10706059Samurai while (argc-- > 0) { 10716059Samurai sscanf(*argv++, "%x", &code); 10726059Samurai code &= 0xff; 107336285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 107436285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 10756059Samurai } 107626516Sbrian return 0; 10776059Samurai} 10786059Samurai 107930715Sbrianstatic struct in_addr 108031343SbrianGetIpAddr(const char *cp) 10816059Samurai{ 10826059Samurai struct hostent *hp; 10836059Samurai struct in_addr ipaddr; 10846059Samurai 108532124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 108632124Sbrian hp = gethostbyname(cp); 108732124Sbrian if (hp && hp->h_addrtype == AF_INET) 108832124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 108932124Sbrian else 109032124Sbrian ipaddr.s_addr = 0; 109132124Sbrian } 109228679Sbrian return (ipaddr); 10936059Samurai} 10946059Samurai 10956059Samuraistatic int 109631343SbrianSetInterfaceAddr(struct cmdargs const *arg) 10976059Samurai{ 109836285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 109932267Sbrian const char *hisaddr; 110032267Sbrian 110132267Sbrian hisaddr = NULL; 110236285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 110336285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 11046059Samurai 110536285Sbrian if (arg->argc > arg->argn + 4) 110628679Sbrian return -1; 110726516Sbrian 110836285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 110936285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 111036285Sbrian iplist_reset(&ipcp->cfg.peer_list); 111128394Sbrian 111236285Sbrian if (arg->argc > arg->argn) { 111336285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 111436285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 111536285Sbrian &ipcp->cfg.my_range.width)) 111628679Sbrian return 1; 111736285Sbrian if (arg->argc > arg->argn+1) { 111836285Sbrian hisaddr = arg->argv[arg->argn+1]; 111936285Sbrian if (arg->argc > arg->argn+2) { 112036285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 112136285Sbrian if (arg->argc > arg->argn+3) { 112236285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 112336285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 11249440Samurai } 11256059Samurai } 11266059Samurai } 11276059Samurai } 112828394Sbrian 11296059Samurai /* 11306059Samurai * For backwards compatibility, 0.0.0.0 means any address. 11316059Samurai */ 113236285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 113336285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 113436285Sbrian ipcp->cfg.my_range.width = 0; 11356059Samurai } 113636285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 113736285Sbrian 113836285Sbrian if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 113936285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 114036285Sbrian ipcp->cfg.peer_range.width = 0; 11416059Samurai } 114228537Sbrian 114336285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 114436465Sbrian arg->bundle->phys_type & PHYS_AUTO)) 114532267Sbrian return 4; 114631121Sbrian 114726516Sbrian return 0; 11486059Samurai} 11496059Samurai 115018752Sjkhstatic int 115131343SbrianSetVariable(struct cmdargs const *arg) 11526059Samurai{ 115336285Sbrian u_long ulong_val; 115431343Sbrian const char *argp; 115536285Sbrian int param = (int)arg->cmd->args, mode; 115636285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 115736285Sbrian const char *err = NULL; 115836285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 115936285Sbrian int dummyint; 116036285Sbrian struct in_addr dummyaddr, *addr; 11616059Samurai 116236285Sbrian if (!l) 116336285Sbrian return -1; 116436285Sbrian 116536285Sbrian if (arg->argc > arg->argn) 116636285Sbrian argp = arg->argv[arg->argn]; 116726551Sbrian else 116831343Sbrian argp = ""; 116926551Sbrian 117036285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 117136285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 117236285Sbrian arg->cmd->name); 117336285Sbrian return 1; 117436285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 117536285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 117636285Sbrian arg->cmd->name, cx->name); 117736285Sbrian cx = NULL; 117836285Sbrian } 117936285Sbrian 118026551Sbrian switch (param) { 118128679Sbrian case VAR_AUTHKEY: 118236285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 118336285Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 118436285Sbrian sizeof arg->bundle->cfg.auth.key - 1); 118536285Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 118636285Sbrian } else { 118736285Sbrian err = "set authkey: Only available at phase DEAD\n"; 118836285Sbrian log_Printf(LogWARN, err); 118936285Sbrian } 119028679Sbrian break; 119128679Sbrian case VAR_AUTHNAME: 119236285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 119336285Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 119436285Sbrian sizeof arg->bundle->cfg.auth.name - 1); 119536285Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 119636285Sbrian } else { 119736285Sbrian err = "set authname: Only available at phase DEAD\n"; 119836285Sbrian log_Printf(LogWARN, err); 119936285Sbrian } 120028679Sbrian break; 120136285Sbrian case VAR_AUTOLOAD: 120236285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 120336285Sbrian arg->bundle->autoload.running = 1; 120436285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 120536285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 120636285Sbrian if (arg->argc == arg->argn + 4) { 120736285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 120836285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 120936285Sbrian } else { 121036285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 121136285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 121236285Sbrian } 121336285Sbrian } else { 121436285Sbrian err = "Set autoload requires two or four arguments\n"; 121536285Sbrian log_Printf(LogWARN, err); 121636285Sbrian } 121736285Sbrian break; 121828679Sbrian case VAR_DIAL: 121936285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 122036285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 122128679Sbrian break; 122228679Sbrian case VAR_LOGIN: 122336285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 122436285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 122528679Sbrian break; 122636285Sbrian case VAR_WINSIZE: 122736285Sbrian if (arg->argc > arg->argn) { 122836285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 122936285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 123036285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 123136285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 123236285Sbrian l->ccp.cfg.deflate.out.winsize); 123336285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 123436285Sbrian } 123536285Sbrian if (arg->argc > arg->argn+1) { 123636285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 123736285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 123836285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 123936285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 124036285Sbrian l->ccp.cfg.deflate.in.winsize); 124136285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 124236285Sbrian } 124336285Sbrian } else 124436285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 124536285Sbrian } else { 124636285Sbrian err = "No window size specified\n"; 124736285Sbrian log_Printf(LogWARN, err); 124836285Sbrian } 124936285Sbrian break; 125028679Sbrian case VAR_DEVICE: 125136285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 125236285Sbrian arg->argv + arg->argn); 125336285Sbrian break; 125436285Sbrian case VAR_ACCMAP: 125536285Sbrian if (arg->argc > arg->argn) { 125636285Sbrian sscanf(argp, "%lx", &ulong_val); 125736285Sbrian cx->physical->link.lcp.cfg.accmap = ulong_val; 125836285Sbrian } else { 125936285Sbrian err = "No accmap specified\n"; 126036285Sbrian log_Printf(LogWARN, err); 126136285Sbrian } 126236285Sbrian break; 126336285Sbrian case VAR_MODE: 126436285Sbrian mode = Nam2mode(argp); 126536285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 126636285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 126736285Sbrian return -1; 126836285Sbrian } 126936285Sbrian bundle_SetMode(arg->bundle, cx, mode); 127036285Sbrian break; 127136285Sbrian case VAR_MRRU: 127236285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 127336285Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); 127429696Sbrian else { 127536285Sbrian ulong_val = atol(argp); 127636285Sbrian if (ulong_val < MIN_MRU) 127736285Sbrian err = "Given MRRU value (%lu) is too small.\n"; 127836285Sbrian else if (ulong_val > MAX_MRU) 127936285Sbrian err = "Given MRRU value (%lu) is too big.\n"; 128036285Sbrian else 128136285Sbrian arg->bundle->ncp.mp.cfg.mrru = ulong_val; 128236285Sbrian if (err) 128336285Sbrian log_Printf(LogWARN, err, ulong_val); 128429696Sbrian } 128528679Sbrian break; 128636285Sbrian case VAR_MRU: 128736285Sbrian ulong_val = atol(argp); 128836285Sbrian if (ulong_val < MIN_MRU) 128936285Sbrian err = "Given MRU value (%lu) is too small.\n"; 129036285Sbrian else if (ulong_val > MAX_MRU) 129136285Sbrian err = "Given MRU value (%lu) is too big.\n"; 129236285Sbrian else 129336285Sbrian l->lcp.cfg.mru = ulong_val; 129436285Sbrian if (err) 129536285Sbrian log_Printf(LogWARN, err, ulong_val); 129628679Sbrian break; 129736285Sbrian case VAR_MTU: 129836285Sbrian ulong_val = atol(argp); 129936285Sbrian if (ulong_val == 0) 130036285Sbrian arg->bundle->cfg.mtu = 0; 130136285Sbrian else if (ulong_val < MIN_MTU) 130236285Sbrian err = "Given MTU value (%lu) is too small.\n"; 130336285Sbrian else if (ulong_val > MAX_MTU) 130436285Sbrian err = "Given MTU value (%lu) is too big.\n"; 130536285Sbrian else 130636285Sbrian arg->bundle->cfg.mtu = ulong_val; 130736285Sbrian if (err) 130836285Sbrian log_Printf(LogWARN, err, ulong_val); 130936285Sbrian break; 131036285Sbrian case VAR_OPENMODE: 131136285Sbrian if (strcasecmp(argp, "active") == 0) 131236285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 131336285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 131436285Sbrian else if (strcasecmp(argp, "passive") == 0) 131536285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 131636285Sbrian else { 131736285Sbrian err = "%s: Invalid openmode\n"; 131836285Sbrian log_Printf(LogWARN, err, argp); 131936285Sbrian } 132036285Sbrian break; 132128679Sbrian case VAR_PHONE: 132236285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 132336285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 132428679Sbrian break; 132528679Sbrian case VAR_HANGUP: 132636285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 132736285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 132828679Sbrian break; 132936285Sbrian case VAR_IDLETIMEOUT: 133036285Sbrian if (arg->argc > arg->argn+1) 133136285Sbrian err = "Too many idle timeout values\n"; 133236285Sbrian else if (arg->argc == arg->argn+1) 133336285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 133436285Sbrian if (err) 133536285Sbrian log_Printf(LogWARN, err); 133629549Sbrian break; 133736285Sbrian case VAR_LQRPERIOD: 133836285Sbrian ulong_val = atol(argp); 133936285Sbrian if (ulong_val <= 0) { 134036285Sbrian err = "%s: Invalid lqr period\n"; 134136285Sbrian log_Printf(LogWARN, err, argp); 134236285Sbrian } else 134336285Sbrian l->lcp.cfg.lqrperiod = ulong_val; 134436285Sbrian break; 134536285Sbrian case VAR_LCPRETRY: 134636285Sbrian ulong_val = atol(argp); 134736285Sbrian if (ulong_val <= 0) { 134836285Sbrian err = "%s: Invalid LCP FSM retry period\n"; 134936285Sbrian log_Printf(LogWARN, err, argp); 135036285Sbrian } else 135136285Sbrian cx->physical->link.lcp.cfg.fsmretry = ulong_val; 135236285Sbrian break; 135336285Sbrian case VAR_CHAPRETRY: 135436285Sbrian ulong_val = atol(argp); 135536285Sbrian if (ulong_val <= 0) { 135636285Sbrian err = "%s: Invalid CHAP retry period\n"; 135736285Sbrian log_Printf(LogWARN, err, argp); 135836285Sbrian } else 135936285Sbrian cx->chap.auth.cfg.fsmretry = ulong_val; 136036285Sbrian break; 136136285Sbrian case VAR_PAPRETRY: 136236285Sbrian ulong_val = atol(argp); 136336285Sbrian if (ulong_val <= 0) { 136436285Sbrian err = "%s: Invalid PAP retry period\n"; 136536285Sbrian log_Printf(LogWARN, err, argp); 136636285Sbrian } else 136736285Sbrian cx->pap.cfg.fsmretry = ulong_val; 136836285Sbrian break; 136936285Sbrian case VAR_CCPRETRY: 137036285Sbrian ulong_val = atol(argp); 137136285Sbrian if (ulong_val <= 0) { 137236285Sbrian err = "%s: Invalid CCP FSM retry period\n"; 137336285Sbrian log_Printf(LogWARN, err, argp); 137436285Sbrian } else 137536285Sbrian l->ccp.cfg.fsmretry = ulong_val; 137636285Sbrian break; 137736285Sbrian case VAR_IPCPRETRY: 137836285Sbrian ulong_val = atol(argp); 137936285Sbrian if (ulong_val <= 0) { 138036285Sbrian err = "%s: Invalid IPCP FSM retry period\n"; 138136285Sbrian log_Printf(LogWARN, err, argp); 138236285Sbrian } else 138336285Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = ulong_val; 138436285Sbrian break; 138536285Sbrian case VAR_NBNS: 138636285Sbrian case VAR_DNS: 138736285Sbrian if (param == VAR_DNS) 138836285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 138936285Sbrian else 139036285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 139136285Sbrian 139236285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 139336285Sbrian 139436285Sbrian if (arg->argc > arg->argn) { 139536285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 139636285Sbrian addr, &dummyaddr, &dummyint); 139736285Sbrian if (arg->argc > arg->argn+1) 139836285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 139936285Sbrian addr + 1, &dummyaddr, &dummyint); 140036285Sbrian 140136285Sbrian if (addr[1].s_addr == INADDR_ANY) 140236285Sbrian addr[1].s_addr = addr[0].s_addr; 140336285Sbrian if (addr[0].s_addr == INADDR_ANY) 140436285Sbrian addr[0].s_addr = addr[1].s_addr; 140536285Sbrian } 140636285Sbrian break; 14076059Samurai } 140836285Sbrian 140936285Sbrian return err ? 1 : 0; 14106059Samurai} 14116059Samurai 141228679Sbrianstatic int 141331343SbrianSetCtsRts(struct cmdargs const *arg) 141420812Sjkh{ 141536285Sbrian if (arg->argc == arg->argn+1) { 141636285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 141736285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 141836285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 141936285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 142020812Sjkh else 142126516Sbrian return -1; 142226516Sbrian return 0; 142320812Sjkh } 142426516Sbrian return -1; 142520812Sjkh} 142620812Sjkh 142730715Sbrianstatic struct cmdtab const SetCommands[] = { 142836285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 142936285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 143028679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 143136285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 143228679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 143336285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 143436285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 143536285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 143636285Sbrian (const void *)VAR_AUTOLOAD}, 143736285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 143836285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 143936285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 144036285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 144136285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 144236285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 144336285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 144436285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 144536285Sbrian (const void *) VAR_WINSIZE}, 144636285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 144736285Sbrian "modem device name", "set device|line device-name[,device-name]", 144836285Sbrian (const void *) VAR_DEVICE}, 144936285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 145036285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 145136285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 145236285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 145336285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 145436285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 145536285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 145636285Sbrian "escape characters", "set escape hex-digit ..."}, 145736285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 145836285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 145936285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 146036285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 146136285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 146236285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 146336285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 146431343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 146536285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 146636285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 146736285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 146836285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 146936285Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, 147036285Sbrian "log level", "set log [local] [+|-]value..."}, 147136285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 147236285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 147336285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 147436285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 147536285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 147636285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 147736285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 147836285Sbrian "set mrru value", (const void *)VAR_MRRU}, 147936285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 148036285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 148136285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 148236285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 148336285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 148436285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 148536285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 148636285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 148736285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 148836285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 148936285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 149036285Sbrian "modem parity", "set parity [odd|even|none]"}, 149136285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 149236285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 149336285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 149436285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 149536285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 149636285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 149728679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 149836285Sbrian "server port", "set server|socket TcpPort|LocalName|none [mask]"}, 149936285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 150036285Sbrian "modem speed", "set speed value"}, 150136285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 150236285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 150336285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 150436285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 150536285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 150636285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 150736285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 150836285Sbrian "datalink weighting", "set weight n"}, 150928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 151031343Sbrian "Display this message", "set help|? [command]", SetCommands}, 151128679Sbrian {NULL, NULL, NULL}, 15126059Samurai}; 15136059Samurai 15146059Samuraistatic int 151531343SbrianSetCommand(struct cmdargs const *arg) 15166059Samurai{ 151736285Sbrian if (arg->argc > arg->argn) 151836285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 151936285Sbrian arg->prompt, arg->cx); 152036285Sbrian else if (arg->prompt) 152136285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 152226516Sbrian " syntax help.\n"); 15236059Samurai else 152436285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 152526516Sbrian 152626516Sbrian return 0; 15276059Samurai} 15286059Samurai 15296059Samurai 15306059Samuraistatic int 153131343SbrianAddCommand(struct cmdargs const *arg) 15326059Samurai{ 15336059Samurai struct in_addr dest, gateway, netmask; 153436285Sbrian int gw, addrs; 15356059Samurai 153636285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 153731598Sbrian return -1; 153831598Sbrian 153936285Sbrian addrs = 0; 154036285Sbrian if (arg->argc == arg->argn+2) { 154136285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 154236285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 154331598Sbrian else { 154436285Sbrian int width; 154536285Sbrian 154636285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 154736285Sbrian &dest, &netmask, &width)) 154836285Sbrian return -1; 154936285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 155036285Sbrian addrs = ROUTE_DSTMYADDR; 155136285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 155236285Sbrian addrs = ROUTE_DSTHISADDR; 155331598Sbrian } 155436285Sbrian gw = 1; 155534536Sbrian } else { 155636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 155736285Sbrian addrs = ROUTE_DSTMYADDR; 155836285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 155936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 156036285Sbrian addrs = ROUTE_DSTHISADDR; 156136285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 156236285Sbrian } else 156336285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 156436285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 156531598Sbrian gw = 2; 15666059Samurai } 156736285Sbrian 156836285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 156936285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 157036285Sbrian addrs |= ROUTE_GWHISADDR; 157136285Sbrian } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0) 157231598Sbrian gateway.s_addr = INADDR_ANY; 157331598Sbrian else 157436285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 157536285Sbrian 157636285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 157736285Sbrian arg->cmd->args ? 1 : 0)) 157836285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 157936285Sbrian 158031598Sbrian return 0; 15816059Samurai} 15826059Samurai 15836059Samuraistatic int 158431343SbrianDeleteCommand(struct cmdargs const *arg) 15856059Samurai{ 158631598Sbrian struct in_addr dest, none; 158736285Sbrian int addrs; 15886059Samurai 158936285Sbrian if (arg->argc == arg->argn+1) { 159036285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 159136285Sbrian route_IfDelete(arg->bundle, 0); 159236285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 159336285Sbrian } else { 159436285Sbrian addrs = 0; 159536285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 159636285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 159736285Sbrian addrs = ROUTE_DSTMYADDR; 159836285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 159936285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 160036285Sbrian addrs = ROUTE_DSTHISADDR; 160136285Sbrian } else { 160236285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 160336285Sbrian dest.s_addr = INADDR_ANY; 160436285Sbrian else 160536285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 160636285Sbrian addrs = ROUTE_STATIC; 160736285Sbrian } 160831598Sbrian none.s_addr = INADDR_ANY; 160936285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 161036285Sbrian arg->cmd->args ? 1 : 0); 161136285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 161231598Sbrian } 161334536Sbrian } else 161426516Sbrian return -1; 161526516Sbrian 161626516Sbrian return 0; 16176059Samurai} 16186059Samurai 161931343Sbrian#ifndef NOALIAS 162026031Sbrianstatic struct cmdtab const AliasCommands[] = 162126031Sbrian{ 162236285Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 162336285Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 162436285Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 162536285Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 162636285Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 162728679Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 162836285Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 162928679Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 163036285Sbrian "log aliasing link creation", "alias log [yes|no]", 163136285Sbrian (const void *) PKT_ALIAS_LOG}, 163236285Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 163336285Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 163428679Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 163536285Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 163636285Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 163736285Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 163836285Sbrian "alias unregistered (private) IP address space only", 163936285Sbrian "alias unregistered_only [yes|no]", 164036285Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 164128679Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 164236285Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 164336285Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 164428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 164536285Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 164628679Sbrian {NULL, NULL, NULL}, 164726031Sbrian}; 164826031Sbrian 164926031Sbrian 165026031Sbrianstatic int 165131343SbrianAliasCommand(struct cmdargs const *arg) 165226031Sbrian{ 165336285Sbrian if (arg->argc > arg->argn) 165436285Sbrian FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv, 165536285Sbrian arg->prompt, arg->cx); 165636285Sbrian else if (arg->prompt) 165736285Sbrian prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 165836285Sbrian " <option>' for syntax help.\n"); 165926031Sbrian else 166036285Sbrian log_Printf(LogWARN, "alias command must have arguments\n"); 166126516Sbrian 166226516Sbrian return 0; 166326031Sbrian} 166426031Sbrian 166526031Sbrianstatic int 166631343SbrianAliasEnable(struct cmdargs const *arg) 166726031Sbrian{ 166836285Sbrian if (arg->argc == arg->argn+1) { 166936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 167036285Sbrian if (alias_Load() == 0) 167136285Sbrian return 0; 167236285Sbrian log_Printf(LogWARN, "Cannot load alias library\n"); 167336285Sbrian return 1; 167436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 167536285Sbrian alias_Unload(); 167626516Sbrian return 0; 167726142Sbrian } 167835449Sbrian } 167936285Sbrian 168026516Sbrian return -1; 168126031Sbrian} 168226031Sbrian 168326031Sbrian 168426031Sbrianstatic int 168531343SbrianAliasOption(struct cmdargs const *arg) 168626031Sbrian{ 168736285Sbrian unsigned param = (unsigned)arg->cmd->args; 168836285Sbrian if (arg->argc == arg->argn+1) { 168936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 169036285Sbrian if (alias_IsEnabled()) { 169136285Sbrian (*PacketAlias.SetMode)(param, param); 169228679Sbrian return 0; 169328679Sbrian } 169436285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 169536285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 169636285Sbrian if (alias_IsEnabled()) { 169736285Sbrian (*PacketAlias.SetMode)(0, param); 169828679Sbrian return 0; 169928679Sbrian } 170036285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 170128679Sbrian } 170235449Sbrian } 170328679Sbrian return -1; 170426031Sbrian} 170531343Sbrian#endif /* #ifndef NOALIAS */ 170631121Sbrian 170731121Sbrianstatic struct cmdtab const AllowCommands[] = { 170836285Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 170936285Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 171031121Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 171131121Sbrian "Allow users access to ppp", "allow users logname..."}, 171231121Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 171331343Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 171431121Sbrian {NULL, NULL, NULL}, 171531121Sbrian}; 171631121Sbrian 171731121Sbrianstatic int 171831343SbrianAllowCommand(struct cmdargs const *arg) 171931121Sbrian{ 172036285Sbrian /* arg->bundle may be NULL (see system_IsValid()) ! */ 172136285Sbrian if (arg->argc > arg->argn) 172236285Sbrian FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv, 172336285Sbrian arg->prompt, arg->cx); 172436285Sbrian else if (arg->prompt) 172536285Sbrian prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 172636285Sbrian " for syntax help.\n"); 172731121Sbrian else 172836285Sbrian log_Printf(LogWARN, "allow command must have arguments\n"); 172931121Sbrian 173031121Sbrian return 0; 173131121Sbrian} 173236285Sbrian 173336285Sbrianstatic int 173436285SbrianLinkCommand(struct cmdargs const *arg) 173536285Sbrian{ 173636285Sbrian if (arg->argc > arg->argn+1) { 173736285Sbrian char namelist[LINE_LEN]; 173836285Sbrian struct datalink *cx; 173936285Sbrian char *name; 174036285Sbrian int result = 0; 174136285Sbrian 174236285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 174336285Sbrian struct datalink *dl; 174436285Sbrian 174536285Sbrian cx = arg->bundle->links; 174636285Sbrian while (cx) { 174736285Sbrian /* Watch it, the command could be a ``remove'' */ 174836285Sbrian dl = cx->next; 174936285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 175036285Sbrian arg->prompt, cx); 175136285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 175236285Sbrian if (cx == dl) 175336285Sbrian break; /* Pointer's still valid ! */ 175436285Sbrian } 175536285Sbrian } else { 175636285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 175736285Sbrian namelist[sizeof namelist - 1] = '\0'; 175836285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 175936285Sbrian if (!bundle2datalink(arg->bundle, name)) { 176036285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 176136285Sbrian return 1; 176236285Sbrian } 176336285Sbrian 176436285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 176536285Sbrian namelist[sizeof namelist - 1] = '\0'; 176636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 176736285Sbrian cx = bundle2datalink(arg->bundle, name); 176836285Sbrian if (cx) 176936285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 177036285Sbrian arg->prompt, cx); 177136285Sbrian else { 177236285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 177336285Sbrian result++; 177436285Sbrian } 177536285Sbrian } 177636285Sbrian } 177736285Sbrian return result; 177836285Sbrian } 177936285Sbrian 178036285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 178136285Sbrian return 2; 178236285Sbrian} 178336285Sbrian 178436285Sbrianstruct link * 178536285Sbriancommand_ChooseLink(struct cmdargs const *arg) 178636285Sbrian{ 178736285Sbrian if (arg->cx) 178836285Sbrian return &arg->cx->physical->link; 178936285Sbrian else if (arg->bundle->ncp.mp.cfg.mrru) 179036285Sbrian return &arg->bundle->ncp.mp.link; 179136285Sbrian else { 179236285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 179336285Sbrian return dl ? &dl->physical->link : NULL; 179436285Sbrian } 179536285Sbrian} 179636285Sbrian 179736285Sbrianstatic const char * 179836285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 179936285Sbrian{ 180036285Sbrian const char *result; 180136285Sbrian 180236285Sbrian switch (*cmd) { 180336285Sbrian case 'A': 180436285Sbrian case 'a': 180536285Sbrian result = "accept"; 180636285Sbrian *keep = NEG_MYMASK; 180736285Sbrian *add = NEG_ACCEPTED; 180836285Sbrian break; 180936285Sbrian case 'D': 181036285Sbrian case 'd': 181136285Sbrian switch (cmd[1]) { 181236285Sbrian case 'E': 181336285Sbrian case 'e': 181436285Sbrian result = "deny"; 181536285Sbrian *keep = NEG_MYMASK; 181636285Sbrian *add = 0; 181736285Sbrian break; 181836285Sbrian case 'I': 181936285Sbrian case 'i': 182036285Sbrian result = "disable"; 182136285Sbrian *keep = NEG_HISMASK; 182236285Sbrian *add = 0; 182336285Sbrian break; 182436285Sbrian default: 182536285Sbrian return NULL; 182636285Sbrian } 182736285Sbrian break; 182836285Sbrian case 'E': 182936285Sbrian case 'e': 183036285Sbrian result = "enable"; 183136285Sbrian *keep = NEG_HISMASK; 183236285Sbrian *add = NEG_ENABLED; 183336285Sbrian break; 183436285Sbrian default: 183536285Sbrian return NULL; 183636285Sbrian } 183736285Sbrian 183836285Sbrian return result; 183936285Sbrian} 184036285Sbrian 184136285Sbrianstatic int 184236285SbrianOptSet(struct cmdargs const *arg) 184336285Sbrian{ 184436285Sbrian int bit = (int)arg->cmd->args; 184536285Sbrian const char *cmd; 184636285Sbrian unsigned keep; /* Keep these bits */ 184736285Sbrian unsigned add; /* Add these bits */ 184836285Sbrian 184936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 185036285Sbrian return 1; 185136285Sbrian 185236285Sbrian if (add) 185336285Sbrian arg->bundle->cfg.opt |= bit; 185436285Sbrian else 185536285Sbrian arg->bundle->cfg.opt &= ~bit; 185636285Sbrian return 0; 185736285Sbrian} 185836285Sbrian 185936285Sbrianstatic int 186036285SbrianNegotiateSet(struct cmdargs const *arg) 186136285Sbrian{ 186236285Sbrian int param = (int)arg->cmd->args; 186336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 186436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 186536285Sbrian const char *cmd; 186636285Sbrian unsigned keep; /* Keep these bits */ 186736285Sbrian unsigned add; /* Add these bits */ 186836285Sbrian 186936285Sbrian if (!l) 187036285Sbrian return -1; 187136285Sbrian 187236285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 187336285Sbrian return 1; 187436285Sbrian 187536285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 187636285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 187736285Sbrian cmd, arg->cmd->name); 187836285Sbrian return 2; 187936285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 188036285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 188136285Sbrian cmd, arg->cmd->name, cx->name); 188236285Sbrian cx = NULL; 188336285Sbrian } 188436285Sbrian 188536285Sbrian switch (param) { 188636285Sbrian case NEG_ACFCOMP: 188736285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 188836285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 188936285Sbrian break; 189036285Sbrian case NEG_CHAP: 189136285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 189236285Sbrian cx->physical->link.lcp.cfg.chap |= add; 189336285Sbrian break; 189436285Sbrian case NEG_DEFLATE: 189536285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 189636285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 189736285Sbrian break; 189836285Sbrian case NEG_DNS: 189936285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 190036285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 190136285Sbrian break; 190236285Sbrian case NEG_LQR: 190336285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 190436285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 190536285Sbrian break; 190636285Sbrian case NEG_PAP: 190736285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 190836285Sbrian cx->physical->link.lcp.cfg.pap |= add; 190936285Sbrian break; 191036285Sbrian case NEG_PPPDDEFLATE: 191136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 191236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 191336285Sbrian break; 191436285Sbrian case NEG_PRED1: 191536285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 191636285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 191736285Sbrian break; 191836285Sbrian case NEG_PROTOCOMP: 191936285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 192036285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 192136285Sbrian break; 192236285Sbrian case NEG_SHORTSEQ: 192336285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 192436285Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); 192536285Sbrian else { 192636285Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 192736285Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 192836285Sbrian } 192936285Sbrian break; 193036285Sbrian case NEG_VJCOMP: 193136285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 193236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 193336285Sbrian break; 193436285Sbrian } 193536285Sbrian 193636285Sbrian return 0; 193736285Sbrian} 193836285Sbrian 193936285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 194036285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 194136285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 194236285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 194336285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 194436285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 194536285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 194636285Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", 194736285Sbrian "disable|enable", (const void *)OPT_PROXY}, 194836285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 194936285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 195036285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 195136285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 195236285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 195336285Sbrian "disable|enable", (const void *)OPT_UTMP}, 195436285Sbrian 195536285Sbrian#define OPT_MAX 7 /* accept/deny allowed below and not above */ 195636285Sbrian 195736285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 195836285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 195936285Sbrian (const void *)NEG_ACFCOMP}, 196036285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 196136285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 196236285Sbrian (const void *)NEG_CHAP}, 196336285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 196436285Sbrian "Deflate compression", "accept|deny|disable|enable", 196536285Sbrian (const void *)NEG_DEFLATE}, 196636285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 196736285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 196836285Sbrian (const void *)NEG_PPPDDEFLATE}, 196936285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 197036285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 197136285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 197236285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 197336285Sbrian (const void *)NEG_LQR}, 197436285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 197536285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 197636285Sbrian (const void *)NEG_PAP}, 197736285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 197836285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 197936285Sbrian (const void *)NEG_PRED1}, 198036285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 198136285Sbrian "Protocol field compression", "accept|deny|disable|enable", 198236285Sbrian (const void *)NEG_PROTOCOMP}, 198336285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 198436285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 198536285Sbrian (const void *)NEG_SHORTSEQ}, 198636285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 198736285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 198836285Sbrian (const void *)NEG_VJCOMP}, 198936285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 199036285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 199136285Sbrian NegotiateCommands}, 199236285Sbrian {NULL, NULL, NULL}, 199336285Sbrian}; 199436285Sbrian 199536285Sbrianstatic int 199636285SbrianNegotiateCommand(struct cmdargs const *arg) 199736285Sbrian{ 199836285Sbrian if (arg->argc > arg->argn) { 199936285Sbrian char const *argv[3]; 200036285Sbrian unsigned keep, add; 200136285Sbrian int n; 200236285Sbrian 200336285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 200436285Sbrian return -1; 200536285Sbrian argv[2] = NULL; 200636285Sbrian 200736285Sbrian for (n = arg->argn; n < arg->argc; n++) { 200836285Sbrian argv[1] = arg->argv[n]; 200936285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 201036285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 201136285Sbrian } 201236285Sbrian } else if (arg->prompt) 201336285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 201436285Sbrian arg->argv[arg->argn-1]); 201536285Sbrian else 201636285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 201736285Sbrian arg->argv[arg->argn] ); 201836285Sbrian 201936285Sbrian return 0; 202036285Sbrian} 202136285Sbrian 202236285Sbrianconst char * 202336285Sbriancommand_ShowNegval(unsigned val) 202436285Sbrian{ 202536285Sbrian switch (val&3) { 202636285Sbrian case 1: return "disabled & accepted"; 202736285Sbrian case 2: return "enabled & denied"; 202836285Sbrian case 3: return "enabled & accepted"; 202936285Sbrian } 203036285Sbrian return "disabled & denied"; 203136285Sbrian} 2032