command.c revision 37160
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 * 2037160Sbrian * $Id: command.c,v 1.148 1998/06/20 00:19:33 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"; 12737160Sbrianconst char VersionDate[] = "$Date: 1998/06/20 00:19:33 $"; 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)) { 27037019Sbrian log_Printf(LogWARN, "%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, 47337160Sbrian "Open an FSM", "open [lcp|ccp|ipcp]"}, 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{ 84037160Sbrian if (arg->argc == arg->argn) 84136285Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL); 84237160Sbrian else if (arg->argc == arg->argn + 1) { 84337160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 84437160Sbrian if (arg->cx) { 84537160Sbrian if (arg->cx->physical->link.lcp.fsm.state == ST_OPENED) 84637160Sbrian fsm_Reopen(&arg->cx->physical->link.lcp.fsm); 84737160Sbrian else 84837160Sbrian bundle_Open(arg->bundle, arg->cx->name, PHYS_ALL); 84937160Sbrian } else 85037160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 85137160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 85237160Sbrian struct link *l; 85337160Sbrian struct fsm *fp; 8546059Samurai 85537160Sbrian if (!(l = command_ChooseLink(arg))) 85637160Sbrian return -1; 85737160Sbrian fp = &l->ccp.fsm; 85836285Sbrian 85937160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 86037160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 86137160Sbrian else if (fp->state == ST_OPENED) 86237160Sbrian fsm_Reopen(fp); 86337160Sbrian else { 86437160Sbrian fp->open_mode = 0; /* Not passive any more */ 86537160Sbrian if (fp->state == ST_STOPPED) { 86637160Sbrian fsm_Down(fp); 86737160Sbrian fsm_Up(fp); 86837160Sbrian } else { 86937160Sbrian fsm_Up(fp); 87037160Sbrian fsm_Open(fp); 87137160Sbrian } 87236285Sbrian } 87337160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 87437160Sbrian if (arg->cx) 87537160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 87637160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 87737160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 87837160Sbrian else 87937160Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL); 88037160Sbrian } else 88137160Sbrian return -1; 88236285Sbrian } else 88336285Sbrian return -1; 88436285Sbrian 88526516Sbrian return 0; 8866059Samurai} 8876059Samurai 88825067Sbrianstatic int 88936285SbrianCloseCommand(struct cmdargs const *arg) 8906059Samurai{ 89137007Sbrian if (arg->argc == arg->argn) 89237007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 89337007Sbrian else if (arg->argc == arg->argn + 1) { 89437007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 89537007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 89637007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 89737007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 89837007Sbrian struct link *l; 89937007Sbrian struct fsm *fp; 9006059Samurai 90137007Sbrian if (!(l = command_ChooseLink(arg))) 90237007Sbrian return -1; 90337007Sbrian fp = &l->ccp.fsm; 90437007Sbrian 90537007Sbrian if (fp->state == ST_OPENED) { 90637007Sbrian fsm_Close(fp); 90737007Sbrian if (arg->argv[arg->argn][3] == '!') 90837007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 90937007Sbrian else 91037007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 91137007Sbrian } 91237007Sbrian } else 91336285Sbrian return -1; 91436285Sbrian } else 91536285Sbrian return -1; 91636285Sbrian 91736285Sbrian return 0; 9186059Samurai} 9196059Samurai 92025067Sbrianstatic int 92136285SbrianDownCommand(struct cmdargs const *arg) 92211336Samurai{ 92337018Sbrian if (arg->argc == arg->argn) { 92437018Sbrian if (arg->cx) 92537018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 92637018Sbrian else 92737018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 92837018Sbrian } else if (arg->argc == arg->argn + 1) { 92937018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 93037018Sbrian if (arg->cx) 93137018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 93237018Sbrian else 93337018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 93437018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 93537018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 93637018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 93737060Sbrian fsm2initial(fp); 93837018Sbrian } else 93937018Sbrian return -1; 94036285Sbrian } else 94136285Sbrian return -1; 94236285Sbrian 94336285Sbrian return 0; 94425067Sbrian} 94525067Sbrian 94625067Sbrianstatic int 94736285SbrianSetModemSpeed(struct cmdargs const *arg) 94825067Sbrian{ 94936285Sbrian long speed; 95036285Sbrian char *end; 95111336Samurai 95236285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 95336285Sbrian if (arg->argc > arg->argn+1) { 95436285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 95536285Sbrian return -1; 95611336Samurai } 95736285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 95836285Sbrian physical_SetSync(arg->cx->physical); 95936285Sbrian return 0; 96036285Sbrian } 96136285Sbrian end = NULL; 96236285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 96336285Sbrian if (*end) { 96436285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 96536285Sbrian arg->argv[arg->argn]); 96636285Sbrian return -1; 96736285Sbrian } 96836285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 96936285Sbrian return 0; 97036285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 97136285Sbrian } else 97236285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 97324939Sbrian 97426516Sbrian return -1; 97511336Samurai} 97611336Samurai 97725067Sbrianstatic int 97831343SbrianSetStoppedTimeout(struct cmdargs const *arg) 97928327Sbrian{ 98036285Sbrian struct link *l = &arg->cx->physical->link; 98136285Sbrian 98236285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 98336285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 98436285Sbrian if (arg->argc <= arg->argn+2) { 98536285Sbrian if (arg->argc > arg->argn) { 98636285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 98736285Sbrian if (arg->argc > arg->argn+1) 98836285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 98928461Sbrian } 99028327Sbrian return 0; 99128327Sbrian } 99228327Sbrian return -1; 99328327Sbrian} 99428327Sbrian 99531081Sbrian#define ismask(x) \ 99631081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 99731081Sbrian 99828327Sbrianstatic int 99931343SbrianSetServer(struct cmdargs const *arg) 100026940Sbrian{ 100126940Sbrian int res = -1; 100226940Sbrian 100336285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 100431081Sbrian const char *port, *passwd, *mask; 100531081Sbrian 100631081Sbrian /* What's what ? */ 100736285Sbrian port = arg->argv[arg->argn]; 100836285Sbrian if (arg->argc == arg->argn + 2) { 100936285Sbrian passwd = arg->argv[arg->argn+1]; 101036285Sbrian mask = NULL; 101136285Sbrian } else if (arg->argc == arg->argn + 3) { 101236285Sbrian passwd = arg->argv[arg->argn+1]; 101336285Sbrian mask = arg->argv[arg->argn+2]; 101431081Sbrian if (!ismask(mask)) 101531081Sbrian return -1; 101636285Sbrian } else if (strcasecmp(port, "none") == 0) { 101736285Sbrian if (server_Close(arg->bundle)) 101836285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 101936285Sbrian return 0; 102031081Sbrian } else 102136285Sbrian return -1; 102231081Sbrian 102336285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 102436285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 102531081Sbrian 102636285Sbrian if (*port == '/') { 102731081Sbrian mode_t imask; 102836285Sbrian char *ptr, name[LINE_LEN + 12]; 102928679Sbrian 103031081Sbrian if (mask != NULL) { 103128679Sbrian unsigned m; 103228679Sbrian 103331081Sbrian if (sscanf(mask, "%o", &m) == 1) 103431081Sbrian imask = m; 103531081Sbrian else 103631081Sbrian return -1; 103731081Sbrian } else 103831081Sbrian imask = (mode_t)-1; 103936285Sbrian 104036285Sbrian ptr = strstr(port, "%d"); 104136285Sbrian if (ptr) { 104236285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 104336285Sbrian ptr - port, port, arg->bundle->unit, ptr + 2); 104436285Sbrian port = name; 104536285Sbrian } 104636285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 104727346Sbrian } else { 104836285Sbrian int iport, add = 0; 104928679Sbrian 105031081Sbrian if (mask != NULL) 105131081Sbrian return -1; 105228679Sbrian 105336285Sbrian if (*port == '+') { 105436285Sbrian port++; 105536285Sbrian add = 1; 105636285Sbrian } 105731081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 105831081Sbrian struct servent *s; 105931081Sbrian 106031081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 106131081Sbrian iport = 0; 106236285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 106328679Sbrian } else 106431081Sbrian iport = ntohs(s->s_port); 106527346Sbrian } else 106631081Sbrian iport = atoi(port); 106736285Sbrian 106836285Sbrian if (iport) { 106936285Sbrian if (add) 107036285Sbrian iport += arg->bundle->unit; 107136285Sbrian res = server_TcpOpen(arg->bundle, iport); 107236285Sbrian } else 107336285Sbrian res = -1; 107427346Sbrian } 107531081Sbrian } 107626940Sbrian 107726940Sbrian return res; 107826940Sbrian} 107926940Sbrian 108026940Sbrianstatic int 108131343SbrianSetModemParity(struct cmdargs const *arg) 10826059Samurai{ 108336285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 108436285Sbrian arg->argv[arg->argn]) : -1; 10856059Samurai} 10866059Samurai 10876059Samuraistatic int 108831343SbrianSetEscape(struct cmdargs const *arg) 10896059Samurai{ 10906059Samurai int code; 109136285Sbrian int argc = arg->argc - arg->argn; 109236285Sbrian char const *const *argv = arg->argv + arg->argn; 10936059Samurai 10946059Samurai for (code = 0; code < 33; code++) 109536285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 109631343Sbrian 10976059Samurai while (argc-- > 0) { 10986059Samurai sscanf(*argv++, "%x", &code); 10996059Samurai code &= 0xff; 110036285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 110136285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 11026059Samurai } 110326516Sbrian return 0; 11046059Samurai} 11056059Samurai 110630715Sbrianstatic struct in_addr 110731343SbrianGetIpAddr(const char *cp) 11086059Samurai{ 11096059Samurai struct hostent *hp; 11106059Samurai struct in_addr ipaddr; 11116059Samurai 111232124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 111332124Sbrian hp = gethostbyname(cp); 111432124Sbrian if (hp && hp->h_addrtype == AF_INET) 111532124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 111632124Sbrian else 111732124Sbrian ipaddr.s_addr = 0; 111832124Sbrian } 111928679Sbrian return (ipaddr); 11206059Samurai} 11216059Samurai 11226059Samuraistatic int 112331343SbrianSetInterfaceAddr(struct cmdargs const *arg) 11246059Samurai{ 112536285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 112632267Sbrian const char *hisaddr; 112732267Sbrian 112832267Sbrian hisaddr = NULL; 112936285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 113036285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 11316059Samurai 113236285Sbrian if (arg->argc > arg->argn + 4) 113328679Sbrian return -1; 113426516Sbrian 113536285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 113636285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 113736285Sbrian iplist_reset(&ipcp->cfg.peer_list); 113828394Sbrian 113936285Sbrian if (arg->argc > arg->argn) { 114036285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 114136285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 114236285Sbrian &ipcp->cfg.my_range.width)) 114328679Sbrian return 1; 114436285Sbrian if (arg->argc > arg->argn+1) { 114536285Sbrian hisaddr = arg->argv[arg->argn+1]; 114636285Sbrian if (arg->argc > arg->argn+2) { 114736285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 114836285Sbrian if (arg->argc > arg->argn+3) { 114936285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 115036285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 11519440Samurai } 11526059Samurai } 11536059Samurai } 11546059Samurai } 115528394Sbrian 11566059Samurai /* 11576059Samurai * For backwards compatibility, 0.0.0.0 means any address. 11586059Samurai */ 115936285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 116036285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 116136285Sbrian ipcp->cfg.my_range.width = 0; 11626059Samurai } 116336285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 116436285Sbrian 116536285Sbrian if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 116636285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 116736285Sbrian ipcp->cfg.peer_range.width = 0; 11686059Samurai } 116928537Sbrian 117036285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 117136928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 117232267Sbrian return 4; 117331121Sbrian 117426516Sbrian return 0; 11756059Samurai} 11766059Samurai 117718752Sjkhstatic int 117831343SbrianSetVariable(struct cmdargs const *arg) 11796059Samurai{ 118036285Sbrian u_long ulong_val; 118131343Sbrian const char *argp; 118236285Sbrian int param = (int)arg->cmd->args, mode; 118336285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 118436285Sbrian const char *err = NULL; 118536285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 118636285Sbrian int dummyint; 118736285Sbrian struct in_addr dummyaddr, *addr; 11886059Samurai 118936285Sbrian if (!l) 119036285Sbrian return -1; 119136285Sbrian 119236285Sbrian if (arg->argc > arg->argn) 119336285Sbrian argp = arg->argv[arg->argn]; 119426551Sbrian else 119531343Sbrian argp = ""; 119626551Sbrian 119736285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 119836285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 119936285Sbrian arg->cmd->name); 120036285Sbrian return 1; 120136285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 120236285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 120336285Sbrian arg->cmd->name, cx->name); 120436285Sbrian cx = NULL; 120536285Sbrian } 120636285Sbrian 120726551Sbrian switch (param) { 120828679Sbrian case VAR_AUTHKEY: 120936285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 121036285Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 121136285Sbrian sizeof arg->bundle->cfg.auth.key - 1); 121236285Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 121336285Sbrian } else { 121436285Sbrian err = "set authkey: Only available at phase DEAD\n"; 121536285Sbrian log_Printf(LogWARN, err); 121636285Sbrian } 121728679Sbrian break; 121828679Sbrian case VAR_AUTHNAME: 121936285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 122036285Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 122136285Sbrian sizeof arg->bundle->cfg.auth.name - 1); 122236285Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 122336285Sbrian } else { 122436285Sbrian err = "set authname: Only available at phase DEAD\n"; 122536285Sbrian log_Printf(LogWARN, err); 122636285Sbrian } 122728679Sbrian break; 122836285Sbrian case VAR_AUTOLOAD: 122936285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 123036285Sbrian arg->bundle->autoload.running = 1; 123136285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 123236285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 123336285Sbrian if (arg->argc == arg->argn + 4) { 123436285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 123536285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 123636285Sbrian } else { 123736285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 123836285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 123936285Sbrian } 124036285Sbrian } else { 124136285Sbrian err = "Set autoload requires two or four arguments\n"; 124236285Sbrian log_Printf(LogWARN, err); 124336285Sbrian } 124436285Sbrian break; 124528679Sbrian case VAR_DIAL: 124636285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 124736285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 124828679Sbrian break; 124928679Sbrian case VAR_LOGIN: 125036285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 125136285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 125228679Sbrian break; 125336285Sbrian case VAR_WINSIZE: 125436285Sbrian if (arg->argc > arg->argn) { 125536285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 125636285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 125736285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 125836285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 125936285Sbrian l->ccp.cfg.deflate.out.winsize); 126036285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 126136285Sbrian } 126236285Sbrian if (arg->argc > arg->argn+1) { 126336285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 126436285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 126536285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 126636285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 126736285Sbrian l->ccp.cfg.deflate.in.winsize); 126836285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 126936285Sbrian } 127036285Sbrian } else 127136285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 127236285Sbrian } else { 127336285Sbrian err = "No window size specified\n"; 127436285Sbrian log_Printf(LogWARN, err); 127536285Sbrian } 127636285Sbrian break; 127728679Sbrian case VAR_DEVICE: 127836285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 127936285Sbrian arg->argv + arg->argn); 128036285Sbrian break; 128136285Sbrian case VAR_ACCMAP: 128236285Sbrian if (arg->argc > arg->argn) { 128336285Sbrian sscanf(argp, "%lx", &ulong_val); 128436285Sbrian cx->physical->link.lcp.cfg.accmap = ulong_val; 128536285Sbrian } else { 128636285Sbrian err = "No accmap specified\n"; 128736285Sbrian log_Printf(LogWARN, err); 128836285Sbrian } 128936285Sbrian break; 129036285Sbrian case VAR_MODE: 129136285Sbrian mode = Nam2mode(argp); 129236285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 129336285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 129436285Sbrian return -1; 129536285Sbrian } 129636285Sbrian bundle_SetMode(arg->bundle, cx, mode); 129736285Sbrian break; 129836285Sbrian case VAR_MRRU: 129936285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 130036285Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); 130129696Sbrian else { 130236285Sbrian ulong_val = atol(argp); 130337020Sbrian if (ulong_val && ulong_val < MIN_MRU) 130436285Sbrian err = "Given MRRU value (%lu) is too small.\n"; 130536285Sbrian else if (ulong_val > MAX_MRU) 130636285Sbrian err = "Given MRRU value (%lu) is too big.\n"; 130736285Sbrian else 130836285Sbrian arg->bundle->ncp.mp.cfg.mrru = ulong_val; 130936285Sbrian if (err) 131036285Sbrian log_Printf(LogWARN, err, ulong_val); 131129696Sbrian } 131228679Sbrian break; 131336285Sbrian case VAR_MRU: 131436285Sbrian ulong_val = atol(argp); 131536285Sbrian if (ulong_val < MIN_MRU) 131636285Sbrian err = "Given MRU value (%lu) is too small.\n"; 131736285Sbrian else if (ulong_val > MAX_MRU) 131836285Sbrian err = "Given MRU value (%lu) is too big.\n"; 131936285Sbrian else 132036285Sbrian l->lcp.cfg.mru = ulong_val; 132136285Sbrian if (err) 132236285Sbrian log_Printf(LogWARN, err, ulong_val); 132328679Sbrian break; 132436285Sbrian case VAR_MTU: 132536285Sbrian ulong_val = atol(argp); 132636285Sbrian if (ulong_val == 0) 132736285Sbrian arg->bundle->cfg.mtu = 0; 132836285Sbrian else if (ulong_val < MIN_MTU) 132936285Sbrian err = "Given MTU value (%lu) is too small.\n"; 133036285Sbrian else if (ulong_val > MAX_MTU) 133136285Sbrian err = "Given MTU value (%lu) is too big.\n"; 133236285Sbrian else 133336285Sbrian arg->bundle->cfg.mtu = ulong_val; 133436285Sbrian if (err) 133536285Sbrian log_Printf(LogWARN, err, ulong_val); 133636285Sbrian break; 133736285Sbrian case VAR_OPENMODE: 133836285Sbrian if (strcasecmp(argp, "active") == 0) 133936285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 134036285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 134136285Sbrian else if (strcasecmp(argp, "passive") == 0) 134236285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 134336285Sbrian else { 134436285Sbrian err = "%s: Invalid openmode\n"; 134536285Sbrian log_Printf(LogWARN, err, argp); 134636285Sbrian } 134736285Sbrian break; 134828679Sbrian case VAR_PHONE: 134936285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 135036285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 135128679Sbrian break; 135228679Sbrian case VAR_HANGUP: 135336285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 135436285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 135528679Sbrian break; 135636285Sbrian case VAR_IDLETIMEOUT: 135736285Sbrian if (arg->argc > arg->argn+1) 135836285Sbrian err = "Too many idle timeout values\n"; 135936285Sbrian else if (arg->argc == arg->argn+1) 136036285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 136136285Sbrian if (err) 136236285Sbrian log_Printf(LogWARN, err); 136329549Sbrian break; 136436285Sbrian case VAR_LQRPERIOD: 136536285Sbrian ulong_val = atol(argp); 136636285Sbrian if (ulong_val <= 0) { 136736285Sbrian err = "%s: Invalid lqr period\n"; 136836285Sbrian log_Printf(LogWARN, err, argp); 136936285Sbrian } else 137036285Sbrian l->lcp.cfg.lqrperiod = ulong_val; 137136285Sbrian break; 137236285Sbrian case VAR_LCPRETRY: 137336285Sbrian ulong_val = atol(argp); 137436285Sbrian if (ulong_val <= 0) { 137536285Sbrian err = "%s: Invalid LCP FSM retry period\n"; 137636285Sbrian log_Printf(LogWARN, err, argp); 137736285Sbrian } else 137836285Sbrian cx->physical->link.lcp.cfg.fsmretry = ulong_val; 137936285Sbrian break; 138036285Sbrian case VAR_CHAPRETRY: 138136285Sbrian ulong_val = atol(argp); 138236285Sbrian if (ulong_val <= 0) { 138336285Sbrian err = "%s: Invalid CHAP retry period\n"; 138436285Sbrian log_Printf(LogWARN, err, argp); 138536285Sbrian } else 138636285Sbrian cx->chap.auth.cfg.fsmretry = ulong_val; 138736285Sbrian break; 138836285Sbrian case VAR_PAPRETRY: 138936285Sbrian ulong_val = atol(argp); 139036285Sbrian if (ulong_val <= 0) { 139136285Sbrian err = "%s: Invalid PAP retry period\n"; 139236285Sbrian log_Printf(LogWARN, err, argp); 139336285Sbrian } else 139436285Sbrian cx->pap.cfg.fsmretry = ulong_val; 139536285Sbrian break; 139636285Sbrian case VAR_CCPRETRY: 139736285Sbrian ulong_val = atol(argp); 139836285Sbrian if (ulong_val <= 0) { 139936285Sbrian err = "%s: Invalid CCP FSM retry period\n"; 140036285Sbrian log_Printf(LogWARN, err, argp); 140136285Sbrian } else 140236285Sbrian l->ccp.cfg.fsmretry = ulong_val; 140336285Sbrian break; 140436285Sbrian case VAR_IPCPRETRY: 140536285Sbrian ulong_val = atol(argp); 140636285Sbrian if (ulong_val <= 0) { 140736285Sbrian err = "%s: Invalid IPCP FSM retry period\n"; 140836285Sbrian log_Printf(LogWARN, err, argp); 140936285Sbrian } else 141036285Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = ulong_val; 141136285Sbrian break; 141236285Sbrian case VAR_NBNS: 141336285Sbrian case VAR_DNS: 141436285Sbrian if (param == VAR_DNS) 141536285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 141636285Sbrian else 141736285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 141836285Sbrian 141936285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 142036285Sbrian 142136285Sbrian if (arg->argc > arg->argn) { 142236285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 142336285Sbrian addr, &dummyaddr, &dummyint); 142436285Sbrian if (arg->argc > arg->argn+1) 142536285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 142636285Sbrian addr + 1, &dummyaddr, &dummyint); 142736285Sbrian 142836285Sbrian if (addr[1].s_addr == INADDR_ANY) 142936285Sbrian addr[1].s_addr = addr[0].s_addr; 143036285Sbrian if (addr[0].s_addr == INADDR_ANY) 143136285Sbrian addr[0].s_addr = addr[1].s_addr; 143236285Sbrian } 143336285Sbrian break; 14346059Samurai } 143536285Sbrian 143636285Sbrian return err ? 1 : 0; 14376059Samurai} 14386059Samurai 143928679Sbrianstatic int 144031343SbrianSetCtsRts(struct cmdargs const *arg) 144120812Sjkh{ 144236285Sbrian if (arg->argc == arg->argn+1) { 144336285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 144436285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 144536285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 144636285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 144720812Sjkh else 144826516Sbrian return -1; 144926516Sbrian return 0; 145020812Sjkh } 145126516Sbrian return -1; 145220812Sjkh} 145320812Sjkh 145430715Sbrianstatic struct cmdtab const SetCommands[] = { 145536285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 145636285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 145728679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 145836285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 145928679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 146036285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 146136285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 146236285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 146336285Sbrian (const void *)VAR_AUTOLOAD}, 146436285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 146536285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 146636285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 146736285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 146836285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 146936285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 147036285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 147136285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 147236285Sbrian (const void *) VAR_WINSIZE}, 147336285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 147436285Sbrian "modem device name", "set device|line device-name[,device-name]", 147536285Sbrian (const void *) VAR_DEVICE}, 147636285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 147736285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 147836285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 147936285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 148036285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 148136285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 148236285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 148336285Sbrian "escape characters", "set escape hex-digit ..."}, 148436285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 148536285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 148636285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 148736285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 148836285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 148936285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 149036285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 149131343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 149236285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 149336285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 149436285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 149536285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 149636712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 149736712Sbrian "set log [local] [+|-]async|ccp|chat|command|connect|debug|hdlc|id0|ipcp|" 149836712Sbrian "lcp|lqm|phase|tcp/ip|timer|tun..."}, 149936285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 150036285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 150136285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 150236285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 150336285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 150436285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 150536285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 150636285Sbrian "set mrru value", (const void *)VAR_MRRU}, 150736285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 150836285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 150936285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 151036285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 151136285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 151236285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 151336285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 151436285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 151536285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 151636285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 151736285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 151836285Sbrian "modem parity", "set parity [odd|even|none]"}, 151936285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 152036285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 152136285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 152236285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 152336285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 152436285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 152528679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 152636774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 152736285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 152836285Sbrian "modem speed", "set speed value"}, 152936285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 153036285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 153136285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 153236285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 153336285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 153436285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 153536285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 153636285Sbrian "datalink weighting", "set weight n"}, 153728679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 153831343Sbrian "Display this message", "set help|? [command]", SetCommands}, 153928679Sbrian {NULL, NULL, NULL}, 15406059Samurai}; 15416059Samurai 15426059Samuraistatic int 154331343SbrianSetCommand(struct cmdargs const *arg) 15446059Samurai{ 154536285Sbrian if (arg->argc > arg->argn) 154636285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 154736285Sbrian arg->prompt, arg->cx); 154836285Sbrian else if (arg->prompt) 154936285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 155026516Sbrian " syntax help.\n"); 15516059Samurai else 155236285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 155326516Sbrian 155426516Sbrian return 0; 15556059Samurai} 15566059Samurai 15576059Samurai 15586059Samuraistatic int 155931343SbrianAddCommand(struct cmdargs const *arg) 15606059Samurai{ 15616059Samurai struct in_addr dest, gateway, netmask; 156236285Sbrian int gw, addrs; 15636059Samurai 156436285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 156531598Sbrian return -1; 156631598Sbrian 156736285Sbrian addrs = 0; 156836285Sbrian if (arg->argc == arg->argn+2) { 156936285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 157036285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 157131598Sbrian else { 157236285Sbrian int width; 157336285Sbrian 157436285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 157536285Sbrian &dest, &netmask, &width)) 157636285Sbrian return -1; 157736285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 157836285Sbrian addrs = ROUTE_DSTMYADDR; 157936285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 158036285Sbrian addrs = ROUTE_DSTHISADDR; 158131598Sbrian } 158236285Sbrian gw = 1; 158334536Sbrian } else { 158436285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 158536285Sbrian addrs = ROUTE_DSTMYADDR; 158636285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 158736285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 158836285Sbrian addrs = ROUTE_DSTHISADDR; 158936285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 159036285Sbrian } else 159136285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 159236285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 159331598Sbrian gw = 2; 15946059Samurai } 159536285Sbrian 159636285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 159736285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 159836285Sbrian addrs |= ROUTE_GWHISADDR; 159936285Sbrian } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0) 160031598Sbrian gateway.s_addr = INADDR_ANY; 160131598Sbrian else 160236285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 160336285Sbrian 160436285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 160536285Sbrian arg->cmd->args ? 1 : 0)) 160636285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 160736285Sbrian 160831598Sbrian return 0; 16096059Samurai} 16106059Samurai 16116059Samuraistatic int 161231343SbrianDeleteCommand(struct cmdargs const *arg) 16136059Samurai{ 161431598Sbrian struct in_addr dest, none; 161536285Sbrian int addrs; 16166059Samurai 161736285Sbrian if (arg->argc == arg->argn+1) { 161836285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 161936285Sbrian route_IfDelete(arg->bundle, 0); 162036285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 162136285Sbrian } else { 162236285Sbrian addrs = 0; 162336285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 162436285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 162536285Sbrian addrs = ROUTE_DSTMYADDR; 162636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 162736285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 162836285Sbrian addrs = ROUTE_DSTHISADDR; 162936285Sbrian } else { 163036285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 163136285Sbrian dest.s_addr = INADDR_ANY; 163236285Sbrian else 163336285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 163436285Sbrian addrs = ROUTE_STATIC; 163536285Sbrian } 163631598Sbrian none.s_addr = INADDR_ANY; 163736285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 163836285Sbrian arg->cmd->args ? 1 : 0); 163936285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 164031598Sbrian } 164134536Sbrian } else 164226516Sbrian return -1; 164326516Sbrian 164426516Sbrian return 0; 16456059Samurai} 16466059Samurai 164731343Sbrian#ifndef NOALIAS 164826031Sbrianstatic struct cmdtab const AliasCommands[] = 164926031Sbrian{ 165036285Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 165136285Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 165236285Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 165336285Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 165436285Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 165528679Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 165636285Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 165728679Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 165836285Sbrian "log aliasing link creation", "alias log [yes|no]", 165936285Sbrian (const void *) PKT_ALIAS_LOG}, 166036285Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 166136285Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 166228679Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 166336285Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 166436285Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 166536285Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 166636285Sbrian "alias unregistered (private) IP address space only", 166736285Sbrian "alias unregistered_only [yes|no]", 166836285Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 166928679Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 167036285Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 167136285Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 167228679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 167336285Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 167428679Sbrian {NULL, NULL, NULL}, 167526031Sbrian}; 167626031Sbrian 167726031Sbrian 167826031Sbrianstatic int 167931343SbrianAliasCommand(struct cmdargs const *arg) 168026031Sbrian{ 168136285Sbrian if (arg->argc > arg->argn) 168236285Sbrian FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv, 168336285Sbrian arg->prompt, arg->cx); 168436285Sbrian else if (arg->prompt) 168536285Sbrian prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 168636285Sbrian " <option>' for syntax help.\n"); 168726031Sbrian else 168836285Sbrian log_Printf(LogWARN, "alias command must have arguments\n"); 168926516Sbrian 169026516Sbrian return 0; 169126031Sbrian} 169226031Sbrian 169326031Sbrianstatic int 169431343SbrianAliasEnable(struct cmdargs const *arg) 169526031Sbrian{ 169636285Sbrian if (arg->argc == arg->argn+1) { 169736285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 169836285Sbrian if (alias_Load() == 0) 169936285Sbrian return 0; 170036285Sbrian log_Printf(LogWARN, "Cannot load alias library\n"); 170136285Sbrian return 1; 170236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 170336285Sbrian alias_Unload(); 170426516Sbrian return 0; 170526142Sbrian } 170635449Sbrian } 170736285Sbrian 170826516Sbrian return -1; 170926031Sbrian} 171026031Sbrian 171126031Sbrian 171226031Sbrianstatic int 171331343SbrianAliasOption(struct cmdargs const *arg) 171426031Sbrian{ 171536285Sbrian unsigned param = (unsigned)arg->cmd->args; 171636285Sbrian if (arg->argc == arg->argn+1) { 171736285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 171836285Sbrian if (alias_IsEnabled()) { 171936285Sbrian (*PacketAlias.SetMode)(param, param); 172028679Sbrian return 0; 172128679Sbrian } 172236285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 172336285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 172436285Sbrian if (alias_IsEnabled()) { 172536285Sbrian (*PacketAlias.SetMode)(0, param); 172628679Sbrian return 0; 172728679Sbrian } 172836285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 172928679Sbrian } 173035449Sbrian } 173128679Sbrian return -1; 173226031Sbrian} 173331343Sbrian#endif /* #ifndef NOALIAS */ 173431121Sbrian 173531121Sbrianstatic struct cmdtab const AllowCommands[] = { 173636285Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 173736285Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 173831121Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 173931121Sbrian "Allow users access to ppp", "allow users logname..."}, 174031121Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 174131343Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 174231121Sbrian {NULL, NULL, NULL}, 174331121Sbrian}; 174431121Sbrian 174531121Sbrianstatic int 174631343SbrianAllowCommand(struct cmdargs const *arg) 174731121Sbrian{ 174836285Sbrian /* arg->bundle may be NULL (see system_IsValid()) ! */ 174936285Sbrian if (arg->argc > arg->argn) 175036285Sbrian FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv, 175136285Sbrian arg->prompt, arg->cx); 175236285Sbrian else if (arg->prompt) 175336285Sbrian prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 175436285Sbrian " for syntax help.\n"); 175531121Sbrian else 175636285Sbrian log_Printf(LogWARN, "allow command must have arguments\n"); 175731121Sbrian 175831121Sbrian return 0; 175931121Sbrian} 176036285Sbrian 176136285Sbrianstatic int 176236285SbrianLinkCommand(struct cmdargs const *arg) 176336285Sbrian{ 176436285Sbrian if (arg->argc > arg->argn+1) { 176536285Sbrian char namelist[LINE_LEN]; 176636285Sbrian struct datalink *cx; 176736285Sbrian char *name; 176836285Sbrian int result = 0; 176936285Sbrian 177036285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 177136285Sbrian struct datalink *dl; 177236285Sbrian 177336285Sbrian cx = arg->bundle->links; 177436285Sbrian while (cx) { 177536285Sbrian /* Watch it, the command could be a ``remove'' */ 177636285Sbrian dl = cx->next; 177736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 177836285Sbrian arg->prompt, cx); 177936285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 178036285Sbrian if (cx == dl) 178136285Sbrian break; /* Pointer's still valid ! */ 178236285Sbrian } 178336285Sbrian } else { 178436285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 178536285Sbrian namelist[sizeof namelist - 1] = '\0'; 178636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 178736285Sbrian if (!bundle2datalink(arg->bundle, name)) { 178836285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 178936285Sbrian return 1; 179036285Sbrian } 179136285Sbrian 179236285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 179336285Sbrian namelist[sizeof namelist - 1] = '\0'; 179436285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 179536285Sbrian cx = bundle2datalink(arg->bundle, name); 179636285Sbrian if (cx) 179736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 179836285Sbrian arg->prompt, cx); 179936285Sbrian else { 180036285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 180136285Sbrian result++; 180236285Sbrian } 180336285Sbrian } 180436285Sbrian } 180536285Sbrian return result; 180636285Sbrian } 180736285Sbrian 180836285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 180936285Sbrian return 2; 181036285Sbrian} 181136285Sbrian 181236285Sbrianstruct link * 181336285Sbriancommand_ChooseLink(struct cmdargs const *arg) 181436285Sbrian{ 181536285Sbrian if (arg->cx) 181636285Sbrian return &arg->cx->physical->link; 181736285Sbrian else if (arg->bundle->ncp.mp.cfg.mrru) 181836285Sbrian return &arg->bundle->ncp.mp.link; 181936285Sbrian else { 182036285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 182136285Sbrian return dl ? &dl->physical->link : NULL; 182236285Sbrian } 182336285Sbrian} 182436285Sbrian 182536285Sbrianstatic const char * 182636285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 182736285Sbrian{ 182836285Sbrian const char *result; 182936285Sbrian 183036285Sbrian switch (*cmd) { 183136285Sbrian case 'A': 183236285Sbrian case 'a': 183336285Sbrian result = "accept"; 183436285Sbrian *keep = NEG_MYMASK; 183536285Sbrian *add = NEG_ACCEPTED; 183636285Sbrian break; 183736285Sbrian case 'D': 183836285Sbrian case 'd': 183936285Sbrian switch (cmd[1]) { 184036285Sbrian case 'E': 184136285Sbrian case 'e': 184236285Sbrian result = "deny"; 184336285Sbrian *keep = NEG_MYMASK; 184436285Sbrian *add = 0; 184536285Sbrian break; 184636285Sbrian case 'I': 184736285Sbrian case 'i': 184836285Sbrian result = "disable"; 184936285Sbrian *keep = NEG_HISMASK; 185036285Sbrian *add = 0; 185136285Sbrian break; 185236285Sbrian default: 185336285Sbrian return NULL; 185436285Sbrian } 185536285Sbrian break; 185636285Sbrian case 'E': 185736285Sbrian case 'e': 185836285Sbrian result = "enable"; 185936285Sbrian *keep = NEG_HISMASK; 186036285Sbrian *add = NEG_ENABLED; 186136285Sbrian break; 186236285Sbrian default: 186336285Sbrian return NULL; 186436285Sbrian } 186536285Sbrian 186636285Sbrian return result; 186736285Sbrian} 186836285Sbrian 186936285Sbrianstatic int 187036285SbrianOptSet(struct cmdargs const *arg) 187136285Sbrian{ 187236285Sbrian int bit = (int)arg->cmd->args; 187336285Sbrian const char *cmd; 187436285Sbrian unsigned keep; /* Keep these bits */ 187536285Sbrian unsigned add; /* Add these bits */ 187636285Sbrian 187736285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 187836285Sbrian return 1; 187936285Sbrian 188036285Sbrian if (add) 188136285Sbrian arg->bundle->cfg.opt |= bit; 188236285Sbrian else 188336285Sbrian arg->bundle->cfg.opt &= ~bit; 188436285Sbrian return 0; 188536285Sbrian} 188636285Sbrian 188736285Sbrianstatic int 188836285SbrianNegotiateSet(struct cmdargs const *arg) 188936285Sbrian{ 189036285Sbrian int param = (int)arg->cmd->args; 189136285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 189236285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 189336285Sbrian const char *cmd; 189436285Sbrian unsigned keep; /* Keep these bits */ 189536285Sbrian unsigned add; /* Add these bits */ 189636285Sbrian 189736285Sbrian if (!l) 189836285Sbrian return -1; 189936285Sbrian 190036285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 190136285Sbrian return 1; 190236285Sbrian 190336285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 190436285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 190536285Sbrian cmd, arg->cmd->name); 190636285Sbrian return 2; 190736285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 190836285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 190936285Sbrian cmd, arg->cmd->name, cx->name); 191036285Sbrian cx = NULL; 191136285Sbrian } 191236285Sbrian 191336285Sbrian switch (param) { 191436285Sbrian case NEG_ACFCOMP: 191536285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 191636285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 191736285Sbrian break; 191836285Sbrian case NEG_CHAP: 191936285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 192036285Sbrian cx->physical->link.lcp.cfg.chap |= add; 192136285Sbrian break; 192236285Sbrian case NEG_DEFLATE: 192336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 192436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 192536285Sbrian break; 192636285Sbrian case NEG_DNS: 192736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 192836285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 192936285Sbrian break; 193036285Sbrian case NEG_LQR: 193136285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 193236285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 193336285Sbrian break; 193436285Sbrian case NEG_PAP: 193536285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 193636285Sbrian cx->physical->link.lcp.cfg.pap |= add; 193736285Sbrian break; 193836285Sbrian case NEG_PPPDDEFLATE: 193936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 194036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 194136285Sbrian break; 194236285Sbrian case NEG_PRED1: 194336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 194436285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 194536285Sbrian break; 194636285Sbrian case NEG_PROTOCOMP: 194736285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 194836285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 194936285Sbrian break; 195036285Sbrian case NEG_SHORTSEQ: 195136285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 195236285Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); 195336285Sbrian else { 195436285Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 195536285Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 195636285Sbrian } 195736285Sbrian break; 195836285Sbrian case NEG_VJCOMP: 195936285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 196036285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 196136285Sbrian break; 196236285Sbrian } 196336285Sbrian 196436285Sbrian return 0; 196536285Sbrian} 196636285Sbrian 196736285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 196836285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 196936285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 197036285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 197136285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 197236285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 197336285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 197436285Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", 197536285Sbrian "disable|enable", (const void *)OPT_PROXY}, 197636285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 197736285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 197836285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 197936285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 198036285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 198136285Sbrian "disable|enable", (const void *)OPT_UTMP}, 198236285Sbrian 198336285Sbrian#define OPT_MAX 7 /* accept/deny allowed below and not above */ 198436285Sbrian 198536285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 198636285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 198736285Sbrian (const void *)NEG_ACFCOMP}, 198836285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 198936285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 199036285Sbrian (const void *)NEG_CHAP}, 199136285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 199236285Sbrian "Deflate compression", "accept|deny|disable|enable", 199336285Sbrian (const void *)NEG_DEFLATE}, 199436285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 199536285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 199636285Sbrian (const void *)NEG_PPPDDEFLATE}, 199736285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 199836285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 199936285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 200036285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 200136285Sbrian (const void *)NEG_LQR}, 200236285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 200336285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 200436285Sbrian (const void *)NEG_PAP}, 200536285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 200636285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 200736285Sbrian (const void *)NEG_PRED1}, 200836285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 200936285Sbrian "Protocol field compression", "accept|deny|disable|enable", 201036285Sbrian (const void *)NEG_PROTOCOMP}, 201136285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 201236285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 201336285Sbrian (const void *)NEG_SHORTSEQ}, 201436285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 201536285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 201636285Sbrian (const void *)NEG_VJCOMP}, 201736285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 201836285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 201936285Sbrian NegotiateCommands}, 202036285Sbrian {NULL, NULL, NULL}, 202136285Sbrian}; 202236285Sbrian 202336285Sbrianstatic int 202436285SbrianNegotiateCommand(struct cmdargs const *arg) 202536285Sbrian{ 202636285Sbrian if (arg->argc > arg->argn) { 202736285Sbrian char const *argv[3]; 202836285Sbrian unsigned keep, add; 202936285Sbrian int n; 203036285Sbrian 203136285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 203236285Sbrian return -1; 203336285Sbrian argv[2] = NULL; 203436285Sbrian 203536285Sbrian for (n = arg->argn; n < arg->argc; n++) { 203636285Sbrian argv[1] = arg->argv[n]; 203736285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 203836285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 203936285Sbrian } 204036285Sbrian } else if (arg->prompt) 204136285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 204236285Sbrian arg->argv[arg->argn-1]); 204336285Sbrian else 204436285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 204536285Sbrian arg->argv[arg->argn] ); 204636285Sbrian 204736285Sbrian return 0; 204836285Sbrian} 204936285Sbrian 205036285Sbrianconst char * 205136285Sbriancommand_ShowNegval(unsigned val) 205236285Sbrian{ 205336285Sbrian switch (val&3) { 205436285Sbrian case 1: return "disabled & accepted"; 205536285Sbrian case 2: return "enabled & denied"; 205636285Sbrian case 3: return "enabled & accepted"; 205736285Sbrian } 205836285Sbrian return "disabled & denied"; 205936285Sbrian} 206036934Sbrian 206136934Sbrianstatic int 206236934SbrianClearCommand(struct cmdargs const *arg) 206336934Sbrian{ 206436934Sbrian struct pppThroughput *t; 206536934Sbrian struct datalink *cx; 206636934Sbrian int i, clear_type; 206736934Sbrian 206836934Sbrian if (arg->argc < arg->argn + 1) 206936934Sbrian return -1; 207036934Sbrian 207136934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 207236934Sbrian cx = arg->cx; 207336934Sbrian if (!cx) 207436934Sbrian cx = bundle2datalink(arg->bundle, NULL); 207536934Sbrian if (!cx) { 207636934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 207736934Sbrian return 1; 207836934Sbrian } 207936934Sbrian t = &cx->physical->link.throughput; 208036934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 208136934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 208236934Sbrian else 208336934Sbrian return -1; 208436934Sbrian 208536934Sbrian if (arg->argc > arg->argn + 1) { 208636934Sbrian clear_type = 0; 208736934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 208836934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 208936934Sbrian clear_type |= THROUGHPUT_OVERALL; 209036934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 209136934Sbrian clear_type |= THROUGHPUT_CURRENT; 209236934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 209336934Sbrian clear_type |= THROUGHPUT_PEAK; 209436934Sbrian else 209536934Sbrian return -1; 209636934Sbrian } else 209736934Sbrian clear_type = THROUGHPUT_ALL; 209836934Sbrian 209936934Sbrian throughput_clear(t, clear_type, arg->prompt); 210036934Sbrian return 0; 210136934Sbrian} 2102