command.c revision 40482
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 * 2040482Sbrian * $Id: command.c,v 1.166 1998/09/17 00:45:26 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" 866059Samurai 8736285Sbrian/* ``set'' values */ 8836285Sbrian#define VAR_AUTHKEY 0 8936285Sbrian#define VAR_DIAL 1 9036285Sbrian#define VAR_LOGIN 2 9136285Sbrian#define VAR_AUTHNAME 3 9236285Sbrian#define VAR_AUTOLOAD 4 9336285Sbrian#define VAR_WINSIZE 5 9436285Sbrian#define VAR_DEVICE 6 9536285Sbrian#define VAR_ACCMAP 7 9636285Sbrian#define VAR_MRRU 8 9736285Sbrian#define VAR_MRU 9 9836285Sbrian#define VAR_MTU 10 9936285Sbrian#define VAR_OPENMODE 11 10036285Sbrian#define VAR_PHONE 12 10136285Sbrian#define VAR_HANGUP 13 10236285Sbrian#define VAR_IDLETIMEOUT 14 10336285Sbrian#define VAR_LQRPERIOD 15 10436285Sbrian#define VAR_LCPRETRY 16 10536285Sbrian#define VAR_CHAPRETRY 17 10636285Sbrian#define VAR_PAPRETRY 18 10736285Sbrian#define VAR_CCPRETRY 19 10836285Sbrian#define VAR_IPCPRETRY 20 10936285Sbrian#define VAR_DNS 21 11036285Sbrian#define VAR_NBNS 22 11136285Sbrian#define VAR_MODE 23 11238174Sbrian#define VAR_CALLBACK 24 11338174Sbrian#define VAR_CBCP 25 11438544Sbrian#define VAR_CHOKED 26 1156059Samurai 11636285Sbrian/* ``accept|deny|disable|enable'' masks */ 11736285Sbrian#define NEG_HISMASK (1) 11836285Sbrian#define NEG_MYMASK (2) 11936285Sbrian 12036285Sbrian/* ``accept|deny|disable|enable'' values */ 12136285Sbrian#define NEG_ACFCOMP 40 12236285Sbrian#define NEG_CHAP 41 12336285Sbrian#define NEG_DEFLATE 42 12436285Sbrian#define NEG_LQR 43 12536285Sbrian#define NEG_PAP 44 12636285Sbrian#define NEG_PPPDDEFLATE 45 12736285Sbrian#define NEG_PRED1 46 12836285Sbrian#define NEG_PROTOCOMP 47 12936285Sbrian#define NEG_SHORTSEQ 48 13036285Sbrian#define NEG_VJCOMP 49 13136285Sbrian#define NEG_DNS 50 13236285Sbrian 13337373Sbrianconst char Version[] = "2.0"; 13440482Sbrianconst char VersionDate[] = "$Date: 1998/09/17 00:45:26 $"; 13536285Sbrian 13636285Sbrianstatic int ShowCommand(struct cmdargs const *); 13736285Sbrianstatic int TerminalCommand(struct cmdargs const *); 13836285Sbrianstatic int QuitCommand(struct cmdargs const *); 13936285Sbrianstatic int OpenCommand(struct cmdargs const *); 14036285Sbrianstatic int CloseCommand(struct cmdargs const *); 14136285Sbrianstatic int DownCommand(struct cmdargs const *); 14236285Sbrianstatic int AllowCommand(struct cmdargs const *); 14336285Sbrianstatic int SetCommand(struct cmdargs const *); 14436285Sbrianstatic int LinkCommand(struct cmdargs const *); 14536285Sbrianstatic int AddCommand(struct cmdargs const *); 14636285Sbrianstatic int DeleteCommand(struct cmdargs const *); 14736285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 14836934Sbrianstatic int ClearCommand(struct cmdargs const *); 14931343Sbrian#ifndef NOALIAS 15036285Sbrianstatic int AliasCommand(struct cmdargs const *); 15136285Sbrianstatic int AliasEnable(struct cmdargs const *); 15236285Sbrianstatic int AliasOption(struct cmdargs const *); 15331343Sbrian#endif 1546059Samurai 15536285Sbrianstatic const char * 15636285Sbrianshowcx(struct cmdtab const *cmd) 15736285Sbrian{ 15836285Sbrian if (cmd->lauth & LOCAL_CX) 15936285Sbrian return "(c)"; 16036285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 16136285Sbrian return "(o)"; 16236285Sbrian 16336285Sbrian return ""; 16436285Sbrian} 16536285Sbrian 1666059Samuraistatic int 16731343SbrianHelpCommand(struct cmdargs const *arg) 1686059Samurai{ 16928679Sbrian struct cmdtab const *cmd; 17036285Sbrian int n, cmax, dmax, cols, cxlen; 17136285Sbrian const char *cx; 1726059Samurai 17336285Sbrian if (!arg->prompt) { 17436285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 17526516Sbrian return 0; 17636285Sbrian } 17726516Sbrian 17836285Sbrian if (arg->argc > arg->argn) { 17936285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 18036285Sbrian if ((cmd->lauth & arg->prompt->auth) && 18136285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 18236285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 18336285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 18428679Sbrian return 0; 1856059Samurai } 18626516Sbrian return -1; 1876059Samurai } 18836285Sbrian 18931372Sbrian cmax = dmax = 0; 19036285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 19136285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 19236285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 19331372Sbrian cmax = n; 19431372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 19531372Sbrian dmax = n; 19631372Sbrian } 19731372Sbrian 19831372Sbrian cols = 80 / (dmax + cmax + 3); 1996059Samurai n = 0; 20036285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 20136285Sbrian " (c) = Context required\n"); 20236285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 20336285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 20436285Sbrian cx = showcx(cmd); 20536285Sbrian cxlen = cmax - strlen(cmd->name); 20640482Sbrian if (n % cols != 0) 20740482Sbrian prompt_Printf(arg->prompt, " "); 20840482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 20936285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 21031372Sbrian if (++n % cols == 0) 21136285Sbrian prompt_Printf(arg->prompt, "\n"); 2126059Samurai } 21331372Sbrian if (n % cols != 0) 21436285Sbrian prompt_Printf(arg->prompt, "\n"); 21526516Sbrian 21626516Sbrian return 0; 2176059Samurai} 2186059Samurai 21936285Sbrianstatic int 22036285SbrianCloneCommand(struct cmdargs const *arg) 2216059Samurai{ 22236285Sbrian char namelist[LINE_LEN]; 22336285Sbrian char *name; 22436285Sbrian int f; 2256059Samurai 22636285Sbrian if (arg->argc == arg->argn) 22736285Sbrian return -1; 22836285Sbrian 22936285Sbrian namelist[sizeof namelist - 1] = '\0'; 23036285Sbrian for (f = arg->argn; f < arg->argc; f++) { 23136285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 23236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 23336285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2346059Samurai } 23536285Sbrian 23636285Sbrian return 0; 2376059Samurai} 2386059Samurai 2396059Samuraistatic int 24036285SbrianRemoveCommand(struct cmdargs const *arg) 2416059Samurai{ 24236285Sbrian if (arg->argc != arg->argn) 24336285Sbrian return -1; 24411336Samurai 24536285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 24636285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 24736285Sbrian return 2; 2486059Samurai } 24926516Sbrian 25036285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 25136285Sbrian return 0; 25236285Sbrian} 25332711Sbrian 25436285Sbrianstatic int 25536285SbrianRenameCommand(struct cmdargs const *arg) 25636285Sbrian{ 25736285Sbrian if (arg->argc != arg->argn + 1) 25836285Sbrian return -1; 25931121Sbrian 26036285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 26136285Sbrian return 0; 26236285Sbrian 26336285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 26436285Sbrian arg->cx->name, arg->argv[arg->argn]); 26536285Sbrian return 1; 26636285Sbrian} 26736285Sbrian 26836285Sbrianint 26936285SbrianLoadCommand(struct cmdargs const *arg) 27036285Sbrian{ 27136285Sbrian const char *name; 27236285Sbrian 27336285Sbrian if (arg->argc > arg->argn) 27436285Sbrian name = arg->argv[arg->argn]; 27536285Sbrian else 27636285Sbrian name = "default"; 27736285Sbrian 27836928Sbrian if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type.all)) { 27937019Sbrian log_Printf(LogWARN, "%s: Label not allowed\n", name); 28036285Sbrian return 1; 28136285Sbrian } else { 28236285Sbrian /* 28336285Sbrian * Set the label before & after so that `set enddisc' works and 28436285Sbrian * we handle nested `load' commands. 28536285Sbrian */ 28636285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28737008Sbrian if (system_Select(arg->bundle, name, CONFFILE, arg->prompt, arg->cx) < 0) { 28836285Sbrian bundle_SetLabel(arg->bundle, NULL); 28936285Sbrian log_Printf(LogWARN, "%s: label not found.\n", name); 29036285Sbrian return -1; 29132403Sbrian } 29236285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 29336285Sbrian } 29426516Sbrian return 0; 2956059Samurai} 2966059Samurai 29736285Sbrianint 29836285SbrianSaveCommand(struct cmdargs const *arg) 29936285Sbrian{ 30036285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 30136285Sbrian return 1; 30236285Sbrian} 30336285Sbrian 30410528Samuraistatic int 30536285SbrianDialCommand(struct cmdargs const *arg) 30628536Sbrian{ 30736285Sbrian int res; 30836285Sbrian 30936465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 31036465Sbrian || (!arg->cx && 31136928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 31236285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 31336285Sbrian " interactive links\n"); 31436285Sbrian return 1; 31534536Sbrian } 31636285Sbrian 31736285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 31836285Sbrian return res; 31936285Sbrian 32037993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 32136285Sbrian 32236285Sbrian return 0; 32328536Sbrian} 32428536Sbrian 32538628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 32638628Sbrian 32738628Sbrianstatic char * 32838628Sbrianstrstrword(char *big, const char *little) 32938628Sbrian{ 33038628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 33138628Sbrian char *pos; 33238628Sbrian int len; 33338628Sbrian 33438628Sbrian pos = big; 33538628Sbrian len = strlen(little); 33638628Sbrian 33738628Sbrian while ((pos = strstr(pos, little)) != NULL) 33838628Sbrian if ((pos == big || !isinword(pos[-1])) && !isinword(pos[len])) 33938628Sbrian break; 34038628Sbrian else 34138628Sbrian pos++; 34238628Sbrian 34338628Sbrian return pos; 34438628Sbrian} 34538628Sbrian 34638628Sbrianstatic char * 34738628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 34838628Sbrian{ 34938628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 35038628Sbrian char *word, *ntgt; 35138628Sbrian int ltgt, loldstr, lnewstr, pos; 35238628Sbrian 35338628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 35438628Sbrian return tgt; 35538628Sbrian 35638628Sbrian ltgt = strlen(tgt) + 1; 35738628Sbrian loldstr = strlen(oldstr); 35838628Sbrian lnewstr = strlen(newstr); 35938628Sbrian do { 36038628Sbrian pos = word - tgt; 36138628Sbrian if (loldstr > lnewstr) 36238628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 36338628Sbrian if (loldstr != lnewstr) { 36438628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 36538628Sbrian if (ntgt == NULL) 36638628Sbrian break; /* Oh wonderful ! */ 36738628Sbrian word = ntgt + pos; 36838628Sbrian tgt = ntgt; 36938628Sbrian } 37038628Sbrian if (lnewstr > loldstr) 37138628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 37238628Sbrian bcopy(newstr, word, lnewstr); 37338628Sbrian } while ((word = strstrword(word, oldstr))); 37438628Sbrian 37538628Sbrian return tgt; 37638628Sbrian} 37738628Sbrian 37838628Sbrianstatic void 37938628Sbrianexpand(char **nargv, int argc, char const *const *oargv, struct bundle *bundle) 38038628Sbrian{ 38138628Sbrian int arg; 38238628Sbrian 38338628Sbrian nargv[0] = strdup(oargv[0]); 38438628Sbrian for (arg = 1; arg < argc; arg++) { 38538629Sbrian nargv[arg] = strdup(oargv[arg]); 38638629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 38738628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 38838629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 38938628Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->ifp.Name); 39038628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 39138629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 39238629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 39338629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 39438629Sbrian bundle->ncp.mp.peer.enddisc.address, 39538629Sbrian bundle->ncp.mp.peer.enddisc.len)); 39638629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 39738629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 39838629Sbrian bundle->ncp.mp.cfg.enddisc.address, 39938629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 40038629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 40138628Sbrian } 40238628Sbrian nargv[arg] = NULL; 40338628Sbrian} 40438628Sbrian 40528536Sbrianstatic int 40631343SbrianShellCommand(struct cmdargs const *arg, int bg) 40710528Samurai{ 40810528Samurai const char *shell; 40910528Samurai pid_t shpid; 41020813Sjkh 41118856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 41226911Sbrian /* we're only allowed to shell when we run ppp interactively */ 41336285Sbrian if (arg->prompt && arg->prompt->owner) { 41436285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 41526516Sbrian return 1; 41610528Samurai } 41726911Sbrian#endif 41828679Sbrian 41936285Sbrian if (arg->argc == arg->argn) { 42036285Sbrian if (!arg->prompt) { 42136285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 42236285Sbrian " a config file\n"); 42328381Sbrian return 1; 42436285Sbrian } else if (arg->prompt->owner) { 42536285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 42636285Sbrian " a socket connection\n"); 42736285Sbrian return 1; 42828381Sbrian } else if (bg) { 42936285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 43028679Sbrian " the foreground mode\n"); 43128381Sbrian return 1; 43228381Sbrian } 43334536Sbrian } 43434536Sbrian 43528679Sbrian if ((shpid = fork()) == 0) { 43636285Sbrian int i, fd; 43718531Sbde 43836285Sbrian if ((shell = getenv("SHELL")) == 0) 43936285Sbrian shell = _PATH_BSHELL; 44032017Sbrian 44136285Sbrian timer_TermService(); 44236285Sbrian 44336285Sbrian if (arg->prompt) 44436285Sbrian fd = arg->prompt->fd_out; 44536285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 44636285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 44736285Sbrian _PATH_DEVNULL, strerror(errno)); 44828679Sbrian exit(1); 44928679Sbrian } 45028679Sbrian for (i = 0; i < 3; i++) 45128679Sbrian dup2(fd, i); 45226516Sbrian 45336285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 45426516Sbrian 45531061Sbrian setuid(geteuid()); 45636285Sbrian if (arg->argc > arg->argn) { 45728679Sbrian /* substitute pseudo args */ 45838628Sbrian char *argv[MAXARGS]; 45938628Sbrian int argc = arg->argc - arg->argn; 46038628Sbrian 46138628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 46238628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 46338628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 46431343Sbrian } 46538628Sbrian expand(argv, argc, arg->argv + arg->argn, arg->bundle); 46628679Sbrian if (bg) { 46728679Sbrian pid_t p; 46810528Samurai 46928679Sbrian p = getpid(); 47028679Sbrian if (daemon(1, 1) == -1) { 47136832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 47228679Sbrian exit(1); 47328679Sbrian } 47436285Sbrian } else if (arg->prompt) 47536285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 47631343Sbrian execvp(argv[0], argv); 47730316Sbrian } else { 47836285Sbrian if (arg->prompt) 47932017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 48036285Sbrian prompt_TtyOldMode(arg->prompt); 48131343Sbrian execl(shell, shell, NULL); 48230316Sbrian } 48320813Sjkh 48436285Sbrian log_Printf(LogWARN, "exec() of %s failed\n", 48536285Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell); 48628679Sbrian exit(255); 48710528Samurai } 48836285Sbrian 48936285Sbrian if (shpid == (pid_t) - 1) 49036285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 49136285Sbrian else { 49210528Samurai int status; 49331343Sbrian waitpid(shpid, &status, 0); 49410528Samurai } 49520813Sjkh 49636285Sbrian if (arg->prompt && !arg->prompt->owner) 49736285Sbrian prompt_TtyCommandMode(arg->prompt); 49820813Sjkh 49936285Sbrian return 0; 50010528Samurai} 50110528Samurai 50231343Sbrianstatic int 50331343SbrianBgShellCommand(struct cmdargs const *arg) 50431343Sbrian{ 50536285Sbrian if (arg->argc == arg->argn) 50631343Sbrian return -1; 50731343Sbrian return ShellCommand(arg, 1); 50831343Sbrian} 50931343Sbrian 51031343Sbrianstatic int 51131343SbrianFgShellCommand(struct cmdargs const *arg) 51231343Sbrian{ 51331343Sbrian return ShellCommand(arg, 0); 51431343Sbrian} 51531343Sbrian 51630715Sbrianstatic struct cmdtab const Commands[] = { 51736285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 51828679Sbrian "accept option request", "accept option .."}, 51928679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 52032109Sbrian "add route", "add dest mask gateway", NULL}, 52136285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 52232109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 52336285Sbrian#ifndef NOALIAS 52436285Sbrian {"alias", NULL, AliasCommand, LOCAL_AUTH, 52536285Sbrian "alias control", "alias option [yes|no]"}, 52636285Sbrian#endif 52731121Sbrian {"allow", "auth", AllowCommand, LOCAL_AUTH, 52831121Sbrian "Allow ppp access", "allow users|modes ...."}, 52928679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 53031372Sbrian "Run a background command", "[!]bg command"}, 53136934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 53236934Sbrian "Clear throughput statistics", "clear ipcp|modem [current|overall|peak]..."}, 53336285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 53436285Sbrian "Clone a link", "clone newname..."}, 53536285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 53636285Sbrian "Close an FSM", "close [lcp|ccp]"}, 53728679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 53832109Sbrian "delete route", "delete dest", NULL}, 53936285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 54032109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 54136285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54228679Sbrian "Deny option request", "deny option .."}, 54336285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54437955Sbrian "Dial and login", "dial|call [remote]", NULL}, 54536285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54628679Sbrian "Disable option", "disable option .."}, 54736285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54836285Sbrian "Generate a down event", "down"}, 54936285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 55028679Sbrian "Enable option", "enable option .."}, 55136285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 55236285Sbrian "Link specific commands", "link name command ..."}, 55337008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 55428679Sbrian "Load settings", "load [remote]"}, 55536285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 55637955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 55736285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 55836285Sbrian "Password for manipulation", "passwd LocalPassword"}, 55936285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 56036285Sbrian "Quit PPP program", "quit|bye [all]"}, 56136285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 56236285Sbrian "Remove a link", "remove"}, 56336285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 56436285Sbrian "Rename a link", "rename name"}, 56528679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 56628679Sbrian "Save settings", "save"}, 56736285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 56828679Sbrian "Set parameters", "set[up] var value"}, 56928679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 57028679Sbrian "Run a subshell", "shell|! [sh command]"}, 57136285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 57231372Sbrian "Show status and stats", "show var"}, 57336285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 57431372Sbrian "Enter terminal mode", "term"}, 57528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 57631343Sbrian "Display this message", "help|? [command]", Commands}, 57728679Sbrian {NULL, NULL, NULL}, 5786059Samurai}; 5796059Samurai 58028536Sbrianstatic int 58131343SbrianShowEscape(struct cmdargs const *arg) 5826059Samurai{ 58336285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 58436285Sbrian int code, bit; 58536285Sbrian const char *sep = ""; 5866059Samurai 58726516Sbrian for (code = 0; code < 32; code++) 58836285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 58928679Sbrian for (bit = 0; bit < 8; bit++) 59036285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 59136285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 59236285Sbrian sep = ", "; 59336285Sbrian } 59436285Sbrian prompt_Printf(arg->prompt, "\n"); 5956059Samurai } 59631077Sbrian return 0; 5976059Samurai} 5986059Samurai 59928679Sbrianstatic int 60036285SbrianShowTimerList(struct cmdargs const *arg) 6016059Samurai{ 60236285Sbrian timer_Show(0, arg->prompt); 60331077Sbrian return 0; 6046059Samurai} 6056059Samurai 60628679Sbrianstatic int 60731343SbrianShowStopped(struct cmdargs const *arg) 60828327Sbrian{ 60936285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 61036285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 61136285Sbrian prompt_Printf(arg->prompt, "Disabled"); 61228327Sbrian else 61336285Sbrian prompt_Printf(arg->prompt, "%ld secs", 61436285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 61528461Sbrian 61636285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 61736285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 61836285Sbrian prompt_Printf(arg->prompt, "Disabled"); 61928461Sbrian else 62036285Sbrian prompt_Printf(arg->prompt, "%ld secs", 62136285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 62228461Sbrian 62336285Sbrian prompt_Printf(arg->prompt, "\n"); 62428461Sbrian 62531077Sbrian return 0; 62628327Sbrian} 62728327Sbrian 62828679Sbrianstatic int 62931343SbrianShowVersion(struct cmdargs const *arg) 6306059Samurai{ 63136285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 63231077Sbrian return 0; 6336059Samurai} 6346059Samurai 63528679Sbrianstatic int 63636285SbrianShowProtocolStats(struct cmdargs const *arg) 63726326Sbrian{ 63836285Sbrian struct link *l = command_ChooseLink(arg); 63926326Sbrian 64036285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 64136285Sbrian link_ReportProtocolStatus(l, arg->prompt); 64231077Sbrian return 0; 64326326Sbrian} 64426326Sbrian 64530715Sbrianstatic struct cmdtab const ShowCommands[] = { 64636285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 64736285Sbrian "bundle details", "show bundle"}, 64836285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 64936285Sbrian "CCP status", "show cpp"}, 65036285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 65136285Sbrian "VJ compression stats", "show compress"}, 65236285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 65336285Sbrian "escape characters", "show escape"}, 65436285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 65536285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 65636285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 65736285Sbrian "HDLC errors", "show hdlc"}, 65836285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 65936285Sbrian "IPCP status", "show ipcp"}, 66036285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 66136285Sbrian "LCP status", "show lcp"}, 66236285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 66336285Sbrian "(high-level) link info", "show link"}, 66436285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 66536285Sbrian "available link names", "show links"}, 66636285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 66736285Sbrian "log levels", "show log"}, 66836285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 66936285Sbrian "mbuf allocations", "show mem"}, 67036285Sbrian {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 67136285Sbrian "(low-level) link info", "show modem"}, 67236285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 67336285Sbrian "multilink setup", "show mp"}, 67436285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 67536285Sbrian "protocol summary", "show proto"}, 67636285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 67736285Sbrian "routing table", "show route"}, 67836285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 67936285Sbrian "STOPPED timeout", "show stopped"}, 68036285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 68136285Sbrian "alarm timers", "show timers"}, 68228679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 68336285Sbrian "version string", "show version"}, 68436285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 68536285Sbrian "client list", "show who"}, 68628679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 68731343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 68828679Sbrian {NULL, NULL, NULL}, 6896059Samurai}; 6906059Samurai 69130715Sbrianstatic struct cmdtab const * 69231343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 6936059Samurai{ 69426516Sbrian int nmatch; 69526516Sbrian int len; 69628679Sbrian struct cmdtab const *found; 6976059Samurai 69826516Sbrian found = NULL; 69926516Sbrian len = strlen(str); 70026516Sbrian nmatch = 0; 7016059Samurai while (cmds->func) { 70225566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 70326516Sbrian if (cmds->name[len] == '\0') { 70428679Sbrian *pmatch = 1; 70528679Sbrian return cmds; 70626516Sbrian } 7076059Samurai nmatch++; 7086059Samurai found = cmds; 70928679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 71026516Sbrian if (cmds->alias[len] == '\0') { 71128679Sbrian *pmatch = 1; 71228679Sbrian return cmds; 71326516Sbrian } 7146059Samurai nmatch++; 7156059Samurai found = cmds; 7166059Samurai } 7176059Samurai cmds++; 7186059Samurai } 7196059Samurai *pmatch = nmatch; 72026516Sbrian return found; 7216059Samurai} 7226059Samurai 72336285Sbrianstatic const char * 72436285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 72536285Sbrian{ 72636285Sbrian int f, tlen, len; 72736285Sbrian 72836285Sbrian tlen = 0; 72936285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 73036285Sbrian if (f) 73136285Sbrian tgt[tlen++] = ' '; 73236285Sbrian len = strlen(argv[f]); 73336285Sbrian if (len > sz - tlen - 1) 73436285Sbrian len = sz - tlen - 1; 73536285Sbrian strncpy(tgt+tlen, argv[f], len); 73636285Sbrian tlen += len; 73736285Sbrian } 73836285Sbrian tgt[tlen] = '\0'; 73936285Sbrian return tgt; 74036285Sbrian} 74136285Sbrian 74230715Sbrianstatic int 74336285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 74436285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 7456059Samurai{ 74628679Sbrian struct cmdtab const *cmd; 7476059Samurai int val = 1; 7486059Samurai int nmatch; 74931343Sbrian struct cmdargs arg; 75036285Sbrian char prefix[100]; 7516059Samurai 75236285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 7536059Samurai if (nmatch > 1) 75436285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 75536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 75636285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 75736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 75836285Sbrian /* We've got no context, but we require it */ 75936285Sbrian cx = bundle2datalink(bundle, NULL); 76036285Sbrian 76136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 76236285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 76336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 76436285Sbrian else { 76536285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 76636285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 76736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 76836285Sbrian cx = NULL; 76936285Sbrian } 77036285Sbrian arg.cmdtab = cmds; 77136285Sbrian arg.cmd = cmd; 77236285Sbrian arg.argc = argc; 77336285Sbrian arg.argn = argn+1; 77436285Sbrian arg.argv = argv; 77536285Sbrian arg.bundle = bundle; 77636285Sbrian arg.cx = cx; 77736285Sbrian arg.prompt = prompt; 77836285Sbrian val = (*cmd->func) (&arg); 77936285Sbrian } 78031343Sbrian } else 78136285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 78236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 78326516Sbrian 78426516Sbrian if (val == -1) 78536285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 78628679Sbrian else if (val) 78736285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 78836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 78926516Sbrian 79026516Sbrian return val; 7916059Samurai} 7926059Samurai 79337009Sbrianint 79437009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 7956059Samurai{ 7966059Samurai char *cp; 7976059Samurai 7986059Samurai if (nb > 0) { 7996059Samurai cp = buff + strcspn(buff, "\r\n"); 8006059Samurai if (cp) 8016059Samurai *cp = '\0'; 80237009Sbrian return MakeArgs(buff, argv, MAXARGS); 80337009Sbrian } 80437009Sbrian return 0; 80531121Sbrian} 8066059Samurai 80731822Sbrianstatic int 80831822Sbrianarghidden(int argc, char const *const *argv, int n) 80931822Sbrian{ 81031822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 81131828Sbrian 81231828Sbrian /* set authkey xxxxx */ 81331828Sbrian /* set key xxxxx */ 81431822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 81531822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 81631822Sbrian return 1; 81731822Sbrian 81831828Sbrian /* passwd xxxxx */ 81931828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 82031828Sbrian return 1; 82131828Sbrian 82236285Sbrian /* set server port xxxxx .... */ 82336285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 82436285Sbrian !strncasecmp(argv[1], "se", 2)) 82536285Sbrian return 1; 82636285Sbrian 82731822Sbrian return 0; 82831822Sbrian} 82931822Sbrian 83031121Sbrianvoid 83136285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 83237008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 83331121Sbrian{ 83431156Sbrian if (argc > 0) { 83536285Sbrian if (log_IsKept(LogCOMMAND)) { 83631156Sbrian static char buf[LINE_LEN]; 83731156Sbrian int f, n; 83831156Sbrian 83931156Sbrian *buf = '\0'; 84031156Sbrian if (label) { 84131962Sbrian strncpy(buf, label, sizeof buf - 3); 84231962Sbrian buf[sizeof buf - 3] = '\0'; 84331156Sbrian strcat(buf, ": "); 84431156Sbrian } 84531156Sbrian n = strlen(buf); 84631156Sbrian for (f = 0; f < argc; f++) { 84731962Sbrian if (n < sizeof buf - 1 && f) 84831156Sbrian buf[n++] = ' '; 84931822Sbrian if (arghidden(argc, argv, f)) 85036285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 85131822Sbrian else 85231962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 85331156Sbrian n += strlen(buf+n); 85431156Sbrian } 85536285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 85631156Sbrian } 85737008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 85831156Sbrian } 8596059Samurai} 8606059Samurai 86131121Sbrianvoid 86236285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 86336285Sbrian const char *label) 86431121Sbrian{ 86531121Sbrian int argc; 86637009Sbrian char *argv[MAXARGS]; 86731121Sbrian 86837009Sbrian argc = command_Interpret(buff, nb, argv); 86937008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 87031121Sbrian} 87131121Sbrian 8726059Samuraistatic int 87331343SbrianShowCommand(struct cmdargs const *arg) 8746059Samurai{ 87536285Sbrian if (!arg->prompt) 87636285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 87736285Sbrian else if (arg->argc > arg->argn) 87836285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 87936285Sbrian arg->prompt, arg->cx); 8806059Samurai else 88136285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 88226516Sbrian 88326516Sbrian return 0; 8846059Samurai} 8856059Samurai 8866059Samuraistatic int 88731343SbrianTerminalCommand(struct cmdargs const *arg) 8886059Samurai{ 88936285Sbrian if (!arg->prompt) { 89036285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 89126516Sbrian return 1; 8926059Samurai } 89336285Sbrian 89436285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 89536285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 89636285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 89736285Sbrian return 1; 8986059Samurai } 89936285Sbrian 90036285Sbrian datalink_Up(arg->cx, 0, 0); 90136285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 90236285Sbrian return 0; 9036059Samurai} 9046059Samurai 9056059Samuraistatic int 90631343SbrianQuitCommand(struct cmdargs const *arg) 9076059Samurai{ 90836285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 90936285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 91036285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 91136285Sbrian Cleanup(EX_NORMAL); 91236285Sbrian if (arg->prompt) 91336285Sbrian prompt_Destroy(arg->prompt, 1); 91426516Sbrian 91526516Sbrian return 0; 9166059Samurai} 9176059Samurai 9186059Samuraistatic int 91936285SbrianOpenCommand(struct cmdargs const *arg) 9206059Samurai{ 92137160Sbrian if (arg->argc == arg->argn) 92237993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 92337160Sbrian else if (arg->argc == arg->argn + 1) { 92437160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 92537385Sbrian struct datalink *cx = arg->cx ? 92637385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 92737385Sbrian if (cx) { 92837385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 92937385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 93037160Sbrian else 93137993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 93237160Sbrian } else 93337160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 93437160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 93537160Sbrian struct fsm *fp; 9366059Samurai 93737210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 93837160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 93937160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 94037160Sbrian else if (fp->state == ST_OPENED) 94137160Sbrian fsm_Reopen(fp); 94237160Sbrian else { 94337160Sbrian fp->open_mode = 0; /* Not passive any more */ 94437160Sbrian if (fp->state == ST_STOPPED) { 94537160Sbrian fsm_Down(fp); 94637160Sbrian fsm_Up(fp); 94737160Sbrian } else { 94837160Sbrian fsm_Up(fp); 94937160Sbrian fsm_Open(fp); 95037160Sbrian } 95136285Sbrian } 95237160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 95337160Sbrian if (arg->cx) 95437160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 95537160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 95637160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 95737160Sbrian else 95837993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 95937160Sbrian } else 96037160Sbrian return -1; 96136285Sbrian } else 96236285Sbrian return -1; 96336285Sbrian 96426516Sbrian return 0; 9656059Samurai} 9666059Samurai 96725067Sbrianstatic int 96836285SbrianCloseCommand(struct cmdargs const *arg) 9696059Samurai{ 97037007Sbrian if (arg->argc == arg->argn) 97137007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 97237007Sbrian else if (arg->argc == arg->argn + 1) { 97337007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 97437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 97537007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 97637007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 97737007Sbrian struct fsm *fp; 9786059Samurai 97937210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 98037007Sbrian if (fp->state == ST_OPENED) { 98137007Sbrian fsm_Close(fp); 98237007Sbrian if (arg->argv[arg->argn][3] == '!') 98337007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 98437007Sbrian else 98537007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 98637007Sbrian } 98737007Sbrian } else 98836285Sbrian return -1; 98936285Sbrian } else 99036285Sbrian return -1; 99136285Sbrian 99236285Sbrian return 0; 9936059Samurai} 9946059Samurai 99525067Sbrianstatic int 99636285SbrianDownCommand(struct cmdargs const *arg) 99711336Samurai{ 99837018Sbrian if (arg->argc == arg->argn) { 99937018Sbrian if (arg->cx) 100037018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 100137018Sbrian else 100237018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 100337018Sbrian } else if (arg->argc == arg->argn + 1) { 100437018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 100537018Sbrian if (arg->cx) 100637018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 100737018Sbrian else 100837018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 100937018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 101037018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 101137018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 101237060Sbrian fsm2initial(fp); 101337018Sbrian } else 101437018Sbrian return -1; 101536285Sbrian } else 101636285Sbrian return -1; 101736285Sbrian 101836285Sbrian return 0; 101925067Sbrian} 102025067Sbrian 102125067Sbrianstatic int 102236285SbrianSetModemSpeed(struct cmdargs const *arg) 102325067Sbrian{ 102436285Sbrian long speed; 102536285Sbrian char *end; 102611336Samurai 102736285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 102836285Sbrian if (arg->argc > arg->argn+1) { 102936285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 103036285Sbrian return -1; 103111336Samurai } 103236285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 103336285Sbrian physical_SetSync(arg->cx->physical); 103436285Sbrian return 0; 103536285Sbrian } 103636285Sbrian end = NULL; 103736285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 103836285Sbrian if (*end) { 103936285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 104036285Sbrian arg->argv[arg->argn]); 104136285Sbrian return -1; 104236285Sbrian } 104336285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 104436285Sbrian return 0; 104536285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 104636285Sbrian } else 104736285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 104824939Sbrian 104926516Sbrian return -1; 105011336Samurai} 105111336Samurai 105225067Sbrianstatic int 105331343SbrianSetStoppedTimeout(struct cmdargs const *arg) 105428327Sbrian{ 105536285Sbrian struct link *l = &arg->cx->physical->link; 105636285Sbrian 105736285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 105836285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 105936285Sbrian if (arg->argc <= arg->argn+2) { 106036285Sbrian if (arg->argc > arg->argn) { 106136285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 106236285Sbrian if (arg->argc > arg->argn+1) 106336285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 106428461Sbrian } 106528327Sbrian return 0; 106628327Sbrian } 106728327Sbrian return -1; 106828327Sbrian} 106928327Sbrian 107031081Sbrian#define ismask(x) \ 107131081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 107231081Sbrian 107328327Sbrianstatic int 107431343SbrianSetServer(struct cmdargs const *arg) 107526940Sbrian{ 107626940Sbrian int res = -1; 107726940Sbrian 107836285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 107931081Sbrian const char *port, *passwd, *mask; 108031081Sbrian 108131081Sbrian /* What's what ? */ 108236285Sbrian port = arg->argv[arg->argn]; 108336285Sbrian if (arg->argc == arg->argn + 2) { 108436285Sbrian passwd = arg->argv[arg->argn+1]; 108536285Sbrian mask = NULL; 108636285Sbrian } else if (arg->argc == arg->argn + 3) { 108736285Sbrian passwd = arg->argv[arg->argn+1]; 108836285Sbrian mask = arg->argv[arg->argn+2]; 108931081Sbrian if (!ismask(mask)) 109031081Sbrian return -1; 109136285Sbrian } else if (strcasecmp(port, "none") == 0) { 109236285Sbrian if (server_Close(arg->bundle)) 109336285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 109436285Sbrian return 0; 109531081Sbrian } else 109636285Sbrian return -1; 109731081Sbrian 109836285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 109936285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 110031081Sbrian 110136285Sbrian if (*port == '/') { 110231081Sbrian mode_t imask; 110336285Sbrian char *ptr, name[LINE_LEN + 12]; 110428679Sbrian 110531081Sbrian if (mask != NULL) { 110628679Sbrian unsigned m; 110728679Sbrian 110831081Sbrian if (sscanf(mask, "%o", &m) == 1) 110931081Sbrian imask = m; 111031081Sbrian else 111131081Sbrian return -1; 111231081Sbrian } else 111331081Sbrian imask = (mode_t)-1; 111436285Sbrian 111536285Sbrian ptr = strstr(port, "%d"); 111636285Sbrian if (ptr) { 111736285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 111837210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 111936285Sbrian port = name; 112036285Sbrian } 112136285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 112227346Sbrian } else { 112336285Sbrian int iport, add = 0; 112428679Sbrian 112531081Sbrian if (mask != NULL) 112631081Sbrian return -1; 112728679Sbrian 112836285Sbrian if (*port == '+') { 112936285Sbrian port++; 113036285Sbrian add = 1; 113136285Sbrian } 113231081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 113331081Sbrian struct servent *s; 113431081Sbrian 113531081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 113631081Sbrian iport = 0; 113736285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 113828679Sbrian } else 113931081Sbrian iport = ntohs(s->s_port); 114027346Sbrian } else 114131081Sbrian iport = atoi(port); 114236285Sbrian 114336285Sbrian if (iport) { 114436285Sbrian if (add) 114536285Sbrian iport += arg->bundle->unit; 114636285Sbrian res = server_TcpOpen(arg->bundle, iport); 114736285Sbrian } else 114836285Sbrian res = -1; 114927346Sbrian } 115031081Sbrian } 115126940Sbrian 115226940Sbrian return res; 115326940Sbrian} 115426940Sbrian 115526940Sbrianstatic int 115631343SbrianSetModemParity(struct cmdargs const *arg) 11576059Samurai{ 115836285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 115936285Sbrian arg->argv[arg->argn]) : -1; 11606059Samurai} 11616059Samurai 11626059Samuraistatic int 116331343SbrianSetEscape(struct cmdargs const *arg) 11646059Samurai{ 11656059Samurai int code; 116636285Sbrian int argc = arg->argc - arg->argn; 116736285Sbrian char const *const *argv = arg->argv + arg->argn; 11686059Samurai 11696059Samurai for (code = 0; code < 33; code++) 117036285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 117131343Sbrian 11726059Samurai while (argc-- > 0) { 11736059Samurai sscanf(*argv++, "%x", &code); 11746059Samurai code &= 0xff; 117536285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 117636285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 11776059Samurai } 117826516Sbrian return 0; 11796059Samurai} 11806059Samurai 118130715Sbrianstatic struct in_addr 118231343SbrianGetIpAddr(const char *cp) 11836059Samurai{ 11846059Samurai struct hostent *hp; 11856059Samurai struct in_addr ipaddr; 11866059Samurai 118732124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 118832124Sbrian hp = gethostbyname(cp); 118932124Sbrian if (hp && hp->h_addrtype == AF_INET) 119032124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 119132124Sbrian else 119232124Sbrian ipaddr.s_addr = 0; 119332124Sbrian } 119428679Sbrian return (ipaddr); 11956059Samurai} 11966059Samurai 11976059Samuraistatic int 119831343SbrianSetInterfaceAddr(struct cmdargs const *arg) 11996059Samurai{ 120036285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 120132267Sbrian const char *hisaddr; 120232267Sbrian 120332267Sbrian hisaddr = NULL; 120436285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 120536285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 12066059Samurai 120736285Sbrian if (arg->argc > arg->argn + 4) 120828679Sbrian return -1; 120926516Sbrian 121036285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 121136285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 121236285Sbrian iplist_reset(&ipcp->cfg.peer_list); 121328394Sbrian 121436285Sbrian if (arg->argc > arg->argn) { 121536285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 121636285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 121736285Sbrian &ipcp->cfg.my_range.width)) 121828679Sbrian return 1; 121936285Sbrian if (arg->argc > arg->argn+1) { 122036285Sbrian hisaddr = arg->argv[arg->argn+1]; 122136285Sbrian if (arg->argc > arg->argn+2) { 122236285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 122336285Sbrian if (arg->argc > arg->argn+3) { 122436285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 122536285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 12269440Samurai } 12276059Samurai } 12286059Samurai } 12296059Samurai } 123028394Sbrian 12316059Samurai /* 12326059Samurai * For backwards compatibility, 0.0.0.0 means any address. 12336059Samurai */ 123436285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 123536285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 123636285Sbrian ipcp->cfg.my_range.width = 0; 12376059Samurai } 123836285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 123936285Sbrian 124036285Sbrian if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 124136285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 124236285Sbrian ipcp->cfg.peer_range.width = 0; 12436059Samurai } 124428537Sbrian 124536285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 124636928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 124732267Sbrian return 4; 124831121Sbrian 124926516Sbrian return 0; 12506059Samurai} 12516059Samurai 125218752Sjkhstatic int 125331343SbrianSetVariable(struct cmdargs const *arg) 12546059Samurai{ 125537210Sbrian long long_val, param = (long)arg->cmd->args; 125637210Sbrian int mode, dummyint; 125731343Sbrian const char *argp; 125836285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 125936285Sbrian const char *err = NULL; 126036285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 126136285Sbrian struct in_addr dummyaddr, *addr; 12626059Samurai 126336285Sbrian if (arg->argc > arg->argn) 126436285Sbrian argp = arg->argv[arg->argn]; 126526551Sbrian else 126631343Sbrian argp = ""; 126726551Sbrian 126836285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 126936285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 127036285Sbrian arg->cmd->name); 127136285Sbrian return 1; 127236285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 127336285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 127436285Sbrian arg->cmd->name, cx->name); 127536285Sbrian cx = NULL; 127636285Sbrian } 127736285Sbrian 127826551Sbrian switch (param) { 127928679Sbrian case VAR_AUTHKEY: 128036285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 128136285Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 128236285Sbrian sizeof arg->bundle->cfg.auth.key - 1); 128336285Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 128436285Sbrian } else { 128536285Sbrian err = "set authkey: Only available at phase DEAD\n"; 128636285Sbrian log_Printf(LogWARN, err); 128736285Sbrian } 128828679Sbrian break; 128937210Sbrian 129028679Sbrian case VAR_AUTHNAME: 129136285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 129236285Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 129336285Sbrian sizeof arg->bundle->cfg.auth.name - 1); 129436285Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 129536285Sbrian } else { 129636285Sbrian err = "set authname: Only available at phase DEAD\n"; 129736285Sbrian log_Printf(LogWARN, err); 129836285Sbrian } 129928679Sbrian break; 130037210Sbrian 130136285Sbrian case VAR_AUTOLOAD: 130236285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 130336285Sbrian arg->bundle->autoload.running = 1; 130436285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 130536285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 130636285Sbrian if (arg->argc == arg->argn + 4) { 130736285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 130836285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 130936285Sbrian } else { 131036285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 131136285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 131236285Sbrian } 131336285Sbrian } else { 131436285Sbrian err = "Set autoload requires two or four arguments\n"; 131536285Sbrian log_Printf(LogWARN, err); 131636285Sbrian } 131736285Sbrian break; 131837210Sbrian 131928679Sbrian case VAR_DIAL: 132036285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 132136285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 132228679Sbrian break; 132337210Sbrian 132428679Sbrian case VAR_LOGIN: 132536285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 132636285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 132728679Sbrian break; 132837210Sbrian 132936285Sbrian case VAR_WINSIZE: 133036285Sbrian if (arg->argc > arg->argn) { 133136285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 133236285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 133336285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 133436285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 133536285Sbrian l->ccp.cfg.deflate.out.winsize); 133636285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 133736285Sbrian } 133836285Sbrian if (arg->argc > arg->argn+1) { 133936285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 134036285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 134136285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 134236285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 134336285Sbrian l->ccp.cfg.deflate.in.winsize); 134436285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 134536285Sbrian } 134636285Sbrian } else 134736285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 134836285Sbrian } else { 134936285Sbrian err = "No window size specified\n"; 135036285Sbrian log_Printf(LogWARN, err); 135136285Sbrian } 135236285Sbrian break; 135337210Sbrian 135428679Sbrian case VAR_DEVICE: 135536285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 135636285Sbrian arg->argv + arg->argn); 135736285Sbrian break; 135837210Sbrian 135936285Sbrian case VAR_ACCMAP: 136036285Sbrian if (arg->argc > arg->argn) { 136137210Sbrian u_long ulong_val; 136236285Sbrian sscanf(argp, "%lx", &ulong_val); 136337210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 136436285Sbrian } else { 136536285Sbrian err = "No accmap specified\n"; 136636285Sbrian log_Printf(LogWARN, err); 136736285Sbrian } 136836285Sbrian break; 136937210Sbrian 137036285Sbrian case VAR_MODE: 137136285Sbrian mode = Nam2mode(argp); 137236285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 137336285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 137436285Sbrian return -1; 137536285Sbrian } 137636285Sbrian bundle_SetMode(arg->bundle, cx, mode); 137736285Sbrian break; 137837210Sbrian 137936285Sbrian case VAR_MRRU: 138037210Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) { 138136285Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); 138237210Sbrian return 1; 138329696Sbrian } 138437210Sbrian long_val = atol(argp); 138537210Sbrian if (long_val && long_val < MIN_MRU) { 138637210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 138737210Sbrian return 1; 138837210Sbrian } else if (long_val > MAX_MRU) { 138937210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 139037210Sbrian return 1; 139137210Sbrian } else 139237210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 139328679Sbrian break; 139437210Sbrian 139536285Sbrian case VAR_MRU: 139637210Sbrian long_val = atol(argp); 139737210Sbrian if (long_val == 0) 139837210Sbrian l->lcp.cfg.mru = DEF_MRU; 139937210Sbrian else if (long_val < MIN_MRU) { 140037210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 140137210Sbrian return 1; 140237210Sbrian } else if (long_val > MAX_MRU) { 140337210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 140437210Sbrian return 1; 140537210Sbrian } else 140637210Sbrian l->lcp.cfg.mru = long_val; 140728679Sbrian break; 140837210Sbrian 140936285Sbrian case VAR_MTU: 141037210Sbrian long_val = atol(argp); 141137210Sbrian if (long_val && long_val < MIN_MTU) { 141237210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 141337210Sbrian return 1; 141437210Sbrian } else if (long_val > MAX_MTU) { 141537210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 141637210Sbrian return 1; 141737210Sbrian } else 141837210Sbrian arg->bundle->cfg.mtu = long_val; 141936285Sbrian break; 142037210Sbrian 142136285Sbrian case VAR_OPENMODE: 142236285Sbrian if (strcasecmp(argp, "active") == 0) 142336285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 142436285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 142536285Sbrian else if (strcasecmp(argp, "passive") == 0) 142636285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 142736285Sbrian else { 142836285Sbrian err = "%s: Invalid openmode\n"; 142936285Sbrian log_Printf(LogWARN, err, argp); 143036285Sbrian } 143136285Sbrian break; 143237210Sbrian 143328679Sbrian case VAR_PHONE: 143436285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 143536285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 143638174Sbrian cx->phone.alt = cx->phone.next = NULL; 143728679Sbrian break; 143837210Sbrian 143928679Sbrian case VAR_HANGUP: 144036285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 144136285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 144228679Sbrian break; 144337210Sbrian 144436285Sbrian case VAR_IDLETIMEOUT: 144536285Sbrian if (arg->argc > arg->argn+1) 144636285Sbrian err = "Too many idle timeout values\n"; 144736285Sbrian else if (arg->argc == arg->argn+1) 144836285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 144936285Sbrian if (err) 145036285Sbrian log_Printf(LogWARN, err); 145129549Sbrian break; 145237210Sbrian 145336285Sbrian case VAR_LQRPERIOD: 145437210Sbrian long_val = atol(argp); 145537210Sbrian if (long_val < MIN_LQRPERIOD) { 145637210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 145737210Sbrian long_val, MIN_LQRPERIOD); 145837210Sbrian return 1; 145936285Sbrian } else 146037210Sbrian l->lcp.cfg.lqrperiod = long_val; 146136285Sbrian break; 146237210Sbrian 146336285Sbrian case VAR_LCPRETRY: 146437210Sbrian long_val = atol(argp); 146537210Sbrian if (long_val < MIN_FSMRETRY) { 146637210Sbrian log_Printf(LogWARN, "%ld: Invalid LCP FSM retry period - min %d\n", 146737210Sbrian long_val, MIN_FSMRETRY); 146837210Sbrian return 1; 146936285Sbrian } else 147037210Sbrian cx->physical->link.lcp.cfg.fsmretry = long_val; 147136285Sbrian break; 147237210Sbrian 147336285Sbrian case VAR_CHAPRETRY: 147437210Sbrian long_val = atol(argp); 147537210Sbrian if (long_val < MIN_FSMRETRY) { 147637210Sbrian log_Printf(LogWARN, "%ld: Invalid CHAP FSM retry period - min %d\n", 147737210Sbrian long_val, MIN_FSMRETRY); 147837210Sbrian return 1; 147936285Sbrian } else 148037210Sbrian cx->chap.auth.cfg.fsmretry = long_val; 148136285Sbrian break; 148237210Sbrian 148336285Sbrian case VAR_PAPRETRY: 148437210Sbrian long_val = atol(argp); 148537210Sbrian if (long_val < MIN_FSMRETRY) { 148637210Sbrian log_Printf(LogWARN, "%ld: Invalid PAP FSM retry period - min %d\n", 148737210Sbrian long_val, MIN_FSMRETRY); 148837210Sbrian return 1; 148936285Sbrian } else 149037210Sbrian cx->pap.cfg.fsmretry = long_val; 149136285Sbrian break; 149237210Sbrian 149336285Sbrian case VAR_CCPRETRY: 149437210Sbrian long_val = atol(argp); 149537210Sbrian if (long_val < MIN_FSMRETRY) { 149637210Sbrian log_Printf(LogWARN, "%ld: Invalid CCP FSM retry period - min %d\n", 149737210Sbrian long_val, MIN_FSMRETRY); 149837210Sbrian return 1; 149936285Sbrian } else 150037210Sbrian l->ccp.cfg.fsmretry = long_val; 150136285Sbrian break; 150237210Sbrian 150336285Sbrian case VAR_IPCPRETRY: 150437210Sbrian long_val = atol(argp); 150537210Sbrian if (long_val < MIN_FSMRETRY) { 150637210Sbrian log_Printf(LogWARN, "%ld: Invalid IPCP FSM retry period - min %d\n", 150737210Sbrian long_val, MIN_FSMRETRY); 150837210Sbrian return 1; 150936285Sbrian } else 151037210Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = long_val; 151136285Sbrian break; 151237210Sbrian 151336285Sbrian case VAR_NBNS: 151436285Sbrian case VAR_DNS: 151536285Sbrian if (param == VAR_DNS) 151636285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 151736285Sbrian else 151836285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 151936285Sbrian 152036285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 152136285Sbrian 152236285Sbrian if (arg->argc > arg->argn) { 152336285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 152436285Sbrian addr, &dummyaddr, &dummyint); 152536285Sbrian if (arg->argc > arg->argn+1) 152636285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 152736285Sbrian addr + 1, &dummyaddr, &dummyint); 152836285Sbrian 152936285Sbrian if (addr[1].s_addr == INADDR_ANY) 153036285Sbrian addr[1].s_addr = addr[0].s_addr; 153136285Sbrian if (addr[0].s_addr == INADDR_ANY) 153236285Sbrian addr[0].s_addr = addr[1].s_addr; 153336285Sbrian } 153436285Sbrian break; 153538174Sbrian 153638174Sbrian case VAR_CALLBACK: 153738174Sbrian cx->cfg.callback.opmask = 0; 153838174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 153938174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 154038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 154138174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 154238174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 154338174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 154438174Sbrian if (dummyint == arg->argc - 1) 154538174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 154638174Sbrian else { 154738174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 154838174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 154938174Sbrian sizeof cx->cfg.callback.msg - 1); 155038174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 155138174Sbrian } 155238174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 155338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 155438174Sbrian else 155538174Sbrian return -1; 155638174Sbrian } 155738174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 155838174Sbrian cx->cfg.callback.opmask = 0; 155938174Sbrian break; 156038174Sbrian 156138174Sbrian case VAR_CBCP: 156238174Sbrian cx->cfg.cbcp.delay = 0; 156338174Sbrian *cx->cfg.cbcp.phone = '\0'; 156438174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 156538174Sbrian if (arg->argc > arg->argn) { 156638174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 156738174Sbrian sizeof cx->cfg.cbcp.phone - 1); 156838174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 156938174Sbrian if (arg->argc > arg->argn + 1) { 157038174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 157138174Sbrian if (arg->argc > arg->argn + 2) { 157238174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 157338174Sbrian if (long_val < MIN_FSMRETRY) 157438174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 157538174Sbrian long_val, MIN_FSMRETRY); 157638174Sbrian else 157738174Sbrian cx->cfg.cbcp.fsmretry = long_val; 157838174Sbrian } 157938174Sbrian } 158038174Sbrian } 158138174Sbrian break; 158238544Sbrian 158338544Sbrian case VAR_CHOKED: 158438544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 158538544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 158638544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 158738544Sbrian break; 158838544Sbrian 15896059Samurai } 159036285Sbrian 159136285Sbrian return err ? 1 : 0; 15926059Samurai} 15936059Samurai 159428679Sbrianstatic int 159531343SbrianSetCtsRts(struct cmdargs const *arg) 159620812Sjkh{ 159736285Sbrian if (arg->argc == arg->argn+1) { 159836285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 159936285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 160036285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 160136285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 160220812Sjkh else 160326516Sbrian return -1; 160426516Sbrian return 0; 160520812Sjkh } 160626516Sbrian return -1; 160720812Sjkh} 160820812Sjkh 160930715Sbrianstatic struct cmdtab const SetCommands[] = { 161036285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 161136285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 161228679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 161336285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 161428679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 161536285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 161636285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 161736285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 161836285Sbrian (const void *)VAR_AUTOLOAD}, 161938174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 162038174Sbrian "callback control", "set callback [none|auth|cbcp|" 162138174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 162238174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 162338174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 162438174Sbrian (const void *)VAR_CBCP}, 162536285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 162636285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 162736285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 162836285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 162938544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 163038544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 163136285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 163236285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 163336285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 163436285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 163536285Sbrian (const void *) VAR_WINSIZE}, 163636285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 163736285Sbrian "modem device name", "set device|line device-name[,device-name]", 163836285Sbrian (const void *) VAR_DEVICE}, 163936285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 164036285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 164136285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 164236285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 164336285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 164436285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 164536285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 164636285Sbrian "escape characters", "set escape hex-digit ..."}, 164736285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 164836285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 164936285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 165036285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 165136285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 165236285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 165336285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 165431343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 165536285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 165636285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 165736285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 165836285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 165936712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 166038622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 166138622Sbrian "ipcp|lcp|lqm|phase|tcp/ip|timer|tun..."}, 166236285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 166336285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 166436285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 166536285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 166636285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 166736285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 166836285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 166936285Sbrian "set mrru value", (const void *)VAR_MRRU}, 167036285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 167136285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 167236285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 167336285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 167436285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 167536285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 167636285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 167736285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 167836285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 167936285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 168036285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 168136285Sbrian "modem parity", "set parity [odd|even|none]"}, 168236285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 168336285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 168436285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 168536285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 168636285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 168736285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 168828679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 168936774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 169036285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 169136285Sbrian "modem speed", "set speed value"}, 169236285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 169336285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 169436285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 169536285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 169636285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 169736285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 169836285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 169936285Sbrian "datalink weighting", "set weight n"}, 170028679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 170131343Sbrian "Display this message", "set help|? [command]", SetCommands}, 170228679Sbrian {NULL, NULL, NULL}, 17036059Samurai}; 17046059Samurai 17056059Samuraistatic int 170631343SbrianSetCommand(struct cmdargs const *arg) 17076059Samurai{ 170836285Sbrian if (arg->argc > arg->argn) 170936285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 171036285Sbrian arg->prompt, arg->cx); 171136285Sbrian else if (arg->prompt) 171236285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 171326516Sbrian " syntax help.\n"); 17146059Samurai else 171536285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 171626516Sbrian 171726516Sbrian return 0; 17186059Samurai} 17196059Samurai 17206059Samurai 17216059Samuraistatic int 172231343SbrianAddCommand(struct cmdargs const *arg) 17236059Samurai{ 17246059Samurai struct in_addr dest, gateway, netmask; 172536285Sbrian int gw, addrs; 17266059Samurai 172736285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 172831598Sbrian return -1; 172931598Sbrian 173036285Sbrian addrs = 0; 173136285Sbrian if (arg->argc == arg->argn+2) { 173236285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 173336285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 173431598Sbrian else { 173536285Sbrian int width; 173636285Sbrian 173736285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 173836285Sbrian &dest, &netmask, &width)) 173936285Sbrian return -1; 174036285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 174136285Sbrian addrs = ROUTE_DSTMYADDR; 174236285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 174336285Sbrian addrs = ROUTE_DSTHISADDR; 174431598Sbrian } 174536285Sbrian gw = 1; 174634536Sbrian } else { 174736285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 174836285Sbrian addrs = ROUTE_DSTMYADDR; 174936285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 175036285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 175136285Sbrian addrs = ROUTE_DSTHISADDR; 175236285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 175336285Sbrian } else 175436285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 175536285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 175631598Sbrian gw = 2; 17576059Samurai } 175836285Sbrian 175936285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 176036285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 176136285Sbrian addrs |= ROUTE_GWHISADDR; 176236285Sbrian } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0) 176331598Sbrian gateway.s_addr = INADDR_ANY; 176431598Sbrian else 176536285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 176636285Sbrian 176736285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 176837927Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0)) 176936285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 177036285Sbrian 177131598Sbrian return 0; 17726059Samurai} 17736059Samurai 17746059Samuraistatic int 177531343SbrianDeleteCommand(struct cmdargs const *arg) 17766059Samurai{ 177731598Sbrian struct in_addr dest, none; 177836285Sbrian int addrs; 17796059Samurai 178036285Sbrian if (arg->argc == arg->argn+1) { 178136285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 178236285Sbrian route_IfDelete(arg->bundle, 0); 178336285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 178436285Sbrian } else { 178536285Sbrian addrs = 0; 178636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 178736285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 178836285Sbrian addrs = ROUTE_DSTMYADDR; 178936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 179036285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 179136285Sbrian addrs = ROUTE_DSTHISADDR; 179236285Sbrian } else { 179336285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 179436285Sbrian dest.s_addr = INADDR_ANY; 179536285Sbrian else 179636285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 179736285Sbrian addrs = ROUTE_STATIC; 179836285Sbrian } 179931598Sbrian none.s_addr = INADDR_ANY; 180036285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 180137927Sbrian arg->cmd->args ? 1 : 0, 0); 180236285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 180331598Sbrian } 180434536Sbrian } else 180526516Sbrian return -1; 180626516Sbrian 180726516Sbrian return 0; 18086059Samurai} 18096059Samurai 181031343Sbrian#ifndef NOALIAS 181126031Sbrianstatic struct cmdtab const AliasCommands[] = 181226031Sbrian{ 181336285Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 181436285Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 181536285Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 181636285Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 181736285Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 181828679Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 181936285Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 182028679Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 182136285Sbrian "log aliasing link creation", "alias log [yes|no]", 182236285Sbrian (const void *) PKT_ALIAS_LOG}, 182336285Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 182436285Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 182528679Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 182636285Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 182736285Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 182836285Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 182936285Sbrian "alias unregistered (private) IP address space only", 183036285Sbrian "alias unregistered_only [yes|no]", 183136285Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 183228679Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 183336285Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 183436285Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 183528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 183636285Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 183728679Sbrian {NULL, NULL, NULL}, 183826031Sbrian}; 183926031Sbrian 184026031Sbrian 184126031Sbrianstatic int 184231343SbrianAliasCommand(struct cmdargs const *arg) 184326031Sbrian{ 184436285Sbrian if (arg->argc > arg->argn) 184536285Sbrian FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv, 184636285Sbrian arg->prompt, arg->cx); 184736285Sbrian else if (arg->prompt) 184836285Sbrian prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 184936285Sbrian " <option>' for syntax help.\n"); 185026031Sbrian else 185136285Sbrian log_Printf(LogWARN, "alias command must have arguments\n"); 185226516Sbrian 185326516Sbrian return 0; 185426031Sbrian} 185526031Sbrian 185626031Sbrianstatic int 185731343SbrianAliasEnable(struct cmdargs const *arg) 185826031Sbrian{ 185936285Sbrian if (arg->argc == arg->argn+1) { 186036285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 186137191Sbrian arg->bundle->AliasEnabled = 1; 186237191Sbrian return 0; 186336285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 186437191Sbrian arg->bundle->AliasEnabled = 0; 186526516Sbrian return 0; 186626142Sbrian } 186735449Sbrian } 186836285Sbrian 186926516Sbrian return -1; 187026031Sbrian} 187126031Sbrian 187226031Sbrian 187326031Sbrianstatic int 187431343SbrianAliasOption(struct cmdargs const *arg) 187526031Sbrian{ 187638559Sbrian long param = (long)arg->cmd->args; 187738559Sbrian 187836285Sbrian if (arg->argc == arg->argn+1) { 187936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 188037191Sbrian if (arg->bundle->AliasEnabled) { 188137191Sbrian PacketAliasSetMode(param, param); 188228679Sbrian return 0; 188328679Sbrian } 188436285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 188536285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 188637191Sbrian if (arg->bundle->AliasEnabled) { 188737191Sbrian PacketAliasSetMode(0, param); 188828679Sbrian return 0; 188928679Sbrian } 189036285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 189128679Sbrian } 189235449Sbrian } 189328679Sbrian return -1; 189426031Sbrian} 189531343Sbrian#endif /* #ifndef NOALIAS */ 189631121Sbrian 189731121Sbrianstatic struct cmdtab const AllowCommands[] = { 189836285Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 189936285Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 190031121Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 190131121Sbrian "Allow users access to ppp", "allow users logname..."}, 190231121Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 190331343Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 190431121Sbrian {NULL, NULL, NULL}, 190531121Sbrian}; 190631121Sbrian 190731121Sbrianstatic int 190831343SbrianAllowCommand(struct cmdargs const *arg) 190931121Sbrian{ 191036285Sbrian /* arg->bundle may be NULL (see system_IsValid()) ! */ 191136285Sbrian if (arg->argc > arg->argn) 191236285Sbrian FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv, 191336285Sbrian arg->prompt, arg->cx); 191436285Sbrian else if (arg->prompt) 191536285Sbrian prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 191636285Sbrian " for syntax help.\n"); 191731121Sbrian else 191836285Sbrian log_Printf(LogWARN, "allow command must have arguments\n"); 191931121Sbrian 192031121Sbrian return 0; 192131121Sbrian} 192236285Sbrian 192336285Sbrianstatic int 192436285SbrianLinkCommand(struct cmdargs const *arg) 192536285Sbrian{ 192636285Sbrian if (arg->argc > arg->argn+1) { 192736285Sbrian char namelist[LINE_LEN]; 192836285Sbrian struct datalink *cx; 192936285Sbrian char *name; 193036285Sbrian int result = 0; 193136285Sbrian 193236285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 193336285Sbrian struct datalink *dl; 193436285Sbrian 193536285Sbrian cx = arg->bundle->links; 193636285Sbrian while (cx) { 193736285Sbrian /* Watch it, the command could be a ``remove'' */ 193836285Sbrian dl = cx->next; 193936285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 194036285Sbrian arg->prompt, cx); 194136285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 194236285Sbrian if (cx == dl) 194336285Sbrian break; /* Pointer's still valid ! */ 194436285Sbrian } 194536285Sbrian } else { 194636285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 194736285Sbrian namelist[sizeof namelist - 1] = '\0'; 194836285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 194936285Sbrian if (!bundle2datalink(arg->bundle, name)) { 195036285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 195136285Sbrian return 1; 195236285Sbrian } 195336285Sbrian 195436285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 195536285Sbrian namelist[sizeof namelist - 1] = '\0'; 195636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 195736285Sbrian cx = bundle2datalink(arg->bundle, name); 195836285Sbrian if (cx) 195936285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 196036285Sbrian arg->prompt, cx); 196136285Sbrian else { 196236285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 196336285Sbrian result++; 196436285Sbrian } 196536285Sbrian } 196636285Sbrian } 196736285Sbrian return result; 196836285Sbrian } 196936285Sbrian 197036285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 197136285Sbrian return 2; 197236285Sbrian} 197336285Sbrian 197436285Sbrianstruct link * 197536285Sbriancommand_ChooseLink(struct cmdargs const *arg) 197636285Sbrian{ 197736285Sbrian if (arg->cx) 197836285Sbrian return &arg->cx->physical->link; 197937210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 198036285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 198137210Sbrian if (dl) 198237210Sbrian return &dl->physical->link; 198336285Sbrian } 198437210Sbrian return &arg->bundle->ncp.mp.link; 198536285Sbrian} 198636285Sbrian 198736285Sbrianstatic const char * 198836285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 198936285Sbrian{ 199036285Sbrian const char *result; 199136285Sbrian 199236285Sbrian switch (*cmd) { 199336285Sbrian case 'A': 199436285Sbrian case 'a': 199536285Sbrian result = "accept"; 199636285Sbrian *keep = NEG_MYMASK; 199736285Sbrian *add = NEG_ACCEPTED; 199836285Sbrian break; 199936285Sbrian case 'D': 200036285Sbrian case 'd': 200136285Sbrian switch (cmd[1]) { 200236285Sbrian case 'E': 200336285Sbrian case 'e': 200436285Sbrian result = "deny"; 200536285Sbrian *keep = NEG_MYMASK; 200636285Sbrian *add = 0; 200736285Sbrian break; 200836285Sbrian case 'I': 200936285Sbrian case 'i': 201036285Sbrian result = "disable"; 201136285Sbrian *keep = NEG_HISMASK; 201236285Sbrian *add = 0; 201336285Sbrian break; 201436285Sbrian default: 201536285Sbrian return NULL; 201636285Sbrian } 201736285Sbrian break; 201836285Sbrian case 'E': 201936285Sbrian case 'e': 202036285Sbrian result = "enable"; 202136285Sbrian *keep = NEG_HISMASK; 202236285Sbrian *add = NEG_ENABLED; 202336285Sbrian break; 202436285Sbrian default: 202536285Sbrian return NULL; 202636285Sbrian } 202736285Sbrian 202836285Sbrian return result; 202936285Sbrian} 203036285Sbrian 203136285Sbrianstatic int 203236285SbrianOptSet(struct cmdargs const *arg) 203336285Sbrian{ 203437574Sbrian int bit = (int)(long)arg->cmd->args; 203536285Sbrian const char *cmd; 203636285Sbrian unsigned keep; /* Keep these bits */ 203736285Sbrian unsigned add; /* Add these bits */ 203836285Sbrian 203936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 204036285Sbrian return 1; 204136285Sbrian 204236285Sbrian if (add) 204336285Sbrian arg->bundle->cfg.opt |= bit; 204436285Sbrian else 204536285Sbrian arg->bundle->cfg.opt &= ~bit; 204636285Sbrian return 0; 204736285Sbrian} 204836285Sbrian 204936285Sbrianstatic int 205036285SbrianNegotiateSet(struct cmdargs const *arg) 205136285Sbrian{ 205237210Sbrian long param = (long)arg->cmd->args; 205336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 205436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 205536285Sbrian const char *cmd; 205636285Sbrian unsigned keep; /* Keep these bits */ 205736285Sbrian unsigned add; /* Add these bits */ 205836285Sbrian 205936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 206036285Sbrian return 1; 206136285Sbrian 206236285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 206336285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 206436285Sbrian cmd, arg->cmd->name); 206536285Sbrian return 2; 206636285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 206736285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 206836285Sbrian cmd, arg->cmd->name, cx->name); 206936285Sbrian cx = NULL; 207036285Sbrian } 207136285Sbrian 207236285Sbrian switch (param) { 207336285Sbrian case NEG_ACFCOMP: 207436285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 207536285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 207636285Sbrian break; 207736285Sbrian case NEG_CHAP: 207836285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 207936285Sbrian cx->physical->link.lcp.cfg.chap |= add; 208036285Sbrian break; 208136285Sbrian case NEG_DEFLATE: 208236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 208336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 208436285Sbrian break; 208536285Sbrian case NEG_DNS: 208636285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 208736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 208836285Sbrian break; 208936285Sbrian case NEG_LQR: 209036285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 209136285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 209236285Sbrian break; 209336285Sbrian case NEG_PAP: 209436285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 209536285Sbrian cx->physical->link.lcp.cfg.pap |= add; 209636285Sbrian break; 209736285Sbrian case NEG_PPPDDEFLATE: 209836285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 209936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 210036285Sbrian break; 210136285Sbrian case NEG_PRED1: 210236285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 210336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 210436285Sbrian break; 210536285Sbrian case NEG_PROTOCOMP: 210636285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 210736285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 210836285Sbrian break; 210936285Sbrian case NEG_SHORTSEQ: 211036285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 211136285Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); 211236285Sbrian else { 211336285Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 211436285Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 211536285Sbrian } 211636285Sbrian break; 211736285Sbrian case NEG_VJCOMP: 211836285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 211936285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 212036285Sbrian break; 212136285Sbrian } 212236285Sbrian 212336285Sbrian return 0; 212436285Sbrian} 212536285Sbrian 212636285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 212736285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 212836285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 212936285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 213036285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 213136285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 213236285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 213336285Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", 213436285Sbrian "disable|enable", (const void *)OPT_PROXY}, 213536285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 213636285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 213736285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 213836285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 213936285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 214036285Sbrian "disable|enable", (const void *)OPT_UTMP}, 214136285Sbrian 214236285Sbrian#define OPT_MAX 7 /* accept/deny allowed below and not above */ 214336285Sbrian 214436285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 214536285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 214636285Sbrian (const void *)NEG_ACFCOMP}, 214736285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 214836285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 214936285Sbrian (const void *)NEG_CHAP}, 215036285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 215136285Sbrian "Deflate compression", "accept|deny|disable|enable", 215236285Sbrian (const void *)NEG_DEFLATE}, 215336285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 215436285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 215536285Sbrian (const void *)NEG_PPPDDEFLATE}, 215636285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 215736285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 215836285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 215936285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 216036285Sbrian (const void *)NEG_LQR}, 216136285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 216236285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 216336285Sbrian (const void *)NEG_PAP}, 216436285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 216536285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 216636285Sbrian (const void *)NEG_PRED1}, 216736285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 216836285Sbrian "Protocol field compression", "accept|deny|disable|enable", 216936285Sbrian (const void *)NEG_PROTOCOMP}, 217036285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 217136285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 217236285Sbrian (const void *)NEG_SHORTSEQ}, 217336285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 217436285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 217536285Sbrian (const void *)NEG_VJCOMP}, 217636285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 217736285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 217836285Sbrian NegotiateCommands}, 217936285Sbrian {NULL, NULL, NULL}, 218036285Sbrian}; 218136285Sbrian 218236285Sbrianstatic int 218336285SbrianNegotiateCommand(struct cmdargs const *arg) 218436285Sbrian{ 218536285Sbrian if (arg->argc > arg->argn) { 218636285Sbrian char const *argv[3]; 218736285Sbrian unsigned keep, add; 218836285Sbrian int n; 218936285Sbrian 219036285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 219136285Sbrian return -1; 219236285Sbrian argv[2] = NULL; 219336285Sbrian 219436285Sbrian for (n = arg->argn; n < arg->argc; n++) { 219536285Sbrian argv[1] = arg->argv[n]; 219636285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 219736285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 219836285Sbrian } 219936285Sbrian } else if (arg->prompt) 220036285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 220136285Sbrian arg->argv[arg->argn-1]); 220236285Sbrian else 220336285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 220436285Sbrian arg->argv[arg->argn] ); 220536285Sbrian 220636285Sbrian return 0; 220736285Sbrian} 220836285Sbrian 220936285Sbrianconst char * 221036285Sbriancommand_ShowNegval(unsigned val) 221136285Sbrian{ 221236285Sbrian switch (val&3) { 221336285Sbrian case 1: return "disabled & accepted"; 221436285Sbrian case 2: return "enabled & denied"; 221536285Sbrian case 3: return "enabled & accepted"; 221636285Sbrian } 221736285Sbrian return "disabled & denied"; 221836285Sbrian} 221936934Sbrian 222036934Sbrianstatic int 222136934SbrianClearCommand(struct cmdargs const *arg) 222236934Sbrian{ 222336934Sbrian struct pppThroughput *t; 222436934Sbrian struct datalink *cx; 222536934Sbrian int i, clear_type; 222636934Sbrian 222736934Sbrian if (arg->argc < arg->argn + 1) 222836934Sbrian return -1; 222936934Sbrian 223036934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 223136934Sbrian cx = arg->cx; 223236934Sbrian if (!cx) 223336934Sbrian cx = bundle2datalink(arg->bundle, NULL); 223436934Sbrian if (!cx) { 223536934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 223636934Sbrian return 1; 223736934Sbrian } 223836934Sbrian t = &cx->physical->link.throughput; 223936934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 224036934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 224136934Sbrian else 224236934Sbrian return -1; 224336934Sbrian 224436934Sbrian if (arg->argc > arg->argn + 1) { 224536934Sbrian clear_type = 0; 224636934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 224736934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 224836934Sbrian clear_type |= THROUGHPUT_OVERALL; 224936934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 225036934Sbrian clear_type |= THROUGHPUT_CURRENT; 225136934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 225236934Sbrian clear_type |= THROUGHPUT_PEAK; 225336934Sbrian else 225436934Sbrian return -1; 225536934Sbrian } else 225636934Sbrian clear_type = THROUGHPUT_ALL; 225736934Sbrian 225836934Sbrian throughput_clear(t, clear_type, arg->prompt); 225936934Sbrian return 0; 226036934Sbrian} 2261