command.c revision 40665
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 * 2040665Sbrian * $Id: command.c,v 1.170 1998/10/26 19:07:36 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 3338628Sbrian#include <ctype.h> 3430715Sbrian#include <errno.h> 3526516Sbrian#include <fcntl.h> 3630715Sbrian#include <paths.h> 3730715Sbrian#include <stdio.h> 3830715Sbrian#include <stdlib.h> 3930715Sbrian#include <string.h> 4030715Sbrian#include <sys/wait.h> 4130715Sbrian#include <termios.h> 4230715Sbrian#include <unistd.h> 4330715Sbrian 4439395Sbrian#ifndef NOALIAS 4539395Sbrian#ifdef __OpenBSD__ 4639395Sbrian#include "alias.h" 4739395Sbrian#else 4839395Sbrian#include <alias.h> 4939395Sbrian#endif 5039395Sbrian#endif 5137009Sbrian#include "defs.h" 5231343Sbrian#include "command.h" 5330715Sbrian#include "mbuf.h" 5430715Sbrian#include "log.h" 5530715Sbrian#include "timer.h" 566059Samurai#include "fsm.h" 576059Samurai#include "lcp.h" 5831690Sbrian#include "iplist.h" 5936285Sbrian#include "throughput.h" 6036285Sbrian#include "slcompress.h" 6138557Sbrian#include "lqr.h" 6238557Sbrian#include "hdlc.h" 636059Samurai#include "ipcp.h" 646059Samurai#include "modem.h" 6531343Sbrian#ifndef NOALIAS 6626031Sbrian#include "alias_cmd.h" 6731343Sbrian#endif 6825630Sbrian#include "systems.h" 6936285Sbrian#include "filter.h" 7036285Sbrian#include "descriptor.h" 7130715Sbrian#include "main.h" 7230715Sbrian#include "route.h" 7330715Sbrian#include "ccp.h" 7431080Sbrian#include "auth.h" 7536285Sbrian#include "async.h" 7636285Sbrian#include "link.h" 7736285Sbrian#include "physical.h" 7836285Sbrian#include "mp.h" 7936285Sbrian#include "bundle.h" 8036285Sbrian#include "server.h" 8136285Sbrian#include "prompt.h" 8236285Sbrian#include "chat.h" 8336285Sbrian#include "chap.h" 8438174Sbrian#include "cbcp.h" 8536285Sbrian#include "datalink.h" 8640561Sbrian#include "iface.h" 876059Samurai 8836285Sbrian/* ``set'' values */ 8936285Sbrian#define VAR_AUTHKEY 0 9036285Sbrian#define VAR_DIAL 1 9136285Sbrian#define VAR_LOGIN 2 9236285Sbrian#define VAR_AUTHNAME 3 9336285Sbrian#define VAR_AUTOLOAD 4 9436285Sbrian#define VAR_WINSIZE 5 9536285Sbrian#define VAR_DEVICE 6 9636285Sbrian#define VAR_ACCMAP 7 9736285Sbrian#define VAR_MRRU 8 9836285Sbrian#define VAR_MRU 9 9936285Sbrian#define VAR_MTU 10 10036285Sbrian#define VAR_OPENMODE 11 10136285Sbrian#define VAR_PHONE 12 10236285Sbrian#define VAR_HANGUP 13 10336285Sbrian#define VAR_IDLETIMEOUT 14 10436285Sbrian#define VAR_LQRPERIOD 15 10536285Sbrian#define VAR_LCPRETRY 16 10636285Sbrian#define VAR_CHAPRETRY 17 10736285Sbrian#define VAR_PAPRETRY 18 10836285Sbrian#define VAR_CCPRETRY 19 10936285Sbrian#define VAR_IPCPRETRY 20 11036285Sbrian#define VAR_DNS 21 11136285Sbrian#define VAR_NBNS 22 11236285Sbrian#define VAR_MODE 23 11338174Sbrian#define VAR_CALLBACK 24 11438174Sbrian#define VAR_CBCP 25 11538544Sbrian#define VAR_CHOKED 26 11640665Sbrian#define VAR_SENDPIPE 27 11740665Sbrian#define VAR_RECVPIPE 28 1186059Samurai 11936285Sbrian/* ``accept|deny|disable|enable'' masks */ 12036285Sbrian#define NEG_HISMASK (1) 12136285Sbrian#define NEG_MYMASK (2) 12236285Sbrian 12336285Sbrian/* ``accept|deny|disable|enable'' values */ 12436285Sbrian#define NEG_ACFCOMP 40 12536285Sbrian#define NEG_CHAP 41 12636285Sbrian#define NEG_DEFLATE 42 12736285Sbrian#define NEG_LQR 43 12836285Sbrian#define NEG_PAP 44 12936285Sbrian#define NEG_PPPDDEFLATE 45 13036285Sbrian#define NEG_PRED1 46 13136285Sbrian#define NEG_PROTOCOMP 47 13236285Sbrian#define NEG_SHORTSEQ 48 13336285Sbrian#define NEG_VJCOMP 49 13436285Sbrian#define NEG_DNS 50 13536285Sbrian 13637373Sbrianconst char Version[] = "2.0"; 13740665Sbrianconst char VersionDate[] = "$Date: 1998/10/26 19:07:36 $"; 13836285Sbrian 13936285Sbrianstatic int ShowCommand(struct cmdargs const *); 14036285Sbrianstatic int TerminalCommand(struct cmdargs const *); 14136285Sbrianstatic int QuitCommand(struct cmdargs const *); 14236285Sbrianstatic int OpenCommand(struct cmdargs const *); 14336285Sbrianstatic int CloseCommand(struct cmdargs const *); 14436285Sbrianstatic int DownCommand(struct cmdargs const *); 14536285Sbrianstatic int SetCommand(struct cmdargs const *); 14636285Sbrianstatic int LinkCommand(struct cmdargs const *); 14736285Sbrianstatic int AddCommand(struct cmdargs const *); 14836285Sbrianstatic int DeleteCommand(struct cmdargs const *); 14936285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 15036934Sbrianstatic int ClearCommand(struct cmdargs const *); 15140561Sbrianstatic int RunListCommand(struct cmdargs const *); 15240561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 15340561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 15440561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 15531343Sbrian#ifndef NOALIAS 15636285Sbrianstatic int AliasEnable(struct cmdargs const *); 15736285Sbrianstatic int AliasOption(struct cmdargs const *); 15831343Sbrian#endif 1596059Samurai 16036285Sbrianstatic const char * 16136285Sbrianshowcx(struct cmdtab const *cmd) 16236285Sbrian{ 16336285Sbrian if (cmd->lauth & LOCAL_CX) 16436285Sbrian return "(c)"; 16536285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 16636285Sbrian return "(o)"; 16736285Sbrian 16836285Sbrian return ""; 16936285Sbrian} 17036285Sbrian 1716059Samuraistatic int 17231343SbrianHelpCommand(struct cmdargs const *arg) 1736059Samurai{ 17428679Sbrian struct cmdtab const *cmd; 17536285Sbrian int n, cmax, dmax, cols, cxlen; 17636285Sbrian const char *cx; 1776059Samurai 17836285Sbrian if (!arg->prompt) { 17936285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 18026516Sbrian return 0; 18136285Sbrian } 18226516Sbrian 18336285Sbrian if (arg->argc > arg->argn) { 18436285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 18536285Sbrian if ((cmd->lauth & arg->prompt->auth) && 18636285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 18736285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 18836285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 18928679Sbrian return 0; 1906059Samurai } 19126516Sbrian return -1; 1926059Samurai } 19336285Sbrian 19431372Sbrian cmax = dmax = 0; 19536285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 19636285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 19736285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 19831372Sbrian cmax = n; 19931372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 20031372Sbrian dmax = n; 20131372Sbrian } 20231372Sbrian 20331372Sbrian cols = 80 / (dmax + cmax + 3); 2046059Samurai n = 0; 20536285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 20636285Sbrian " (c) = Context required\n"); 20736285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 20836285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 20936285Sbrian cx = showcx(cmd); 21036285Sbrian cxlen = cmax - strlen(cmd->name); 21140482Sbrian if (n % cols != 0) 21240482Sbrian prompt_Printf(arg->prompt, " "); 21340482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 21436285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 21531372Sbrian if (++n % cols == 0) 21636285Sbrian prompt_Printf(arg->prompt, "\n"); 2176059Samurai } 21831372Sbrian if (n % cols != 0) 21936285Sbrian prompt_Printf(arg->prompt, "\n"); 22026516Sbrian 22126516Sbrian return 0; 2226059Samurai} 2236059Samurai 22436285Sbrianstatic int 22536285SbrianCloneCommand(struct cmdargs const *arg) 2266059Samurai{ 22736285Sbrian char namelist[LINE_LEN]; 22836285Sbrian char *name; 22936285Sbrian int f; 2306059Samurai 23136285Sbrian if (arg->argc == arg->argn) 23236285Sbrian return -1; 23336285Sbrian 23436285Sbrian namelist[sizeof namelist - 1] = '\0'; 23536285Sbrian for (f = arg->argn; f < arg->argc; f++) { 23636285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 23736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 23836285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2396059Samurai } 24036285Sbrian 24136285Sbrian return 0; 2426059Samurai} 2436059Samurai 2446059Samuraistatic int 24536285SbrianRemoveCommand(struct cmdargs const *arg) 2466059Samurai{ 24736285Sbrian if (arg->argc != arg->argn) 24836285Sbrian return -1; 24911336Samurai 25036285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 25136285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 25236285Sbrian return 2; 2536059Samurai } 25426516Sbrian 25536285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 25636285Sbrian return 0; 25736285Sbrian} 25832711Sbrian 25936285Sbrianstatic int 26036285SbrianRenameCommand(struct cmdargs const *arg) 26136285Sbrian{ 26236285Sbrian if (arg->argc != arg->argn + 1) 26336285Sbrian return -1; 26431121Sbrian 26536285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 26636285Sbrian return 0; 26736285Sbrian 26836285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 26936285Sbrian arg->cx->name, arg->argv[arg->argn]); 27036285Sbrian return 1; 27136285Sbrian} 27236285Sbrian 27336285Sbrianint 27436285SbrianLoadCommand(struct cmdargs const *arg) 27536285Sbrian{ 27636285Sbrian const char *name; 27736285Sbrian 27836285Sbrian if (arg->argc > arg->argn) 27936285Sbrian name = arg->argv[arg->argn]; 28036285Sbrian else 28136285Sbrian name = "default"; 28236285Sbrian 28336928Sbrian if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type.all)) { 28437019Sbrian log_Printf(LogWARN, "%s: Label not allowed\n", name); 28536285Sbrian return 1; 28636285Sbrian } else { 28736285Sbrian /* 28836285Sbrian * Set the label before & after so that `set enddisc' works and 28936285Sbrian * we handle nested `load' commands. 29036285Sbrian */ 29136285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 29237008Sbrian if (system_Select(arg->bundle, name, CONFFILE, arg->prompt, arg->cx) < 0) { 29336285Sbrian bundle_SetLabel(arg->bundle, NULL); 29436285Sbrian log_Printf(LogWARN, "%s: label not found.\n", name); 29536285Sbrian return -1; 29632403Sbrian } 29736285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 29836285Sbrian } 29926516Sbrian return 0; 3006059Samurai} 3016059Samurai 30236285Sbrianint 30336285SbrianSaveCommand(struct cmdargs const *arg) 30436285Sbrian{ 30536285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 30636285Sbrian return 1; 30736285Sbrian} 30836285Sbrian 30910528Samuraistatic int 31036285SbrianDialCommand(struct cmdargs const *arg) 31128536Sbrian{ 31236285Sbrian int res; 31336285Sbrian 31436465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 31536465Sbrian || (!arg->cx && 31636928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 31736285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 31836285Sbrian " interactive links\n"); 31936285Sbrian return 1; 32034536Sbrian } 32136285Sbrian 32236285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 32336285Sbrian return res; 32436285Sbrian 32537993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 32636285Sbrian 32736285Sbrian return 0; 32828536Sbrian} 32928536Sbrian 33038628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 33138628Sbrian 33238628Sbrianstatic char * 33338628Sbrianstrstrword(char *big, const char *little) 33438628Sbrian{ 33538628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 33638628Sbrian char *pos; 33738628Sbrian int len; 33838628Sbrian 33938628Sbrian pos = big; 34038628Sbrian len = strlen(little); 34138628Sbrian 34238628Sbrian while ((pos = strstr(pos, little)) != NULL) 34338628Sbrian if ((pos == big || !isinword(pos[-1])) && !isinword(pos[len])) 34438628Sbrian break; 34538628Sbrian else 34638628Sbrian pos++; 34738628Sbrian 34838628Sbrian return pos; 34938628Sbrian} 35038628Sbrian 35138628Sbrianstatic char * 35238628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 35338628Sbrian{ 35438628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 35538628Sbrian char *word, *ntgt; 35638628Sbrian int ltgt, loldstr, lnewstr, pos; 35738628Sbrian 35838628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 35938628Sbrian return tgt; 36038628Sbrian 36138628Sbrian ltgt = strlen(tgt) + 1; 36238628Sbrian loldstr = strlen(oldstr); 36338628Sbrian lnewstr = strlen(newstr); 36438628Sbrian do { 36538628Sbrian pos = word - tgt; 36638628Sbrian if (loldstr > lnewstr) 36738628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 36838628Sbrian if (loldstr != lnewstr) { 36938628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 37038628Sbrian if (ntgt == NULL) 37138628Sbrian break; /* Oh wonderful ! */ 37238628Sbrian word = ntgt + pos; 37338628Sbrian tgt = ntgt; 37438628Sbrian } 37538628Sbrian if (lnewstr > loldstr) 37638628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 37738628Sbrian bcopy(newstr, word, lnewstr); 37838628Sbrian } while ((word = strstrword(word, oldstr))); 37938628Sbrian 38038628Sbrian return tgt; 38138628Sbrian} 38238628Sbrian 38338628Sbrianstatic void 38438628Sbrianexpand(char **nargv, int argc, char const *const *oargv, struct bundle *bundle) 38538628Sbrian{ 38638628Sbrian int arg; 38738628Sbrian 38838628Sbrian nargv[0] = strdup(oargv[0]); 38938628Sbrian for (arg = 1; arg < argc; arg++) { 39038629Sbrian nargv[arg] = strdup(oargv[arg]); 39138629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 39238628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 39338629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 39440561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 39538628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 39638629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 39738629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 39838629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 39938629Sbrian bundle->ncp.mp.peer.enddisc.address, 40038629Sbrian bundle->ncp.mp.peer.enddisc.len)); 40138629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 40238629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 40338629Sbrian bundle->ncp.mp.cfg.enddisc.address, 40438629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 40538629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 40638628Sbrian } 40738628Sbrian nargv[arg] = NULL; 40838628Sbrian} 40938628Sbrian 41028536Sbrianstatic int 41131343SbrianShellCommand(struct cmdargs const *arg, int bg) 41210528Samurai{ 41310528Samurai const char *shell; 41410528Samurai pid_t shpid; 41520813Sjkh 41618856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 41726911Sbrian /* we're only allowed to shell when we run ppp interactively */ 41836285Sbrian if (arg->prompt && arg->prompt->owner) { 41936285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 42026516Sbrian return 1; 42110528Samurai } 42226911Sbrian#endif 42328679Sbrian 42436285Sbrian if (arg->argc == arg->argn) { 42536285Sbrian if (!arg->prompt) { 42636285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 42736285Sbrian " a config file\n"); 42828381Sbrian return 1; 42936285Sbrian } else if (arg->prompt->owner) { 43036285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 43136285Sbrian " a socket connection\n"); 43236285Sbrian return 1; 43328381Sbrian } else if (bg) { 43436285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 43528679Sbrian " the foreground mode\n"); 43628381Sbrian return 1; 43728381Sbrian } 43834536Sbrian } 43934536Sbrian 44028679Sbrian if ((shpid = fork()) == 0) { 44136285Sbrian int i, fd; 44218531Sbde 44336285Sbrian if ((shell = getenv("SHELL")) == 0) 44436285Sbrian shell = _PATH_BSHELL; 44532017Sbrian 44636285Sbrian timer_TermService(); 44736285Sbrian 44836285Sbrian if (arg->prompt) 44936285Sbrian fd = arg->prompt->fd_out; 45036285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 45136285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 45236285Sbrian _PATH_DEVNULL, strerror(errno)); 45328679Sbrian exit(1); 45428679Sbrian } 45528679Sbrian for (i = 0; i < 3; i++) 45628679Sbrian dup2(fd, i); 45726516Sbrian 45836285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 45926516Sbrian 46031061Sbrian setuid(geteuid()); 46136285Sbrian if (arg->argc > arg->argn) { 46228679Sbrian /* substitute pseudo args */ 46338628Sbrian char *argv[MAXARGS]; 46438628Sbrian int argc = arg->argc - arg->argn; 46538628Sbrian 46638628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 46738628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 46838628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 46931343Sbrian } 47038628Sbrian expand(argv, argc, arg->argv + arg->argn, arg->bundle); 47128679Sbrian if (bg) { 47228679Sbrian pid_t p; 47310528Samurai 47428679Sbrian p = getpid(); 47528679Sbrian if (daemon(1, 1) == -1) { 47636832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 47728679Sbrian exit(1); 47828679Sbrian } 47936285Sbrian } else if (arg->prompt) 48036285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 48131343Sbrian execvp(argv[0], argv); 48230316Sbrian } else { 48336285Sbrian if (arg->prompt) 48432017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 48536285Sbrian prompt_TtyOldMode(arg->prompt); 48631343Sbrian execl(shell, shell, NULL); 48730316Sbrian } 48820813Sjkh 48940665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 49040665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 49140665Sbrian strerror(errno)); 49228679Sbrian exit(255); 49310528Samurai } 49436285Sbrian 49536285Sbrian if (shpid == (pid_t) - 1) 49636285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 49736285Sbrian else { 49810528Samurai int status; 49931343Sbrian waitpid(shpid, &status, 0); 50010528Samurai } 50120813Sjkh 50236285Sbrian if (arg->prompt && !arg->prompt->owner) 50336285Sbrian prompt_TtyCommandMode(arg->prompt); 50420813Sjkh 50536285Sbrian return 0; 50610528Samurai} 50710528Samurai 50831343Sbrianstatic int 50931343SbrianBgShellCommand(struct cmdargs const *arg) 51031343Sbrian{ 51136285Sbrian if (arg->argc == arg->argn) 51231343Sbrian return -1; 51331343Sbrian return ShellCommand(arg, 1); 51431343Sbrian} 51531343Sbrian 51631343Sbrianstatic int 51731343SbrianFgShellCommand(struct cmdargs const *arg) 51831343Sbrian{ 51931343Sbrian return ShellCommand(arg, 0); 52031343Sbrian} 52131343Sbrian 52240561Sbrian#ifndef NOALIAS 52340561Sbrianstatic struct cmdtab const AliasCommands[] = 52440561Sbrian{ 52540561Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 52640561Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 52740561Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 52840561Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 52940561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 53040561Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 53140561Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 53240561Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 53340561Sbrian "log aliasing link creation", "alias log [yes|no]", 53440561Sbrian (const void *) PKT_ALIAS_LOG}, 53540561Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 53640561Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 53740561Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 53840561Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 53940561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 54040561Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 54140561Sbrian "alias unregistered (private) IP address space only", 54240561Sbrian "alias unregistered_only [yes|no]", 54340561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 54440561Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 54540561Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 54640561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 54740561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 54840561Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 54940561Sbrian {NULL, NULL, NULL}, 55040561Sbrian}; 55140561Sbrian#endif 55240561Sbrian 55340561Sbrianstatic struct cmdtab const AllowCommands[] = { 55440561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 55540561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 55640561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 55740561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 55840561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 55940561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 56040561Sbrian {NULL, NULL, NULL}, 56140561Sbrian}; 56240561Sbrian 56340561Sbrianstatic struct cmdtab const IfaceCommands[] = 56440561Sbrian{ 56540561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 56640561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 56740561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 56840561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 56940561Sbrian (void *)1}, 57040561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 57140561Sbrian "Clear iface address(es)", "iface clear"}, 57240561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 57340561Sbrian "Delete iface address", "iface delete addr", NULL}, 57440561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 57540561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 57640561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 57740561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 57840561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 57940561Sbrian "Show iface address(es)", "iface show"}, 58040561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 58140561Sbrian "Display this message", "alias help|? [command]", IfaceCommands}, 58240561Sbrian {NULL, NULL, NULL}, 58340561Sbrian}; 58440561Sbrian 58530715Sbrianstatic struct cmdtab const Commands[] = { 58636285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 58728679Sbrian "accept option request", "accept option .."}, 58828679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 58932109Sbrian "add route", "add dest mask gateway", NULL}, 59036285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 59132109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 59236285Sbrian#ifndef NOALIAS 59340561Sbrian {"alias", NULL, RunListCommand, LOCAL_AUTH, 59440561Sbrian "alias control", "alias option [yes|no]", AliasCommands}, 59536285Sbrian#endif 59640561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 59740561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 59828679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 59931372Sbrian "Run a background command", "[!]bg command"}, 60036934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 60136934Sbrian "Clear throughput statistics", "clear ipcp|modem [current|overall|peak]..."}, 60236285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 60336285Sbrian "Clone a link", "clone newname..."}, 60436285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 60536285Sbrian "Close an FSM", "close [lcp|ccp]"}, 60628679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 60732109Sbrian "delete route", "delete dest", NULL}, 60836285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 60932109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 61036285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61128679Sbrian "Deny option request", "deny option .."}, 61236285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61337955Sbrian "Dial and login", "dial|call [remote]", NULL}, 61436285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61528679Sbrian "Disable option", "disable option .."}, 61636285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61736285Sbrian "Generate a down event", "down"}, 61836285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61928679Sbrian "Enable option", "enable option .."}, 62040561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 62140561Sbrian "interface control", "iface option ...", IfaceCommands}, 62236285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 62336285Sbrian "Link specific commands", "link name command ..."}, 62437008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 62528679Sbrian "Load settings", "load [remote]"}, 62636285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 62737955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 62836285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 62936285Sbrian "Password for manipulation", "passwd LocalPassword"}, 63036285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 63136285Sbrian "Quit PPP program", "quit|bye [all]"}, 63236285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 63336285Sbrian "Remove a link", "remove"}, 63436285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 63536285Sbrian "Rename a link", "rename name"}, 63628679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 63728679Sbrian "Save settings", "save"}, 63836285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63928679Sbrian "Set parameters", "set[up] var value"}, 64028679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 64128679Sbrian "Run a subshell", "shell|! [sh command]"}, 64236285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64331372Sbrian "Show status and stats", "show var"}, 64436285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 64531372Sbrian "Enter terminal mode", "term"}, 64628679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 64731343Sbrian "Display this message", "help|? [command]", Commands}, 64828679Sbrian {NULL, NULL, NULL}, 6496059Samurai}; 6506059Samurai 65128536Sbrianstatic int 65231343SbrianShowEscape(struct cmdargs const *arg) 6536059Samurai{ 65436285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 65536285Sbrian int code, bit; 65636285Sbrian const char *sep = ""; 6576059Samurai 65826516Sbrian for (code = 0; code < 32; code++) 65936285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 66028679Sbrian for (bit = 0; bit < 8; bit++) 66136285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 66236285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 66336285Sbrian sep = ", "; 66436285Sbrian } 66536285Sbrian prompt_Printf(arg->prompt, "\n"); 6666059Samurai } 66731077Sbrian return 0; 6686059Samurai} 6696059Samurai 67028679Sbrianstatic int 67136285SbrianShowTimerList(struct cmdargs const *arg) 6726059Samurai{ 67336285Sbrian timer_Show(0, arg->prompt); 67431077Sbrian return 0; 6756059Samurai} 6766059Samurai 67728679Sbrianstatic int 67831343SbrianShowStopped(struct cmdargs const *arg) 67928327Sbrian{ 68036285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 68136285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 68236285Sbrian prompt_Printf(arg->prompt, "Disabled"); 68328327Sbrian else 68436285Sbrian prompt_Printf(arg->prompt, "%ld secs", 68536285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 68628461Sbrian 68736285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 68836285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 68936285Sbrian prompt_Printf(arg->prompt, "Disabled"); 69028461Sbrian else 69136285Sbrian prompt_Printf(arg->prompt, "%ld secs", 69236285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 69328461Sbrian 69436285Sbrian prompt_Printf(arg->prompt, "\n"); 69528461Sbrian 69631077Sbrian return 0; 69728327Sbrian} 69828327Sbrian 69928679Sbrianstatic int 70031343SbrianShowVersion(struct cmdargs const *arg) 7016059Samurai{ 70236285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 70331077Sbrian return 0; 7046059Samurai} 7056059Samurai 70628679Sbrianstatic int 70736285SbrianShowProtocolStats(struct cmdargs const *arg) 70826326Sbrian{ 70936285Sbrian struct link *l = command_ChooseLink(arg); 71026326Sbrian 71136285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 71236285Sbrian link_ReportProtocolStatus(l, arg->prompt); 71331077Sbrian return 0; 71426326Sbrian} 71526326Sbrian 71630715Sbrianstatic struct cmdtab const ShowCommands[] = { 71736285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 71836285Sbrian "bundle details", "show bundle"}, 71936285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 72036285Sbrian "CCP status", "show cpp"}, 72136285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 72236285Sbrian "VJ compression stats", "show compress"}, 72336285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 72436285Sbrian "escape characters", "show escape"}, 72536285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 72636285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 72736285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 72836285Sbrian "HDLC errors", "show hdlc"}, 72940561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 73040561Sbrian "Interface status", "show iface"}, 73136285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 73236285Sbrian "IPCP status", "show ipcp"}, 73336285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 73436285Sbrian "LCP status", "show lcp"}, 73536285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 73636285Sbrian "(high-level) link info", "show link"}, 73736285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 73836285Sbrian "available link names", "show links"}, 73936285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 74036285Sbrian "log levels", "show log"}, 74136285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 74236285Sbrian "mbuf allocations", "show mem"}, 74336285Sbrian {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 74436285Sbrian "(low-level) link info", "show modem"}, 74536285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 74636285Sbrian "multilink setup", "show mp"}, 74736285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 74836285Sbrian "protocol summary", "show proto"}, 74936285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 75036285Sbrian "routing table", "show route"}, 75136285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 75236285Sbrian "STOPPED timeout", "show stopped"}, 75336285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 75436285Sbrian "alarm timers", "show timers"}, 75528679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 75636285Sbrian "version string", "show version"}, 75736285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 75836285Sbrian "client list", "show who"}, 75928679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 76031343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 76128679Sbrian {NULL, NULL, NULL}, 7626059Samurai}; 7636059Samurai 76430715Sbrianstatic struct cmdtab const * 76531343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 7666059Samurai{ 76726516Sbrian int nmatch; 76826516Sbrian int len; 76928679Sbrian struct cmdtab const *found; 7706059Samurai 77126516Sbrian found = NULL; 77226516Sbrian len = strlen(str); 77326516Sbrian nmatch = 0; 7746059Samurai while (cmds->func) { 77525566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 77626516Sbrian if (cmds->name[len] == '\0') { 77728679Sbrian *pmatch = 1; 77828679Sbrian return cmds; 77926516Sbrian } 7806059Samurai nmatch++; 7816059Samurai found = cmds; 78228679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 78326516Sbrian if (cmds->alias[len] == '\0') { 78428679Sbrian *pmatch = 1; 78528679Sbrian return cmds; 78626516Sbrian } 7876059Samurai nmatch++; 7886059Samurai found = cmds; 7896059Samurai } 7906059Samurai cmds++; 7916059Samurai } 7926059Samurai *pmatch = nmatch; 79326516Sbrian return found; 7946059Samurai} 7956059Samurai 79636285Sbrianstatic const char * 79736285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 79836285Sbrian{ 79936285Sbrian int f, tlen, len; 80036285Sbrian 80136285Sbrian tlen = 0; 80236285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 80336285Sbrian if (f) 80436285Sbrian tgt[tlen++] = ' '; 80536285Sbrian len = strlen(argv[f]); 80636285Sbrian if (len > sz - tlen - 1) 80736285Sbrian len = sz - tlen - 1; 80836285Sbrian strncpy(tgt+tlen, argv[f], len); 80936285Sbrian tlen += len; 81036285Sbrian } 81136285Sbrian tgt[tlen] = '\0'; 81236285Sbrian return tgt; 81336285Sbrian} 81436285Sbrian 81530715Sbrianstatic int 81636285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 81736285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8186059Samurai{ 81928679Sbrian struct cmdtab const *cmd; 8206059Samurai int val = 1; 8216059Samurai int nmatch; 82231343Sbrian struct cmdargs arg; 82336285Sbrian char prefix[100]; 8246059Samurai 82536285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8266059Samurai if (nmatch > 1) 82736285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 82836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 82936285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 83036285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 83136285Sbrian /* We've got no context, but we require it */ 83236285Sbrian cx = bundle2datalink(bundle, NULL); 83336285Sbrian 83436285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 83536285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 83636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 83736285Sbrian else { 83836285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 83936285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 84036285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 84136285Sbrian cx = NULL; 84236285Sbrian } 84336285Sbrian arg.cmdtab = cmds; 84436285Sbrian arg.cmd = cmd; 84536285Sbrian arg.argc = argc; 84636285Sbrian arg.argn = argn+1; 84736285Sbrian arg.argv = argv; 84836285Sbrian arg.bundle = bundle; 84936285Sbrian arg.cx = cx; 85036285Sbrian arg.prompt = prompt; 85136285Sbrian val = (*cmd->func) (&arg); 85236285Sbrian } 85331343Sbrian } else 85436285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 85536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 85626516Sbrian 85726516Sbrian if (val == -1) 85836285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 85928679Sbrian else if (val) 86036285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 86136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 86226516Sbrian 86326516Sbrian return val; 8646059Samurai} 8656059Samurai 86637009Sbrianint 86737009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 8686059Samurai{ 8696059Samurai char *cp; 8706059Samurai 8716059Samurai if (nb > 0) { 8726059Samurai cp = buff + strcspn(buff, "\r\n"); 8736059Samurai if (cp) 8746059Samurai *cp = '\0'; 87537009Sbrian return MakeArgs(buff, argv, MAXARGS); 87637009Sbrian } 87737009Sbrian return 0; 87831121Sbrian} 8796059Samurai 88031822Sbrianstatic int 88131822Sbrianarghidden(int argc, char const *const *argv, int n) 88231822Sbrian{ 88331822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 88431828Sbrian 88531828Sbrian /* set authkey xxxxx */ 88631828Sbrian /* set key xxxxx */ 88731822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 88831822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 88931822Sbrian return 1; 89031822Sbrian 89131828Sbrian /* passwd xxxxx */ 89231828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 89331828Sbrian return 1; 89431828Sbrian 89536285Sbrian /* set server port xxxxx .... */ 89636285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 89736285Sbrian !strncasecmp(argv[1], "se", 2)) 89836285Sbrian return 1; 89936285Sbrian 90031822Sbrian return 0; 90131822Sbrian} 90231822Sbrian 90331121Sbrianvoid 90436285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 90537008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 90631121Sbrian{ 90731156Sbrian if (argc > 0) { 90836285Sbrian if (log_IsKept(LogCOMMAND)) { 90931156Sbrian static char buf[LINE_LEN]; 91031156Sbrian int f, n; 91131156Sbrian 91231156Sbrian *buf = '\0'; 91331156Sbrian if (label) { 91431962Sbrian strncpy(buf, label, sizeof buf - 3); 91531962Sbrian buf[sizeof buf - 3] = '\0'; 91631156Sbrian strcat(buf, ": "); 91731156Sbrian } 91831156Sbrian n = strlen(buf); 91931156Sbrian for (f = 0; f < argc; f++) { 92031962Sbrian if (n < sizeof buf - 1 && f) 92131156Sbrian buf[n++] = ' '; 92231822Sbrian if (arghidden(argc, argv, f)) 92336285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 92431822Sbrian else 92531962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 92631156Sbrian n += strlen(buf+n); 92731156Sbrian } 92836285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 92931156Sbrian } 93037008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 93131156Sbrian } 9326059Samurai} 9336059Samurai 93431121Sbrianvoid 93536285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 93636285Sbrian const char *label) 93731121Sbrian{ 93831121Sbrian int argc; 93937009Sbrian char *argv[MAXARGS]; 94031121Sbrian 94137009Sbrian argc = command_Interpret(buff, nb, argv); 94237008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 94331121Sbrian} 94431121Sbrian 9456059Samuraistatic int 94631343SbrianShowCommand(struct cmdargs const *arg) 9476059Samurai{ 94836285Sbrian if (!arg->prompt) 94936285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 95036285Sbrian else if (arg->argc > arg->argn) 95136285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 95236285Sbrian arg->prompt, arg->cx); 9536059Samurai else 95436285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 95526516Sbrian 95626516Sbrian return 0; 9576059Samurai} 9586059Samurai 9596059Samuraistatic int 96031343SbrianTerminalCommand(struct cmdargs const *arg) 9616059Samurai{ 96236285Sbrian if (!arg->prompt) { 96336285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 96426516Sbrian return 1; 9656059Samurai } 96636285Sbrian 96736285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 96836285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 96936285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 97036285Sbrian return 1; 9716059Samurai } 97236285Sbrian 97336285Sbrian datalink_Up(arg->cx, 0, 0); 97436285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 97536285Sbrian return 0; 9766059Samurai} 9776059Samurai 9786059Samuraistatic int 97931343SbrianQuitCommand(struct cmdargs const *arg) 9806059Samurai{ 98136285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 98236285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 98336285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 98436285Sbrian Cleanup(EX_NORMAL); 98536285Sbrian if (arg->prompt) 98636285Sbrian prompt_Destroy(arg->prompt, 1); 98726516Sbrian 98826516Sbrian return 0; 9896059Samurai} 9906059Samurai 9916059Samuraistatic int 99236285SbrianOpenCommand(struct cmdargs const *arg) 9936059Samurai{ 99437160Sbrian if (arg->argc == arg->argn) 99537993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 99637160Sbrian else if (arg->argc == arg->argn + 1) { 99737160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 99837385Sbrian struct datalink *cx = arg->cx ? 99937385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 100037385Sbrian if (cx) { 100137385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 100237385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 100337160Sbrian else 100437993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 100537160Sbrian } else 100637160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 100737160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 100837160Sbrian struct fsm *fp; 10096059Samurai 101037210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 101137160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 101237160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 101337160Sbrian else if (fp->state == ST_OPENED) 101437160Sbrian fsm_Reopen(fp); 101537160Sbrian else { 101637160Sbrian fp->open_mode = 0; /* Not passive any more */ 101737160Sbrian if (fp->state == ST_STOPPED) { 101837160Sbrian fsm_Down(fp); 101937160Sbrian fsm_Up(fp); 102037160Sbrian } else { 102137160Sbrian fsm_Up(fp); 102237160Sbrian fsm_Open(fp); 102337160Sbrian } 102436285Sbrian } 102537160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 102637160Sbrian if (arg->cx) 102737160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 102837160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 102937160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 103037160Sbrian else 103137993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 103237160Sbrian } else 103337160Sbrian return -1; 103436285Sbrian } else 103536285Sbrian return -1; 103636285Sbrian 103726516Sbrian return 0; 10386059Samurai} 10396059Samurai 104025067Sbrianstatic int 104136285SbrianCloseCommand(struct cmdargs const *arg) 10426059Samurai{ 104337007Sbrian if (arg->argc == arg->argn) 104437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 104537007Sbrian else if (arg->argc == arg->argn + 1) { 104637007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 104737007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 104837007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 104937007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 105037007Sbrian struct fsm *fp; 10516059Samurai 105237210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 105337007Sbrian if (fp->state == ST_OPENED) { 105437007Sbrian fsm_Close(fp); 105537007Sbrian if (arg->argv[arg->argn][3] == '!') 105637007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 105737007Sbrian else 105837007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 105937007Sbrian } 106037007Sbrian } else 106136285Sbrian return -1; 106236285Sbrian } else 106336285Sbrian return -1; 106436285Sbrian 106536285Sbrian return 0; 10666059Samurai} 10676059Samurai 106825067Sbrianstatic int 106936285SbrianDownCommand(struct cmdargs const *arg) 107011336Samurai{ 107137018Sbrian if (arg->argc == arg->argn) { 107237018Sbrian if (arg->cx) 107337018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 107437018Sbrian else 107537018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 107637018Sbrian } else if (arg->argc == arg->argn + 1) { 107737018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 107837018Sbrian if (arg->cx) 107937018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 108037018Sbrian else 108137018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 108237018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 108337018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 108437018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 108537060Sbrian fsm2initial(fp); 108637018Sbrian } else 108737018Sbrian return -1; 108836285Sbrian } else 108936285Sbrian return -1; 109036285Sbrian 109136285Sbrian return 0; 109225067Sbrian} 109325067Sbrian 109425067Sbrianstatic int 109536285SbrianSetModemSpeed(struct cmdargs const *arg) 109625067Sbrian{ 109736285Sbrian long speed; 109836285Sbrian char *end; 109911336Samurai 110036285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 110136285Sbrian if (arg->argc > arg->argn+1) { 110236285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 110336285Sbrian return -1; 110411336Samurai } 110536285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 110636285Sbrian physical_SetSync(arg->cx->physical); 110736285Sbrian return 0; 110836285Sbrian } 110936285Sbrian end = NULL; 111036285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 111136285Sbrian if (*end) { 111236285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 111336285Sbrian arg->argv[arg->argn]); 111436285Sbrian return -1; 111536285Sbrian } 111636285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 111736285Sbrian return 0; 111836285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 111936285Sbrian } else 112036285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 112124939Sbrian 112226516Sbrian return -1; 112311336Samurai} 112411336Samurai 112525067Sbrianstatic int 112631343SbrianSetStoppedTimeout(struct cmdargs const *arg) 112728327Sbrian{ 112836285Sbrian struct link *l = &arg->cx->physical->link; 112936285Sbrian 113036285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 113136285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 113236285Sbrian if (arg->argc <= arg->argn+2) { 113336285Sbrian if (arg->argc > arg->argn) { 113436285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 113536285Sbrian if (arg->argc > arg->argn+1) 113636285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 113728461Sbrian } 113828327Sbrian return 0; 113928327Sbrian } 114028327Sbrian return -1; 114128327Sbrian} 114228327Sbrian 114331081Sbrian#define ismask(x) \ 114431081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 114531081Sbrian 114628327Sbrianstatic int 114731343SbrianSetServer(struct cmdargs const *arg) 114826940Sbrian{ 114926940Sbrian int res = -1; 115026940Sbrian 115136285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 115231081Sbrian const char *port, *passwd, *mask; 115331081Sbrian 115431081Sbrian /* What's what ? */ 115536285Sbrian port = arg->argv[arg->argn]; 115636285Sbrian if (arg->argc == arg->argn + 2) { 115736285Sbrian passwd = arg->argv[arg->argn+1]; 115836285Sbrian mask = NULL; 115936285Sbrian } else if (arg->argc == arg->argn + 3) { 116036285Sbrian passwd = arg->argv[arg->argn+1]; 116136285Sbrian mask = arg->argv[arg->argn+2]; 116231081Sbrian if (!ismask(mask)) 116331081Sbrian return -1; 116436285Sbrian } else if (strcasecmp(port, "none") == 0) { 116536285Sbrian if (server_Close(arg->bundle)) 116636285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 116736285Sbrian return 0; 116831081Sbrian } else 116936285Sbrian return -1; 117031081Sbrian 117136285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 117236285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 117331081Sbrian 117436285Sbrian if (*port == '/') { 117531081Sbrian mode_t imask; 117636285Sbrian char *ptr, name[LINE_LEN + 12]; 117728679Sbrian 117831081Sbrian if (mask != NULL) { 117928679Sbrian unsigned m; 118028679Sbrian 118131081Sbrian if (sscanf(mask, "%o", &m) == 1) 118231081Sbrian imask = m; 118331081Sbrian else 118431081Sbrian return -1; 118531081Sbrian } else 118631081Sbrian imask = (mode_t)-1; 118736285Sbrian 118836285Sbrian ptr = strstr(port, "%d"); 118936285Sbrian if (ptr) { 119036285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 119137210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 119236285Sbrian port = name; 119336285Sbrian } 119436285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 119527346Sbrian } else { 119636285Sbrian int iport, add = 0; 119728679Sbrian 119831081Sbrian if (mask != NULL) 119931081Sbrian return -1; 120028679Sbrian 120136285Sbrian if (*port == '+') { 120236285Sbrian port++; 120336285Sbrian add = 1; 120436285Sbrian } 120531081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 120631081Sbrian struct servent *s; 120731081Sbrian 120831081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 120931081Sbrian iport = 0; 121036285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 121128679Sbrian } else 121231081Sbrian iport = ntohs(s->s_port); 121327346Sbrian } else 121431081Sbrian iport = atoi(port); 121536285Sbrian 121636285Sbrian if (iport) { 121736285Sbrian if (add) 121836285Sbrian iport += arg->bundle->unit; 121936285Sbrian res = server_TcpOpen(arg->bundle, iport); 122036285Sbrian } else 122136285Sbrian res = -1; 122227346Sbrian } 122331081Sbrian } 122426940Sbrian 122526940Sbrian return res; 122626940Sbrian} 122726940Sbrian 122826940Sbrianstatic int 122931343SbrianSetModemParity(struct cmdargs const *arg) 12306059Samurai{ 123136285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 123236285Sbrian arg->argv[arg->argn]) : -1; 12336059Samurai} 12346059Samurai 12356059Samuraistatic int 123631343SbrianSetEscape(struct cmdargs const *arg) 12376059Samurai{ 12386059Samurai int code; 123936285Sbrian int argc = arg->argc - arg->argn; 124036285Sbrian char const *const *argv = arg->argv + arg->argn; 12416059Samurai 12426059Samurai for (code = 0; code < 33; code++) 124336285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 124431343Sbrian 12456059Samurai while (argc-- > 0) { 12466059Samurai sscanf(*argv++, "%x", &code); 12476059Samurai code &= 0xff; 124836285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 124936285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 12506059Samurai } 125126516Sbrian return 0; 12526059Samurai} 12536059Samurai 125430715Sbrianstatic struct in_addr 125531343SbrianGetIpAddr(const char *cp) 12566059Samurai{ 12576059Samurai struct hostent *hp; 12586059Samurai struct in_addr ipaddr; 12596059Samurai 126032124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 126132124Sbrian hp = gethostbyname(cp); 126232124Sbrian if (hp && hp->h_addrtype == AF_INET) 126332124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 126432124Sbrian else 126532124Sbrian ipaddr.s_addr = 0; 126632124Sbrian } 126728679Sbrian return (ipaddr); 12686059Samurai} 12696059Samurai 12706059Samuraistatic int 127131343SbrianSetInterfaceAddr(struct cmdargs const *arg) 12726059Samurai{ 127336285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 127432267Sbrian const char *hisaddr; 127532267Sbrian 127640561Sbrian if (arg->argc > arg->argn + 4) 127740561Sbrian return -1; 127840561Sbrian 127932267Sbrian hisaddr = NULL; 128036285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 128136285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 128236285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 128336285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 128436285Sbrian iplist_reset(&ipcp->cfg.peer_list); 128528394Sbrian 128636285Sbrian if (arg->argc > arg->argn) { 128736285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 128836285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 128936285Sbrian &ipcp->cfg.my_range.width)) 129028679Sbrian return 1; 129136285Sbrian if (arg->argc > arg->argn+1) { 129236285Sbrian hisaddr = arg->argv[arg->argn+1]; 129336285Sbrian if (arg->argc > arg->argn+2) { 129436285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 129536285Sbrian if (arg->argc > arg->argn+3) { 129636285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 129736285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 12989440Samurai } 12996059Samurai } 13006059Samurai } 13016059Samurai } 130228394Sbrian 130340561Sbrian /* 0.0.0.0 means any address (0 bits) */ 130436285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 130536285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 130636285Sbrian ipcp->cfg.my_range.width = 0; 13076059Samurai } 130836285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 130936285Sbrian 131036285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 131136928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 131232267Sbrian return 4; 131331121Sbrian 131426516Sbrian return 0; 13156059Samurai} 13166059Samurai 131718752Sjkhstatic int 131831343SbrianSetVariable(struct cmdargs const *arg) 13196059Samurai{ 132037210Sbrian long long_val, param = (long)arg->cmd->args; 132137210Sbrian int mode, dummyint; 132231343Sbrian const char *argp; 132336285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 132436285Sbrian const char *err = NULL; 132536285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 132636285Sbrian struct in_addr dummyaddr, *addr; 13276059Samurai 132836285Sbrian if (arg->argc > arg->argn) 132936285Sbrian argp = arg->argv[arg->argn]; 133026551Sbrian else 133131343Sbrian argp = ""; 133226551Sbrian 133336285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 133436285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 133536285Sbrian arg->cmd->name); 133636285Sbrian return 1; 133736285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 133836285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 133936285Sbrian arg->cmd->name, cx->name); 134036285Sbrian cx = NULL; 134136285Sbrian } 134236285Sbrian 134326551Sbrian switch (param) { 134428679Sbrian case VAR_AUTHKEY: 134540622Sbrian switch (bundle_Phase(arg->bundle)) { 134640622Sbrian case PHASE_DEAD: 134740622Sbrian case PHASE_ESTABLISH: 134840622Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 134940622Sbrian sizeof arg->bundle->cfg.auth.key - 1); 135040622Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 135140622Sbrian break; 135240622Sbrian default: 135340622Sbrian err = "set authkey: Only available at phase DEAD/ESTABLISH\n"; 135440622Sbrian log_Printf(LogWARN, err); 135540622Sbrian break; 135636285Sbrian } 135728679Sbrian break; 135837210Sbrian 135928679Sbrian case VAR_AUTHNAME: 136040622Sbrian switch (bundle_Phase(arg->bundle)) { 136140622Sbrian case PHASE_DEAD: 136240622Sbrian case PHASE_ESTABLISH: 136340622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 136440622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 136540622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 136640622Sbrian break; 136740622Sbrian default: 136840622Sbrian err = "set authname: Only available at phase DEAD/ESTABLISH\n"; 136940622Sbrian log_Printf(LogWARN, err); 137040622Sbrian break; 137136285Sbrian } 137228679Sbrian break; 137337210Sbrian 137436285Sbrian case VAR_AUTOLOAD: 137536285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 137636285Sbrian arg->bundle->autoload.running = 1; 137736285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 137836285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 137936285Sbrian if (arg->argc == arg->argn + 4) { 138036285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 138136285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 138236285Sbrian } else { 138336285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 138436285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 138536285Sbrian } 138636285Sbrian } else { 138736285Sbrian err = "Set autoload requires two or four arguments\n"; 138836285Sbrian log_Printf(LogWARN, err); 138936285Sbrian } 139036285Sbrian break; 139137210Sbrian 139228679Sbrian case VAR_DIAL: 139336285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 139436285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 139528679Sbrian break; 139637210Sbrian 139728679Sbrian case VAR_LOGIN: 139836285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 139936285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 140028679Sbrian break; 140137210Sbrian 140236285Sbrian case VAR_WINSIZE: 140336285Sbrian if (arg->argc > arg->argn) { 140436285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 140536285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 140636285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 140736285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 140836285Sbrian l->ccp.cfg.deflate.out.winsize); 140936285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 141036285Sbrian } 141136285Sbrian if (arg->argc > arg->argn+1) { 141236285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 141336285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 141436285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 141536285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 141636285Sbrian l->ccp.cfg.deflate.in.winsize); 141736285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 141836285Sbrian } 141936285Sbrian } else 142036285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 142136285Sbrian } else { 142236285Sbrian err = "No window size specified\n"; 142336285Sbrian log_Printf(LogWARN, err); 142436285Sbrian } 142536285Sbrian break; 142637210Sbrian 142728679Sbrian case VAR_DEVICE: 142836285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 142936285Sbrian arg->argv + arg->argn); 143036285Sbrian break; 143137210Sbrian 143236285Sbrian case VAR_ACCMAP: 143336285Sbrian if (arg->argc > arg->argn) { 143437210Sbrian u_long ulong_val; 143536285Sbrian sscanf(argp, "%lx", &ulong_val); 143637210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 143736285Sbrian } else { 143836285Sbrian err = "No accmap specified\n"; 143936285Sbrian log_Printf(LogWARN, err); 144036285Sbrian } 144136285Sbrian break; 144237210Sbrian 144336285Sbrian case VAR_MODE: 144436285Sbrian mode = Nam2mode(argp); 144536285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 144636285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 144736285Sbrian return -1; 144836285Sbrian } 144936285Sbrian bundle_SetMode(arg->bundle, cx, mode); 145036285Sbrian break; 145137210Sbrian 145236285Sbrian case VAR_MRRU: 145340622Sbrian switch (bundle_Phase(arg->bundle)) { 145440622Sbrian case PHASE_DEAD: 145540622Sbrian break; 145640622Sbrian case PHASE_ESTABLISH: 145740622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 145840622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 145940622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 146040622Sbrian return 1; 146140622Sbrian } 146240622Sbrian break; 146340622Sbrian default: 146440622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 146540622Sbrian return 1; 146629696Sbrian } 146737210Sbrian long_val = atol(argp); 146837210Sbrian if (long_val && long_val < MIN_MRU) { 146937210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 147037210Sbrian return 1; 147137210Sbrian } else if (long_val > MAX_MRU) { 147237210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 147337210Sbrian return 1; 147437210Sbrian } else 147537210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 147628679Sbrian break; 147737210Sbrian 147836285Sbrian case VAR_MRU: 147937210Sbrian long_val = atol(argp); 148037210Sbrian if (long_val == 0) 148137210Sbrian l->lcp.cfg.mru = DEF_MRU; 148237210Sbrian else if (long_val < MIN_MRU) { 148337210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 148437210Sbrian return 1; 148537210Sbrian } else if (long_val > MAX_MRU) { 148637210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 148737210Sbrian return 1; 148837210Sbrian } else 148937210Sbrian l->lcp.cfg.mru = long_val; 149028679Sbrian break; 149137210Sbrian 149236285Sbrian case VAR_MTU: 149337210Sbrian long_val = atol(argp); 149437210Sbrian if (long_val && long_val < MIN_MTU) { 149537210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 149637210Sbrian return 1; 149737210Sbrian } else if (long_val > MAX_MTU) { 149837210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 149937210Sbrian return 1; 150037210Sbrian } else 150137210Sbrian arg->bundle->cfg.mtu = long_val; 150236285Sbrian break; 150337210Sbrian 150436285Sbrian case VAR_OPENMODE: 150536285Sbrian if (strcasecmp(argp, "active") == 0) 150636285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 150736285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 150836285Sbrian else if (strcasecmp(argp, "passive") == 0) 150936285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 151036285Sbrian else { 151136285Sbrian err = "%s: Invalid openmode\n"; 151236285Sbrian log_Printf(LogWARN, err, argp); 151336285Sbrian } 151436285Sbrian break; 151537210Sbrian 151628679Sbrian case VAR_PHONE: 151736285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 151836285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 151938174Sbrian cx->phone.alt = cx->phone.next = NULL; 152028679Sbrian break; 152137210Sbrian 152228679Sbrian case VAR_HANGUP: 152336285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 152436285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 152528679Sbrian break; 152637210Sbrian 152736285Sbrian case VAR_IDLETIMEOUT: 152836285Sbrian if (arg->argc > arg->argn+1) 152936285Sbrian err = "Too many idle timeout values\n"; 153036285Sbrian else if (arg->argc == arg->argn+1) 153136285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 153236285Sbrian if (err) 153336285Sbrian log_Printf(LogWARN, err); 153429549Sbrian break; 153537210Sbrian 153636285Sbrian case VAR_LQRPERIOD: 153737210Sbrian long_val = atol(argp); 153837210Sbrian if (long_val < MIN_LQRPERIOD) { 153937210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 154037210Sbrian long_val, MIN_LQRPERIOD); 154137210Sbrian return 1; 154236285Sbrian } else 154337210Sbrian l->lcp.cfg.lqrperiod = long_val; 154436285Sbrian break; 154537210Sbrian 154636285Sbrian case VAR_LCPRETRY: 154737210Sbrian long_val = atol(argp); 154837210Sbrian if (long_val < MIN_FSMRETRY) { 154937210Sbrian log_Printf(LogWARN, "%ld: Invalid LCP FSM retry period - min %d\n", 155037210Sbrian long_val, MIN_FSMRETRY); 155137210Sbrian return 1; 155236285Sbrian } else 155337210Sbrian cx->physical->link.lcp.cfg.fsmretry = long_val; 155436285Sbrian break; 155537210Sbrian 155636285Sbrian case VAR_CHAPRETRY: 155737210Sbrian long_val = atol(argp); 155837210Sbrian if (long_val < MIN_FSMRETRY) { 155937210Sbrian log_Printf(LogWARN, "%ld: Invalid CHAP FSM retry period - min %d\n", 156037210Sbrian long_val, MIN_FSMRETRY); 156137210Sbrian return 1; 156236285Sbrian } else 156337210Sbrian cx->chap.auth.cfg.fsmretry = long_val; 156436285Sbrian break; 156537210Sbrian 156636285Sbrian case VAR_PAPRETRY: 156737210Sbrian long_val = atol(argp); 156837210Sbrian if (long_val < MIN_FSMRETRY) { 156937210Sbrian log_Printf(LogWARN, "%ld: Invalid PAP FSM retry period - min %d\n", 157037210Sbrian long_val, MIN_FSMRETRY); 157137210Sbrian return 1; 157236285Sbrian } else 157337210Sbrian cx->pap.cfg.fsmretry = long_val; 157436285Sbrian break; 157537210Sbrian 157636285Sbrian case VAR_CCPRETRY: 157737210Sbrian long_val = atol(argp); 157837210Sbrian if (long_val < MIN_FSMRETRY) { 157937210Sbrian log_Printf(LogWARN, "%ld: Invalid CCP FSM retry period - min %d\n", 158037210Sbrian long_val, MIN_FSMRETRY); 158137210Sbrian return 1; 158236285Sbrian } else 158337210Sbrian l->ccp.cfg.fsmretry = long_val; 158436285Sbrian break; 158537210Sbrian 158636285Sbrian case VAR_IPCPRETRY: 158737210Sbrian long_val = atol(argp); 158837210Sbrian if (long_val < MIN_FSMRETRY) { 158937210Sbrian log_Printf(LogWARN, "%ld: Invalid IPCP FSM retry period - min %d\n", 159037210Sbrian long_val, MIN_FSMRETRY); 159137210Sbrian return 1; 159236285Sbrian } else 159337210Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = long_val; 159436285Sbrian break; 159537210Sbrian 159636285Sbrian case VAR_NBNS: 159736285Sbrian case VAR_DNS: 159836285Sbrian if (param == VAR_DNS) 159936285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 160036285Sbrian else 160136285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 160236285Sbrian 160336285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 160436285Sbrian 160536285Sbrian if (arg->argc > arg->argn) { 160636285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 160736285Sbrian addr, &dummyaddr, &dummyint); 160836285Sbrian if (arg->argc > arg->argn+1) 160936285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 161036285Sbrian addr + 1, &dummyaddr, &dummyint); 161136285Sbrian 161236285Sbrian if (addr[1].s_addr == INADDR_ANY) 161336285Sbrian addr[1].s_addr = addr[0].s_addr; 161436285Sbrian if (addr[0].s_addr == INADDR_ANY) 161536285Sbrian addr[0].s_addr = addr[1].s_addr; 161636285Sbrian } 161736285Sbrian break; 161838174Sbrian 161938174Sbrian case VAR_CALLBACK: 162038174Sbrian cx->cfg.callback.opmask = 0; 162138174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 162238174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 162338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 162438174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 162538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 162638174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 162738174Sbrian if (dummyint == arg->argc - 1) 162838174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 162938174Sbrian else { 163038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 163138174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 163238174Sbrian sizeof cx->cfg.callback.msg - 1); 163338174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 163438174Sbrian } 163538174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 163638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 163738174Sbrian else 163838174Sbrian return -1; 163938174Sbrian } 164038174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 164138174Sbrian cx->cfg.callback.opmask = 0; 164238174Sbrian break; 164338174Sbrian 164438174Sbrian case VAR_CBCP: 164538174Sbrian cx->cfg.cbcp.delay = 0; 164638174Sbrian *cx->cfg.cbcp.phone = '\0'; 164738174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 164838174Sbrian if (arg->argc > arg->argn) { 164938174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 165038174Sbrian sizeof cx->cfg.cbcp.phone - 1); 165138174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 165238174Sbrian if (arg->argc > arg->argn + 1) { 165338174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 165438174Sbrian if (arg->argc > arg->argn + 2) { 165538174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 165638174Sbrian if (long_val < MIN_FSMRETRY) 165738174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 165838174Sbrian long_val, MIN_FSMRETRY); 165938174Sbrian else 166038174Sbrian cx->cfg.cbcp.fsmretry = long_val; 166138174Sbrian } 166238174Sbrian } 166338174Sbrian } 166438174Sbrian break; 166538544Sbrian 166638544Sbrian case VAR_CHOKED: 166738544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 166838544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 166938544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 167038544Sbrian break; 167140665Sbrian 167240665Sbrian case VAR_SENDPIPE: 167340665Sbrian long_val = atol(argp); 167440665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 167540665Sbrian break; 167640665Sbrian 167740665Sbrian case VAR_RECVPIPE: 167840665Sbrian long_val = atol(argp); 167940665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 168040665Sbrian break; 16816059Samurai } 168236285Sbrian 168336285Sbrian return err ? 1 : 0; 16846059Samurai} 16856059Samurai 168628679Sbrianstatic int 168731343SbrianSetCtsRts(struct cmdargs const *arg) 168820812Sjkh{ 168936285Sbrian if (arg->argc == arg->argn+1) { 169036285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 169136285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 169236285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 169336285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 169420812Sjkh else 169526516Sbrian return -1; 169626516Sbrian return 0; 169720812Sjkh } 169826516Sbrian return -1; 169920812Sjkh} 170020812Sjkh 170130715Sbrianstatic struct cmdtab const SetCommands[] = { 170236285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 170336285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 170428679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 170536285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 170628679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 170736285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 170836285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 170936285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 171036285Sbrian (const void *)VAR_AUTOLOAD}, 171138174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 171238174Sbrian "callback control", "set callback [none|auth|cbcp|" 171338174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 171438174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 171538174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 171638174Sbrian (const void *)VAR_CBCP}, 171736285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 171836285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 171936285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 172036285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 172138544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 172238544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 172336285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 172436285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 172536285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 172636285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 172736285Sbrian (const void *) VAR_WINSIZE}, 172836285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 172936285Sbrian "modem device name", "set device|line device-name[,device-name]", 173036285Sbrian (const void *) VAR_DEVICE}, 173136285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 173236285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 173336285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 173436285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 173536285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 173636285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 173736285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 173836285Sbrian "escape characters", "set escape hex-digit ..."}, 173936285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 174036285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 174136285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 174236285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 174336285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 174436285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 174536285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 174631343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 174736285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 174836285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 174936285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 175036285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 175136712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 175238622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 175338622Sbrian "ipcp|lcp|lqm|phase|tcp/ip|timer|tun..."}, 175436285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 175536285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 175636285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 175736285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 175836285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 175936285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 176036285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 176136285Sbrian "set mrru value", (const void *)VAR_MRRU}, 176236285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 176336285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 176436285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 176536285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 176636285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 176736285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 176836285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 176936285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 177036285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 177136285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 177236285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 177336285Sbrian "modem parity", "set parity [odd|even|none]"}, 177436285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 177536285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 177636285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 177736285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 177840665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 177940665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 178036285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 178136285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 178240665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 178340665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 178428679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 178536774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 178636285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 178736285Sbrian "modem speed", "set speed value"}, 178836285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 178936285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 179036285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 179136285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 179236285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 179336285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 179436285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 179536285Sbrian "datalink weighting", "set weight n"}, 179628679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 179731343Sbrian "Display this message", "set help|? [command]", SetCommands}, 179828679Sbrian {NULL, NULL, NULL}, 17996059Samurai}; 18006059Samurai 18016059Samuraistatic int 180231343SbrianSetCommand(struct cmdargs const *arg) 18036059Samurai{ 180436285Sbrian if (arg->argc > arg->argn) 180536285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 180636285Sbrian arg->prompt, arg->cx); 180736285Sbrian else if (arg->prompt) 180836285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 180926516Sbrian " syntax help.\n"); 18106059Samurai else 181136285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 181226516Sbrian 181326516Sbrian return 0; 18146059Samurai} 18156059Samurai 18166059Samuraistatic int 181731343SbrianAddCommand(struct cmdargs const *arg) 18186059Samurai{ 18196059Samurai struct in_addr dest, gateway, netmask; 182036285Sbrian int gw, addrs; 18216059Samurai 182236285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 182331598Sbrian return -1; 182431598Sbrian 182536285Sbrian addrs = 0; 182636285Sbrian if (arg->argc == arg->argn+2) { 182736285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 182836285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 182931598Sbrian else { 183036285Sbrian int width; 183136285Sbrian 183236285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 183336285Sbrian &dest, &netmask, &width)) 183436285Sbrian return -1; 183536285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 183636285Sbrian addrs = ROUTE_DSTMYADDR; 183736285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 183836285Sbrian addrs = ROUTE_DSTHISADDR; 183931598Sbrian } 184036285Sbrian gw = 1; 184134536Sbrian } else { 184236285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 184336285Sbrian addrs = ROUTE_DSTMYADDR; 184436285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 184536285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 184636285Sbrian addrs = ROUTE_DSTHISADDR; 184736285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 184836285Sbrian } else 184936285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 185036285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 185131598Sbrian gw = 2; 18526059Samurai } 185336285Sbrian 185436285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 185536285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 185636285Sbrian addrs |= ROUTE_GWHISADDR; 185740561Sbrian } else 185836285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 185936285Sbrian 186036285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 186137927Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0)) 186236285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 186336285Sbrian 186431598Sbrian return 0; 18656059Samurai} 18666059Samurai 18676059Samuraistatic int 186831343SbrianDeleteCommand(struct cmdargs const *arg) 18696059Samurai{ 187031598Sbrian struct in_addr dest, none; 187136285Sbrian int addrs; 18726059Samurai 187336285Sbrian if (arg->argc == arg->argn+1) { 187436285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 187536285Sbrian route_IfDelete(arg->bundle, 0); 187636285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 187736285Sbrian } else { 187836285Sbrian addrs = 0; 187936285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 188036285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 188136285Sbrian addrs = ROUTE_DSTMYADDR; 188236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 188336285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 188436285Sbrian addrs = ROUTE_DSTHISADDR; 188536285Sbrian } else { 188636285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 188736285Sbrian dest.s_addr = INADDR_ANY; 188836285Sbrian else 188936285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 189036285Sbrian addrs = ROUTE_STATIC; 189136285Sbrian } 189231598Sbrian none.s_addr = INADDR_ANY; 189336285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 189437927Sbrian arg->cmd->args ? 1 : 0, 0); 189536285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 189631598Sbrian } 189734536Sbrian } else 189826516Sbrian return -1; 189926516Sbrian 190026516Sbrian return 0; 19016059Samurai} 19026059Samurai 190331343Sbrian#ifndef NOALIAS 190426031Sbrianstatic int 190531343SbrianAliasEnable(struct cmdargs const *arg) 190626031Sbrian{ 190736285Sbrian if (arg->argc == arg->argn+1) { 190836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 190937191Sbrian arg->bundle->AliasEnabled = 1; 191037191Sbrian return 0; 191136285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 191237191Sbrian arg->bundle->AliasEnabled = 0; 191340561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 191440561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 191526516Sbrian return 0; 191626142Sbrian } 191735449Sbrian } 191836285Sbrian 191926516Sbrian return -1; 192026031Sbrian} 192126031Sbrian 192226031Sbrian 192326031Sbrianstatic int 192431343SbrianAliasOption(struct cmdargs const *arg) 192526031Sbrian{ 192638559Sbrian long param = (long)arg->cmd->args; 192738559Sbrian 192836285Sbrian if (arg->argc == arg->argn+1) { 192936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 193037191Sbrian if (arg->bundle->AliasEnabled) { 193137191Sbrian PacketAliasSetMode(param, param); 193228679Sbrian return 0; 193328679Sbrian } 193436285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 193536285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 193637191Sbrian if (arg->bundle->AliasEnabled) { 193737191Sbrian PacketAliasSetMode(0, param); 193828679Sbrian return 0; 193928679Sbrian } 194036285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 194128679Sbrian } 194235449Sbrian } 194328679Sbrian return -1; 194426031Sbrian} 194531343Sbrian#endif /* #ifndef NOALIAS */ 194631121Sbrian 194731121Sbrianstatic int 194836285SbrianLinkCommand(struct cmdargs const *arg) 194936285Sbrian{ 195036285Sbrian if (arg->argc > arg->argn+1) { 195136285Sbrian char namelist[LINE_LEN]; 195236285Sbrian struct datalink *cx; 195336285Sbrian char *name; 195436285Sbrian int result = 0; 195536285Sbrian 195636285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 195736285Sbrian struct datalink *dl; 195836285Sbrian 195936285Sbrian cx = arg->bundle->links; 196036285Sbrian while (cx) { 196136285Sbrian /* Watch it, the command could be a ``remove'' */ 196236285Sbrian dl = cx->next; 196336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 196436285Sbrian arg->prompt, cx); 196536285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 196636285Sbrian if (cx == dl) 196736285Sbrian break; /* Pointer's still valid ! */ 196836285Sbrian } 196936285Sbrian } else { 197036285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 197136285Sbrian namelist[sizeof namelist - 1] = '\0'; 197236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 197336285Sbrian if (!bundle2datalink(arg->bundle, name)) { 197436285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 197536285Sbrian return 1; 197636285Sbrian } 197736285Sbrian 197836285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 197936285Sbrian namelist[sizeof namelist - 1] = '\0'; 198036285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 198136285Sbrian cx = bundle2datalink(arg->bundle, name); 198236285Sbrian if (cx) 198336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 198436285Sbrian arg->prompt, cx); 198536285Sbrian else { 198636285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 198736285Sbrian result++; 198836285Sbrian } 198936285Sbrian } 199036285Sbrian } 199136285Sbrian return result; 199236285Sbrian } 199336285Sbrian 199436285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 199536285Sbrian return 2; 199636285Sbrian} 199736285Sbrian 199836285Sbrianstruct link * 199936285Sbriancommand_ChooseLink(struct cmdargs const *arg) 200036285Sbrian{ 200136285Sbrian if (arg->cx) 200236285Sbrian return &arg->cx->physical->link; 200337210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 200436285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 200537210Sbrian if (dl) 200637210Sbrian return &dl->physical->link; 200736285Sbrian } 200837210Sbrian return &arg->bundle->ncp.mp.link; 200936285Sbrian} 201036285Sbrian 201136285Sbrianstatic const char * 201236285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 201336285Sbrian{ 201436285Sbrian const char *result; 201536285Sbrian 201636285Sbrian switch (*cmd) { 201736285Sbrian case 'A': 201836285Sbrian case 'a': 201936285Sbrian result = "accept"; 202036285Sbrian *keep = NEG_MYMASK; 202136285Sbrian *add = NEG_ACCEPTED; 202236285Sbrian break; 202336285Sbrian case 'D': 202436285Sbrian case 'd': 202536285Sbrian switch (cmd[1]) { 202636285Sbrian case 'E': 202736285Sbrian case 'e': 202836285Sbrian result = "deny"; 202936285Sbrian *keep = NEG_MYMASK; 203036285Sbrian *add = 0; 203136285Sbrian break; 203236285Sbrian case 'I': 203336285Sbrian case 'i': 203436285Sbrian result = "disable"; 203536285Sbrian *keep = NEG_HISMASK; 203636285Sbrian *add = 0; 203736285Sbrian break; 203836285Sbrian default: 203936285Sbrian return NULL; 204036285Sbrian } 204136285Sbrian break; 204236285Sbrian case 'E': 204336285Sbrian case 'e': 204436285Sbrian result = "enable"; 204536285Sbrian *keep = NEG_HISMASK; 204636285Sbrian *add = NEG_ENABLED; 204736285Sbrian break; 204836285Sbrian default: 204936285Sbrian return NULL; 205036285Sbrian } 205136285Sbrian 205236285Sbrian return result; 205336285Sbrian} 205436285Sbrian 205536285Sbrianstatic int 205636285SbrianOptSet(struct cmdargs const *arg) 205736285Sbrian{ 205837574Sbrian int bit = (int)(long)arg->cmd->args; 205936285Sbrian const char *cmd; 206036285Sbrian unsigned keep; /* Keep these bits */ 206136285Sbrian unsigned add; /* Add these bits */ 206236285Sbrian 206336285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 206436285Sbrian return 1; 206536285Sbrian 206636285Sbrian if (add) 206736285Sbrian arg->bundle->cfg.opt |= bit; 206836285Sbrian else 206936285Sbrian arg->bundle->cfg.opt &= ~bit; 207036285Sbrian return 0; 207136285Sbrian} 207236285Sbrian 207336285Sbrianstatic int 207440561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 207540561Sbrian{ 207640561Sbrian unsigned save = arg->bundle->cfg.opt; 207740561Sbrian int result = OptSet(arg); 207840561Sbrian 207940561Sbrian if (result == 0) 208040561Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->AliasEnabled) { 208140561Sbrian arg->bundle->cfg.opt = save; 208240561Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without IP aliasing\n"); 208340561Sbrian result = 2; 208440561Sbrian } 208540561Sbrian 208640561Sbrian return result; 208740561Sbrian} 208840561Sbrian 208940561Sbrianstatic int 209036285SbrianNegotiateSet(struct cmdargs const *arg) 209136285Sbrian{ 209237210Sbrian long param = (long)arg->cmd->args; 209336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 209436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 209536285Sbrian const char *cmd; 209636285Sbrian unsigned keep; /* Keep these bits */ 209736285Sbrian unsigned add; /* Add these bits */ 209836285Sbrian 209936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 210036285Sbrian return 1; 210136285Sbrian 210236285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 210336285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 210436285Sbrian cmd, arg->cmd->name); 210536285Sbrian return 2; 210636285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 210736285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 210836285Sbrian cmd, arg->cmd->name, cx->name); 210936285Sbrian cx = NULL; 211036285Sbrian } 211136285Sbrian 211236285Sbrian switch (param) { 211336285Sbrian case NEG_ACFCOMP: 211436285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 211536285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 211636285Sbrian break; 211736285Sbrian case NEG_CHAP: 211836285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 211936285Sbrian cx->physical->link.lcp.cfg.chap |= add; 212036285Sbrian break; 212136285Sbrian case NEG_DEFLATE: 212236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 212336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 212436285Sbrian break; 212536285Sbrian case NEG_DNS: 212636285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 212736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 212836285Sbrian break; 212936285Sbrian case NEG_LQR: 213036285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 213136285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 213236285Sbrian break; 213336285Sbrian case NEG_PAP: 213436285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 213536285Sbrian cx->physical->link.lcp.cfg.pap |= add; 213636285Sbrian break; 213736285Sbrian case NEG_PPPDDEFLATE: 213836285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 213936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 214036285Sbrian break; 214136285Sbrian case NEG_PRED1: 214236285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 214336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 214436285Sbrian break; 214536285Sbrian case NEG_PROTOCOMP: 214636285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 214736285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 214836285Sbrian break; 214936285Sbrian case NEG_SHORTSEQ: 215040622Sbrian switch (bundle_Phase(arg->bundle)) { 215140622Sbrian case PHASE_DEAD: 215240622Sbrian break; 215340622Sbrian case PHASE_ESTABLISH: 215440622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 215540622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 215640622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 215740622Sbrian " LCP negotiations\n"); 215840622Sbrian return 1; 215940622Sbrian } 216040622Sbrian break; 216140622Sbrian default: 216240622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 216340622Sbrian " DEAD/ESTABLISH\n"); 216440622Sbrian return 1; 216536285Sbrian } 216640622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 216740622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 216836285Sbrian break; 216936285Sbrian case NEG_VJCOMP: 217036285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 217136285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 217236285Sbrian break; 217336285Sbrian } 217436285Sbrian 217536285Sbrian return 0; 217636285Sbrian} 217736285Sbrian 217836285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 217936285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 218036285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 218136285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 218236285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 218336285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 218436285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 218540665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 218636285Sbrian "disable|enable", (const void *)OPT_PROXY}, 218740665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 218840665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 218936285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 219036285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 219136285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 219236285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 219336285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 219436285Sbrian "disable|enable", (const void *)OPT_UTMP}, 219540561Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 219640561Sbrian "maintain interface addresses", "disable|enable", 219740561Sbrian (const void *)OPT_IFACEALIAS}, 219836285Sbrian 219940665Sbrian#define OPT_MAX 9 /* accept/deny allowed below and not above */ 220036285Sbrian 220136285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 220236285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 220336285Sbrian (const void *)NEG_ACFCOMP}, 220436285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 220536285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 220636285Sbrian (const void *)NEG_CHAP}, 220736285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 220836285Sbrian "Deflate compression", "accept|deny|disable|enable", 220936285Sbrian (const void *)NEG_DEFLATE}, 221036285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 221136285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 221236285Sbrian (const void *)NEG_PPPDDEFLATE}, 221336285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 221436285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 221536285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 221636285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 221736285Sbrian (const void *)NEG_LQR}, 221836285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 221936285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 222036285Sbrian (const void *)NEG_PAP}, 222136285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 222236285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 222336285Sbrian (const void *)NEG_PRED1}, 222436285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 222536285Sbrian "Protocol field compression", "accept|deny|disable|enable", 222636285Sbrian (const void *)NEG_PROTOCOMP}, 222736285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 222836285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 222936285Sbrian (const void *)NEG_SHORTSEQ}, 223036285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 223136285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 223236285Sbrian (const void *)NEG_VJCOMP}, 223336285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 223436285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 223536285Sbrian NegotiateCommands}, 223636285Sbrian {NULL, NULL, NULL}, 223736285Sbrian}; 223836285Sbrian 223936285Sbrianstatic int 224036285SbrianNegotiateCommand(struct cmdargs const *arg) 224136285Sbrian{ 224236285Sbrian if (arg->argc > arg->argn) { 224336285Sbrian char const *argv[3]; 224436285Sbrian unsigned keep, add; 224536285Sbrian int n; 224636285Sbrian 224736285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 224836285Sbrian return -1; 224936285Sbrian argv[2] = NULL; 225036285Sbrian 225136285Sbrian for (n = arg->argn; n < arg->argc; n++) { 225236285Sbrian argv[1] = arg->argv[n]; 225336285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 225436285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 225536285Sbrian } 225636285Sbrian } else if (arg->prompt) 225736285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 225836285Sbrian arg->argv[arg->argn-1]); 225936285Sbrian else 226036285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 226136285Sbrian arg->argv[arg->argn] ); 226236285Sbrian 226336285Sbrian return 0; 226436285Sbrian} 226536285Sbrian 226636285Sbrianconst char * 226736285Sbriancommand_ShowNegval(unsigned val) 226836285Sbrian{ 226936285Sbrian switch (val&3) { 227036285Sbrian case 1: return "disabled & accepted"; 227136285Sbrian case 2: return "enabled & denied"; 227236285Sbrian case 3: return "enabled & accepted"; 227336285Sbrian } 227436285Sbrian return "disabled & denied"; 227536285Sbrian} 227636934Sbrian 227736934Sbrianstatic int 227836934SbrianClearCommand(struct cmdargs const *arg) 227936934Sbrian{ 228036934Sbrian struct pppThroughput *t; 228136934Sbrian struct datalink *cx; 228236934Sbrian int i, clear_type; 228336934Sbrian 228436934Sbrian if (arg->argc < arg->argn + 1) 228536934Sbrian return -1; 228636934Sbrian 228736934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 228836934Sbrian cx = arg->cx; 228936934Sbrian if (!cx) 229036934Sbrian cx = bundle2datalink(arg->bundle, NULL); 229136934Sbrian if (!cx) { 229236934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 229336934Sbrian return 1; 229436934Sbrian } 229536934Sbrian t = &cx->physical->link.throughput; 229636934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 229736934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 229836934Sbrian else 229936934Sbrian return -1; 230036934Sbrian 230136934Sbrian if (arg->argc > arg->argn + 1) { 230236934Sbrian clear_type = 0; 230336934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 230436934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 230536934Sbrian clear_type |= THROUGHPUT_OVERALL; 230636934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 230736934Sbrian clear_type |= THROUGHPUT_CURRENT; 230836934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 230936934Sbrian clear_type |= THROUGHPUT_PEAK; 231036934Sbrian else 231136934Sbrian return -1; 231236934Sbrian } else 231336934Sbrian clear_type = THROUGHPUT_ALL; 231436934Sbrian 231536934Sbrian throughput_clear(t, clear_type, arg->prompt); 231636934Sbrian return 0; 231736934Sbrian} 231840561Sbrian 231940561Sbrianstatic int 232040561SbrianRunListCommand(struct cmdargs const *arg) 232140561Sbrian{ 232240561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 232340561Sbrian 232440561Sbrian if (arg->argc > arg->argn) 232540561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 232640561Sbrian arg->prompt, arg->cx); 232740561Sbrian else if (arg->prompt) 232840561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 232940561Sbrian " <option>' for syntax help.\n", cmd, cmd); 233040561Sbrian else 233140561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 233240561Sbrian 233340561Sbrian return 0; 233440561Sbrian} 233540561Sbrian 233640561Sbrianstatic int 233740561SbrianIfaceAddCommand(struct cmdargs const *arg) 233840561Sbrian{ 233940561Sbrian int bits, n, how; 234040561Sbrian struct in_addr ifa, mask, brd; 234140561Sbrian 234240664Sbrian if (arg->argc == arg->argn + 1) { 234340561Sbrian if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL)) 234440561Sbrian return -1; 234540664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 234640664Sbrian } else { 234740664Sbrian if (arg->argc == arg->argn + 2) { 234840664Sbrian if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, &mask, &bits)) 234940664Sbrian return -1; 235040664Sbrian n = 1; 235140664Sbrian } else if (arg->argc == arg->argn + 3) { 235240664Sbrian if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL)) 235340664Sbrian return -1; 235440664Sbrian if (!ParseAddr(NULL, 1, arg->argv + arg->argn + 1, &mask, NULL, NULL)) 235540664Sbrian return -1; 235640664Sbrian n = 2; 235740664Sbrian } else 235840561Sbrian return -1; 235940561Sbrian 236040664Sbrian if (!ParseAddr(NULL, 1, arg->argv + arg->argn + n, &brd, NULL, NULL)) 236140664Sbrian return -1; 236240664Sbrian } 236340561Sbrian 236440561Sbrian how = IFACE_ADD_LAST; 236540561Sbrian if (arg->cmd->args) 236640561Sbrian how |= IFACE_FORCE_ADD; 236740561Sbrian 236840561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 236940561Sbrian} 237040561Sbrian 237140561Sbrianstatic int 237240561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 237340561Sbrian{ 237440561Sbrian struct in_addr ifa; 237540561Sbrian int ok; 237640561Sbrian 237740561Sbrian if (arg->argc != arg->argn + 1) 237840561Sbrian return -1; 237940561Sbrian 238040561Sbrian if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL)) 238140561Sbrian return -1; 238240561Sbrian 238340561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 238440561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 238540561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 238640561Sbrian inet_ntoa(ifa)); 238740561Sbrian return 1; 238840561Sbrian } 238940561Sbrian 239040561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 239140561Sbrian if (!ok) { 239240561Sbrian if (arg->cmd->args) 239340561Sbrian ok = 1; 239440561Sbrian else if (arg->prompt) 239540561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 239640561Sbrian else 239740561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 239840561Sbrian } 239940561Sbrian 240040561Sbrian return !ok; 240140561Sbrian} 240240561Sbrian 240340561Sbrianstatic int 240440561SbrianIfaceClearCommand(struct cmdargs const *arg) 240540561Sbrian{ 240640561Sbrian int how; 240740561Sbrian 240840561Sbrian if (arg->argc != arg->argn) 240940561Sbrian return -1; 241040561Sbrian 241140561Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED ? 241240561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 241340561Sbrian iface_Clear(arg->bundle->iface, how); 241440561Sbrian 241540561Sbrian return 0; 241640561Sbrian} 2417