command.c revision 38557
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 * 2038557Sbrian * $Id: command.c,v 1.160 1998/08/25 17:48:42 brian Exp $ 218857Srgrimes * 226059Samurai */ 2336285Sbrian#include <sys/types.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3331343Sbrian#ifndef NOALIAS 3426031Sbrian#include <alias.h> 3531343Sbrian#endif 3630715Sbrian#include <errno.h> 3726516Sbrian#include <fcntl.h> 3830715Sbrian#include <paths.h> 3930715Sbrian#include <stdio.h> 4030715Sbrian#include <stdlib.h> 4130715Sbrian#include <string.h> 4230715Sbrian#include <sys/wait.h> 4330715Sbrian#include <termios.h> 4430715Sbrian#include <unistd.h> 4530715Sbrian 4637009Sbrian#include "defs.h" 4731343Sbrian#include "command.h" 4830715Sbrian#include "mbuf.h" 4930715Sbrian#include "log.h" 5030715Sbrian#include "timer.h" 516059Samurai#include "fsm.h" 526059Samurai#include "lcp.h" 5331690Sbrian#include "iplist.h" 5436285Sbrian#include "throughput.h" 5536285Sbrian#include "slcompress.h" 5638557Sbrian#include "lqr.h" 5738557Sbrian#include "hdlc.h" 586059Samurai#include "ipcp.h" 596059Samurai#include "modem.h" 6031343Sbrian#ifndef NOALIAS 6126031Sbrian#include "alias_cmd.h" 6231343Sbrian#endif 6325630Sbrian#include "systems.h" 6436285Sbrian#include "filter.h" 6536285Sbrian#include "descriptor.h" 6630715Sbrian#include "main.h" 6730715Sbrian#include "route.h" 6830715Sbrian#include "ccp.h" 6931080Sbrian#include "auth.h" 7036285Sbrian#include "async.h" 7136285Sbrian#include "link.h" 7236285Sbrian#include "physical.h" 7336285Sbrian#include "mp.h" 7436285Sbrian#include "bundle.h" 7536285Sbrian#include "server.h" 7636285Sbrian#include "prompt.h" 7736285Sbrian#include "chat.h" 7836285Sbrian#include "chap.h" 7938174Sbrian#include "cbcp.h" 8036285Sbrian#include "datalink.h" 816059Samurai 8236285Sbrian/* ``set'' values */ 8336285Sbrian#define VAR_AUTHKEY 0 8436285Sbrian#define VAR_DIAL 1 8536285Sbrian#define VAR_LOGIN 2 8636285Sbrian#define VAR_AUTHNAME 3 8736285Sbrian#define VAR_AUTOLOAD 4 8836285Sbrian#define VAR_WINSIZE 5 8936285Sbrian#define VAR_DEVICE 6 9036285Sbrian#define VAR_ACCMAP 7 9136285Sbrian#define VAR_MRRU 8 9236285Sbrian#define VAR_MRU 9 9336285Sbrian#define VAR_MTU 10 9436285Sbrian#define VAR_OPENMODE 11 9536285Sbrian#define VAR_PHONE 12 9636285Sbrian#define VAR_HANGUP 13 9736285Sbrian#define VAR_IDLETIMEOUT 14 9836285Sbrian#define VAR_LQRPERIOD 15 9936285Sbrian#define VAR_LCPRETRY 16 10036285Sbrian#define VAR_CHAPRETRY 17 10136285Sbrian#define VAR_PAPRETRY 18 10236285Sbrian#define VAR_CCPRETRY 19 10336285Sbrian#define VAR_IPCPRETRY 20 10436285Sbrian#define VAR_DNS 21 10536285Sbrian#define VAR_NBNS 22 10636285Sbrian#define VAR_MODE 23 10738174Sbrian#define VAR_CALLBACK 24 10838174Sbrian#define VAR_CBCP 25 10938544Sbrian#define VAR_CHOKED 26 1106059Samurai 11136285Sbrian/* ``accept|deny|disable|enable'' masks */ 11236285Sbrian#define NEG_HISMASK (1) 11336285Sbrian#define NEG_MYMASK (2) 11436285Sbrian 11536285Sbrian/* ``accept|deny|disable|enable'' values */ 11636285Sbrian#define NEG_ACFCOMP 40 11736285Sbrian#define NEG_CHAP 41 11836285Sbrian#define NEG_DEFLATE 42 11936285Sbrian#define NEG_LQR 43 12036285Sbrian#define NEG_PAP 44 12136285Sbrian#define NEG_PPPDDEFLATE 45 12236285Sbrian#define NEG_PRED1 46 12336285Sbrian#define NEG_PROTOCOMP 47 12436285Sbrian#define NEG_SHORTSEQ 48 12536285Sbrian#define NEG_VJCOMP 49 12636285Sbrian#define NEG_DNS 50 12736285Sbrian 12837373Sbrianconst char Version[] = "2.0"; 12938557Sbrianconst char VersionDate[] = "$Date: 1998/08/25 17:48:42 $"; 13036285Sbrian 13136285Sbrianstatic int ShowCommand(struct cmdargs const *); 13236285Sbrianstatic int TerminalCommand(struct cmdargs const *); 13336285Sbrianstatic int QuitCommand(struct cmdargs const *); 13436285Sbrianstatic int OpenCommand(struct cmdargs const *); 13536285Sbrianstatic int CloseCommand(struct cmdargs const *); 13636285Sbrianstatic int DownCommand(struct cmdargs const *); 13736285Sbrianstatic int AllowCommand(struct cmdargs const *); 13836285Sbrianstatic int SetCommand(struct cmdargs const *); 13936285Sbrianstatic int LinkCommand(struct cmdargs const *); 14036285Sbrianstatic int AddCommand(struct cmdargs const *); 14136285Sbrianstatic int DeleteCommand(struct cmdargs const *); 14236285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 14336934Sbrianstatic int ClearCommand(struct cmdargs const *); 14431343Sbrian#ifndef NOALIAS 14536285Sbrianstatic int AliasCommand(struct cmdargs const *); 14636285Sbrianstatic int AliasEnable(struct cmdargs const *); 14736285Sbrianstatic int AliasOption(struct cmdargs const *); 14831343Sbrian#endif 1496059Samurai 15036285Sbrianstatic const char * 15136285Sbrianshowcx(struct cmdtab const *cmd) 15236285Sbrian{ 15336285Sbrian if (cmd->lauth & LOCAL_CX) 15436285Sbrian return "(c)"; 15536285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 15636285Sbrian return "(o)"; 15736285Sbrian 15836285Sbrian return ""; 15936285Sbrian} 16036285Sbrian 1616059Samuraistatic int 16231343SbrianHelpCommand(struct cmdargs const *arg) 1636059Samurai{ 16428679Sbrian struct cmdtab const *cmd; 16536285Sbrian int n, cmax, dmax, cols, cxlen; 16636285Sbrian const char *cx; 1676059Samurai 16836285Sbrian if (!arg->prompt) { 16936285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 17026516Sbrian return 0; 17136285Sbrian } 17226516Sbrian 17336285Sbrian if (arg->argc > arg->argn) { 17436285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 17536285Sbrian if ((cmd->lauth & arg->prompt->auth) && 17636285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 17736285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 17836285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 17928679Sbrian return 0; 1806059Samurai } 18126516Sbrian return -1; 1826059Samurai } 18336285Sbrian 18431372Sbrian cmax = dmax = 0; 18536285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 18636285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 18736285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 18831372Sbrian cmax = n; 18931372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 19031372Sbrian dmax = n; 19131372Sbrian } 19231372Sbrian 19331372Sbrian cols = 80 / (dmax + cmax + 3); 1946059Samurai n = 0; 19536285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 19636285Sbrian " (c) = Context required\n"); 19736285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 19836285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 19936285Sbrian cx = showcx(cmd); 20036285Sbrian cxlen = cmax - strlen(cmd->name); 20136285Sbrian prompt_Printf(arg->prompt, " %s%-*.*s: %-*.*s", 20236285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 20331372Sbrian if (++n % cols == 0) 20436285Sbrian prompt_Printf(arg->prompt, "\n"); 2056059Samurai } 20631372Sbrian if (n % cols != 0) 20736285Sbrian prompt_Printf(arg->prompt, "\n"); 20826516Sbrian 20926516Sbrian return 0; 2106059Samurai} 2116059Samurai 21236285Sbrianstatic int 21336285SbrianCloneCommand(struct cmdargs const *arg) 2146059Samurai{ 21536285Sbrian char namelist[LINE_LEN]; 21636285Sbrian char *name; 21736285Sbrian int f; 2186059Samurai 21936285Sbrian if (arg->argc == arg->argn) 22036285Sbrian return -1; 22136285Sbrian 22236285Sbrian namelist[sizeof namelist - 1] = '\0'; 22336285Sbrian for (f = arg->argn; f < arg->argc; f++) { 22436285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 22536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 22636285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2276059Samurai } 22836285Sbrian 22936285Sbrian return 0; 2306059Samurai} 2316059Samurai 2326059Samuraistatic int 23336285SbrianRemoveCommand(struct cmdargs const *arg) 2346059Samurai{ 23536285Sbrian if (arg->argc != arg->argn) 23636285Sbrian return -1; 23711336Samurai 23836285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 23936285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 24036285Sbrian return 2; 2416059Samurai } 24226516Sbrian 24336285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 24436285Sbrian return 0; 24536285Sbrian} 24632711Sbrian 24736285Sbrianstatic int 24836285SbrianRenameCommand(struct cmdargs const *arg) 24936285Sbrian{ 25036285Sbrian if (arg->argc != arg->argn + 1) 25136285Sbrian return -1; 25231121Sbrian 25336285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 25436285Sbrian return 0; 25536285Sbrian 25636285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 25736285Sbrian arg->cx->name, arg->argv[arg->argn]); 25836285Sbrian return 1; 25936285Sbrian} 26036285Sbrian 26136285Sbrianint 26236285SbrianLoadCommand(struct cmdargs const *arg) 26336285Sbrian{ 26436285Sbrian const char *name; 26536285Sbrian 26636285Sbrian if (arg->argc > arg->argn) 26736285Sbrian name = arg->argv[arg->argn]; 26836285Sbrian else 26936285Sbrian name = "default"; 27036285Sbrian 27136928Sbrian if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type.all)) { 27237019Sbrian log_Printf(LogWARN, "%s: Label not allowed\n", name); 27336285Sbrian return 1; 27436285Sbrian } else { 27536285Sbrian /* 27636285Sbrian * Set the label before & after so that `set enddisc' works and 27736285Sbrian * we handle nested `load' commands. 27836285Sbrian */ 27936285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28037008Sbrian if (system_Select(arg->bundle, name, CONFFILE, arg->prompt, arg->cx) < 0) { 28136285Sbrian bundle_SetLabel(arg->bundle, NULL); 28236285Sbrian log_Printf(LogWARN, "%s: label not found.\n", name); 28336285Sbrian return -1; 28432403Sbrian } 28536285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28636285Sbrian } 28726516Sbrian return 0; 2886059Samurai} 2896059Samurai 29036285Sbrianint 29136285SbrianSaveCommand(struct cmdargs const *arg) 29236285Sbrian{ 29336285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 29436285Sbrian return 1; 29536285Sbrian} 29636285Sbrian 29710528Samuraistatic int 29836285SbrianDialCommand(struct cmdargs const *arg) 29928536Sbrian{ 30036285Sbrian int res; 30136285Sbrian 30236465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 30336465Sbrian || (!arg->cx && 30436928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 30536285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 30636285Sbrian " interactive links\n"); 30736285Sbrian return 1; 30834536Sbrian } 30936285Sbrian 31036285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 31136285Sbrian return res; 31236285Sbrian 31337993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 31436285Sbrian 31536285Sbrian return 0; 31628536Sbrian} 31728536Sbrian 31828536Sbrianstatic int 31931343SbrianShellCommand(struct cmdargs const *arg, int bg) 32010528Samurai{ 32110528Samurai const char *shell; 32210528Samurai pid_t shpid; 32331343Sbrian int argc; 32431343Sbrian char *argv[MAXARGS]; 32520813Sjkh 32618856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 32726911Sbrian /* we're only allowed to shell when we run ppp interactively */ 32836285Sbrian if (arg->prompt && arg->prompt->owner) { 32936285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 33026516Sbrian return 1; 33110528Samurai } 33226911Sbrian#endif 33328679Sbrian 33436285Sbrian if (arg->argc == arg->argn) { 33536285Sbrian if (!arg->prompt) { 33636285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 33736285Sbrian " a config file\n"); 33828381Sbrian return 1; 33936285Sbrian } else if (arg->prompt->owner) { 34036285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 34136285Sbrian " a socket connection\n"); 34236285Sbrian return 1; 34328381Sbrian } else if (bg) { 34436285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 34528679Sbrian " the foreground mode\n"); 34628381Sbrian return 1; 34728381Sbrian } 34834536Sbrian } 34934536Sbrian 35028679Sbrian if ((shpid = fork()) == 0) { 35136285Sbrian int i, fd; 35218531Sbde 35336285Sbrian if ((shell = getenv("SHELL")) == 0) 35436285Sbrian shell = _PATH_BSHELL; 35532017Sbrian 35636285Sbrian timer_TermService(); 35736285Sbrian 35836285Sbrian if (arg->prompt) 35936285Sbrian fd = arg->prompt->fd_out; 36036285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 36136285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 36236285Sbrian _PATH_DEVNULL, strerror(errno)); 36328679Sbrian exit(1); 36428679Sbrian } 36528679Sbrian for (i = 0; i < 3; i++) 36628679Sbrian dup2(fd, i); 36726516Sbrian 36836285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 36926516Sbrian 37031061Sbrian setuid(geteuid()); 37136285Sbrian if (arg->argc > arg->argn) { 37228679Sbrian /* substitute pseudo args */ 37336285Sbrian argv[0] = strdup(arg->argv[arg->argn]); 37436285Sbrian for (argc = 1; argc < arg->argc - arg->argn; argc++) { 37536285Sbrian if (strcasecmp(arg->argv[argc + arg->argn], "HISADDR") == 0) 37636285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.peer_ip)); 37736285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "INTERFACE") == 0) 37836285Sbrian argv[argc] = strdup(arg->bundle->ifp.Name); 37936285Sbrian else if (strcasecmp(arg->argv[argc + arg->argn], "MYADDR") == 0) 38036285Sbrian argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.my_ip)); 38131343Sbrian else 38236285Sbrian argv[argc] = strdup(arg->argv[argc + arg->argn]); 38331343Sbrian } 38431343Sbrian argv[argc] = NULL; 38528679Sbrian if (bg) { 38628679Sbrian pid_t p; 38710528Samurai 38828679Sbrian p = getpid(); 38928679Sbrian if (daemon(1, 1) == -1) { 39036832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 39128679Sbrian exit(1); 39228679Sbrian } 39336285Sbrian } else if (arg->prompt) 39436285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 39531343Sbrian execvp(argv[0], argv); 39630316Sbrian } else { 39736285Sbrian if (arg->prompt) 39832017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 39936285Sbrian prompt_TtyOldMode(arg->prompt); 40031343Sbrian execl(shell, shell, NULL); 40130316Sbrian } 40220813Sjkh 40336285Sbrian log_Printf(LogWARN, "exec() of %s failed\n", 40436285Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell); 40528679Sbrian exit(255); 40610528Samurai } 40736285Sbrian 40836285Sbrian if (shpid == (pid_t) - 1) 40936285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 41036285Sbrian else { 41110528Samurai int status; 41231343Sbrian waitpid(shpid, &status, 0); 41310528Samurai } 41420813Sjkh 41536285Sbrian if (arg->prompt && !arg->prompt->owner) 41636285Sbrian prompt_TtyCommandMode(arg->prompt); 41720813Sjkh 41836285Sbrian return 0; 41910528Samurai} 42010528Samurai 42131343Sbrianstatic int 42231343SbrianBgShellCommand(struct cmdargs const *arg) 42331343Sbrian{ 42436285Sbrian if (arg->argc == arg->argn) 42531343Sbrian return -1; 42631343Sbrian return ShellCommand(arg, 1); 42731343Sbrian} 42831343Sbrian 42931343Sbrianstatic int 43031343SbrianFgShellCommand(struct cmdargs const *arg) 43131343Sbrian{ 43231343Sbrian return ShellCommand(arg, 0); 43331343Sbrian} 43431343Sbrian 43530715Sbrianstatic struct cmdtab const Commands[] = { 43636285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 43728679Sbrian "accept option request", "accept option .."}, 43828679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 43932109Sbrian "add route", "add dest mask gateway", NULL}, 44036285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 44132109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 44236285Sbrian#ifndef NOALIAS 44336285Sbrian {"alias", NULL, AliasCommand, LOCAL_AUTH, 44436285Sbrian "alias control", "alias option [yes|no]"}, 44536285Sbrian#endif 44631121Sbrian {"allow", "auth", AllowCommand, LOCAL_AUTH, 44731121Sbrian "Allow ppp access", "allow users|modes ...."}, 44828679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 44931372Sbrian "Run a background command", "[!]bg command"}, 45036934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45136934Sbrian "Clear throughput statistics", "clear ipcp|modem [current|overall|peak]..."}, 45236285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 45336285Sbrian "Clone a link", "clone newname..."}, 45436285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 45536285Sbrian "Close an FSM", "close [lcp|ccp]"}, 45628679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 45732109Sbrian "delete route", "delete dest", NULL}, 45836285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 45932109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 46036285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46128679Sbrian "Deny option request", "deny option .."}, 46236285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46337955Sbrian "Dial and login", "dial|call [remote]", NULL}, 46436285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46528679Sbrian "Disable option", "disable option .."}, 46636285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46736285Sbrian "Generate a down event", "down"}, 46836285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 46928679Sbrian "Enable option", "enable option .."}, 47036285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 47136285Sbrian "Link specific commands", "link name command ..."}, 47237008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 47328679Sbrian "Load settings", "load [remote]"}, 47436285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 47537955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 47636285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 47736285Sbrian "Password for manipulation", "passwd LocalPassword"}, 47836285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 47936285Sbrian "Quit PPP program", "quit|bye [all]"}, 48036285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 48136285Sbrian "Remove a link", "remove"}, 48236285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 48336285Sbrian "Rename a link", "rename name"}, 48428679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 48528679Sbrian "Save settings", "save"}, 48636285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 48728679Sbrian "Set parameters", "set[up] var value"}, 48828679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 48928679Sbrian "Run a subshell", "shell|! [sh command]"}, 49036285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 49131372Sbrian "Show status and stats", "show var"}, 49236285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 49331372Sbrian "Enter terminal mode", "term"}, 49428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 49531343Sbrian "Display this message", "help|? [command]", Commands}, 49628679Sbrian {NULL, NULL, NULL}, 4976059Samurai}; 4986059Samurai 49928536Sbrianstatic int 50031343SbrianShowEscape(struct cmdargs const *arg) 5016059Samurai{ 50236285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 50336285Sbrian int code, bit; 50436285Sbrian const char *sep = ""; 5056059Samurai 50626516Sbrian for (code = 0; code < 32; code++) 50736285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 50828679Sbrian for (bit = 0; bit < 8; bit++) 50936285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 51036285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 51136285Sbrian sep = ", "; 51236285Sbrian } 51336285Sbrian prompt_Printf(arg->prompt, "\n"); 5146059Samurai } 51531077Sbrian return 0; 5166059Samurai} 5176059Samurai 51828679Sbrianstatic int 51936285SbrianShowTimerList(struct cmdargs const *arg) 5206059Samurai{ 52136285Sbrian timer_Show(0, arg->prompt); 52231077Sbrian return 0; 5236059Samurai} 5246059Samurai 52528679Sbrianstatic int 52631343SbrianShowStopped(struct cmdargs const *arg) 52728327Sbrian{ 52836285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 52936285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 53036285Sbrian prompt_Printf(arg->prompt, "Disabled"); 53128327Sbrian else 53236285Sbrian prompt_Printf(arg->prompt, "%ld secs", 53336285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 53428461Sbrian 53536285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 53636285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 53736285Sbrian prompt_Printf(arg->prompt, "Disabled"); 53828461Sbrian else 53936285Sbrian prompt_Printf(arg->prompt, "%ld secs", 54036285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 54128461Sbrian 54236285Sbrian prompt_Printf(arg->prompt, "\n"); 54328461Sbrian 54431077Sbrian return 0; 54528327Sbrian} 54628327Sbrian 54728679Sbrianstatic int 54831343SbrianShowVersion(struct cmdargs const *arg) 5496059Samurai{ 55036285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 55131077Sbrian return 0; 5526059Samurai} 5536059Samurai 55428679Sbrianstatic int 55536285SbrianShowProtocolStats(struct cmdargs const *arg) 55626326Sbrian{ 55736285Sbrian struct link *l = command_ChooseLink(arg); 55826326Sbrian 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) 84137993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 84237160Sbrian else if (arg->argc == arg->argn + 1) { 84337160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 84437385Sbrian struct datalink *cx = arg->cx ? 84537385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 84637385Sbrian if (cx) { 84737385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 84837385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 84937160Sbrian else 85037993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 85137160Sbrian } else 85237160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 85337160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 85437160Sbrian struct fsm *fp; 8556059Samurai 85637210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 85737160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 85837160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 85937160Sbrian else if (fp->state == ST_OPENED) 86037160Sbrian fsm_Reopen(fp); 86137160Sbrian else { 86237160Sbrian fp->open_mode = 0; /* Not passive any more */ 86337160Sbrian if (fp->state == ST_STOPPED) { 86437160Sbrian fsm_Down(fp); 86537160Sbrian fsm_Up(fp); 86637160Sbrian } else { 86737160Sbrian fsm_Up(fp); 86837160Sbrian fsm_Open(fp); 86937160Sbrian } 87036285Sbrian } 87137160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 87237160Sbrian if (arg->cx) 87337160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 87437160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 87537160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 87637160Sbrian else 87737993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 87837160Sbrian } else 87937160Sbrian return -1; 88036285Sbrian } else 88136285Sbrian return -1; 88236285Sbrian 88326516Sbrian return 0; 8846059Samurai} 8856059Samurai 88625067Sbrianstatic int 88736285SbrianCloseCommand(struct cmdargs const *arg) 8886059Samurai{ 88937007Sbrian if (arg->argc == arg->argn) 89037007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 89137007Sbrian else if (arg->argc == arg->argn + 1) { 89237007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 89337007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 89437007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 89537007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 89637007Sbrian struct fsm *fp; 8976059Samurai 89837210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 89937007Sbrian if (fp->state == ST_OPENED) { 90037007Sbrian fsm_Close(fp); 90137007Sbrian if (arg->argv[arg->argn][3] == '!') 90237007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 90337007Sbrian else 90437007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 90537007Sbrian } 90637007Sbrian } else 90736285Sbrian return -1; 90836285Sbrian } else 90936285Sbrian return -1; 91036285Sbrian 91136285Sbrian return 0; 9126059Samurai} 9136059Samurai 91425067Sbrianstatic int 91536285SbrianDownCommand(struct cmdargs const *arg) 91611336Samurai{ 91737018Sbrian if (arg->argc == arg->argn) { 91837018Sbrian if (arg->cx) 91937018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 92037018Sbrian else 92137018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 92237018Sbrian } else if (arg->argc == arg->argn + 1) { 92337018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 92437018Sbrian if (arg->cx) 92537018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 92637018Sbrian else 92737018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 92837018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 92937018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 93037018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 93137060Sbrian fsm2initial(fp); 93237018Sbrian } else 93337018Sbrian return -1; 93436285Sbrian } else 93536285Sbrian return -1; 93636285Sbrian 93736285Sbrian return 0; 93825067Sbrian} 93925067Sbrian 94025067Sbrianstatic int 94136285SbrianSetModemSpeed(struct cmdargs const *arg) 94225067Sbrian{ 94336285Sbrian long speed; 94436285Sbrian char *end; 94511336Samurai 94636285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 94736285Sbrian if (arg->argc > arg->argn+1) { 94836285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 94936285Sbrian return -1; 95011336Samurai } 95136285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 95236285Sbrian physical_SetSync(arg->cx->physical); 95336285Sbrian return 0; 95436285Sbrian } 95536285Sbrian end = NULL; 95636285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 95736285Sbrian if (*end) { 95836285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 95936285Sbrian arg->argv[arg->argn]); 96036285Sbrian return -1; 96136285Sbrian } 96236285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 96336285Sbrian return 0; 96436285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 96536285Sbrian } else 96636285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 96724939Sbrian 96826516Sbrian return -1; 96911336Samurai} 97011336Samurai 97125067Sbrianstatic int 97231343SbrianSetStoppedTimeout(struct cmdargs const *arg) 97328327Sbrian{ 97436285Sbrian struct link *l = &arg->cx->physical->link; 97536285Sbrian 97636285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 97736285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 97836285Sbrian if (arg->argc <= arg->argn+2) { 97936285Sbrian if (arg->argc > arg->argn) { 98036285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 98136285Sbrian if (arg->argc > arg->argn+1) 98236285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 98328461Sbrian } 98428327Sbrian return 0; 98528327Sbrian } 98628327Sbrian return -1; 98728327Sbrian} 98828327Sbrian 98931081Sbrian#define ismask(x) \ 99031081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 99131081Sbrian 99228327Sbrianstatic int 99331343SbrianSetServer(struct cmdargs const *arg) 99426940Sbrian{ 99526940Sbrian int res = -1; 99626940Sbrian 99736285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 99831081Sbrian const char *port, *passwd, *mask; 99931081Sbrian 100031081Sbrian /* What's what ? */ 100136285Sbrian port = arg->argv[arg->argn]; 100236285Sbrian if (arg->argc == arg->argn + 2) { 100336285Sbrian passwd = arg->argv[arg->argn+1]; 100436285Sbrian mask = NULL; 100536285Sbrian } else if (arg->argc == arg->argn + 3) { 100636285Sbrian passwd = arg->argv[arg->argn+1]; 100736285Sbrian mask = arg->argv[arg->argn+2]; 100831081Sbrian if (!ismask(mask)) 100931081Sbrian return -1; 101036285Sbrian } else if (strcasecmp(port, "none") == 0) { 101136285Sbrian if (server_Close(arg->bundle)) 101236285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 101336285Sbrian return 0; 101431081Sbrian } else 101536285Sbrian return -1; 101631081Sbrian 101736285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 101836285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 101931081Sbrian 102036285Sbrian if (*port == '/') { 102131081Sbrian mode_t imask; 102236285Sbrian char *ptr, name[LINE_LEN + 12]; 102328679Sbrian 102431081Sbrian if (mask != NULL) { 102528679Sbrian unsigned m; 102628679Sbrian 102731081Sbrian if (sscanf(mask, "%o", &m) == 1) 102831081Sbrian imask = m; 102931081Sbrian else 103031081Sbrian return -1; 103131081Sbrian } else 103231081Sbrian imask = (mode_t)-1; 103336285Sbrian 103436285Sbrian ptr = strstr(port, "%d"); 103536285Sbrian if (ptr) { 103636285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 103737210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 103836285Sbrian port = name; 103936285Sbrian } 104036285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 104127346Sbrian } else { 104236285Sbrian int iport, add = 0; 104328679Sbrian 104431081Sbrian if (mask != NULL) 104531081Sbrian return -1; 104628679Sbrian 104736285Sbrian if (*port == '+') { 104836285Sbrian port++; 104936285Sbrian add = 1; 105036285Sbrian } 105131081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 105231081Sbrian struct servent *s; 105331081Sbrian 105431081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 105531081Sbrian iport = 0; 105636285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 105728679Sbrian } else 105831081Sbrian iport = ntohs(s->s_port); 105927346Sbrian } else 106031081Sbrian iport = atoi(port); 106136285Sbrian 106236285Sbrian if (iport) { 106336285Sbrian if (add) 106436285Sbrian iport += arg->bundle->unit; 106536285Sbrian res = server_TcpOpen(arg->bundle, iport); 106636285Sbrian } else 106736285Sbrian res = -1; 106827346Sbrian } 106931081Sbrian } 107026940Sbrian 107126940Sbrian return res; 107226940Sbrian} 107326940Sbrian 107426940Sbrianstatic int 107531343SbrianSetModemParity(struct cmdargs const *arg) 10766059Samurai{ 107736285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 107836285Sbrian arg->argv[arg->argn]) : -1; 10796059Samurai} 10806059Samurai 10816059Samuraistatic int 108231343SbrianSetEscape(struct cmdargs const *arg) 10836059Samurai{ 10846059Samurai int code; 108536285Sbrian int argc = arg->argc - arg->argn; 108636285Sbrian char const *const *argv = arg->argv + arg->argn; 10876059Samurai 10886059Samurai for (code = 0; code < 33; code++) 108936285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 109031343Sbrian 10916059Samurai while (argc-- > 0) { 10926059Samurai sscanf(*argv++, "%x", &code); 10936059Samurai code &= 0xff; 109436285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 109536285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 10966059Samurai } 109726516Sbrian return 0; 10986059Samurai} 10996059Samurai 110030715Sbrianstatic struct in_addr 110131343SbrianGetIpAddr(const char *cp) 11026059Samurai{ 11036059Samurai struct hostent *hp; 11046059Samurai struct in_addr ipaddr; 11056059Samurai 110632124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 110732124Sbrian hp = gethostbyname(cp); 110832124Sbrian if (hp && hp->h_addrtype == AF_INET) 110932124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 111032124Sbrian else 111132124Sbrian ipaddr.s_addr = 0; 111232124Sbrian } 111328679Sbrian return (ipaddr); 11146059Samurai} 11156059Samurai 11166059Samuraistatic int 111731343SbrianSetInterfaceAddr(struct cmdargs const *arg) 11186059Samurai{ 111936285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 112032267Sbrian const char *hisaddr; 112132267Sbrian 112232267Sbrian hisaddr = NULL; 112336285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 112436285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 11256059Samurai 112636285Sbrian if (arg->argc > arg->argn + 4) 112728679Sbrian return -1; 112826516Sbrian 112936285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 113036285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 113136285Sbrian iplist_reset(&ipcp->cfg.peer_list); 113228394Sbrian 113336285Sbrian if (arg->argc > arg->argn) { 113436285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 113536285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 113636285Sbrian &ipcp->cfg.my_range.width)) 113728679Sbrian return 1; 113836285Sbrian if (arg->argc > arg->argn+1) { 113936285Sbrian hisaddr = arg->argv[arg->argn+1]; 114036285Sbrian if (arg->argc > arg->argn+2) { 114136285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 114236285Sbrian if (arg->argc > arg->argn+3) { 114336285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 114436285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 11459440Samurai } 11466059Samurai } 11476059Samurai } 11486059Samurai } 114928394Sbrian 11506059Samurai /* 11516059Samurai * For backwards compatibility, 0.0.0.0 means any address. 11526059Samurai */ 115336285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 115436285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 115536285Sbrian ipcp->cfg.my_range.width = 0; 11566059Samurai } 115736285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 115836285Sbrian 115936285Sbrian if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 116036285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 116136285Sbrian ipcp->cfg.peer_range.width = 0; 11626059Samurai } 116328537Sbrian 116436285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 116536928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 116632267Sbrian return 4; 116731121Sbrian 116826516Sbrian return 0; 11696059Samurai} 11706059Samurai 117118752Sjkhstatic int 117231343SbrianSetVariable(struct cmdargs const *arg) 11736059Samurai{ 117437210Sbrian long long_val, param = (long)arg->cmd->args; 117537210Sbrian int mode, dummyint; 117631343Sbrian const char *argp; 117736285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 117836285Sbrian const char *err = NULL; 117936285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 118036285Sbrian struct in_addr dummyaddr, *addr; 11816059Samurai 118236285Sbrian if (arg->argc > arg->argn) 118336285Sbrian argp = arg->argv[arg->argn]; 118426551Sbrian else 118531343Sbrian argp = ""; 118626551Sbrian 118736285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 118836285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 118936285Sbrian arg->cmd->name); 119036285Sbrian return 1; 119136285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 119236285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 119336285Sbrian arg->cmd->name, cx->name); 119436285Sbrian cx = NULL; 119536285Sbrian } 119636285Sbrian 119726551Sbrian switch (param) { 119828679Sbrian case VAR_AUTHKEY: 119936285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 120036285Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 120136285Sbrian sizeof arg->bundle->cfg.auth.key - 1); 120236285Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 120336285Sbrian } else { 120436285Sbrian err = "set authkey: Only available at phase DEAD\n"; 120536285Sbrian log_Printf(LogWARN, err); 120636285Sbrian } 120728679Sbrian break; 120837210Sbrian 120928679Sbrian case VAR_AUTHNAME: 121036285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 121136285Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 121236285Sbrian sizeof arg->bundle->cfg.auth.name - 1); 121336285Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 121436285Sbrian } else { 121536285Sbrian err = "set authname: Only available at phase DEAD\n"; 121636285Sbrian log_Printf(LogWARN, err); 121736285Sbrian } 121828679Sbrian break; 121937210Sbrian 122036285Sbrian case VAR_AUTOLOAD: 122136285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 122236285Sbrian arg->bundle->autoload.running = 1; 122336285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 122436285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 122536285Sbrian if (arg->argc == arg->argn + 4) { 122636285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 122736285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 122836285Sbrian } else { 122936285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 123036285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 123136285Sbrian } 123236285Sbrian } else { 123336285Sbrian err = "Set autoload requires two or four arguments\n"; 123436285Sbrian log_Printf(LogWARN, err); 123536285Sbrian } 123636285Sbrian break; 123737210Sbrian 123828679Sbrian case VAR_DIAL: 123936285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 124036285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 124128679Sbrian break; 124237210Sbrian 124328679Sbrian case VAR_LOGIN: 124436285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 124536285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 124628679Sbrian break; 124737210Sbrian 124836285Sbrian case VAR_WINSIZE: 124936285Sbrian if (arg->argc > arg->argn) { 125036285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 125136285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 125236285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 125336285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 125436285Sbrian l->ccp.cfg.deflate.out.winsize); 125536285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 125636285Sbrian } 125736285Sbrian if (arg->argc > arg->argn+1) { 125836285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 125936285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 126036285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 126136285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 126236285Sbrian l->ccp.cfg.deflate.in.winsize); 126336285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 126436285Sbrian } 126536285Sbrian } else 126636285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 126736285Sbrian } else { 126836285Sbrian err = "No window size specified\n"; 126936285Sbrian log_Printf(LogWARN, err); 127036285Sbrian } 127136285Sbrian break; 127237210Sbrian 127328679Sbrian case VAR_DEVICE: 127436285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 127536285Sbrian arg->argv + arg->argn); 127636285Sbrian break; 127737210Sbrian 127836285Sbrian case VAR_ACCMAP: 127936285Sbrian if (arg->argc > arg->argn) { 128037210Sbrian u_long ulong_val; 128136285Sbrian sscanf(argp, "%lx", &ulong_val); 128237210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 128336285Sbrian } else { 128436285Sbrian err = "No accmap specified\n"; 128536285Sbrian log_Printf(LogWARN, err); 128636285Sbrian } 128736285Sbrian break; 128837210Sbrian 128936285Sbrian case VAR_MODE: 129036285Sbrian mode = Nam2mode(argp); 129136285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 129236285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 129336285Sbrian return -1; 129436285Sbrian } 129536285Sbrian bundle_SetMode(arg->bundle, cx, mode); 129636285Sbrian break; 129737210Sbrian 129836285Sbrian case VAR_MRRU: 129937210Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) { 130036285Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); 130137210Sbrian return 1; 130229696Sbrian } 130337210Sbrian long_val = atol(argp); 130437210Sbrian if (long_val && long_val < MIN_MRU) { 130537210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 130637210Sbrian return 1; 130737210Sbrian } else if (long_val > MAX_MRU) { 130837210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 130937210Sbrian return 1; 131037210Sbrian } else 131137210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 131228679Sbrian break; 131337210Sbrian 131436285Sbrian case VAR_MRU: 131537210Sbrian long_val = atol(argp); 131637210Sbrian if (long_val == 0) 131737210Sbrian l->lcp.cfg.mru = DEF_MRU; 131837210Sbrian else if (long_val < MIN_MRU) { 131937210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 132037210Sbrian return 1; 132137210Sbrian } else if (long_val > MAX_MRU) { 132237210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 132337210Sbrian return 1; 132437210Sbrian } else 132537210Sbrian l->lcp.cfg.mru = long_val; 132628679Sbrian break; 132737210Sbrian 132836285Sbrian case VAR_MTU: 132937210Sbrian long_val = atol(argp); 133037210Sbrian if (long_val && long_val < MIN_MTU) { 133137210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 133237210Sbrian return 1; 133337210Sbrian } else if (long_val > MAX_MTU) { 133437210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 133537210Sbrian return 1; 133637210Sbrian } else 133737210Sbrian arg->bundle->cfg.mtu = long_val; 133836285Sbrian break; 133937210Sbrian 134036285Sbrian case VAR_OPENMODE: 134136285Sbrian if (strcasecmp(argp, "active") == 0) 134236285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 134336285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 134436285Sbrian else if (strcasecmp(argp, "passive") == 0) 134536285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 134636285Sbrian else { 134736285Sbrian err = "%s: Invalid openmode\n"; 134836285Sbrian log_Printf(LogWARN, err, argp); 134936285Sbrian } 135036285Sbrian break; 135137210Sbrian 135228679Sbrian case VAR_PHONE: 135336285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 135436285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 135538174Sbrian cx->phone.alt = cx->phone.next = NULL; 135628679Sbrian break; 135737210Sbrian 135828679Sbrian case VAR_HANGUP: 135936285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 136036285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 136128679Sbrian break; 136237210Sbrian 136336285Sbrian case VAR_IDLETIMEOUT: 136436285Sbrian if (arg->argc > arg->argn+1) 136536285Sbrian err = "Too many idle timeout values\n"; 136636285Sbrian else if (arg->argc == arg->argn+1) 136736285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 136836285Sbrian if (err) 136936285Sbrian log_Printf(LogWARN, err); 137029549Sbrian break; 137137210Sbrian 137236285Sbrian case VAR_LQRPERIOD: 137337210Sbrian long_val = atol(argp); 137437210Sbrian if (long_val < MIN_LQRPERIOD) { 137537210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 137637210Sbrian long_val, MIN_LQRPERIOD); 137737210Sbrian return 1; 137836285Sbrian } else 137937210Sbrian l->lcp.cfg.lqrperiod = long_val; 138036285Sbrian break; 138137210Sbrian 138236285Sbrian case VAR_LCPRETRY: 138337210Sbrian long_val = atol(argp); 138437210Sbrian if (long_val < MIN_FSMRETRY) { 138537210Sbrian log_Printf(LogWARN, "%ld: Invalid LCP FSM retry period - min %d\n", 138637210Sbrian long_val, MIN_FSMRETRY); 138737210Sbrian return 1; 138836285Sbrian } else 138937210Sbrian cx->physical->link.lcp.cfg.fsmretry = long_val; 139036285Sbrian break; 139137210Sbrian 139236285Sbrian case VAR_CHAPRETRY: 139337210Sbrian long_val = atol(argp); 139437210Sbrian if (long_val < MIN_FSMRETRY) { 139537210Sbrian log_Printf(LogWARN, "%ld: Invalid CHAP FSM retry period - min %d\n", 139637210Sbrian long_val, MIN_FSMRETRY); 139737210Sbrian return 1; 139836285Sbrian } else 139937210Sbrian cx->chap.auth.cfg.fsmretry = long_val; 140036285Sbrian break; 140137210Sbrian 140236285Sbrian case VAR_PAPRETRY: 140337210Sbrian long_val = atol(argp); 140437210Sbrian if (long_val < MIN_FSMRETRY) { 140537210Sbrian log_Printf(LogWARN, "%ld: Invalid PAP FSM retry period - min %d\n", 140637210Sbrian long_val, MIN_FSMRETRY); 140737210Sbrian return 1; 140836285Sbrian } else 140937210Sbrian cx->pap.cfg.fsmretry = long_val; 141036285Sbrian break; 141137210Sbrian 141236285Sbrian case VAR_CCPRETRY: 141337210Sbrian long_val = atol(argp); 141437210Sbrian if (long_val < MIN_FSMRETRY) { 141537210Sbrian log_Printf(LogWARN, "%ld: Invalid CCP FSM retry period - min %d\n", 141637210Sbrian long_val, MIN_FSMRETRY); 141737210Sbrian return 1; 141836285Sbrian } else 141937210Sbrian l->ccp.cfg.fsmretry = long_val; 142036285Sbrian break; 142137210Sbrian 142236285Sbrian case VAR_IPCPRETRY: 142337210Sbrian long_val = atol(argp); 142437210Sbrian if (long_val < MIN_FSMRETRY) { 142537210Sbrian log_Printf(LogWARN, "%ld: Invalid IPCP FSM retry period - min %d\n", 142637210Sbrian long_val, MIN_FSMRETRY); 142737210Sbrian return 1; 142836285Sbrian } else 142937210Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = long_val; 143036285Sbrian break; 143137210Sbrian 143236285Sbrian case VAR_NBNS: 143336285Sbrian case VAR_DNS: 143436285Sbrian if (param == VAR_DNS) 143536285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 143636285Sbrian else 143736285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 143836285Sbrian 143936285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 144036285Sbrian 144136285Sbrian if (arg->argc > arg->argn) { 144236285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 144336285Sbrian addr, &dummyaddr, &dummyint); 144436285Sbrian if (arg->argc > arg->argn+1) 144536285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 144636285Sbrian addr + 1, &dummyaddr, &dummyint); 144736285Sbrian 144836285Sbrian if (addr[1].s_addr == INADDR_ANY) 144936285Sbrian addr[1].s_addr = addr[0].s_addr; 145036285Sbrian if (addr[0].s_addr == INADDR_ANY) 145136285Sbrian addr[0].s_addr = addr[1].s_addr; 145236285Sbrian } 145336285Sbrian break; 145438174Sbrian 145538174Sbrian case VAR_CALLBACK: 145638174Sbrian cx->cfg.callback.opmask = 0; 145738174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 145838174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 145938174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 146038174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 146138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 146238174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 146338174Sbrian if (dummyint == arg->argc - 1) 146438174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 146538174Sbrian else { 146638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 146738174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 146838174Sbrian sizeof cx->cfg.callback.msg - 1); 146938174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 147038174Sbrian } 147138174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 147238174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 147338174Sbrian else 147438174Sbrian return -1; 147538174Sbrian } 147638174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 147738174Sbrian cx->cfg.callback.opmask = 0; 147838174Sbrian break; 147938174Sbrian 148038174Sbrian case VAR_CBCP: 148138174Sbrian cx->cfg.cbcp.delay = 0; 148238174Sbrian *cx->cfg.cbcp.phone = '\0'; 148338174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 148438174Sbrian if (arg->argc > arg->argn) { 148538174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 148638174Sbrian sizeof cx->cfg.cbcp.phone - 1); 148738174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 148838174Sbrian if (arg->argc > arg->argn + 1) { 148938174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 149038174Sbrian if (arg->argc > arg->argn + 2) { 149138174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 149238174Sbrian if (long_val < MIN_FSMRETRY) 149338174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 149438174Sbrian long_val, MIN_FSMRETRY); 149538174Sbrian else 149638174Sbrian cx->cfg.cbcp.fsmretry = long_val; 149738174Sbrian } 149838174Sbrian } 149938174Sbrian } 150038174Sbrian break; 150138544Sbrian 150238544Sbrian case VAR_CHOKED: 150338544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 150438544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 150538544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 150638544Sbrian break; 150738544Sbrian 15086059Samurai } 150936285Sbrian 151036285Sbrian return err ? 1 : 0; 15116059Samurai} 15126059Samurai 151328679Sbrianstatic int 151431343SbrianSetCtsRts(struct cmdargs const *arg) 151520812Sjkh{ 151636285Sbrian if (arg->argc == arg->argn+1) { 151736285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 151836285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 151936285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 152036285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 152120812Sjkh else 152226516Sbrian return -1; 152326516Sbrian return 0; 152420812Sjkh } 152526516Sbrian return -1; 152620812Sjkh} 152720812Sjkh 152830715Sbrianstatic struct cmdtab const SetCommands[] = { 152936285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 153036285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 153128679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 153236285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 153328679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 153436285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 153536285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 153636285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 153736285Sbrian (const void *)VAR_AUTOLOAD}, 153838174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 153938174Sbrian "callback control", "set callback [none|auth|cbcp|" 154038174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 154138174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 154238174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 154338174Sbrian (const void *)VAR_CBCP}, 154436285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 154536285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 154636285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 154736285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 154838544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 154938544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 155036285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 155136285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 155236285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 155336285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 155436285Sbrian (const void *) VAR_WINSIZE}, 155536285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 155636285Sbrian "modem device name", "set device|line device-name[,device-name]", 155736285Sbrian (const void *) VAR_DEVICE}, 155836285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 155936285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 156036285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 156136285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 156236285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 156336285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 156436285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 156536285Sbrian "escape characters", "set escape hex-digit ..."}, 156636285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 156736285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 156836285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 156936285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 157036285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 157136285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 157236285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 157331343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 157436285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 157536285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 157636285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 157736285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 157836712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 157936712Sbrian "set log [local] [+|-]async|ccp|chat|command|connect|debug|hdlc|id0|ipcp|" 158036712Sbrian "lcp|lqm|phase|tcp/ip|timer|tun..."}, 158136285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 158236285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 158336285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 158436285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 158536285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 158636285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 158736285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 158836285Sbrian "set mrru value", (const void *)VAR_MRRU}, 158936285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 159036285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 159136285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 159236285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 159336285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 159436285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 159536285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 159636285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 159736285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 159836285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 159936285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 160036285Sbrian "modem parity", "set parity [odd|even|none]"}, 160136285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 160236285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 160336285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 160436285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 160536285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 160636285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 160728679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 160836774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 160936285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 161036285Sbrian "modem speed", "set speed value"}, 161136285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 161236285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 161336285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 161436285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 161536285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 161636285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 161736285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 161836285Sbrian "datalink weighting", "set weight n"}, 161928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 162031343Sbrian "Display this message", "set help|? [command]", SetCommands}, 162128679Sbrian {NULL, NULL, NULL}, 16226059Samurai}; 16236059Samurai 16246059Samuraistatic int 162531343SbrianSetCommand(struct cmdargs const *arg) 16266059Samurai{ 162736285Sbrian if (arg->argc > arg->argn) 162836285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 162936285Sbrian arg->prompt, arg->cx); 163036285Sbrian else if (arg->prompt) 163136285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 163226516Sbrian " syntax help.\n"); 16336059Samurai else 163436285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 163526516Sbrian 163626516Sbrian return 0; 16376059Samurai} 16386059Samurai 16396059Samurai 16406059Samuraistatic int 164131343SbrianAddCommand(struct cmdargs const *arg) 16426059Samurai{ 16436059Samurai struct in_addr dest, gateway, netmask; 164436285Sbrian int gw, addrs; 16456059Samurai 164636285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 164731598Sbrian return -1; 164831598Sbrian 164936285Sbrian addrs = 0; 165036285Sbrian if (arg->argc == arg->argn+2) { 165136285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 165236285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 165331598Sbrian else { 165436285Sbrian int width; 165536285Sbrian 165636285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 165736285Sbrian &dest, &netmask, &width)) 165836285Sbrian return -1; 165936285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 166036285Sbrian addrs = ROUTE_DSTMYADDR; 166136285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 166236285Sbrian addrs = ROUTE_DSTHISADDR; 166331598Sbrian } 166436285Sbrian gw = 1; 166534536Sbrian } else { 166636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 166736285Sbrian addrs = ROUTE_DSTMYADDR; 166836285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 166936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 167036285Sbrian addrs = ROUTE_DSTHISADDR; 167136285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 167236285Sbrian } else 167336285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 167436285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 167531598Sbrian gw = 2; 16766059Samurai } 167736285Sbrian 167836285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 167936285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 168036285Sbrian addrs |= ROUTE_GWHISADDR; 168136285Sbrian } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0) 168231598Sbrian gateway.s_addr = INADDR_ANY; 168331598Sbrian else 168436285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 168536285Sbrian 168636285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 168737927Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0)) 168836285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 168936285Sbrian 169031598Sbrian return 0; 16916059Samurai} 16926059Samurai 16936059Samuraistatic int 169431343SbrianDeleteCommand(struct cmdargs const *arg) 16956059Samurai{ 169631598Sbrian struct in_addr dest, none; 169736285Sbrian int addrs; 16986059Samurai 169936285Sbrian if (arg->argc == arg->argn+1) { 170036285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 170136285Sbrian route_IfDelete(arg->bundle, 0); 170236285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 170336285Sbrian } else { 170436285Sbrian addrs = 0; 170536285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 170636285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 170736285Sbrian addrs = ROUTE_DSTMYADDR; 170836285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 170936285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 171036285Sbrian addrs = ROUTE_DSTHISADDR; 171136285Sbrian } else { 171236285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 171336285Sbrian dest.s_addr = INADDR_ANY; 171436285Sbrian else 171536285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 171636285Sbrian addrs = ROUTE_STATIC; 171736285Sbrian } 171831598Sbrian none.s_addr = INADDR_ANY; 171936285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 172037927Sbrian arg->cmd->args ? 1 : 0, 0); 172136285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 172231598Sbrian } 172334536Sbrian } else 172426516Sbrian return -1; 172526516Sbrian 172626516Sbrian return 0; 17276059Samurai} 17286059Samurai 172931343Sbrian#ifndef NOALIAS 173026031Sbrianstatic struct cmdtab const AliasCommands[] = 173126031Sbrian{ 173236285Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 173336285Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 173436285Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 173536285Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 173636285Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 173728679Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 173836285Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 173928679Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 174036285Sbrian "log aliasing link creation", "alias log [yes|no]", 174136285Sbrian (const void *) PKT_ALIAS_LOG}, 174236285Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 174336285Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 174428679Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 174536285Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 174636285Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 174736285Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 174836285Sbrian "alias unregistered (private) IP address space only", 174936285Sbrian "alias unregistered_only [yes|no]", 175036285Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 175128679Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 175236285Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 175336285Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 175428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 175536285Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 175628679Sbrian {NULL, NULL, NULL}, 175726031Sbrian}; 175826031Sbrian 175926031Sbrian 176026031Sbrianstatic int 176131343SbrianAliasCommand(struct cmdargs const *arg) 176226031Sbrian{ 176336285Sbrian if (arg->argc > arg->argn) 176436285Sbrian FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv, 176536285Sbrian arg->prompt, arg->cx); 176636285Sbrian else if (arg->prompt) 176736285Sbrian prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 176836285Sbrian " <option>' for syntax help.\n"); 176926031Sbrian else 177036285Sbrian log_Printf(LogWARN, "alias command must have arguments\n"); 177126516Sbrian 177226516Sbrian return 0; 177326031Sbrian} 177426031Sbrian 177526031Sbrianstatic int 177631343SbrianAliasEnable(struct cmdargs const *arg) 177726031Sbrian{ 177836285Sbrian if (arg->argc == arg->argn+1) { 177936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 178037191Sbrian arg->bundle->AliasEnabled = 1; 178137191Sbrian return 0; 178236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 178337191Sbrian arg->bundle->AliasEnabled = 0; 178426516Sbrian return 0; 178526142Sbrian } 178635449Sbrian } 178736285Sbrian 178826516Sbrian return -1; 178926031Sbrian} 179026031Sbrian 179126031Sbrian 179226031Sbrianstatic int 179331343SbrianAliasOption(struct cmdargs const *arg) 179426031Sbrian{ 179536285Sbrian unsigned param = (unsigned)arg->cmd->args; 179636285Sbrian if (arg->argc == arg->argn+1) { 179736285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 179837191Sbrian if (arg->bundle->AliasEnabled) { 179937191Sbrian PacketAliasSetMode(param, param); 180028679Sbrian return 0; 180128679Sbrian } 180236285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 180336285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 180437191Sbrian if (arg->bundle->AliasEnabled) { 180537191Sbrian PacketAliasSetMode(0, param); 180628679Sbrian return 0; 180728679Sbrian } 180836285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 180928679Sbrian } 181035449Sbrian } 181128679Sbrian return -1; 181226031Sbrian} 181331343Sbrian#endif /* #ifndef NOALIAS */ 181431121Sbrian 181531121Sbrianstatic struct cmdtab const AllowCommands[] = { 181636285Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 181736285Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 181831121Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 181931121Sbrian "Allow users access to ppp", "allow users logname..."}, 182031121Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 182131343Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 182231121Sbrian {NULL, NULL, NULL}, 182331121Sbrian}; 182431121Sbrian 182531121Sbrianstatic int 182631343SbrianAllowCommand(struct cmdargs const *arg) 182731121Sbrian{ 182836285Sbrian /* arg->bundle may be NULL (see system_IsValid()) ! */ 182936285Sbrian if (arg->argc > arg->argn) 183036285Sbrian FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv, 183136285Sbrian arg->prompt, arg->cx); 183236285Sbrian else if (arg->prompt) 183336285Sbrian prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 183436285Sbrian " for syntax help.\n"); 183531121Sbrian else 183636285Sbrian log_Printf(LogWARN, "allow command must have arguments\n"); 183731121Sbrian 183831121Sbrian return 0; 183931121Sbrian} 184036285Sbrian 184136285Sbrianstatic int 184236285SbrianLinkCommand(struct cmdargs const *arg) 184336285Sbrian{ 184436285Sbrian if (arg->argc > arg->argn+1) { 184536285Sbrian char namelist[LINE_LEN]; 184636285Sbrian struct datalink *cx; 184736285Sbrian char *name; 184836285Sbrian int result = 0; 184936285Sbrian 185036285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 185136285Sbrian struct datalink *dl; 185236285Sbrian 185336285Sbrian cx = arg->bundle->links; 185436285Sbrian while (cx) { 185536285Sbrian /* Watch it, the command could be a ``remove'' */ 185636285Sbrian dl = cx->next; 185736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 185836285Sbrian arg->prompt, cx); 185936285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 186036285Sbrian if (cx == dl) 186136285Sbrian break; /* Pointer's still valid ! */ 186236285Sbrian } 186336285Sbrian } else { 186436285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 186536285Sbrian namelist[sizeof namelist - 1] = '\0'; 186636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 186736285Sbrian if (!bundle2datalink(arg->bundle, name)) { 186836285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 186936285Sbrian return 1; 187036285Sbrian } 187136285Sbrian 187236285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 187336285Sbrian namelist[sizeof namelist - 1] = '\0'; 187436285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 187536285Sbrian cx = bundle2datalink(arg->bundle, name); 187636285Sbrian if (cx) 187736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 187836285Sbrian arg->prompt, cx); 187936285Sbrian else { 188036285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 188136285Sbrian result++; 188236285Sbrian } 188336285Sbrian } 188436285Sbrian } 188536285Sbrian return result; 188636285Sbrian } 188736285Sbrian 188836285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 188936285Sbrian return 2; 189036285Sbrian} 189136285Sbrian 189236285Sbrianstruct link * 189336285Sbriancommand_ChooseLink(struct cmdargs const *arg) 189436285Sbrian{ 189536285Sbrian if (arg->cx) 189636285Sbrian return &arg->cx->physical->link; 189737210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 189836285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 189937210Sbrian if (dl) 190037210Sbrian return &dl->physical->link; 190136285Sbrian } 190237210Sbrian return &arg->bundle->ncp.mp.link; 190336285Sbrian} 190436285Sbrian 190536285Sbrianstatic const char * 190636285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 190736285Sbrian{ 190836285Sbrian const char *result; 190936285Sbrian 191036285Sbrian switch (*cmd) { 191136285Sbrian case 'A': 191236285Sbrian case 'a': 191336285Sbrian result = "accept"; 191436285Sbrian *keep = NEG_MYMASK; 191536285Sbrian *add = NEG_ACCEPTED; 191636285Sbrian break; 191736285Sbrian case 'D': 191836285Sbrian case 'd': 191936285Sbrian switch (cmd[1]) { 192036285Sbrian case 'E': 192136285Sbrian case 'e': 192236285Sbrian result = "deny"; 192336285Sbrian *keep = NEG_MYMASK; 192436285Sbrian *add = 0; 192536285Sbrian break; 192636285Sbrian case 'I': 192736285Sbrian case 'i': 192836285Sbrian result = "disable"; 192936285Sbrian *keep = NEG_HISMASK; 193036285Sbrian *add = 0; 193136285Sbrian break; 193236285Sbrian default: 193336285Sbrian return NULL; 193436285Sbrian } 193536285Sbrian break; 193636285Sbrian case 'E': 193736285Sbrian case 'e': 193836285Sbrian result = "enable"; 193936285Sbrian *keep = NEG_HISMASK; 194036285Sbrian *add = NEG_ENABLED; 194136285Sbrian break; 194236285Sbrian default: 194336285Sbrian return NULL; 194436285Sbrian } 194536285Sbrian 194636285Sbrian return result; 194736285Sbrian} 194836285Sbrian 194936285Sbrianstatic int 195036285SbrianOptSet(struct cmdargs const *arg) 195136285Sbrian{ 195237574Sbrian int bit = (int)(long)arg->cmd->args; 195336285Sbrian const char *cmd; 195436285Sbrian unsigned keep; /* Keep these bits */ 195536285Sbrian unsigned add; /* Add these bits */ 195636285Sbrian 195736285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 195836285Sbrian return 1; 195936285Sbrian 196036285Sbrian if (add) 196136285Sbrian arg->bundle->cfg.opt |= bit; 196236285Sbrian else 196336285Sbrian arg->bundle->cfg.opt &= ~bit; 196436285Sbrian return 0; 196536285Sbrian} 196636285Sbrian 196736285Sbrianstatic int 196836285SbrianNegotiateSet(struct cmdargs const *arg) 196936285Sbrian{ 197037210Sbrian long param = (long)arg->cmd->args; 197136285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 197236285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 197336285Sbrian const char *cmd; 197436285Sbrian unsigned keep; /* Keep these bits */ 197536285Sbrian unsigned add; /* Add these bits */ 197636285Sbrian 197736285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 197836285Sbrian return 1; 197936285Sbrian 198036285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 198136285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 198236285Sbrian cmd, arg->cmd->name); 198336285Sbrian return 2; 198436285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 198536285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 198636285Sbrian cmd, arg->cmd->name, cx->name); 198736285Sbrian cx = NULL; 198836285Sbrian } 198936285Sbrian 199036285Sbrian switch (param) { 199136285Sbrian case NEG_ACFCOMP: 199236285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 199336285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 199436285Sbrian break; 199536285Sbrian case NEG_CHAP: 199636285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 199736285Sbrian cx->physical->link.lcp.cfg.chap |= add; 199836285Sbrian break; 199936285Sbrian case NEG_DEFLATE: 200036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 200136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 200236285Sbrian break; 200336285Sbrian case NEG_DNS: 200436285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 200536285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 200636285Sbrian break; 200736285Sbrian case NEG_LQR: 200836285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 200936285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 201036285Sbrian break; 201136285Sbrian case NEG_PAP: 201236285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 201336285Sbrian cx->physical->link.lcp.cfg.pap |= add; 201436285Sbrian break; 201536285Sbrian case NEG_PPPDDEFLATE: 201636285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 201736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 201836285Sbrian break; 201936285Sbrian case NEG_PRED1: 202036285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 202136285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 202236285Sbrian break; 202336285Sbrian case NEG_PROTOCOMP: 202436285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 202536285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 202636285Sbrian break; 202736285Sbrian case NEG_SHORTSEQ: 202836285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 202936285Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); 203036285Sbrian else { 203136285Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 203236285Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 203336285Sbrian } 203436285Sbrian break; 203536285Sbrian case NEG_VJCOMP: 203636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 203736285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 203836285Sbrian break; 203936285Sbrian } 204036285Sbrian 204136285Sbrian return 0; 204236285Sbrian} 204336285Sbrian 204436285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 204536285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 204636285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 204736285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 204836285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 204936285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 205036285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 205136285Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", 205236285Sbrian "disable|enable", (const void *)OPT_PROXY}, 205336285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 205436285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 205536285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 205636285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 205736285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 205836285Sbrian "disable|enable", (const void *)OPT_UTMP}, 205936285Sbrian 206036285Sbrian#define OPT_MAX 7 /* accept/deny allowed below and not above */ 206136285Sbrian 206236285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 206336285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 206436285Sbrian (const void *)NEG_ACFCOMP}, 206536285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 206636285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 206736285Sbrian (const void *)NEG_CHAP}, 206836285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 206936285Sbrian "Deflate compression", "accept|deny|disable|enable", 207036285Sbrian (const void *)NEG_DEFLATE}, 207136285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 207236285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 207336285Sbrian (const void *)NEG_PPPDDEFLATE}, 207436285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 207536285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 207636285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 207736285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 207836285Sbrian (const void *)NEG_LQR}, 207936285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 208036285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 208136285Sbrian (const void *)NEG_PAP}, 208236285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 208336285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 208436285Sbrian (const void *)NEG_PRED1}, 208536285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 208636285Sbrian "Protocol field compression", "accept|deny|disable|enable", 208736285Sbrian (const void *)NEG_PROTOCOMP}, 208836285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 208936285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 209036285Sbrian (const void *)NEG_SHORTSEQ}, 209136285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 209236285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 209336285Sbrian (const void *)NEG_VJCOMP}, 209436285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 209536285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 209636285Sbrian NegotiateCommands}, 209736285Sbrian {NULL, NULL, NULL}, 209836285Sbrian}; 209936285Sbrian 210036285Sbrianstatic int 210136285SbrianNegotiateCommand(struct cmdargs const *arg) 210236285Sbrian{ 210336285Sbrian if (arg->argc > arg->argn) { 210436285Sbrian char const *argv[3]; 210536285Sbrian unsigned keep, add; 210636285Sbrian int n; 210736285Sbrian 210836285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 210936285Sbrian return -1; 211036285Sbrian argv[2] = NULL; 211136285Sbrian 211236285Sbrian for (n = arg->argn; n < arg->argc; n++) { 211336285Sbrian argv[1] = arg->argv[n]; 211436285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 211536285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 211636285Sbrian } 211736285Sbrian } else if (arg->prompt) 211836285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 211936285Sbrian arg->argv[arg->argn-1]); 212036285Sbrian else 212136285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 212236285Sbrian arg->argv[arg->argn] ); 212336285Sbrian 212436285Sbrian return 0; 212536285Sbrian} 212636285Sbrian 212736285Sbrianconst char * 212836285Sbriancommand_ShowNegval(unsigned val) 212936285Sbrian{ 213036285Sbrian switch (val&3) { 213136285Sbrian case 1: return "disabled & accepted"; 213236285Sbrian case 2: return "enabled & denied"; 213336285Sbrian case 3: return "enabled & accepted"; 213436285Sbrian } 213536285Sbrian return "disabled & denied"; 213636285Sbrian} 213736934Sbrian 213836934Sbrianstatic int 213936934SbrianClearCommand(struct cmdargs const *arg) 214036934Sbrian{ 214136934Sbrian struct pppThroughput *t; 214236934Sbrian struct datalink *cx; 214336934Sbrian int i, clear_type; 214436934Sbrian 214536934Sbrian if (arg->argc < arg->argn + 1) 214636934Sbrian return -1; 214736934Sbrian 214836934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 214936934Sbrian cx = arg->cx; 215036934Sbrian if (!cx) 215136934Sbrian cx = bundle2datalink(arg->bundle, NULL); 215236934Sbrian if (!cx) { 215336934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 215436934Sbrian return 1; 215536934Sbrian } 215636934Sbrian t = &cx->physical->link.throughput; 215736934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 215836934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 215936934Sbrian else 216036934Sbrian return -1; 216136934Sbrian 216236934Sbrian if (arg->argc > arg->argn + 1) { 216336934Sbrian clear_type = 0; 216436934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 216536934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 216636934Sbrian clear_type |= THROUGHPUT_OVERALL; 216736934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 216836934Sbrian clear_type |= THROUGHPUT_CURRENT; 216936934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 217036934Sbrian clear_type |= THROUGHPUT_PEAK; 217136934Sbrian else 217236934Sbrian return -1; 217336934Sbrian } else 217436934Sbrian clear_type = THROUGHPUT_ALL; 217536934Sbrian 217636934Sbrian throughput_clear(t, clear_type, arg->prompt); 217736934Sbrian return 0; 217836934Sbrian} 2179