command.c revision 37009
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 * 2037009Sbrian * $Id: command.c,v 1.143 1998/06/15 19:05:40 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 4737009Sbrian#include "defs.h" 4831343Sbrian#include "command.h" 4930715Sbrian#include "mbuf.h" 5030715Sbrian#include "log.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"; 12737009Sbrianconst char VersionDate[] = "$Date: 1998/06/15 19:05:40 $"; 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 *); 14136934Sbrianstatic int ClearCommand(struct cmdargs const *); 14231343Sbrian#ifndef NOALIAS 14336285Sbrianstatic int AliasCommand(struct cmdargs const *); 14436285Sbrianstatic int AliasEnable(struct cmdargs const *); 14536285Sbrianstatic int AliasOption(struct cmdargs const *); 14631343Sbrian#endif 1476059Samurai 14836285Sbrianstatic const char * 14936285Sbrianshowcx(struct cmdtab const *cmd) 15036285Sbrian{ 15136285Sbrian if (cmd->lauth & LOCAL_CX) 15236285Sbrian return "(c)"; 15336285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 15436285Sbrian return "(o)"; 15536285Sbrian 15636285Sbrian return ""; 15736285Sbrian} 15836285Sbrian 1596059Samuraistatic int 16031343SbrianHelpCommand(struct cmdargs const *arg) 1616059Samurai{ 16228679Sbrian struct cmdtab const *cmd; 16336285Sbrian int n, cmax, dmax, cols, cxlen; 16436285Sbrian const char *cx; 1656059Samurai 16636285Sbrian if (!arg->prompt) { 16736285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 16826516Sbrian return 0; 16936285Sbrian } 17026516Sbrian 17136285Sbrian if (arg->argc > arg->argn) { 17236285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 17336285Sbrian if ((cmd->lauth & arg->prompt->auth) && 17436285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 17536285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 17636285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 17728679Sbrian return 0; 1786059Samurai } 17926516Sbrian return -1; 1806059Samurai } 18136285Sbrian 18231372Sbrian cmax = dmax = 0; 18336285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 18436285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 18536285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 18631372Sbrian cmax = n; 18731372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 18831372Sbrian dmax = n; 18931372Sbrian } 19031372Sbrian 19131372Sbrian cols = 80 / (dmax + cmax + 3); 1926059Samurai n = 0; 19336285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 19436285Sbrian " (c) = Context required\n"); 19536285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 19636285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 19736285Sbrian cx = showcx(cmd); 19836285Sbrian cxlen = cmax - strlen(cmd->name); 19936285Sbrian prompt_Printf(arg->prompt, " %s%-*.*s: %-*.*s", 20036285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 20131372Sbrian if (++n % cols == 0) 20236285Sbrian prompt_Printf(arg->prompt, "\n"); 2036059Samurai } 20431372Sbrian if (n % cols != 0) 20536285Sbrian prompt_Printf(arg->prompt, "\n"); 20626516Sbrian 20726516Sbrian return 0; 2086059Samurai} 2096059Samurai 21036285Sbrianstatic int 21136285SbrianCloneCommand(struct cmdargs const *arg) 2126059Samurai{ 21336285Sbrian char namelist[LINE_LEN]; 21436285Sbrian char *name; 21536285Sbrian int f; 2166059Samurai 21736285Sbrian if (arg->argc == arg->argn) 21836285Sbrian return -1; 21936285Sbrian 22036285Sbrian namelist[sizeof namelist - 1] = '\0'; 22136285Sbrian for (f = arg->argn; f < arg->argc; f++) { 22236285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 22336285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 22436285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2256059Samurai } 22636285Sbrian 22736285Sbrian return 0; 2286059Samurai} 2296059Samurai 2306059Samuraistatic int 23136285SbrianRemoveCommand(struct cmdargs const *arg) 2326059Samurai{ 23336285Sbrian if (arg->argc != arg->argn) 23436285Sbrian return -1; 23511336Samurai 23636285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 23736285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 23836285Sbrian return 2; 2396059Samurai } 24026516Sbrian 24136285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 24236285Sbrian return 0; 24336285Sbrian} 24432711Sbrian 24536285Sbrianstatic int 24636285SbrianRenameCommand(struct cmdargs const *arg) 24736285Sbrian{ 24836285Sbrian if (arg->argc != arg->argn + 1) 24936285Sbrian return -1; 25031121Sbrian 25136285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 25236285Sbrian return 0; 25336285Sbrian 25436285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 25536285Sbrian arg->cx->name, arg->argv[arg->argn]); 25636285Sbrian return 1; 25736285Sbrian} 25836285Sbrian 25936285Sbrianint 26036285SbrianLoadCommand(struct cmdargs const *arg) 26136285Sbrian{ 26236285Sbrian const char *name; 26336285Sbrian 26436285Sbrian if (arg->argc > arg->argn) 26536285Sbrian name = arg->argv[arg->argn]; 26636285Sbrian else 26736285Sbrian name = "default"; 26836285Sbrian 26936928Sbrian if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type.all)) { 27036285Sbrian log_Printf(LogERROR, "%s: Label not allowed\n", name); 27136285Sbrian return 1; 27236285Sbrian } else { 27336285Sbrian /* 27436285Sbrian * Set the label before & after so that `set enddisc' works and 27536285Sbrian * we handle nested `load' commands. 27636285Sbrian */ 27736285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 27837008Sbrian if (system_Select(arg->bundle, name, CONFFILE, arg->prompt, arg->cx) < 0) { 27936285Sbrian bundle_SetLabel(arg->bundle, NULL); 28036285Sbrian log_Printf(LogWARN, "%s: label not found.\n", name); 28136285Sbrian return -1; 28232403Sbrian } 28336285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28436285Sbrian } 28526516Sbrian return 0; 2866059Samurai} 2876059Samurai 28836285Sbrianint 28936285SbrianSaveCommand(struct cmdargs const *arg) 29036285Sbrian{ 29136285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 29236285Sbrian return 1; 29336285Sbrian} 29436285Sbrian 29510528Samuraistatic int 29636285SbrianDialCommand(struct cmdargs const *arg) 29728536Sbrian{ 29836285Sbrian int res; 29936285Sbrian 30036465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 30136465Sbrian || (!arg->cx && 30236928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 30336285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 30436285Sbrian " interactive links\n"); 30536285Sbrian return 1; 30634536Sbrian } 30736285Sbrian 30836285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 30936285Sbrian return res; 31036285Sbrian 31136285Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 31236285Sbrian 31336285Sbrian return 0; 31428536Sbrian} 31528536Sbrian 31628536Sbrianstatic int 31731343SbrianShellCommand(struct cmdargs const *arg, int bg) 31810528Samurai{ 31910528Samurai const char *shell; 32010528Samurai pid_t shpid; 32131343Sbrian int argc; 32231343Sbrian char *argv[MAXARGS]; 32320813Sjkh 32418856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 32526911Sbrian /* we're only allowed to shell when we run ppp interactively */ 32636285Sbrian if (arg->prompt && arg->prompt->owner) { 32736285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 32826516Sbrian return 1; 32910528Samurai } 33026911Sbrian#endif 33128679Sbrian 33236285Sbrian if (arg->argc == arg->argn) { 33336285Sbrian if (!arg->prompt) { 33436285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 33536285Sbrian " a config file\n"); 33628381Sbrian return 1; 33736285Sbrian } else if (arg->prompt->owner) { 33836285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 33936285Sbrian " a socket connection\n"); 34036285Sbrian return 1; 34128381Sbrian } else if (bg) { 34236285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 34328679Sbrian " the foreground mode\n"); 34428381Sbrian return 1; 34528381Sbrian } 34634536Sbrian } 34734536Sbrian 34828679Sbrian if ((shpid = fork()) == 0) { 34936285Sbrian int i, fd; 35018531Sbde 35136285Sbrian if ((shell = getenv("SHELL")) == 0) 35236285Sbrian shell = _PATH_BSHELL; 35332017Sbrian 35436285Sbrian timer_TermService(); 35536285Sbrian 35636285Sbrian if (arg->prompt) 35736285Sbrian fd = arg->prompt->fd_out; 35836285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 35936285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 36036285Sbrian _PATH_DEVNULL, strerror(errno)); 36128679Sbrian exit(1); 36228679Sbrian } 36328679Sbrian for (i = 0; i < 3; i++) 36428679Sbrian dup2(fd, i); 36526516Sbrian 36636285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 36726516Sbrian 36831061Sbrian setuid(geteuid()); 36936285Sbrian if (arg->argc > arg->argn) { 37028679Sbrian /* substitute pseudo args */ 37136285Sbrian argv[0] = strdup(arg->argv[arg->argn]); 37236285Sbrian for (argc = 1; argc < arg->argc - arg->argn; argc++) { 37336285Sbrian if (strcasecmp(arg->argv[argc + arg->argn], "HISADDR") == 0) 37436285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.peer_ip)); 37536285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "INTERFACE") == 0) 37636285Sbrian argv[argc] = strdup(arg->bundle->ifp.Name); 37736285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "MYADDR") == 0) 37836285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.my_ip)); 37931343Sbrian else 38036285Sbrian argv[argc] = strdup(arg->argv[argc + arg->argn]); 38131343Sbrian } 38231343Sbrian argv[argc] = NULL; 38328679Sbrian if (bg) { 38428679Sbrian pid_t p; 38510528Samurai 38628679Sbrian p = getpid(); 38728679Sbrian if (daemon(1, 1) == -1) { 38836832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 38928679Sbrian exit(1); 39028679Sbrian } 39136285Sbrian } else if (arg->prompt) 39236285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 39331343Sbrian execvp(argv[0], argv); 39430316Sbrian } else { 39536285Sbrian if (arg->prompt) 39632017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 39736285Sbrian prompt_TtyOldMode(arg->prompt); 39831343Sbrian execl(shell, shell, NULL); 39930316Sbrian } 40020813Sjkh 40136285Sbrian log_Printf(LogWARN, "exec() of %s failed\n", 40236285Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell); 40328679Sbrian exit(255); 40410528Samurai } 40536285Sbrian 40636285Sbrian if (shpid == (pid_t) - 1) 40736285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 40836285Sbrian else { 40910528Samurai int status; 41031343Sbrian waitpid(shpid, &status, 0); 41110528Samurai } 41220813Sjkh 41336285Sbrian if (arg->prompt && !arg->prompt->owner) 41436285Sbrian prompt_TtyCommandMode(arg->prompt); 41520813Sjkh 41636285Sbrian return 0; 41710528Samurai} 41810528Samurai 41931343Sbrianstatic int 42031343SbrianBgShellCommand(struct cmdargs const *arg) 42131343Sbrian{ 42236285Sbrian if (arg->argc == arg->argn) 42331343Sbrian return -1; 42431343Sbrian return ShellCommand(arg, 1); 42531343Sbrian} 42631343Sbrian 42731343Sbrianstatic int 42831343SbrianFgShellCommand(struct cmdargs const *arg) 42931343Sbrian{ 43031343Sbrian return ShellCommand(arg, 0); 43131343Sbrian} 43231343Sbrian 43330715Sbrianstatic struct cmdtab const Commands[] = { 43436285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 43528679Sbrian "accept option request", "accept option .."}, 43628679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 43732109Sbrian "add route", "add dest mask gateway", NULL}, 43836285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 43932109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 44036285Sbrian#ifndef NOALIAS 44136285Sbrian {"alias", NULL, AliasCommand, LOCAL_AUTH, 44236285Sbrian "alias control", "alias option [yes|no]"}, 44336285Sbrian#endif 44431121Sbrian {"allow", "auth", AllowCommand, LOCAL_AUTH, 44531121Sbrian "Allow ppp access", "allow users|modes ...."}, 44628679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 44731372Sbrian "Run a background command", "[!]bg command"}, 44836934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 44936934Sbrian "Clear throughput statistics", "clear ipcp|modem [current|overall|peak]..."}, 45036285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 45136285Sbrian "Clone a link", "clone newname..."}, 45236285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45336285Sbrian "Close an FSM", "close [lcp|ccp]"}, 45428679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 45532109Sbrian "delete route", "delete dest", NULL}, 45636285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 45732109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 45836285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45928679Sbrian "Deny option request", "deny option .."}, 46036285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46128679Sbrian "Dial and login", "dial|call [remote]"}, 46236285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46328679Sbrian "Disable option", "disable option .."}, 46436285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46536285Sbrian "Generate a down event", "down"}, 46636285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46728679Sbrian "Enable option", "enable option .."}, 46836285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 46936285Sbrian "Link specific commands", "link name command ..."}, 47037008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 47128679Sbrian "Load settings", "load [remote]"}, 47236285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 47336285Sbrian "Open an FSM", "open [lcp|ccp]"}, 47436285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 47536285Sbrian "Password for manipulation", "passwd LocalPassword"}, 47636285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 47736285Sbrian "Quit PPP program", "quit|bye [all]"}, 47836285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 47936285Sbrian "Remove a link", "remove"}, 48036285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 48136285Sbrian "Rename a link", "rename name"}, 48228679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 48328679Sbrian "Save settings", "save"}, 48436285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 48528679Sbrian "Set parameters", "set[up] var value"}, 48628679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 48728679Sbrian "Run a subshell", "shell|! [sh command]"}, 48836285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 48931372Sbrian "Show status and stats", "show var"}, 49036285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 49131372Sbrian "Enter terminal mode", "term"}, 49228679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 49331343Sbrian "Display this message", "help|? [command]", Commands}, 49428679Sbrian {NULL, NULL, NULL}, 4956059Samurai}; 4966059Samurai 49728536Sbrianstatic int 49831343SbrianShowEscape(struct cmdargs const *arg) 4996059Samurai{ 50036285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 50136285Sbrian int code, bit; 50236285Sbrian const char *sep = ""; 5036059Samurai 50426516Sbrian for (code = 0; code < 32; code++) 50536285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 50628679Sbrian for (bit = 0; bit < 8; bit++) 50736285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 50836285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 50936285Sbrian sep = ", "; 51036285Sbrian } 51136285Sbrian prompt_Printf(arg->prompt, "\n"); 5126059Samurai } 51331077Sbrian return 0; 5146059Samurai} 5156059Samurai 51628679Sbrianstatic int 51736285SbrianShowTimerList(struct cmdargs const *arg) 5186059Samurai{ 51936285Sbrian timer_Show(0, arg->prompt); 52031077Sbrian return 0; 5216059Samurai} 5226059Samurai 52328679Sbrianstatic int 52431343SbrianShowStopped(struct cmdargs const *arg) 52528327Sbrian{ 52636285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 52736285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 52836285Sbrian prompt_Printf(arg->prompt, "Disabled"); 52928327Sbrian else 53036285Sbrian prompt_Printf(arg->prompt, "%ld secs", 53136285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 53228461Sbrian 53336285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 53436285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 53536285Sbrian prompt_Printf(arg->prompt, "Disabled"); 53628461Sbrian else 53736285Sbrian prompt_Printf(arg->prompt, "%ld secs", 53836285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 53928461Sbrian 54036285Sbrian prompt_Printf(arg->prompt, "\n"); 54128461Sbrian 54231077Sbrian return 0; 54328327Sbrian} 54428327Sbrian 54528679Sbrianstatic int 54631343SbrianShowVersion(struct cmdargs const *arg) 5476059Samurai{ 54836285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 54931077Sbrian return 0; 5506059Samurai} 5516059Samurai 55228679Sbrianstatic int 55336285SbrianShowProtocolStats(struct cmdargs const *arg) 55426326Sbrian{ 55536285Sbrian struct link *l = command_ChooseLink(arg); 55626326Sbrian 55736285Sbrian if (!l) 55836285Sbrian return -1; 55936285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 56036285Sbrian link_ReportProtocolStatus(l, arg->prompt); 56131077Sbrian return 0; 56226326Sbrian} 56326326Sbrian 56430715Sbrianstatic struct cmdtab const ShowCommands[] = { 56536285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 56636285Sbrian "bundle details", "show bundle"}, 56736285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 56836285Sbrian "CCP status", "show cpp"}, 56936285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 57036285Sbrian "VJ compression stats", "show compress"}, 57136285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 57236285Sbrian "escape characters", "show escape"}, 57336285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 57436285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 57536285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 57636285Sbrian "HDLC errors", "show hdlc"}, 57736285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 57836285Sbrian "IPCP status", "show ipcp"}, 57936285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 58036285Sbrian "LCP status", "show lcp"}, 58136285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 58236285Sbrian "(high-level) link info", "show link"}, 58336285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 58436285Sbrian "available link names", "show links"}, 58536285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 58636285Sbrian "log levels", "show log"}, 58736285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 58836285Sbrian "mbuf allocations", "show mem"}, 58936285Sbrian {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 59036285Sbrian "(low-level) link info", "show modem"}, 59136285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 59236285Sbrian "multilink setup", "show mp"}, 59336285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 59436285Sbrian "protocol summary", "show proto"}, 59536285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 59636285Sbrian "routing table", "show route"}, 59736285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 59836285Sbrian "STOPPED timeout", "show stopped"}, 59936285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 60036285Sbrian "alarm timers", "show timers"}, 60128679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 60236285Sbrian "version string", "show version"}, 60336285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 60436285Sbrian "client list", "show who"}, 60528679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 60631343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 60728679Sbrian {NULL, NULL, NULL}, 6086059Samurai}; 6096059Samurai 61030715Sbrianstatic struct cmdtab const * 61131343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 6126059Samurai{ 61326516Sbrian int nmatch; 61426516Sbrian int len; 61528679Sbrian struct cmdtab const *found; 6166059Samurai 61726516Sbrian found = NULL; 61826516Sbrian len = strlen(str); 61926516Sbrian nmatch = 0; 6206059Samurai while (cmds->func) { 62125566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 62226516Sbrian if (cmds->name[len] == '\0') { 62328679Sbrian *pmatch = 1; 62428679Sbrian return cmds; 62526516Sbrian } 6266059Samurai nmatch++; 6276059Samurai found = cmds; 62828679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 62926516Sbrian if (cmds->alias[len] == '\0') { 63028679Sbrian *pmatch = 1; 63128679Sbrian return cmds; 63226516Sbrian } 6336059Samurai nmatch++; 6346059Samurai found = cmds; 6356059Samurai } 6366059Samurai cmds++; 6376059Samurai } 6386059Samurai *pmatch = nmatch; 63926516Sbrian return found; 6406059Samurai} 6416059Samurai 64236285Sbrianstatic const char * 64336285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 64436285Sbrian{ 64536285Sbrian int f, tlen, len; 64636285Sbrian 64736285Sbrian tlen = 0; 64836285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 64936285Sbrian if (f) 65036285Sbrian tgt[tlen++] = ' '; 65136285Sbrian len = strlen(argv[f]); 65236285Sbrian if (len > sz - tlen - 1) 65336285Sbrian len = sz - tlen - 1; 65436285Sbrian strncpy(tgt+tlen, argv[f], len); 65536285Sbrian tlen += len; 65636285Sbrian } 65736285Sbrian tgt[tlen] = '\0'; 65836285Sbrian return tgt; 65936285Sbrian} 66036285Sbrian 66130715Sbrianstatic int 66236285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 66336285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 6646059Samurai{ 66528679Sbrian struct cmdtab const *cmd; 6666059Samurai int val = 1; 6676059Samurai int nmatch; 66831343Sbrian struct cmdargs arg; 66936285Sbrian char prefix[100]; 6706059Samurai 67136285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 6726059Samurai if (nmatch > 1) 67336285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 67436285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 67536285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 67636285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 67736285Sbrian /* We've got no context, but we require it */ 67836285Sbrian cx = bundle2datalink(bundle, NULL); 67936285Sbrian 68036285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 68136285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 68236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 68336285Sbrian else { 68436285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 68536285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 68636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 68736285Sbrian cx = NULL; 68836285Sbrian } 68936285Sbrian arg.cmdtab = cmds; 69036285Sbrian arg.cmd = cmd; 69136285Sbrian arg.argc = argc; 69236285Sbrian arg.argn = argn+1; 69336285Sbrian arg.argv = argv; 69436285Sbrian arg.bundle = bundle; 69536285Sbrian arg.cx = cx; 69636285Sbrian arg.prompt = prompt; 69736285Sbrian val = (*cmd->func) (&arg); 69836285Sbrian } 69931343Sbrian } else 70036285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 70136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 70226516Sbrian 70326516Sbrian if (val == -1) 70436285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 70528679Sbrian else if (val) 70636285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 70736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 70826516Sbrian 70926516Sbrian return val; 7106059Samurai} 7116059Samurai 71237009Sbrianint 71337009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 7146059Samurai{ 7156059Samurai char *cp; 7166059Samurai 7176059Samurai if (nb > 0) { 7186059Samurai cp = buff + strcspn(buff, "\r\n"); 7196059Samurai if (cp) 7206059Samurai *cp = '\0'; 72137009Sbrian return MakeArgs(buff, argv, MAXARGS); 72237009Sbrian } 72337009Sbrian return 0; 72431121Sbrian} 7256059Samurai 72631822Sbrianstatic int 72731822Sbrianarghidden(int argc, char const *const *argv, int n) 72831822Sbrian{ 72931822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 73031828Sbrian 73131828Sbrian /* set authkey xxxxx */ 73231828Sbrian /* set key xxxxx */ 73331822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 73431822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 73531822Sbrian return 1; 73631822Sbrian 73731828Sbrian /* passwd xxxxx */ 73831828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 73931828Sbrian return 1; 74031828Sbrian 74136285Sbrian /* set server port xxxxx .... */ 74236285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 74336285Sbrian !strncasecmp(argv[1], "se", 2)) 74436285Sbrian return 1; 74536285Sbrian 74631822Sbrian return 0; 74731822Sbrian} 74831822Sbrian 74931121Sbrianvoid 75036285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 75137008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 75231121Sbrian{ 75331156Sbrian if (argc > 0) { 75436285Sbrian if (log_IsKept(LogCOMMAND)) { 75531156Sbrian static char buf[LINE_LEN]; 75631156Sbrian int f, n; 75731156Sbrian 75831156Sbrian *buf = '\0'; 75931156Sbrian if (label) { 76031962Sbrian strncpy(buf, label, sizeof buf - 3); 76131962Sbrian buf[sizeof buf - 3] = '\0'; 76231156Sbrian strcat(buf, ": "); 76331156Sbrian } 76431156Sbrian n = strlen(buf); 76531156Sbrian for (f = 0; f < argc; f++) { 76631962Sbrian if (n < sizeof buf - 1 && f) 76731156Sbrian buf[n++] = ' '; 76831822Sbrian if (arghidden(argc, argv, f)) 76936285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 77031822Sbrian else 77131962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 77231156Sbrian n += strlen(buf+n); 77331156Sbrian } 77436285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 77531156Sbrian } 77637008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 77731156Sbrian } 7786059Samurai} 7796059Samurai 78031121Sbrianvoid 78136285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 78236285Sbrian const char *label) 78331121Sbrian{ 78431121Sbrian int argc; 78537009Sbrian char *argv[MAXARGS]; 78631121Sbrian 78737009Sbrian argc = command_Interpret(buff, nb, argv); 78837008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 78931121Sbrian} 79031121Sbrian 7916059Samuraistatic int 79231343SbrianShowCommand(struct cmdargs const *arg) 7936059Samurai{ 79436285Sbrian if (!arg->prompt) 79536285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 79636285Sbrian else if (arg->argc > arg->argn) 79736285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 79836285Sbrian arg->prompt, arg->cx); 7996059Samurai else 80036285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 80126516Sbrian 80226516Sbrian return 0; 8036059Samurai} 8046059Samurai 8056059Samuraistatic int 80631343SbrianTerminalCommand(struct cmdargs const *arg) 8076059Samurai{ 80836285Sbrian if (!arg->prompt) { 80936285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 81026516Sbrian return 1; 8116059Samurai } 81236285Sbrian 81336285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 81436285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 81536285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 81636285Sbrian return 1; 8176059Samurai } 81836285Sbrian 81936285Sbrian datalink_Up(arg->cx, 0, 0); 82036285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 82136285Sbrian return 0; 8226059Samurai} 8236059Samurai 8246059Samuraistatic int 82531343SbrianQuitCommand(struct cmdargs const *arg) 8266059Samurai{ 82736285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 82836285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 82936285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 83036285Sbrian Cleanup(EX_NORMAL); 83136285Sbrian if (arg->prompt) 83236285Sbrian prompt_Destroy(arg->prompt, 1); 83326516Sbrian 83426516Sbrian return 0; 8356059Samurai} 8366059Samurai 8376059Samuraistatic int 83836285SbrianOpenCommand(struct cmdargs const *arg) 8396059Samurai{ 84036285Sbrian if (arg->argc == arg->argn || 84136285Sbrian (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp"))) 84236285Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 84336285Sbrian else if (arg->argc == arg->argn+1 && 84436285Sbrian !strcasecmp(arg->argv[arg->argn], "ccp")) { 84536285Sbrian struct link *l; 84636285Sbrian struct fsm *fp; 8476059Samurai 84836285Sbrian if (!(l = command_ChooseLink(arg))) 84936285Sbrian return -1; 85036285Sbrian fp = &l->ccp.fsm; 85136285Sbrian 85236285Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 85336285Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 85436285Sbrian else if (fp->state != ST_OPENED) { 85536285Sbrian fp->open_mode = 0; /* Not passive any more */ 85636285Sbrian if (fp->state == ST_STOPPED) { 85736285Sbrian fsm_Down(fp); 85836285Sbrian fsm_Up(fp); 85936285Sbrian } else { 86036285Sbrian fsm_Up(fp); 86136285Sbrian fsm_Open(fp); 86236285Sbrian } 86336285Sbrian } 86436285Sbrian } else 86536285Sbrian return -1; 86636285Sbrian 86726516Sbrian return 0; 8686059Samurai} 8696059Samurai 87025067Sbrianstatic int 87136285SbrianCloseCommand(struct cmdargs const *arg) 8726059Samurai{ 87337007Sbrian if (arg->argc == arg->argn) 87437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 87537007Sbrian else if (arg->argc == arg->argn + 1) { 87637007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 87737007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 87837007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 87937007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 88037007Sbrian struct link *l; 88137007Sbrian struct fsm *fp; 8826059Samurai 88337007Sbrian if (!(l = command_ChooseLink(arg))) 88437007Sbrian return -1; 88537007Sbrian fp = &l->ccp.fsm; 88637007Sbrian 88737007Sbrian if (fp->state == ST_OPENED) { 88837007Sbrian fsm_Close(fp); 88937007Sbrian if (arg->argv[arg->argn][3] == '!') 89037007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 89137007Sbrian else 89237007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 89337007Sbrian } 89437007Sbrian } else 89536285Sbrian return -1; 89636285Sbrian } else 89736285Sbrian return -1; 89836285Sbrian 89936285Sbrian return 0; 9006059Samurai} 9016059Samurai 90225067Sbrianstatic int 90336285SbrianDownCommand(struct cmdargs const *arg) 90411336Samurai{ 90536285Sbrian if (arg->argc == arg->argn || 90636285Sbrian (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp"))) { 90736285Sbrian if (arg->cx) 90837007Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 90936285Sbrian else 91036285Sbrian bundle_Down(arg->bundle); 91136285Sbrian } else if (arg->argc == arg->argn+1 && 91236285Sbrian !strcasecmp(arg->argv[arg->argn], "ccp")) { 91336285Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 91436285Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 91536285Sbrian fsm_Down(fp); 91636285Sbrian fsm_Close(fp); 91736285Sbrian } else 91836285Sbrian return -1; 91936285Sbrian 92036285Sbrian return 0; 92125067Sbrian} 92225067Sbrian 92325067Sbrianstatic int 92436285SbrianSetModemSpeed(struct cmdargs const *arg) 92525067Sbrian{ 92636285Sbrian long speed; 92736285Sbrian char *end; 92811336Samurai 92936285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 93036285Sbrian if (arg->argc > arg->argn+1) { 93136285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 93236285Sbrian return -1; 93311336Samurai } 93436285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 93536285Sbrian physical_SetSync(arg->cx->physical); 93636285Sbrian return 0; 93736285Sbrian } 93836285Sbrian end = NULL; 93936285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 94036285Sbrian if (*end) { 94136285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 94236285Sbrian arg->argv[arg->argn]); 94336285Sbrian return -1; 94436285Sbrian } 94536285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 94636285Sbrian return 0; 94736285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 94836285Sbrian } else 94936285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 95024939Sbrian 95126516Sbrian return -1; 95211336Samurai} 95311336Samurai 95425067Sbrianstatic int 95531343SbrianSetStoppedTimeout(struct cmdargs const *arg) 95628327Sbrian{ 95736285Sbrian struct link *l = &arg->cx->physical->link; 95836285Sbrian 95936285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 96036285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 96136285Sbrian if (arg->argc <= arg->argn+2) { 96236285Sbrian if (arg->argc > arg->argn) { 96336285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 96436285Sbrian if (arg->argc > arg->argn+1) 96536285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 96628461Sbrian } 96728327Sbrian return 0; 96828327Sbrian } 96928327Sbrian return -1; 97028327Sbrian} 97128327Sbrian 97231081Sbrian#define ismask(x) \ 97331081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 97431081Sbrian 97528327Sbrianstatic int 97631343SbrianSetServer(struct cmdargs const *arg) 97726940Sbrian{ 97826940Sbrian int res = -1; 97926940Sbrian 98036285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 98131081Sbrian const char *port, *passwd, *mask; 98231081Sbrian 98331081Sbrian /* What's what ? */ 98436285Sbrian port = arg->argv[arg->argn]; 98536285Sbrian if (arg->argc == arg->argn + 2) { 98636285Sbrian passwd = arg->argv[arg->argn+1]; 98736285Sbrian mask = NULL; 98836285Sbrian } else if (arg->argc == arg->argn + 3) { 98936285Sbrian passwd = arg->argv[arg->argn+1]; 99036285Sbrian mask = arg->argv[arg->argn+2]; 99131081Sbrian if (!ismask(mask)) 99231081Sbrian return -1; 99336285Sbrian } else if (strcasecmp(port, "none") == 0) { 99436285Sbrian if (server_Close(arg->bundle)) 99536285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 99636285Sbrian return 0; 99731081Sbrian } else 99836285Sbrian return -1; 99931081Sbrian 100036285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 100136285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 100231081Sbrian 100336285Sbrian if (*port == '/') { 100431081Sbrian mode_t imask; 100536285Sbrian char *ptr, name[LINE_LEN + 12]; 100628679Sbrian 100731081Sbrian if (mask != NULL) { 100828679Sbrian unsigned m; 100928679Sbrian 101031081Sbrian if (sscanf(mask, "%o", &m) == 1) 101131081Sbrian imask = m; 101231081Sbrian else 101331081Sbrian return -1; 101431081Sbrian } else 101531081Sbrian imask = (mode_t)-1; 101636285Sbrian 101736285Sbrian ptr = strstr(port, "%d"); 101836285Sbrian if (ptr) { 101936285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 102036285Sbrian ptr - port, port, arg->bundle->unit, ptr + 2); 102136285Sbrian port = name; 102236285Sbrian } 102336285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 102427346Sbrian } else { 102536285Sbrian int iport, add = 0; 102628679Sbrian 102731081Sbrian if (mask != NULL) 102831081Sbrian return -1; 102928679Sbrian 103036285Sbrian if (*port == '+') { 103136285Sbrian port++; 103236285Sbrian add = 1; 103336285Sbrian } 103431081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 103531081Sbrian struct servent *s; 103631081Sbrian 103731081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 103831081Sbrian iport = 0; 103936285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 104028679Sbrian } else 104131081Sbrian iport = ntohs(s->s_port); 104227346Sbrian } else 104331081Sbrian iport = atoi(port); 104436285Sbrian 104536285Sbrian if (iport) { 104636285Sbrian if (add) 104736285Sbrian iport += arg->bundle->unit; 104836285Sbrian res = server_TcpOpen(arg->bundle, iport); 104936285Sbrian } else 105036285Sbrian res = -1; 105127346Sbrian } 105231081Sbrian } 105326940Sbrian 105426940Sbrian return res; 105526940Sbrian} 105626940Sbrian 105726940Sbrianstatic int 105831343SbrianSetModemParity(struct cmdargs const *arg) 10596059Samurai{ 106036285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 106136285Sbrian arg->argv[arg->argn]) : -1; 10626059Samurai} 10636059Samurai 10646059Samuraistatic int 106531343SbrianSetEscape(struct cmdargs const *arg) 10666059Samurai{ 10676059Samurai int code; 106836285Sbrian int argc = arg->argc - arg->argn; 106936285Sbrian char const *const *argv = arg->argv + arg->argn; 10706059Samurai 10716059Samurai for (code = 0; code < 33; code++) 107236285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 107331343Sbrian 10746059Samurai while (argc-- > 0) { 10756059Samurai sscanf(*argv++, "%x", &code); 10766059Samurai code &= 0xff; 107736285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 107836285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 10796059Samurai } 108026516Sbrian return 0; 10816059Samurai} 10826059Samurai 108330715Sbrianstatic struct in_addr 108431343SbrianGetIpAddr(const char *cp) 10856059Samurai{ 10866059Samurai struct hostent *hp; 10876059Samurai struct in_addr ipaddr; 10886059Samurai 108932124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 109032124Sbrian hp = gethostbyname(cp); 109132124Sbrian if (hp && hp->h_addrtype == AF_INET) 109232124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 109332124Sbrian else 109432124Sbrian ipaddr.s_addr = 0; 109532124Sbrian } 109628679Sbrian return (ipaddr); 10976059Samurai} 10986059Samurai 10996059Samuraistatic int 110031343SbrianSetInterfaceAddr(struct cmdargs const *arg) 11016059Samurai{ 110236285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 110332267Sbrian const char *hisaddr; 110432267Sbrian 110532267Sbrian hisaddr = NULL; 110636285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 110736285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 11086059Samurai 110936285Sbrian if (arg->argc > arg->argn + 4) 111028679Sbrian return -1; 111126516Sbrian 111236285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 111336285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 111436285Sbrian iplist_reset(&ipcp->cfg.peer_list); 111528394Sbrian 111636285Sbrian if (arg->argc > arg->argn) { 111736285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 111836285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 111936285Sbrian &ipcp->cfg.my_range.width)) 112028679Sbrian return 1; 112136285Sbrian if (arg->argc > arg->argn+1) { 112236285Sbrian hisaddr = arg->argv[arg->argn+1]; 112336285Sbrian if (arg->argc > arg->argn+2) { 112436285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 112536285Sbrian if (arg->argc > arg->argn+3) { 112636285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 112736285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 11289440Samurai } 11296059Samurai } 11306059Samurai } 11316059Samurai } 113228394Sbrian 11336059Samurai /* 11346059Samurai * For backwards compatibility, 0.0.0.0 means any address. 11356059Samurai */ 113636285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 113736285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 113836285Sbrian ipcp->cfg.my_range.width = 0; 11396059Samurai } 114036285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 114136285Sbrian 114236285Sbrian if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 114336285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 114436285Sbrian ipcp->cfg.peer_range.width = 0; 11456059Samurai } 114628537Sbrian 114736285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 114836928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 114932267Sbrian return 4; 115031121Sbrian 115126516Sbrian return 0; 11526059Samurai} 11536059Samurai 115418752Sjkhstatic int 115531343SbrianSetVariable(struct cmdargs const *arg) 11566059Samurai{ 115736285Sbrian u_long ulong_val; 115831343Sbrian const char *argp; 115936285Sbrian int param = (int)arg->cmd->args, mode; 116036285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 116136285Sbrian const char *err = NULL; 116236285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 116336285Sbrian int dummyint; 116436285Sbrian struct in_addr dummyaddr, *addr; 11656059Samurai 116636285Sbrian if (!l) 116736285Sbrian return -1; 116836285Sbrian 116936285Sbrian if (arg->argc > arg->argn) 117036285Sbrian argp = arg->argv[arg->argn]; 117126551Sbrian else 117231343Sbrian argp = ""; 117326551Sbrian 117436285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 117536285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 117636285Sbrian arg->cmd->name); 117736285Sbrian return 1; 117836285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 117936285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 118036285Sbrian arg->cmd->name, cx->name); 118136285Sbrian cx = NULL; 118236285Sbrian } 118336285Sbrian 118426551Sbrian switch (param) { 118528679Sbrian case VAR_AUTHKEY: 118636285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 118736285Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 118836285Sbrian sizeof arg->bundle->cfg.auth.key - 1); 118936285Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 119036285Sbrian } else { 119136285Sbrian err = "set authkey: Only available at phase DEAD\n"; 119236285Sbrian log_Printf(LogWARN, err); 119336285Sbrian } 119428679Sbrian break; 119528679Sbrian case VAR_AUTHNAME: 119636285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 119736285Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 119836285Sbrian sizeof arg->bundle->cfg.auth.name - 1); 119936285Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 120036285Sbrian } else { 120136285Sbrian err = "set authname: Only available at phase DEAD\n"; 120236285Sbrian log_Printf(LogWARN, err); 120336285Sbrian } 120428679Sbrian break; 120536285Sbrian case VAR_AUTOLOAD: 120636285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 120736285Sbrian arg->bundle->autoload.running = 1; 120836285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 120936285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 121036285Sbrian if (arg->argc == arg->argn + 4) { 121136285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 121236285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 121336285Sbrian } else { 121436285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 121536285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 121636285Sbrian } 121736285Sbrian } else { 121836285Sbrian err = "Set autoload requires two or four arguments\n"; 121936285Sbrian log_Printf(LogWARN, err); 122036285Sbrian } 122136285Sbrian break; 122228679Sbrian case VAR_DIAL: 122336285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 122436285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 122528679Sbrian break; 122628679Sbrian case VAR_LOGIN: 122736285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 122836285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 122928679Sbrian break; 123036285Sbrian case VAR_WINSIZE: 123136285Sbrian if (arg->argc > arg->argn) { 123236285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 123336285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 123436285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 123536285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 123636285Sbrian l->ccp.cfg.deflate.out.winsize); 123736285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 123836285Sbrian } 123936285Sbrian if (arg->argc > arg->argn+1) { 124036285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 124136285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 124236285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 124336285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 124436285Sbrian l->ccp.cfg.deflate.in.winsize); 124536285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 124636285Sbrian } 124736285Sbrian } else 124836285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 124936285Sbrian } else { 125036285Sbrian err = "No window size specified\n"; 125136285Sbrian log_Printf(LogWARN, err); 125236285Sbrian } 125336285Sbrian break; 125428679Sbrian case VAR_DEVICE: 125536285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 125636285Sbrian arg->argv + arg->argn); 125736285Sbrian break; 125836285Sbrian case VAR_ACCMAP: 125936285Sbrian if (arg->argc > arg->argn) { 126036285Sbrian sscanf(argp, "%lx", &ulong_val); 126136285Sbrian cx->physical->link.lcp.cfg.accmap = ulong_val; 126236285Sbrian } else { 126336285Sbrian err = "No accmap specified\n"; 126436285Sbrian log_Printf(LogWARN, err); 126536285Sbrian } 126636285Sbrian break; 126736285Sbrian case VAR_MODE: 126836285Sbrian mode = Nam2mode(argp); 126936285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 127036285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 127136285Sbrian return -1; 127236285Sbrian } 127336285Sbrian bundle_SetMode(arg->bundle, cx, mode); 127436285Sbrian break; 127536285Sbrian case VAR_MRRU: 127636285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 127736285Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); 127829696Sbrian else { 127936285Sbrian ulong_val = atol(argp); 128036285Sbrian if (ulong_val < MIN_MRU) 128136285Sbrian err = "Given MRRU value (%lu) is too small.\n"; 128236285Sbrian else if (ulong_val > MAX_MRU) 128336285Sbrian err = "Given MRRU value (%lu) is too big.\n"; 128436285Sbrian else 128536285Sbrian arg->bundle->ncp.mp.cfg.mrru = ulong_val; 128636285Sbrian if (err) 128736285Sbrian log_Printf(LogWARN, err, ulong_val); 128829696Sbrian } 128928679Sbrian break; 129036285Sbrian case VAR_MRU: 129136285Sbrian ulong_val = atol(argp); 129236285Sbrian if (ulong_val < MIN_MRU) 129336285Sbrian err = "Given MRU value (%lu) is too small.\n"; 129436285Sbrian else if (ulong_val > MAX_MRU) 129536285Sbrian err = "Given MRU value (%lu) is too big.\n"; 129636285Sbrian else 129736285Sbrian l->lcp.cfg.mru = ulong_val; 129836285Sbrian if (err) 129936285Sbrian log_Printf(LogWARN, err, ulong_val); 130028679Sbrian break; 130136285Sbrian case VAR_MTU: 130236285Sbrian ulong_val = atol(argp); 130336285Sbrian if (ulong_val == 0) 130436285Sbrian arg->bundle->cfg.mtu = 0; 130536285Sbrian else if (ulong_val < MIN_MTU) 130636285Sbrian err = "Given MTU value (%lu) is too small.\n"; 130736285Sbrian else if (ulong_val > MAX_MTU) 130836285Sbrian err = "Given MTU value (%lu) is too big.\n"; 130936285Sbrian else 131036285Sbrian arg->bundle->cfg.mtu = ulong_val; 131136285Sbrian if (err) 131236285Sbrian log_Printf(LogWARN, err, ulong_val); 131336285Sbrian break; 131436285Sbrian case VAR_OPENMODE: 131536285Sbrian if (strcasecmp(argp, "active") == 0) 131636285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 131736285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 131836285Sbrian else if (strcasecmp(argp, "passive") == 0) 131936285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 132036285Sbrian else { 132136285Sbrian err = "%s: Invalid openmode\n"; 132236285Sbrian log_Printf(LogWARN, err, argp); 132336285Sbrian } 132436285Sbrian break; 132528679Sbrian case VAR_PHONE: 132636285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 132736285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 132828679Sbrian break; 132928679Sbrian case VAR_HANGUP: 133036285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 133136285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 133228679Sbrian break; 133336285Sbrian case VAR_IDLETIMEOUT: 133436285Sbrian if (arg->argc > arg->argn+1) 133536285Sbrian err = "Too many idle timeout values\n"; 133636285Sbrian else if (arg->argc == arg->argn+1) 133736285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 133836285Sbrian if (err) 133936285Sbrian log_Printf(LogWARN, err); 134029549Sbrian break; 134136285Sbrian case VAR_LQRPERIOD: 134236285Sbrian ulong_val = atol(argp); 134336285Sbrian if (ulong_val <= 0) { 134436285Sbrian err = "%s: Invalid lqr period\n"; 134536285Sbrian log_Printf(LogWARN, err, argp); 134636285Sbrian } else 134736285Sbrian l->lcp.cfg.lqrperiod = ulong_val; 134836285Sbrian break; 134936285Sbrian case VAR_LCPRETRY: 135036285Sbrian ulong_val = atol(argp); 135136285Sbrian if (ulong_val <= 0) { 135236285Sbrian err = "%s: Invalid LCP FSM retry period\n"; 135336285Sbrian log_Printf(LogWARN, err, argp); 135436285Sbrian } else 135536285Sbrian cx->physical->link.lcp.cfg.fsmretry = ulong_val; 135636285Sbrian break; 135736285Sbrian case VAR_CHAPRETRY: 135836285Sbrian ulong_val = atol(argp); 135936285Sbrian if (ulong_val <= 0) { 136036285Sbrian err = "%s: Invalid CHAP retry period\n"; 136136285Sbrian log_Printf(LogWARN, err, argp); 136236285Sbrian } else 136336285Sbrian cx->chap.auth.cfg.fsmretry = ulong_val; 136436285Sbrian break; 136536285Sbrian case VAR_PAPRETRY: 136636285Sbrian ulong_val = atol(argp); 136736285Sbrian if (ulong_val <= 0) { 136836285Sbrian err = "%s: Invalid PAP retry period\n"; 136936285Sbrian log_Printf(LogWARN, err, argp); 137036285Sbrian } else 137136285Sbrian cx->pap.cfg.fsmretry = ulong_val; 137236285Sbrian break; 137336285Sbrian case VAR_CCPRETRY: 137436285Sbrian ulong_val = atol(argp); 137536285Sbrian if (ulong_val <= 0) { 137636285Sbrian err = "%s: Invalid CCP FSM retry period\n"; 137736285Sbrian log_Printf(LogWARN, err, argp); 137836285Sbrian } else 137936285Sbrian l->ccp.cfg.fsmretry = ulong_val; 138036285Sbrian break; 138136285Sbrian case VAR_IPCPRETRY: 138236285Sbrian ulong_val = atol(argp); 138336285Sbrian if (ulong_val <= 0) { 138436285Sbrian err = "%s: Invalid IPCP FSM retry period\n"; 138536285Sbrian log_Printf(LogWARN, err, argp); 138636285Sbrian } else 138736285Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = ulong_val; 138836285Sbrian break; 138936285Sbrian case VAR_NBNS: 139036285Sbrian case VAR_DNS: 139136285Sbrian if (param == VAR_DNS) 139236285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 139336285Sbrian else 139436285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 139536285Sbrian 139636285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 139736285Sbrian 139836285Sbrian if (arg->argc > arg->argn) { 139936285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 140036285Sbrian addr, &dummyaddr, &dummyint); 140136285Sbrian if (arg->argc > arg->argn+1) 140236285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 140336285Sbrian addr + 1, &dummyaddr, &dummyint); 140436285Sbrian 140536285Sbrian if (addr[1].s_addr == INADDR_ANY) 140636285Sbrian addr[1].s_addr = addr[0].s_addr; 140736285Sbrian if (addr[0].s_addr == INADDR_ANY) 140836285Sbrian addr[0].s_addr = addr[1].s_addr; 140936285Sbrian } 141036285Sbrian break; 14116059Samurai } 141236285Sbrian 141336285Sbrian return err ? 1 : 0; 14146059Samurai} 14156059Samurai 141628679Sbrianstatic int 141731343SbrianSetCtsRts(struct cmdargs const *arg) 141820812Sjkh{ 141936285Sbrian if (arg->argc == arg->argn+1) { 142036285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 142136285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 142236285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 142336285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 142420812Sjkh else 142526516Sbrian return -1; 142626516Sbrian return 0; 142720812Sjkh } 142826516Sbrian return -1; 142920812Sjkh} 143020812Sjkh 143130715Sbrianstatic struct cmdtab const SetCommands[] = { 143236285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 143336285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 143428679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 143536285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 143628679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 143736285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 143836285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 143936285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 144036285Sbrian (const void *)VAR_AUTOLOAD}, 144136285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 144236285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 144336285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 144436285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 144536285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 144636285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 144736285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 144836285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 144936285Sbrian (const void *) VAR_WINSIZE}, 145036285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 145136285Sbrian "modem device name", "set device|line device-name[,device-name]", 145236285Sbrian (const void *) VAR_DEVICE}, 145336285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 145436285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 145536285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 145636285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 145736285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 145836285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 145936285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 146036285Sbrian "escape characters", "set escape hex-digit ..."}, 146136285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 146236285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 146336285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 146436285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 146536285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 146636285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 146736285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 146831343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 146936285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 147036285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 147136285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 147236285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 147336712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 147436712Sbrian "set log [local] [+|-]async|ccp|chat|command|connect|debug|hdlc|id0|ipcp|" 147536712Sbrian "lcp|lqm|phase|tcp/ip|timer|tun..."}, 147636285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 147736285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 147836285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 147936285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 148036285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 148136285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 148236285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 148336285Sbrian "set mrru value", (const void *)VAR_MRRU}, 148436285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 148536285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 148636285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 148736285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 148836285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 148936285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 149036285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 149136285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 149236285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 149336285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 149436285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 149536285Sbrian "modem parity", "set parity [odd|even|none]"}, 149636285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 149736285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 149836285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 149936285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 150036285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 150136285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 150228679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 150336774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 150436285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 150536285Sbrian "modem speed", "set speed value"}, 150636285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 150736285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 150836285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 150936285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 151036285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 151136285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 151236285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 151336285Sbrian "datalink weighting", "set weight n"}, 151428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 151531343Sbrian "Display this message", "set help|? [command]", SetCommands}, 151628679Sbrian {NULL, NULL, NULL}, 15176059Samurai}; 15186059Samurai 15196059Samuraistatic int 152031343SbrianSetCommand(struct cmdargs const *arg) 15216059Samurai{ 152236285Sbrian if (arg->argc > arg->argn) 152336285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 152436285Sbrian arg->prompt, arg->cx); 152536285Sbrian else if (arg->prompt) 152636285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 152726516Sbrian " syntax help.\n"); 15286059Samurai else 152936285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 153026516Sbrian 153126516Sbrian return 0; 15326059Samurai} 15336059Samurai 15346059Samurai 15356059Samuraistatic int 153631343SbrianAddCommand(struct cmdargs const *arg) 15376059Samurai{ 15386059Samurai struct in_addr dest, gateway, netmask; 153936285Sbrian int gw, addrs; 15406059Samurai 154136285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 154231598Sbrian return -1; 154331598Sbrian 154436285Sbrian addrs = 0; 154536285Sbrian if (arg->argc == arg->argn+2) { 154636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 154736285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 154831598Sbrian else { 154936285Sbrian int width; 155036285Sbrian 155136285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 155236285Sbrian &dest, &netmask, &width)) 155336285Sbrian return -1; 155436285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 155536285Sbrian addrs = ROUTE_DSTMYADDR; 155636285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 155736285Sbrian addrs = ROUTE_DSTHISADDR; 155831598Sbrian } 155936285Sbrian gw = 1; 156034536Sbrian } else { 156136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 156236285Sbrian addrs = ROUTE_DSTMYADDR; 156336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 156436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 156536285Sbrian addrs = ROUTE_DSTHISADDR; 156636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 156736285Sbrian } else 156836285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 156936285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 157031598Sbrian gw = 2; 15716059Samurai } 157236285Sbrian 157336285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 157436285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 157536285Sbrian addrs |= ROUTE_GWHISADDR; 157636285Sbrian } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0) 157731598Sbrian gateway.s_addr = INADDR_ANY; 157831598Sbrian else 157936285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 158036285Sbrian 158136285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 158236285Sbrian arg->cmd->args ? 1 : 0)) 158336285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 158436285Sbrian 158531598Sbrian return 0; 15866059Samurai} 15876059Samurai 15886059Samuraistatic int 158931343SbrianDeleteCommand(struct cmdargs const *arg) 15906059Samurai{ 159131598Sbrian struct in_addr dest, none; 159236285Sbrian int addrs; 15936059Samurai 159436285Sbrian if (arg->argc == arg->argn+1) { 159536285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 159636285Sbrian route_IfDelete(arg->bundle, 0); 159736285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 159836285Sbrian } else { 159936285Sbrian addrs = 0; 160036285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 160136285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 160236285Sbrian addrs = ROUTE_DSTMYADDR; 160336285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 160436285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 160536285Sbrian addrs = ROUTE_DSTHISADDR; 160636285Sbrian } else { 160736285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 160836285Sbrian dest.s_addr = INADDR_ANY; 160936285Sbrian else 161036285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 161136285Sbrian addrs = ROUTE_STATIC; 161236285Sbrian } 161331598Sbrian none.s_addr = INADDR_ANY; 161436285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 161536285Sbrian arg->cmd->args ? 1 : 0); 161636285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 161731598Sbrian } 161834536Sbrian } else 161926516Sbrian return -1; 162026516Sbrian 162126516Sbrian return 0; 16226059Samurai} 16236059Samurai 162431343Sbrian#ifndef NOALIAS 162526031Sbrianstatic struct cmdtab const AliasCommands[] = 162626031Sbrian{ 162736285Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 162836285Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 162936285Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 163036285Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 163136285Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 163228679Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 163336285Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 163428679Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 163536285Sbrian "log aliasing link creation", "alias log [yes|no]", 163636285Sbrian (const void *) PKT_ALIAS_LOG}, 163736285Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 163836285Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 163928679Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 164036285Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 164136285Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 164236285Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 164336285Sbrian "alias unregistered (private) IP address space only", 164436285Sbrian "alias unregistered_only [yes|no]", 164536285Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 164628679Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 164736285Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 164836285Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 164928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 165036285Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 165128679Sbrian {NULL, NULL, NULL}, 165226031Sbrian}; 165326031Sbrian 165426031Sbrian 165526031Sbrianstatic int 165631343SbrianAliasCommand(struct cmdargs const *arg) 165726031Sbrian{ 165836285Sbrian if (arg->argc > arg->argn) 165936285Sbrian FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv, 166036285Sbrian arg->prompt, arg->cx); 166136285Sbrian else if (arg->prompt) 166236285Sbrian prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 166336285Sbrian " <option>' for syntax help.\n"); 166426031Sbrian else 166536285Sbrian log_Printf(LogWARN, "alias command must have arguments\n"); 166626516Sbrian 166726516Sbrian return 0; 166826031Sbrian} 166926031Sbrian 167026031Sbrianstatic int 167131343SbrianAliasEnable(struct cmdargs const *arg) 167226031Sbrian{ 167336285Sbrian if (arg->argc == arg->argn+1) { 167436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 167536285Sbrian if (alias_Load() == 0) 167636285Sbrian return 0; 167736285Sbrian log_Printf(LogWARN, "Cannot load alias library\n"); 167836285Sbrian return 1; 167936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 168036285Sbrian alias_Unload(); 168126516Sbrian return 0; 168226142Sbrian } 168335449Sbrian } 168436285Sbrian 168526516Sbrian return -1; 168626031Sbrian} 168726031Sbrian 168826031Sbrian 168926031Sbrianstatic int 169031343SbrianAliasOption(struct cmdargs const *arg) 169126031Sbrian{ 169236285Sbrian unsigned param = (unsigned)arg->cmd->args; 169336285Sbrian if (arg->argc == arg->argn+1) { 169436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 169536285Sbrian if (alias_IsEnabled()) { 169636285Sbrian (*PacketAlias.SetMode)(param, param); 169728679Sbrian return 0; 169828679Sbrian } 169936285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 170036285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 170136285Sbrian if (alias_IsEnabled()) { 170236285Sbrian (*PacketAlias.SetMode)(0, param); 170328679Sbrian return 0; 170428679Sbrian } 170536285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 170628679Sbrian } 170735449Sbrian } 170828679Sbrian return -1; 170926031Sbrian} 171031343Sbrian#endif /* #ifndef NOALIAS */ 171131121Sbrian 171231121Sbrianstatic struct cmdtab const AllowCommands[] = { 171336285Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 171436285Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 171531121Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 171631121Sbrian "Allow users access to ppp", "allow users logname..."}, 171731121Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 171831343Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 171931121Sbrian {NULL, NULL, NULL}, 172031121Sbrian}; 172131121Sbrian 172231121Sbrianstatic int 172331343SbrianAllowCommand(struct cmdargs const *arg) 172431121Sbrian{ 172536285Sbrian /* arg->bundle may be NULL (see system_IsValid()) ! */ 172636285Sbrian if (arg->argc > arg->argn) 172736285Sbrian FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv, 172836285Sbrian arg->prompt, arg->cx); 172936285Sbrian else if (arg->prompt) 173036285Sbrian prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 173136285Sbrian " for syntax help.\n"); 173231121Sbrian else 173336285Sbrian log_Printf(LogWARN, "allow command must have arguments\n"); 173431121Sbrian 173531121Sbrian return 0; 173631121Sbrian} 173736285Sbrian 173836285Sbrianstatic int 173936285SbrianLinkCommand(struct cmdargs const *arg) 174036285Sbrian{ 174136285Sbrian if (arg->argc > arg->argn+1) { 174236285Sbrian char namelist[LINE_LEN]; 174336285Sbrian struct datalink *cx; 174436285Sbrian char *name; 174536285Sbrian int result = 0; 174636285Sbrian 174736285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 174836285Sbrian struct datalink *dl; 174936285Sbrian 175036285Sbrian cx = arg->bundle->links; 175136285Sbrian while (cx) { 175236285Sbrian /* Watch it, the command could be a ``remove'' */ 175336285Sbrian dl = cx->next; 175436285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 175536285Sbrian arg->prompt, cx); 175636285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 175736285Sbrian if (cx == dl) 175836285Sbrian break; /* Pointer's still valid ! */ 175936285Sbrian } 176036285Sbrian } else { 176136285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 176236285Sbrian namelist[sizeof namelist - 1] = '\0'; 176336285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 176436285Sbrian if (!bundle2datalink(arg->bundle, name)) { 176536285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 176636285Sbrian return 1; 176736285Sbrian } 176836285Sbrian 176936285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 177036285Sbrian namelist[sizeof namelist - 1] = '\0'; 177136285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 177236285Sbrian cx = bundle2datalink(arg->bundle, name); 177336285Sbrian if (cx) 177436285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 177536285Sbrian arg->prompt, cx); 177636285Sbrian else { 177736285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 177836285Sbrian result++; 177936285Sbrian } 178036285Sbrian } 178136285Sbrian } 178236285Sbrian return result; 178336285Sbrian } 178436285Sbrian 178536285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 178636285Sbrian return 2; 178736285Sbrian} 178836285Sbrian 178936285Sbrianstruct link * 179036285Sbriancommand_ChooseLink(struct cmdargs const *arg) 179136285Sbrian{ 179236285Sbrian if (arg->cx) 179336285Sbrian return &arg->cx->physical->link; 179436285Sbrian else if (arg->bundle->ncp.mp.cfg.mrru) 179536285Sbrian return &arg->bundle->ncp.mp.link; 179636285Sbrian else { 179736285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 179836285Sbrian return dl ? &dl->physical->link : NULL; 179936285Sbrian } 180036285Sbrian} 180136285Sbrian 180236285Sbrianstatic const char * 180336285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 180436285Sbrian{ 180536285Sbrian const char *result; 180636285Sbrian 180736285Sbrian switch (*cmd) { 180836285Sbrian case 'A': 180936285Sbrian case 'a': 181036285Sbrian result = "accept"; 181136285Sbrian *keep = NEG_MYMASK; 181236285Sbrian *add = NEG_ACCEPTED; 181336285Sbrian break; 181436285Sbrian case 'D': 181536285Sbrian case 'd': 181636285Sbrian switch (cmd[1]) { 181736285Sbrian case 'E': 181836285Sbrian case 'e': 181936285Sbrian result = "deny"; 182036285Sbrian *keep = NEG_MYMASK; 182136285Sbrian *add = 0; 182236285Sbrian break; 182336285Sbrian case 'I': 182436285Sbrian case 'i': 182536285Sbrian result = "disable"; 182636285Sbrian *keep = NEG_HISMASK; 182736285Sbrian *add = 0; 182836285Sbrian break; 182936285Sbrian default: 183036285Sbrian return NULL; 183136285Sbrian } 183236285Sbrian break; 183336285Sbrian case 'E': 183436285Sbrian case 'e': 183536285Sbrian result = "enable"; 183636285Sbrian *keep = NEG_HISMASK; 183736285Sbrian *add = NEG_ENABLED; 183836285Sbrian break; 183936285Sbrian default: 184036285Sbrian return NULL; 184136285Sbrian } 184236285Sbrian 184336285Sbrian return result; 184436285Sbrian} 184536285Sbrian 184636285Sbrianstatic int 184736285SbrianOptSet(struct cmdargs const *arg) 184836285Sbrian{ 184936285Sbrian int bit = (int)arg->cmd->args; 185036285Sbrian const char *cmd; 185136285Sbrian unsigned keep; /* Keep these bits */ 185236285Sbrian unsigned add; /* Add these bits */ 185336285Sbrian 185436285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 185536285Sbrian return 1; 185636285Sbrian 185736285Sbrian if (add) 185836285Sbrian arg->bundle->cfg.opt |= bit; 185936285Sbrian else 186036285Sbrian arg->bundle->cfg.opt &= ~bit; 186136285Sbrian return 0; 186236285Sbrian} 186336285Sbrian 186436285Sbrianstatic int 186536285SbrianNegotiateSet(struct cmdargs const *arg) 186636285Sbrian{ 186736285Sbrian int param = (int)arg->cmd->args; 186836285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 186936285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 187036285Sbrian const char *cmd; 187136285Sbrian unsigned keep; /* Keep these bits */ 187236285Sbrian unsigned add; /* Add these bits */ 187336285Sbrian 187436285Sbrian if (!l) 187536285Sbrian return -1; 187636285Sbrian 187736285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 187836285Sbrian return 1; 187936285Sbrian 188036285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 188136285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 188236285Sbrian cmd, arg->cmd->name); 188336285Sbrian return 2; 188436285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 188536285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 188636285Sbrian cmd, arg->cmd->name, cx->name); 188736285Sbrian cx = NULL; 188836285Sbrian } 188936285Sbrian 189036285Sbrian switch (param) { 189136285Sbrian case NEG_ACFCOMP: 189236285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 189336285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 189436285Sbrian break; 189536285Sbrian case NEG_CHAP: 189636285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 189736285Sbrian cx->physical->link.lcp.cfg.chap |= add; 189836285Sbrian break; 189936285Sbrian case NEG_DEFLATE: 190036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 190136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 190236285Sbrian break; 190336285Sbrian case NEG_DNS: 190436285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 190536285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 190636285Sbrian break; 190736285Sbrian case NEG_LQR: 190836285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 190936285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 191036285Sbrian break; 191136285Sbrian case NEG_PAP: 191236285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 191336285Sbrian cx->physical->link.lcp.cfg.pap |= add; 191436285Sbrian break; 191536285Sbrian case NEG_PPPDDEFLATE: 191636285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 191736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 191836285Sbrian break; 191936285Sbrian case NEG_PRED1: 192036285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 192136285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 192236285Sbrian break; 192336285Sbrian case NEG_PROTOCOMP: 192436285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 192536285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 192636285Sbrian break; 192736285Sbrian case NEG_SHORTSEQ: 192836285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 192936285Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); 193036285Sbrian else { 193136285Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 193236285Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 193336285Sbrian } 193436285Sbrian break; 193536285Sbrian case NEG_VJCOMP: 193636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 193736285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 193836285Sbrian break; 193936285Sbrian } 194036285Sbrian 194136285Sbrian return 0; 194236285Sbrian} 194336285Sbrian 194436285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 194536285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 194636285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 194736285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 194836285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 194936285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 195036285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 195136285Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", 195236285Sbrian "disable|enable", (const void *)OPT_PROXY}, 195336285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 195436285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 195536285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 195636285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 195736285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 195836285Sbrian "disable|enable", (const void *)OPT_UTMP}, 195936285Sbrian 196036285Sbrian#define OPT_MAX 7 /* accept/deny allowed below and not above */ 196136285Sbrian 196236285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 196336285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 196436285Sbrian (const void *)NEG_ACFCOMP}, 196536285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 196636285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 196736285Sbrian (const void *)NEG_CHAP}, 196836285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 196936285Sbrian "Deflate compression", "accept|deny|disable|enable", 197036285Sbrian (const void *)NEG_DEFLATE}, 197136285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 197236285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 197336285Sbrian (const void *)NEG_PPPDDEFLATE}, 197436285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 197536285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 197636285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 197736285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 197836285Sbrian (const void *)NEG_LQR}, 197936285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 198036285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 198136285Sbrian (const void *)NEG_PAP}, 198236285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 198336285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 198436285Sbrian (const void *)NEG_PRED1}, 198536285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 198636285Sbrian "Protocol field compression", "accept|deny|disable|enable", 198736285Sbrian (const void *)NEG_PROTOCOMP}, 198836285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 198936285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 199036285Sbrian (const void *)NEG_SHORTSEQ}, 199136285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 199236285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 199336285Sbrian (const void *)NEG_VJCOMP}, 199436285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 199536285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 199636285Sbrian NegotiateCommands}, 199736285Sbrian {NULL, NULL, NULL}, 199836285Sbrian}; 199936285Sbrian 200036285Sbrianstatic int 200136285SbrianNegotiateCommand(struct cmdargs const *arg) 200236285Sbrian{ 200336285Sbrian if (arg->argc > arg->argn) { 200436285Sbrian char const *argv[3]; 200536285Sbrian unsigned keep, add; 200636285Sbrian int n; 200736285Sbrian 200836285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 200936285Sbrian return -1; 201036285Sbrian argv[2] = NULL; 201136285Sbrian 201236285Sbrian for (n = arg->argn; n < arg->argc; n++) { 201336285Sbrian argv[1] = arg->argv[n]; 201436285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 201536285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 201636285Sbrian } 201736285Sbrian } else if (arg->prompt) 201836285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 201936285Sbrian arg->argv[arg->argn-1]); 202036285Sbrian else 202136285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 202236285Sbrian arg->argv[arg->argn] ); 202336285Sbrian 202436285Sbrian return 0; 202536285Sbrian} 202636285Sbrian 202736285Sbrianconst char * 202836285Sbriancommand_ShowNegval(unsigned val) 202936285Sbrian{ 203036285Sbrian switch (val&3) { 203136285Sbrian case 1: return "disabled & accepted"; 203236285Sbrian case 2: return "enabled & denied"; 203336285Sbrian case 3: return "enabled & accepted"; 203436285Sbrian } 203536285Sbrian return "disabled & denied"; 203636285Sbrian} 203736934Sbrian 203836934Sbrianstatic int 203936934SbrianClearCommand(struct cmdargs const *arg) 204036934Sbrian{ 204136934Sbrian struct pppThroughput *t; 204236934Sbrian struct datalink *cx; 204336934Sbrian int i, clear_type; 204436934Sbrian 204536934Sbrian if (arg->argc < arg->argn + 1) 204636934Sbrian return -1; 204736934Sbrian 204836934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 204936934Sbrian cx = arg->cx; 205036934Sbrian if (!cx) 205136934Sbrian cx = bundle2datalink(arg->bundle, NULL); 205236934Sbrian if (!cx) { 205336934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 205436934Sbrian return 1; 205536934Sbrian } 205636934Sbrian t = &cx->physical->link.throughput; 205736934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 205836934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 205936934Sbrian else 206036934Sbrian return -1; 206136934Sbrian 206236934Sbrian if (arg->argc > arg->argn + 1) { 206336934Sbrian clear_type = 0; 206436934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 206536934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 206636934Sbrian clear_type |= THROUGHPUT_OVERALL; 206736934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 206836934Sbrian clear_type |= THROUGHPUT_CURRENT; 206936934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 207036934Sbrian clear_type |= THROUGHPUT_PEAK; 207136934Sbrian else 207236934Sbrian return -1; 207336934Sbrian } else 207436934Sbrian clear_type = THROUGHPUT_ALL; 207536934Sbrian 207636934Sbrian throughput_clear(t, clear_type, arg->prompt); 207736934Sbrian return 0; 207836934Sbrian} 2079