command.c revision 38629
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 * 2038629Sbrian * $Id: command.c,v 1.164 1998/08/29 23:02:39 brian Exp $ 218857Srgrimes * 226059Samurai */ 2336285Sbrian#include <sys/types.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3331343Sbrian#ifndef NOALIAS 3426031Sbrian#include <alias.h> 3531343Sbrian#endif 3638628Sbrian#include <ctype.h> 3730715Sbrian#include <errno.h> 3826516Sbrian#include <fcntl.h> 3930715Sbrian#include <paths.h> 4030715Sbrian#include <stdio.h> 4130715Sbrian#include <stdlib.h> 4230715Sbrian#include <string.h> 4330715Sbrian#include <sys/wait.h> 4430715Sbrian#include <termios.h> 4530715Sbrian#include <unistd.h> 4630715Sbrian 4737009Sbrian#include "defs.h" 4831343Sbrian#include "command.h" 4930715Sbrian#include "mbuf.h" 5030715Sbrian#include "log.h" 5130715Sbrian#include "timer.h" 526059Samurai#include "fsm.h" 536059Samurai#include "lcp.h" 5431690Sbrian#include "iplist.h" 5536285Sbrian#include "throughput.h" 5636285Sbrian#include "slcompress.h" 5738557Sbrian#include "lqr.h" 5838557Sbrian#include "hdlc.h" 596059Samurai#include "ipcp.h" 606059Samurai#include "modem.h" 6131343Sbrian#ifndef NOALIAS 6226031Sbrian#include "alias_cmd.h" 6331343Sbrian#endif 6425630Sbrian#include "systems.h" 6536285Sbrian#include "filter.h" 6636285Sbrian#include "descriptor.h" 6730715Sbrian#include "main.h" 6830715Sbrian#include "route.h" 6930715Sbrian#include "ccp.h" 7031080Sbrian#include "auth.h" 7136285Sbrian#include "async.h" 7236285Sbrian#include "link.h" 7336285Sbrian#include "physical.h" 7436285Sbrian#include "mp.h" 7536285Sbrian#include "bundle.h" 7636285Sbrian#include "server.h" 7736285Sbrian#include "prompt.h" 7836285Sbrian#include "chat.h" 7936285Sbrian#include "chap.h" 8038174Sbrian#include "cbcp.h" 8136285Sbrian#include "datalink.h" 826059Samurai 8336285Sbrian/* ``set'' values */ 8436285Sbrian#define VAR_AUTHKEY 0 8536285Sbrian#define VAR_DIAL 1 8636285Sbrian#define VAR_LOGIN 2 8736285Sbrian#define VAR_AUTHNAME 3 8836285Sbrian#define VAR_AUTOLOAD 4 8936285Sbrian#define VAR_WINSIZE 5 9036285Sbrian#define VAR_DEVICE 6 9136285Sbrian#define VAR_ACCMAP 7 9236285Sbrian#define VAR_MRRU 8 9336285Sbrian#define VAR_MRU 9 9436285Sbrian#define VAR_MTU 10 9536285Sbrian#define VAR_OPENMODE 11 9636285Sbrian#define VAR_PHONE 12 9736285Sbrian#define VAR_HANGUP 13 9836285Sbrian#define VAR_IDLETIMEOUT 14 9936285Sbrian#define VAR_LQRPERIOD 15 10036285Sbrian#define VAR_LCPRETRY 16 10136285Sbrian#define VAR_CHAPRETRY 17 10236285Sbrian#define VAR_PAPRETRY 18 10336285Sbrian#define VAR_CCPRETRY 19 10436285Sbrian#define VAR_IPCPRETRY 20 10536285Sbrian#define VAR_DNS 21 10636285Sbrian#define VAR_NBNS 22 10736285Sbrian#define VAR_MODE 23 10838174Sbrian#define VAR_CALLBACK 24 10938174Sbrian#define VAR_CBCP 25 11038544Sbrian#define VAR_CHOKED 26 1116059Samurai 11236285Sbrian/* ``accept|deny|disable|enable'' masks */ 11336285Sbrian#define NEG_HISMASK (1) 11436285Sbrian#define NEG_MYMASK (2) 11536285Sbrian 11636285Sbrian/* ``accept|deny|disable|enable'' values */ 11736285Sbrian#define NEG_ACFCOMP 40 11836285Sbrian#define NEG_CHAP 41 11936285Sbrian#define NEG_DEFLATE 42 12036285Sbrian#define NEG_LQR 43 12136285Sbrian#define NEG_PAP 44 12236285Sbrian#define NEG_PPPDDEFLATE 45 12336285Sbrian#define NEG_PRED1 46 12436285Sbrian#define NEG_PROTOCOMP 47 12536285Sbrian#define NEG_SHORTSEQ 48 12636285Sbrian#define NEG_VJCOMP 49 12736285Sbrian#define NEG_DNS 50 12836285Sbrian 12937373Sbrianconst char Version[] = "2.0"; 13038629Sbrianconst char VersionDate[] = "$Date: 1998/08/29 23:02:39 $"; 13136285Sbrian 13236285Sbrianstatic int ShowCommand(struct cmdargs const *); 13336285Sbrianstatic int TerminalCommand(struct cmdargs const *); 13436285Sbrianstatic int QuitCommand(struct cmdargs const *); 13536285Sbrianstatic int OpenCommand(struct cmdargs const *); 13636285Sbrianstatic int CloseCommand(struct cmdargs const *); 13736285Sbrianstatic int DownCommand(struct cmdargs const *); 13836285Sbrianstatic int AllowCommand(struct cmdargs const *); 13936285Sbrianstatic int SetCommand(struct cmdargs const *); 14036285Sbrianstatic int LinkCommand(struct cmdargs const *); 14136285Sbrianstatic int AddCommand(struct cmdargs const *); 14236285Sbrianstatic int DeleteCommand(struct cmdargs const *); 14336285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 14436934Sbrianstatic int ClearCommand(struct cmdargs const *); 14531343Sbrian#ifndef NOALIAS 14636285Sbrianstatic int AliasCommand(struct cmdargs const *); 14736285Sbrianstatic int AliasEnable(struct cmdargs const *); 14836285Sbrianstatic int AliasOption(struct cmdargs const *); 14931343Sbrian#endif 1506059Samurai 15136285Sbrianstatic const char * 15236285Sbrianshowcx(struct cmdtab const *cmd) 15336285Sbrian{ 15436285Sbrian if (cmd->lauth & LOCAL_CX) 15536285Sbrian return "(c)"; 15636285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 15736285Sbrian return "(o)"; 15836285Sbrian 15936285Sbrian return ""; 16036285Sbrian} 16136285Sbrian 1626059Samuraistatic int 16331343SbrianHelpCommand(struct cmdargs const *arg) 1646059Samurai{ 16528679Sbrian struct cmdtab const *cmd; 16636285Sbrian int n, cmax, dmax, cols, cxlen; 16736285Sbrian const char *cx; 1686059Samurai 16936285Sbrian if (!arg->prompt) { 17036285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 17126516Sbrian return 0; 17236285Sbrian } 17326516Sbrian 17436285Sbrian if (arg->argc > arg->argn) { 17536285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 17636285Sbrian if ((cmd->lauth & arg->prompt->auth) && 17736285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 17836285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 17936285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 18028679Sbrian return 0; 1816059Samurai } 18226516Sbrian return -1; 1836059Samurai } 18436285Sbrian 18531372Sbrian cmax = dmax = 0; 18636285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 18736285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 18836285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 18931372Sbrian cmax = n; 19031372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 19131372Sbrian dmax = n; 19231372Sbrian } 19331372Sbrian 19431372Sbrian cols = 80 / (dmax + cmax + 3); 1956059Samurai n = 0; 19636285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 19736285Sbrian " (c) = Context required\n"); 19836285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 19936285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 20036285Sbrian cx = showcx(cmd); 20136285Sbrian cxlen = cmax - strlen(cmd->name); 20236285Sbrian prompt_Printf(arg->prompt, " %s%-*.*s: %-*.*s", 20336285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 20431372Sbrian if (++n % cols == 0) 20536285Sbrian prompt_Printf(arg->prompt, "\n"); 2066059Samurai } 20731372Sbrian if (n % cols != 0) 20836285Sbrian prompt_Printf(arg->prompt, "\n"); 20926516Sbrian 21026516Sbrian return 0; 2116059Samurai} 2126059Samurai 21336285Sbrianstatic int 21436285SbrianCloneCommand(struct cmdargs const *arg) 2156059Samurai{ 21636285Sbrian char namelist[LINE_LEN]; 21736285Sbrian char *name; 21836285Sbrian int f; 2196059Samurai 22036285Sbrian if (arg->argc == arg->argn) 22136285Sbrian return -1; 22236285Sbrian 22336285Sbrian namelist[sizeof namelist - 1] = '\0'; 22436285Sbrian for (f = arg->argn; f < arg->argc; f++) { 22536285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 22636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 22736285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2286059Samurai } 22936285Sbrian 23036285Sbrian return 0; 2316059Samurai} 2326059Samurai 2336059Samuraistatic int 23436285SbrianRemoveCommand(struct cmdargs const *arg) 2356059Samurai{ 23636285Sbrian if (arg->argc != arg->argn) 23736285Sbrian return -1; 23811336Samurai 23936285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 24036285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 24136285Sbrian return 2; 2426059Samurai } 24326516Sbrian 24436285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 24536285Sbrian return 0; 24636285Sbrian} 24732711Sbrian 24836285Sbrianstatic int 24936285SbrianRenameCommand(struct cmdargs const *arg) 25036285Sbrian{ 25136285Sbrian if (arg->argc != arg->argn + 1) 25236285Sbrian return -1; 25331121Sbrian 25436285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 25536285Sbrian return 0; 25636285Sbrian 25736285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 25836285Sbrian arg->cx->name, arg->argv[arg->argn]); 25936285Sbrian return 1; 26036285Sbrian} 26136285Sbrian 26236285Sbrianint 26336285SbrianLoadCommand(struct cmdargs const *arg) 26436285Sbrian{ 26536285Sbrian const char *name; 26636285Sbrian 26736285Sbrian if (arg->argc > arg->argn) 26836285Sbrian name = arg->argv[arg->argn]; 26936285Sbrian else 27036285Sbrian name = "default"; 27136285Sbrian 27236928Sbrian if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type.all)) { 27337019Sbrian log_Printf(LogWARN, "%s: Label not allowed\n", name); 27436285Sbrian return 1; 27536285Sbrian } else { 27636285Sbrian /* 27736285Sbrian * Set the label before & after so that `set enddisc' works and 27836285Sbrian * we handle nested `load' commands. 27936285Sbrian */ 28036285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28137008Sbrian if (system_Select(arg->bundle, name, CONFFILE, arg->prompt, arg->cx) < 0) { 28236285Sbrian bundle_SetLabel(arg->bundle, NULL); 28336285Sbrian log_Printf(LogWARN, "%s: label not found.\n", name); 28436285Sbrian return -1; 28532403Sbrian } 28636285Sbrian bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL); 28736285Sbrian } 28826516Sbrian return 0; 2896059Samurai} 2906059Samurai 29136285Sbrianint 29236285SbrianSaveCommand(struct cmdargs const *arg) 29336285Sbrian{ 29436285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 29536285Sbrian return 1; 29636285Sbrian} 29736285Sbrian 29810528Samuraistatic int 29936285SbrianDialCommand(struct cmdargs const *arg) 30028536Sbrian{ 30136285Sbrian int res; 30236285Sbrian 30336465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 30436465Sbrian || (!arg->cx && 30536928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 30636285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 30736285Sbrian " interactive links\n"); 30836285Sbrian return 1; 30934536Sbrian } 31036285Sbrian 31136285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 31236285Sbrian return res; 31336285Sbrian 31437993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 31536285Sbrian 31636285Sbrian return 0; 31728536Sbrian} 31828536Sbrian 31938628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 32038628Sbrian 32138628Sbrianstatic char * 32238628Sbrianstrstrword(char *big, const char *little) 32338628Sbrian{ 32438628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 32538628Sbrian char *pos; 32638628Sbrian int len; 32738628Sbrian 32838628Sbrian pos = big; 32938628Sbrian len = strlen(little); 33038628Sbrian 33138628Sbrian while ((pos = strstr(pos, little)) != NULL) 33238628Sbrian if ((pos == big || !isinword(pos[-1])) && !isinword(pos[len])) 33338628Sbrian break; 33438628Sbrian else 33538628Sbrian pos++; 33638628Sbrian 33738628Sbrian return pos; 33838628Sbrian} 33938628Sbrian 34038628Sbrianstatic char * 34138628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 34238628Sbrian{ 34338628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 34438628Sbrian char *word, *ntgt; 34538628Sbrian int ltgt, loldstr, lnewstr, pos; 34638628Sbrian 34738628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 34838628Sbrian return tgt; 34938628Sbrian 35038628Sbrian ltgt = strlen(tgt) + 1; 35138628Sbrian loldstr = strlen(oldstr); 35238628Sbrian lnewstr = strlen(newstr); 35338628Sbrian do { 35438628Sbrian pos = word - tgt; 35538628Sbrian if (loldstr > lnewstr) 35638628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 35738628Sbrian if (loldstr != lnewstr) { 35838628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 35938628Sbrian if (ntgt == NULL) 36038628Sbrian break; /* Oh wonderful ! */ 36138628Sbrian word = ntgt + pos; 36238628Sbrian tgt = ntgt; 36338628Sbrian } 36438628Sbrian if (lnewstr > loldstr) 36538628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 36638628Sbrian bcopy(newstr, word, lnewstr); 36738628Sbrian } while ((word = strstrword(word, oldstr))); 36838628Sbrian 36938628Sbrian return tgt; 37038628Sbrian} 37138628Sbrian 37238628Sbrianstatic void 37338628Sbrianexpand(char **nargv, int argc, char const *const *oargv, struct bundle *bundle) 37438628Sbrian{ 37538628Sbrian int arg; 37638628Sbrian 37738628Sbrian nargv[0] = strdup(oargv[0]); 37838628Sbrian for (arg = 1; arg < argc; arg++) { 37938629Sbrian nargv[arg] = strdup(oargv[arg]); 38038629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 38138628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 38238629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 38338628Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->ifp.Name); 38438628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 38538629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 38638629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 38738629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 38838629Sbrian bundle->ncp.mp.peer.enddisc.address, 38938629Sbrian bundle->ncp.mp.peer.enddisc.len)); 39038629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 39138629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 39238629Sbrian bundle->ncp.mp.cfg.enddisc.address, 39338629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 39438629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 39538628Sbrian } 39638628Sbrian nargv[arg] = NULL; 39738628Sbrian} 39838628Sbrian 39928536Sbrianstatic int 40031343SbrianShellCommand(struct cmdargs const *arg, int bg) 40110528Samurai{ 40210528Samurai const char *shell; 40310528Samurai pid_t shpid; 40420813Sjkh 40518856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 40626911Sbrian /* we're only allowed to shell when we run ppp interactively */ 40736285Sbrian if (arg->prompt && arg->prompt->owner) { 40836285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 40926516Sbrian return 1; 41010528Samurai } 41126911Sbrian#endif 41228679Sbrian 41336285Sbrian if (arg->argc == arg->argn) { 41436285Sbrian if (!arg->prompt) { 41536285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 41636285Sbrian " a config file\n"); 41728381Sbrian return 1; 41836285Sbrian } else if (arg->prompt->owner) { 41936285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 42036285Sbrian " a socket connection\n"); 42136285Sbrian return 1; 42228381Sbrian } else if (bg) { 42336285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 42428679Sbrian " the foreground mode\n"); 42528381Sbrian return 1; 42628381Sbrian } 42734536Sbrian } 42834536Sbrian 42928679Sbrian if ((shpid = fork()) == 0) { 43036285Sbrian int i, fd; 43118531Sbde 43236285Sbrian if ((shell = getenv("SHELL")) == 0) 43336285Sbrian shell = _PATH_BSHELL; 43432017Sbrian 43536285Sbrian timer_TermService(); 43636285Sbrian 43736285Sbrian if (arg->prompt) 43836285Sbrian fd = arg->prompt->fd_out; 43936285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 44036285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 44136285Sbrian _PATH_DEVNULL, strerror(errno)); 44228679Sbrian exit(1); 44328679Sbrian } 44428679Sbrian for (i = 0; i < 3; i++) 44528679Sbrian dup2(fd, i); 44626516Sbrian 44736285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 44826516Sbrian 44931061Sbrian setuid(geteuid()); 45036285Sbrian if (arg->argc > arg->argn) { 45128679Sbrian /* substitute pseudo args */ 45238628Sbrian char *argv[MAXARGS]; 45338628Sbrian int argc = arg->argc - arg->argn; 45438628Sbrian 45538628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 45638628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 45738628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 45831343Sbrian } 45938628Sbrian expand(argv, argc, arg->argv + arg->argn, arg->bundle); 46028679Sbrian if (bg) { 46128679Sbrian pid_t p; 46210528Samurai 46328679Sbrian p = getpid(); 46428679Sbrian if (daemon(1, 1) == -1) { 46536832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 46628679Sbrian exit(1); 46728679Sbrian } 46836285Sbrian } else if (arg->prompt) 46936285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 47031343Sbrian execvp(argv[0], argv); 47130316Sbrian } else { 47236285Sbrian if (arg->prompt) 47332017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 47436285Sbrian prompt_TtyOldMode(arg->prompt); 47531343Sbrian execl(shell, shell, NULL); 47630316Sbrian } 47720813Sjkh 47836285Sbrian log_Printf(LogWARN, "exec() of %s failed\n", 47936285Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell); 48028679Sbrian exit(255); 48110528Samurai } 48236285Sbrian 48336285Sbrian if (shpid == (pid_t) - 1) 48436285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 48536285Sbrian else { 48610528Samurai int status; 48731343Sbrian waitpid(shpid, &status, 0); 48810528Samurai } 48920813Sjkh 49036285Sbrian if (arg->prompt && !arg->prompt->owner) 49136285Sbrian prompt_TtyCommandMode(arg->prompt); 49220813Sjkh 49336285Sbrian return 0; 49410528Samurai} 49510528Samurai 49631343Sbrianstatic int 49731343SbrianBgShellCommand(struct cmdargs const *arg) 49831343Sbrian{ 49936285Sbrian if (arg->argc == arg->argn) 50031343Sbrian return -1; 50131343Sbrian return ShellCommand(arg, 1); 50231343Sbrian} 50331343Sbrian 50431343Sbrianstatic int 50531343SbrianFgShellCommand(struct cmdargs const *arg) 50631343Sbrian{ 50731343Sbrian return ShellCommand(arg, 0); 50831343Sbrian} 50931343Sbrian 51030715Sbrianstatic struct cmdtab const Commands[] = { 51136285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 51228679Sbrian "accept option request", "accept option .."}, 51328679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 51432109Sbrian "add route", "add dest mask gateway", NULL}, 51536285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 51632109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 51736285Sbrian#ifndef NOALIAS 51836285Sbrian {"alias", NULL, AliasCommand, LOCAL_AUTH, 51936285Sbrian "alias control", "alias option [yes|no]"}, 52036285Sbrian#endif 52131121Sbrian {"allow", "auth", AllowCommand, LOCAL_AUTH, 52231121Sbrian "Allow ppp access", "allow users|modes ...."}, 52328679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 52431372Sbrian "Run a background command", "[!]bg command"}, 52536934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 52636934Sbrian "Clear throughput statistics", "clear ipcp|modem [current|overall|peak]..."}, 52736285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 52836285Sbrian "Clone a link", "clone newname..."}, 52936285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 53036285Sbrian "Close an FSM", "close [lcp|ccp]"}, 53128679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 53232109Sbrian "delete route", "delete dest", NULL}, 53336285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 53432109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 53536285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 53628679Sbrian "Deny option request", "deny option .."}, 53736285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 53837955Sbrian "Dial and login", "dial|call [remote]", NULL}, 53936285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54028679Sbrian "Disable option", "disable option .."}, 54136285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54236285Sbrian "Generate a down event", "down"}, 54336285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54428679Sbrian "Enable option", "enable option .."}, 54536285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 54636285Sbrian "Link specific commands", "link name command ..."}, 54737008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 54828679Sbrian "Load settings", "load [remote]"}, 54936285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 55037955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 55136285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 55236285Sbrian "Password for manipulation", "passwd LocalPassword"}, 55336285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 55436285Sbrian "Quit PPP program", "quit|bye [all]"}, 55536285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 55636285Sbrian "Remove a link", "remove"}, 55736285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 55836285Sbrian "Rename a link", "rename name"}, 55928679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 56028679Sbrian "Save settings", "save"}, 56136285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 56228679Sbrian "Set parameters", "set[up] var value"}, 56328679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 56428679Sbrian "Run a subshell", "shell|! [sh command]"}, 56536285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 56631372Sbrian "Show status and stats", "show var"}, 56736285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 56831372Sbrian "Enter terminal mode", "term"}, 56928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 57031343Sbrian "Display this message", "help|? [command]", Commands}, 57128679Sbrian {NULL, NULL, NULL}, 5726059Samurai}; 5736059Samurai 57428536Sbrianstatic int 57531343SbrianShowEscape(struct cmdargs const *arg) 5766059Samurai{ 57736285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 57836285Sbrian int code, bit; 57936285Sbrian const char *sep = ""; 5806059Samurai 58126516Sbrian for (code = 0; code < 32; code++) 58236285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 58328679Sbrian for (bit = 0; bit < 8; bit++) 58436285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 58536285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 58636285Sbrian sep = ", "; 58736285Sbrian } 58836285Sbrian prompt_Printf(arg->prompt, "\n"); 5896059Samurai } 59031077Sbrian return 0; 5916059Samurai} 5926059Samurai 59328679Sbrianstatic int 59436285SbrianShowTimerList(struct cmdargs const *arg) 5956059Samurai{ 59636285Sbrian timer_Show(0, arg->prompt); 59731077Sbrian return 0; 5986059Samurai} 5996059Samurai 60028679Sbrianstatic int 60131343SbrianShowStopped(struct cmdargs const *arg) 60228327Sbrian{ 60336285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 60436285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 60536285Sbrian prompt_Printf(arg->prompt, "Disabled"); 60628327Sbrian else 60736285Sbrian prompt_Printf(arg->prompt, "%ld secs", 60836285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 60928461Sbrian 61036285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 61136285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 61236285Sbrian prompt_Printf(arg->prompt, "Disabled"); 61328461Sbrian else 61436285Sbrian prompt_Printf(arg->prompt, "%ld secs", 61536285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 61628461Sbrian 61736285Sbrian prompt_Printf(arg->prompt, "\n"); 61828461Sbrian 61931077Sbrian return 0; 62028327Sbrian} 62128327Sbrian 62228679Sbrianstatic int 62331343SbrianShowVersion(struct cmdargs const *arg) 6246059Samurai{ 62536285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 62631077Sbrian return 0; 6276059Samurai} 6286059Samurai 62928679Sbrianstatic int 63036285SbrianShowProtocolStats(struct cmdargs const *arg) 63126326Sbrian{ 63236285Sbrian struct link *l = command_ChooseLink(arg); 63326326Sbrian 63436285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 63536285Sbrian link_ReportProtocolStatus(l, arg->prompt); 63631077Sbrian return 0; 63726326Sbrian} 63826326Sbrian 63930715Sbrianstatic struct cmdtab const ShowCommands[] = { 64036285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 64136285Sbrian "bundle details", "show bundle"}, 64236285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 64336285Sbrian "CCP status", "show cpp"}, 64436285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 64536285Sbrian "VJ compression stats", "show compress"}, 64636285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 64736285Sbrian "escape characters", "show escape"}, 64836285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 64936285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 65036285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 65136285Sbrian "HDLC errors", "show hdlc"}, 65236285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 65336285Sbrian "IPCP status", "show ipcp"}, 65436285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 65536285Sbrian "LCP status", "show lcp"}, 65636285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 65736285Sbrian "(high-level) link info", "show link"}, 65836285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 65936285Sbrian "available link names", "show links"}, 66036285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 66136285Sbrian "log levels", "show log"}, 66236285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 66336285Sbrian "mbuf allocations", "show mem"}, 66436285Sbrian {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 66536285Sbrian "(low-level) link info", "show modem"}, 66636285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 66736285Sbrian "multilink setup", "show mp"}, 66836285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 66936285Sbrian "protocol summary", "show proto"}, 67036285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 67136285Sbrian "routing table", "show route"}, 67236285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 67336285Sbrian "STOPPED timeout", "show stopped"}, 67436285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 67536285Sbrian "alarm timers", "show timers"}, 67628679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 67736285Sbrian "version string", "show version"}, 67836285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 67936285Sbrian "client list", "show who"}, 68028679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 68131343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 68228679Sbrian {NULL, NULL, NULL}, 6836059Samurai}; 6846059Samurai 68530715Sbrianstatic struct cmdtab const * 68631343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 6876059Samurai{ 68826516Sbrian int nmatch; 68926516Sbrian int len; 69028679Sbrian struct cmdtab const *found; 6916059Samurai 69226516Sbrian found = NULL; 69326516Sbrian len = strlen(str); 69426516Sbrian nmatch = 0; 6956059Samurai while (cmds->func) { 69625566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 69726516Sbrian if (cmds->name[len] == '\0') { 69828679Sbrian *pmatch = 1; 69928679Sbrian return cmds; 70026516Sbrian } 7016059Samurai nmatch++; 7026059Samurai found = cmds; 70328679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 70426516Sbrian if (cmds->alias[len] == '\0') { 70528679Sbrian *pmatch = 1; 70628679Sbrian return cmds; 70726516Sbrian } 7086059Samurai nmatch++; 7096059Samurai found = cmds; 7106059Samurai } 7116059Samurai cmds++; 7126059Samurai } 7136059Samurai *pmatch = nmatch; 71426516Sbrian return found; 7156059Samurai} 7166059Samurai 71736285Sbrianstatic const char * 71836285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 71936285Sbrian{ 72036285Sbrian int f, tlen, len; 72136285Sbrian 72236285Sbrian tlen = 0; 72336285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 72436285Sbrian if (f) 72536285Sbrian tgt[tlen++] = ' '; 72636285Sbrian len = strlen(argv[f]); 72736285Sbrian if (len > sz - tlen - 1) 72836285Sbrian len = sz - tlen - 1; 72936285Sbrian strncpy(tgt+tlen, argv[f], len); 73036285Sbrian tlen += len; 73136285Sbrian } 73236285Sbrian tgt[tlen] = '\0'; 73336285Sbrian return tgt; 73436285Sbrian} 73536285Sbrian 73630715Sbrianstatic int 73736285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 73836285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 7396059Samurai{ 74028679Sbrian struct cmdtab const *cmd; 7416059Samurai int val = 1; 7426059Samurai int nmatch; 74331343Sbrian struct cmdargs arg; 74436285Sbrian char prefix[100]; 7456059Samurai 74636285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 7476059Samurai if (nmatch > 1) 74836285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 74936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 75036285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 75136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 75236285Sbrian /* We've got no context, but we require it */ 75336285Sbrian cx = bundle2datalink(bundle, NULL); 75436285Sbrian 75536285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 75636285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 75736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 75836285Sbrian else { 75936285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 76036285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 76136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 76236285Sbrian cx = NULL; 76336285Sbrian } 76436285Sbrian arg.cmdtab = cmds; 76536285Sbrian arg.cmd = cmd; 76636285Sbrian arg.argc = argc; 76736285Sbrian arg.argn = argn+1; 76836285Sbrian arg.argv = argv; 76936285Sbrian arg.bundle = bundle; 77036285Sbrian arg.cx = cx; 77136285Sbrian arg.prompt = prompt; 77236285Sbrian val = (*cmd->func) (&arg); 77336285Sbrian } 77431343Sbrian } else 77536285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 77636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 77726516Sbrian 77826516Sbrian if (val == -1) 77936285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 78028679Sbrian else if (val) 78136285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 78236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 78326516Sbrian 78426516Sbrian return val; 7856059Samurai} 7866059Samurai 78737009Sbrianint 78837009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 7896059Samurai{ 7906059Samurai char *cp; 7916059Samurai 7926059Samurai if (nb > 0) { 7936059Samurai cp = buff + strcspn(buff, "\r\n"); 7946059Samurai if (cp) 7956059Samurai *cp = '\0'; 79637009Sbrian return MakeArgs(buff, argv, MAXARGS); 79737009Sbrian } 79837009Sbrian return 0; 79931121Sbrian} 8006059Samurai 80131822Sbrianstatic int 80231822Sbrianarghidden(int argc, char const *const *argv, int n) 80331822Sbrian{ 80431822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 80531828Sbrian 80631828Sbrian /* set authkey xxxxx */ 80731828Sbrian /* set key xxxxx */ 80831822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 80931822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 81031822Sbrian return 1; 81131822Sbrian 81231828Sbrian /* passwd xxxxx */ 81331828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 81431828Sbrian return 1; 81531828Sbrian 81636285Sbrian /* set server port xxxxx .... */ 81736285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 81836285Sbrian !strncasecmp(argv[1], "se", 2)) 81936285Sbrian return 1; 82036285Sbrian 82131822Sbrian return 0; 82231822Sbrian} 82331822Sbrian 82431121Sbrianvoid 82536285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 82637008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 82731121Sbrian{ 82831156Sbrian if (argc > 0) { 82936285Sbrian if (log_IsKept(LogCOMMAND)) { 83031156Sbrian static char buf[LINE_LEN]; 83131156Sbrian int f, n; 83231156Sbrian 83331156Sbrian *buf = '\0'; 83431156Sbrian if (label) { 83531962Sbrian strncpy(buf, label, sizeof buf - 3); 83631962Sbrian buf[sizeof buf - 3] = '\0'; 83731156Sbrian strcat(buf, ": "); 83831156Sbrian } 83931156Sbrian n = strlen(buf); 84031156Sbrian for (f = 0; f < argc; f++) { 84131962Sbrian if (n < sizeof buf - 1 && f) 84231156Sbrian buf[n++] = ' '; 84331822Sbrian if (arghidden(argc, argv, f)) 84436285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 84531822Sbrian else 84631962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 84731156Sbrian n += strlen(buf+n); 84831156Sbrian } 84936285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 85031156Sbrian } 85137008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 85231156Sbrian } 8536059Samurai} 8546059Samurai 85531121Sbrianvoid 85636285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 85736285Sbrian const char *label) 85831121Sbrian{ 85931121Sbrian int argc; 86037009Sbrian char *argv[MAXARGS]; 86131121Sbrian 86237009Sbrian argc = command_Interpret(buff, nb, argv); 86337008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 86431121Sbrian} 86531121Sbrian 8666059Samuraistatic int 86731343SbrianShowCommand(struct cmdargs const *arg) 8686059Samurai{ 86936285Sbrian if (!arg->prompt) 87036285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 87136285Sbrian else if (arg->argc > arg->argn) 87236285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 87336285Sbrian arg->prompt, arg->cx); 8746059Samurai else 87536285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 87626516Sbrian 87726516Sbrian return 0; 8786059Samurai} 8796059Samurai 8806059Samuraistatic int 88131343SbrianTerminalCommand(struct cmdargs const *arg) 8826059Samurai{ 88336285Sbrian if (!arg->prompt) { 88436285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 88526516Sbrian return 1; 8866059Samurai } 88736285Sbrian 88836285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 88936285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 89036285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 89136285Sbrian return 1; 8926059Samurai } 89336285Sbrian 89436285Sbrian datalink_Up(arg->cx, 0, 0); 89536285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 89636285Sbrian return 0; 8976059Samurai} 8986059Samurai 8996059Samuraistatic int 90031343SbrianQuitCommand(struct cmdargs const *arg) 9016059Samurai{ 90236285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 90336285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 90436285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 90536285Sbrian Cleanup(EX_NORMAL); 90636285Sbrian if (arg->prompt) 90736285Sbrian prompt_Destroy(arg->prompt, 1); 90826516Sbrian 90926516Sbrian return 0; 9106059Samurai} 9116059Samurai 9126059Samuraistatic int 91336285SbrianOpenCommand(struct cmdargs const *arg) 9146059Samurai{ 91537160Sbrian if (arg->argc == arg->argn) 91637993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 91737160Sbrian else if (arg->argc == arg->argn + 1) { 91837160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 91937385Sbrian struct datalink *cx = arg->cx ? 92037385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 92137385Sbrian if (cx) { 92237385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 92337385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 92437160Sbrian else 92537993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 92637160Sbrian } else 92737160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 92837160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 92937160Sbrian struct fsm *fp; 9306059Samurai 93137210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 93237160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 93337160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 93437160Sbrian else if (fp->state == ST_OPENED) 93537160Sbrian fsm_Reopen(fp); 93637160Sbrian else { 93737160Sbrian fp->open_mode = 0; /* Not passive any more */ 93837160Sbrian if (fp->state == ST_STOPPED) { 93937160Sbrian fsm_Down(fp); 94037160Sbrian fsm_Up(fp); 94137160Sbrian } else { 94237160Sbrian fsm_Up(fp); 94337160Sbrian fsm_Open(fp); 94437160Sbrian } 94536285Sbrian } 94637160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 94737160Sbrian if (arg->cx) 94837160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 94937160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 95037160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 95137160Sbrian else 95237993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 95337160Sbrian } else 95437160Sbrian return -1; 95536285Sbrian } else 95636285Sbrian return -1; 95736285Sbrian 95826516Sbrian return 0; 9596059Samurai} 9606059Samurai 96125067Sbrianstatic int 96236285SbrianCloseCommand(struct cmdargs const *arg) 9636059Samurai{ 96437007Sbrian if (arg->argc == arg->argn) 96537007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 96637007Sbrian else if (arg->argc == arg->argn + 1) { 96737007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 96837007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 96937007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 97037007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 97137007Sbrian struct fsm *fp; 9726059Samurai 97337210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 97437007Sbrian if (fp->state == ST_OPENED) { 97537007Sbrian fsm_Close(fp); 97637007Sbrian if (arg->argv[arg->argn][3] == '!') 97737007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 97837007Sbrian else 97937007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 98037007Sbrian } 98137007Sbrian } else 98236285Sbrian return -1; 98336285Sbrian } else 98436285Sbrian return -1; 98536285Sbrian 98636285Sbrian return 0; 9876059Samurai} 9886059Samurai 98925067Sbrianstatic int 99036285SbrianDownCommand(struct cmdargs const *arg) 99111336Samurai{ 99237018Sbrian if (arg->argc == arg->argn) { 99337018Sbrian if (arg->cx) 99437018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 99537018Sbrian else 99637018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 99737018Sbrian } else if (arg->argc == arg->argn + 1) { 99837018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 99937018Sbrian if (arg->cx) 100037018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 100137018Sbrian else 100237018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 100337018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 100437018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 100537018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 100637060Sbrian fsm2initial(fp); 100737018Sbrian } else 100837018Sbrian return -1; 100936285Sbrian } else 101036285Sbrian return -1; 101136285Sbrian 101236285Sbrian return 0; 101325067Sbrian} 101425067Sbrian 101525067Sbrianstatic int 101636285SbrianSetModemSpeed(struct cmdargs const *arg) 101725067Sbrian{ 101836285Sbrian long speed; 101936285Sbrian char *end; 102011336Samurai 102136285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 102236285Sbrian if (arg->argc > arg->argn+1) { 102336285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 102436285Sbrian return -1; 102511336Samurai } 102636285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 102736285Sbrian physical_SetSync(arg->cx->physical); 102836285Sbrian return 0; 102936285Sbrian } 103036285Sbrian end = NULL; 103136285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 103236285Sbrian if (*end) { 103336285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 103436285Sbrian arg->argv[arg->argn]); 103536285Sbrian return -1; 103636285Sbrian } 103736285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 103836285Sbrian return 0; 103936285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 104036285Sbrian } else 104136285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 104224939Sbrian 104326516Sbrian return -1; 104411336Samurai} 104511336Samurai 104625067Sbrianstatic int 104731343SbrianSetStoppedTimeout(struct cmdargs const *arg) 104828327Sbrian{ 104936285Sbrian struct link *l = &arg->cx->physical->link; 105036285Sbrian 105136285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 105236285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 105336285Sbrian if (arg->argc <= arg->argn+2) { 105436285Sbrian if (arg->argc > arg->argn) { 105536285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 105636285Sbrian if (arg->argc > arg->argn+1) 105736285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 105828461Sbrian } 105928327Sbrian return 0; 106028327Sbrian } 106128327Sbrian return -1; 106228327Sbrian} 106328327Sbrian 106431081Sbrian#define ismask(x) \ 106531081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 106631081Sbrian 106728327Sbrianstatic int 106831343SbrianSetServer(struct cmdargs const *arg) 106926940Sbrian{ 107026940Sbrian int res = -1; 107126940Sbrian 107236285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 107331081Sbrian const char *port, *passwd, *mask; 107431081Sbrian 107531081Sbrian /* What's what ? */ 107636285Sbrian port = arg->argv[arg->argn]; 107736285Sbrian if (arg->argc == arg->argn + 2) { 107836285Sbrian passwd = arg->argv[arg->argn+1]; 107936285Sbrian mask = NULL; 108036285Sbrian } else if (arg->argc == arg->argn + 3) { 108136285Sbrian passwd = arg->argv[arg->argn+1]; 108236285Sbrian mask = arg->argv[arg->argn+2]; 108331081Sbrian if (!ismask(mask)) 108431081Sbrian return -1; 108536285Sbrian } else if (strcasecmp(port, "none") == 0) { 108636285Sbrian if (server_Close(arg->bundle)) 108736285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 108836285Sbrian return 0; 108931081Sbrian } else 109036285Sbrian return -1; 109131081Sbrian 109236285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 109336285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 109431081Sbrian 109536285Sbrian if (*port == '/') { 109631081Sbrian mode_t imask; 109736285Sbrian char *ptr, name[LINE_LEN + 12]; 109828679Sbrian 109931081Sbrian if (mask != NULL) { 110028679Sbrian unsigned m; 110128679Sbrian 110231081Sbrian if (sscanf(mask, "%o", &m) == 1) 110331081Sbrian imask = m; 110431081Sbrian else 110531081Sbrian return -1; 110631081Sbrian } else 110731081Sbrian imask = (mode_t)-1; 110836285Sbrian 110936285Sbrian ptr = strstr(port, "%d"); 111036285Sbrian if (ptr) { 111136285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 111237210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 111336285Sbrian port = name; 111436285Sbrian } 111536285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 111627346Sbrian } else { 111736285Sbrian int iport, add = 0; 111828679Sbrian 111931081Sbrian if (mask != NULL) 112031081Sbrian return -1; 112128679Sbrian 112236285Sbrian if (*port == '+') { 112336285Sbrian port++; 112436285Sbrian add = 1; 112536285Sbrian } 112631081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 112731081Sbrian struct servent *s; 112831081Sbrian 112931081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 113031081Sbrian iport = 0; 113136285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 113228679Sbrian } else 113331081Sbrian iport = ntohs(s->s_port); 113427346Sbrian } else 113531081Sbrian iport = atoi(port); 113636285Sbrian 113736285Sbrian if (iport) { 113836285Sbrian if (add) 113936285Sbrian iport += arg->bundle->unit; 114036285Sbrian res = server_TcpOpen(arg->bundle, iport); 114136285Sbrian } else 114236285Sbrian res = -1; 114327346Sbrian } 114431081Sbrian } 114526940Sbrian 114626940Sbrian return res; 114726940Sbrian} 114826940Sbrian 114926940Sbrianstatic int 115031343SbrianSetModemParity(struct cmdargs const *arg) 11516059Samurai{ 115236285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 115336285Sbrian arg->argv[arg->argn]) : -1; 11546059Samurai} 11556059Samurai 11566059Samuraistatic int 115731343SbrianSetEscape(struct cmdargs const *arg) 11586059Samurai{ 11596059Samurai int code; 116036285Sbrian int argc = arg->argc - arg->argn; 116136285Sbrian char const *const *argv = arg->argv + arg->argn; 11626059Samurai 11636059Samurai for (code = 0; code < 33; code++) 116436285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 116531343Sbrian 11666059Samurai while (argc-- > 0) { 11676059Samurai sscanf(*argv++, "%x", &code); 11686059Samurai code &= 0xff; 116936285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 117036285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 11716059Samurai } 117226516Sbrian return 0; 11736059Samurai} 11746059Samurai 117530715Sbrianstatic struct in_addr 117631343SbrianGetIpAddr(const char *cp) 11776059Samurai{ 11786059Samurai struct hostent *hp; 11796059Samurai struct in_addr ipaddr; 11806059Samurai 118132124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 118232124Sbrian hp = gethostbyname(cp); 118332124Sbrian if (hp && hp->h_addrtype == AF_INET) 118432124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 118532124Sbrian else 118632124Sbrian ipaddr.s_addr = 0; 118732124Sbrian } 118828679Sbrian return (ipaddr); 11896059Samurai} 11906059Samurai 11916059Samuraistatic int 119231343SbrianSetInterfaceAddr(struct cmdargs const *arg) 11936059Samurai{ 119436285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 119532267Sbrian const char *hisaddr; 119632267Sbrian 119732267Sbrian hisaddr = NULL; 119836285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 119936285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 12006059Samurai 120136285Sbrian if (arg->argc > arg->argn + 4) 120228679Sbrian return -1; 120326516Sbrian 120436285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 120536285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 120636285Sbrian iplist_reset(&ipcp->cfg.peer_list); 120728394Sbrian 120836285Sbrian if (arg->argc > arg->argn) { 120936285Sbrian if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn, 121036285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 121136285Sbrian &ipcp->cfg.my_range.width)) 121228679Sbrian return 1; 121336285Sbrian if (arg->argc > arg->argn+1) { 121436285Sbrian hisaddr = arg->argv[arg->argn+1]; 121536285Sbrian if (arg->argc > arg->argn+2) { 121636285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 121736285Sbrian if (arg->argc > arg->argn+3) { 121836285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 121936285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 12209440Samurai } 12216059Samurai } 12226059Samurai } 12236059Samurai } 122428394Sbrian 12256059Samurai /* 12266059Samurai * For backwards compatibility, 0.0.0.0 means any address. 12276059Samurai */ 122836285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 122936285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 123036285Sbrian ipcp->cfg.my_range.width = 0; 12316059Samurai } 123236285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 123336285Sbrian 123436285Sbrian if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 123536285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY; 123636285Sbrian ipcp->cfg.peer_range.width = 0; 12376059Samurai } 123828537Sbrian 123936285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 124036928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 124132267Sbrian return 4; 124231121Sbrian 124326516Sbrian return 0; 12446059Samurai} 12456059Samurai 124618752Sjkhstatic int 124731343SbrianSetVariable(struct cmdargs const *arg) 12486059Samurai{ 124937210Sbrian long long_val, param = (long)arg->cmd->args; 125037210Sbrian int mode, dummyint; 125131343Sbrian const char *argp; 125236285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 125336285Sbrian const char *err = NULL; 125436285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 125536285Sbrian struct in_addr dummyaddr, *addr; 12566059Samurai 125736285Sbrian if (arg->argc > arg->argn) 125836285Sbrian argp = arg->argv[arg->argn]; 125926551Sbrian else 126031343Sbrian argp = ""; 126126551Sbrian 126236285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 126336285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 126436285Sbrian arg->cmd->name); 126536285Sbrian return 1; 126636285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 126736285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 126836285Sbrian arg->cmd->name, cx->name); 126936285Sbrian cx = NULL; 127036285Sbrian } 127136285Sbrian 127226551Sbrian switch (param) { 127328679Sbrian case VAR_AUTHKEY: 127436285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 127536285Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 127636285Sbrian sizeof arg->bundle->cfg.auth.key - 1); 127736285Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 127836285Sbrian } else { 127936285Sbrian err = "set authkey: Only available at phase DEAD\n"; 128036285Sbrian log_Printf(LogWARN, err); 128136285Sbrian } 128228679Sbrian break; 128337210Sbrian 128428679Sbrian case VAR_AUTHNAME: 128536285Sbrian if (bundle_Phase(arg->bundle) == PHASE_DEAD) { 128636285Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 128736285Sbrian sizeof arg->bundle->cfg.auth.name - 1); 128836285Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; 128936285Sbrian } else { 129036285Sbrian err = "set authname: Only available at phase DEAD\n"; 129136285Sbrian log_Printf(LogWARN, err); 129236285Sbrian } 129328679Sbrian break; 129437210Sbrian 129536285Sbrian case VAR_AUTOLOAD: 129636285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 129736285Sbrian arg->bundle->autoload.running = 1; 129836285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 129936285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 130036285Sbrian if (arg->argc == arg->argn + 4) { 130136285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 130236285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 130336285Sbrian } else { 130436285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 130536285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 130636285Sbrian } 130736285Sbrian } else { 130836285Sbrian err = "Set autoload requires two or four arguments\n"; 130936285Sbrian log_Printf(LogWARN, err); 131036285Sbrian } 131136285Sbrian break; 131237210Sbrian 131328679Sbrian case VAR_DIAL: 131436285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 131536285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 131628679Sbrian break; 131737210Sbrian 131828679Sbrian case VAR_LOGIN: 131936285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 132036285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 132128679Sbrian break; 132237210Sbrian 132336285Sbrian case VAR_WINSIZE: 132436285Sbrian if (arg->argc > arg->argn) { 132536285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 132636285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 132736285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 132836285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 132936285Sbrian l->ccp.cfg.deflate.out.winsize); 133036285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 133136285Sbrian } 133236285Sbrian if (arg->argc > arg->argn+1) { 133336285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 133436285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 133536285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 133636285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 133736285Sbrian l->ccp.cfg.deflate.in.winsize); 133836285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 133936285Sbrian } 134036285Sbrian } else 134136285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 134236285Sbrian } else { 134336285Sbrian err = "No window size specified\n"; 134436285Sbrian log_Printf(LogWARN, err); 134536285Sbrian } 134636285Sbrian break; 134737210Sbrian 134828679Sbrian case VAR_DEVICE: 134936285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 135036285Sbrian arg->argv + arg->argn); 135136285Sbrian break; 135237210Sbrian 135336285Sbrian case VAR_ACCMAP: 135436285Sbrian if (arg->argc > arg->argn) { 135537210Sbrian u_long ulong_val; 135636285Sbrian sscanf(argp, "%lx", &ulong_val); 135737210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 135836285Sbrian } else { 135936285Sbrian err = "No accmap specified\n"; 136036285Sbrian log_Printf(LogWARN, err); 136136285Sbrian } 136236285Sbrian break; 136337210Sbrian 136436285Sbrian case VAR_MODE: 136536285Sbrian mode = Nam2mode(argp); 136636285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 136736285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 136836285Sbrian return -1; 136936285Sbrian } 137036285Sbrian bundle_SetMode(arg->bundle, cx, mode); 137136285Sbrian break; 137237210Sbrian 137336285Sbrian case VAR_MRRU: 137437210Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) { 137536285Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); 137637210Sbrian return 1; 137729696Sbrian } 137837210Sbrian long_val = atol(argp); 137937210Sbrian if (long_val && long_val < MIN_MRU) { 138037210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 138137210Sbrian return 1; 138237210Sbrian } else if (long_val > MAX_MRU) { 138337210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 138437210Sbrian return 1; 138537210Sbrian } else 138637210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 138728679Sbrian break; 138837210Sbrian 138936285Sbrian case VAR_MRU: 139037210Sbrian long_val = atol(argp); 139137210Sbrian if (long_val == 0) 139237210Sbrian l->lcp.cfg.mru = DEF_MRU; 139337210Sbrian else if (long_val < MIN_MRU) { 139437210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 139537210Sbrian return 1; 139637210Sbrian } else if (long_val > MAX_MRU) { 139737210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 139837210Sbrian return 1; 139937210Sbrian } else 140037210Sbrian l->lcp.cfg.mru = long_val; 140128679Sbrian break; 140237210Sbrian 140336285Sbrian case VAR_MTU: 140437210Sbrian long_val = atol(argp); 140537210Sbrian if (long_val && long_val < MIN_MTU) { 140637210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 140737210Sbrian return 1; 140837210Sbrian } else if (long_val > MAX_MTU) { 140937210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 141037210Sbrian return 1; 141137210Sbrian } else 141237210Sbrian arg->bundle->cfg.mtu = long_val; 141336285Sbrian break; 141437210Sbrian 141536285Sbrian case VAR_OPENMODE: 141636285Sbrian if (strcasecmp(argp, "active") == 0) 141736285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 141836285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 141936285Sbrian else if (strcasecmp(argp, "passive") == 0) 142036285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 142136285Sbrian else { 142236285Sbrian err = "%s: Invalid openmode\n"; 142336285Sbrian log_Printf(LogWARN, err, argp); 142436285Sbrian } 142536285Sbrian break; 142637210Sbrian 142728679Sbrian case VAR_PHONE: 142836285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 142936285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 143038174Sbrian cx->phone.alt = cx->phone.next = NULL; 143128679Sbrian break; 143237210Sbrian 143328679Sbrian case VAR_HANGUP: 143436285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 143536285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 143628679Sbrian break; 143737210Sbrian 143836285Sbrian case VAR_IDLETIMEOUT: 143936285Sbrian if (arg->argc > arg->argn+1) 144036285Sbrian err = "Too many idle timeout values\n"; 144136285Sbrian else if (arg->argc == arg->argn+1) 144236285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 144336285Sbrian if (err) 144436285Sbrian log_Printf(LogWARN, err); 144529549Sbrian break; 144637210Sbrian 144736285Sbrian case VAR_LQRPERIOD: 144837210Sbrian long_val = atol(argp); 144937210Sbrian if (long_val < MIN_LQRPERIOD) { 145037210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 145137210Sbrian long_val, MIN_LQRPERIOD); 145237210Sbrian return 1; 145336285Sbrian } else 145437210Sbrian l->lcp.cfg.lqrperiod = long_val; 145536285Sbrian break; 145637210Sbrian 145736285Sbrian case VAR_LCPRETRY: 145837210Sbrian long_val = atol(argp); 145937210Sbrian if (long_val < MIN_FSMRETRY) { 146037210Sbrian log_Printf(LogWARN, "%ld: Invalid LCP FSM retry period - min %d\n", 146137210Sbrian long_val, MIN_FSMRETRY); 146237210Sbrian return 1; 146336285Sbrian } else 146437210Sbrian cx->physical->link.lcp.cfg.fsmretry = long_val; 146536285Sbrian break; 146637210Sbrian 146736285Sbrian case VAR_CHAPRETRY: 146837210Sbrian long_val = atol(argp); 146937210Sbrian if (long_val < MIN_FSMRETRY) { 147037210Sbrian log_Printf(LogWARN, "%ld: Invalid CHAP FSM retry period - min %d\n", 147137210Sbrian long_val, MIN_FSMRETRY); 147237210Sbrian return 1; 147336285Sbrian } else 147437210Sbrian cx->chap.auth.cfg.fsmretry = long_val; 147536285Sbrian break; 147637210Sbrian 147736285Sbrian case VAR_PAPRETRY: 147837210Sbrian long_val = atol(argp); 147937210Sbrian if (long_val < MIN_FSMRETRY) { 148037210Sbrian log_Printf(LogWARN, "%ld: Invalid PAP FSM retry period - min %d\n", 148137210Sbrian long_val, MIN_FSMRETRY); 148237210Sbrian return 1; 148336285Sbrian } else 148437210Sbrian cx->pap.cfg.fsmretry = long_val; 148536285Sbrian break; 148637210Sbrian 148736285Sbrian case VAR_CCPRETRY: 148837210Sbrian long_val = atol(argp); 148937210Sbrian if (long_val < MIN_FSMRETRY) { 149037210Sbrian log_Printf(LogWARN, "%ld: Invalid CCP FSM retry period - min %d\n", 149137210Sbrian long_val, MIN_FSMRETRY); 149237210Sbrian return 1; 149336285Sbrian } else 149437210Sbrian l->ccp.cfg.fsmretry = long_val; 149536285Sbrian break; 149637210Sbrian 149736285Sbrian case VAR_IPCPRETRY: 149837210Sbrian long_val = atol(argp); 149937210Sbrian if (long_val < MIN_FSMRETRY) { 150037210Sbrian log_Printf(LogWARN, "%ld: Invalid IPCP FSM retry period - min %d\n", 150137210Sbrian long_val, MIN_FSMRETRY); 150237210Sbrian return 1; 150336285Sbrian } else 150437210Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = long_val; 150536285Sbrian break; 150637210Sbrian 150736285Sbrian case VAR_NBNS: 150836285Sbrian case VAR_DNS: 150936285Sbrian if (param == VAR_DNS) 151036285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 151136285Sbrian else 151236285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 151336285Sbrian 151436285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 151536285Sbrian 151636285Sbrian if (arg->argc > arg->argn) { 151736285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 151836285Sbrian addr, &dummyaddr, &dummyint); 151936285Sbrian if (arg->argc > arg->argn+1) 152036285Sbrian ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1, 152136285Sbrian addr + 1, &dummyaddr, &dummyint); 152236285Sbrian 152336285Sbrian if (addr[1].s_addr == INADDR_ANY) 152436285Sbrian addr[1].s_addr = addr[0].s_addr; 152536285Sbrian if (addr[0].s_addr == INADDR_ANY) 152636285Sbrian addr[0].s_addr = addr[1].s_addr; 152736285Sbrian } 152836285Sbrian break; 152938174Sbrian 153038174Sbrian case VAR_CALLBACK: 153138174Sbrian cx->cfg.callback.opmask = 0; 153238174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 153338174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 153438174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 153538174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 153638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 153738174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 153838174Sbrian if (dummyint == arg->argc - 1) 153938174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 154038174Sbrian else { 154138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 154238174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 154338174Sbrian sizeof cx->cfg.callback.msg - 1); 154438174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 154538174Sbrian } 154638174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 154738174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 154838174Sbrian else 154938174Sbrian return -1; 155038174Sbrian } 155138174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 155238174Sbrian cx->cfg.callback.opmask = 0; 155338174Sbrian break; 155438174Sbrian 155538174Sbrian case VAR_CBCP: 155638174Sbrian cx->cfg.cbcp.delay = 0; 155738174Sbrian *cx->cfg.cbcp.phone = '\0'; 155838174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 155938174Sbrian if (arg->argc > arg->argn) { 156038174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 156138174Sbrian sizeof cx->cfg.cbcp.phone - 1); 156238174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 156338174Sbrian if (arg->argc > arg->argn + 1) { 156438174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 156538174Sbrian if (arg->argc > arg->argn + 2) { 156638174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 156738174Sbrian if (long_val < MIN_FSMRETRY) 156838174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 156938174Sbrian long_val, MIN_FSMRETRY); 157038174Sbrian else 157138174Sbrian cx->cfg.cbcp.fsmretry = long_val; 157238174Sbrian } 157338174Sbrian } 157438174Sbrian } 157538174Sbrian break; 157638544Sbrian 157738544Sbrian case VAR_CHOKED: 157838544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 157938544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 158038544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 158138544Sbrian break; 158238544Sbrian 15836059Samurai } 158436285Sbrian 158536285Sbrian return err ? 1 : 0; 15866059Samurai} 15876059Samurai 158828679Sbrianstatic int 158931343SbrianSetCtsRts(struct cmdargs const *arg) 159020812Sjkh{ 159136285Sbrian if (arg->argc == arg->argn+1) { 159236285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 159336285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 159436285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 159536285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 159620812Sjkh else 159726516Sbrian return -1; 159826516Sbrian return 0; 159920812Sjkh } 160026516Sbrian return -1; 160120812Sjkh} 160220812Sjkh 160330715Sbrianstatic struct cmdtab const SetCommands[] = { 160436285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 160536285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 160628679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 160736285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 160828679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 160936285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 161036285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 161136285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 161236285Sbrian (const void *)VAR_AUTOLOAD}, 161338174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 161438174Sbrian "callback control", "set callback [none|auth|cbcp|" 161538174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 161638174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 161738174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 161838174Sbrian (const void *)VAR_CBCP}, 161936285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 162036285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 162136285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 162236285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 162338544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 162438544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 162536285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 162636285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 162736285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 162836285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 162936285Sbrian (const void *) VAR_WINSIZE}, 163036285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 163136285Sbrian "modem device name", "set device|line device-name[,device-name]", 163236285Sbrian (const void *) VAR_DEVICE}, 163336285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 163436285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 163536285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 163636285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 163736285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 163836285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 163936285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 164036285Sbrian "escape characters", "set escape hex-digit ..."}, 164136285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 164236285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 164336285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 164436285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 164536285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 164636285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 164736285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 164831343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 164936285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 165036285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 165136285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 165236285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 165336712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 165438622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 165538622Sbrian "ipcp|lcp|lqm|phase|tcp/ip|timer|tun..."}, 165636285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 165736285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 165836285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 165936285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 166036285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 166136285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 166236285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 166336285Sbrian "set mrru value", (const void *)VAR_MRRU}, 166436285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 166536285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 166636285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 166736285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 166836285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 166936285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 167036285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 167136285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 167236285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 167336285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 167436285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 167536285Sbrian "modem parity", "set parity [odd|even|none]"}, 167636285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 167736285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 167836285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 167936285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 168036285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 168136285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 168228679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 168336774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 168436285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 168536285Sbrian "modem speed", "set speed value"}, 168636285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 168736285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 168836285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 168936285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 169036285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 169136285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 169236285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 169336285Sbrian "datalink weighting", "set weight n"}, 169428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 169531343Sbrian "Display this message", "set help|? [command]", SetCommands}, 169628679Sbrian {NULL, NULL, NULL}, 16976059Samurai}; 16986059Samurai 16996059Samuraistatic int 170031343SbrianSetCommand(struct cmdargs const *arg) 17016059Samurai{ 170236285Sbrian if (arg->argc > arg->argn) 170336285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 170436285Sbrian arg->prompt, arg->cx); 170536285Sbrian else if (arg->prompt) 170636285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 170726516Sbrian " syntax help.\n"); 17086059Samurai else 170936285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 171026516Sbrian 171126516Sbrian return 0; 17126059Samurai} 17136059Samurai 17146059Samurai 17156059Samuraistatic int 171631343SbrianAddCommand(struct cmdargs const *arg) 17176059Samurai{ 17186059Samurai struct in_addr dest, gateway, netmask; 171936285Sbrian int gw, addrs; 17206059Samurai 172136285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 172231598Sbrian return -1; 172331598Sbrian 172436285Sbrian addrs = 0; 172536285Sbrian if (arg->argc == arg->argn+2) { 172636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 172736285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 172831598Sbrian else { 172936285Sbrian int width; 173036285Sbrian 173136285Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn, 173236285Sbrian &dest, &netmask, &width)) 173336285Sbrian return -1; 173436285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 173536285Sbrian addrs = ROUTE_DSTMYADDR; 173636285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 173736285Sbrian addrs = ROUTE_DSTHISADDR; 173831598Sbrian } 173936285Sbrian gw = 1; 174034536Sbrian } else { 174136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 174236285Sbrian addrs = ROUTE_DSTMYADDR; 174336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 174436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 174536285Sbrian addrs = ROUTE_DSTHISADDR; 174636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 174736285Sbrian } else 174836285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 174936285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 175031598Sbrian gw = 2; 17516059Samurai } 175236285Sbrian 175336285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 175436285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 175536285Sbrian addrs |= ROUTE_GWHISADDR; 175636285Sbrian } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0) 175731598Sbrian gateway.s_addr = INADDR_ANY; 175831598Sbrian else 175936285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 176036285Sbrian 176136285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 176237927Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0)) 176336285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 176436285Sbrian 176531598Sbrian return 0; 17666059Samurai} 17676059Samurai 17686059Samuraistatic int 176931343SbrianDeleteCommand(struct cmdargs const *arg) 17706059Samurai{ 177131598Sbrian struct in_addr dest, none; 177236285Sbrian int addrs; 17736059Samurai 177436285Sbrian if (arg->argc == arg->argn+1) { 177536285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 177636285Sbrian route_IfDelete(arg->bundle, 0); 177736285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 177836285Sbrian } else { 177936285Sbrian addrs = 0; 178036285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 178136285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 178236285Sbrian addrs = ROUTE_DSTMYADDR; 178336285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 178436285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 178536285Sbrian addrs = ROUTE_DSTHISADDR; 178636285Sbrian } else { 178736285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 178836285Sbrian dest.s_addr = INADDR_ANY; 178936285Sbrian else 179036285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 179136285Sbrian addrs = ROUTE_STATIC; 179236285Sbrian } 179331598Sbrian none.s_addr = INADDR_ANY; 179436285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 179537927Sbrian arg->cmd->args ? 1 : 0, 0); 179636285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 179731598Sbrian } 179834536Sbrian } else 179926516Sbrian return -1; 180026516Sbrian 180126516Sbrian return 0; 18026059Samurai} 18036059Samurai 180431343Sbrian#ifndef NOALIAS 180526031Sbrianstatic struct cmdtab const AliasCommands[] = 180626031Sbrian{ 180736285Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 180836285Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 180936285Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 181036285Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 181136285Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 181228679Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 181336285Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 181428679Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 181536285Sbrian "log aliasing link creation", "alias log [yes|no]", 181636285Sbrian (const void *) PKT_ALIAS_LOG}, 181736285Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 181836285Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 181928679Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 182036285Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 182136285Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 182236285Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 182336285Sbrian "alias unregistered (private) IP address space only", 182436285Sbrian "alias unregistered_only [yes|no]", 182536285Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 182628679Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 182736285Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 182836285Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 182928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 183036285Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 183128679Sbrian {NULL, NULL, NULL}, 183226031Sbrian}; 183326031Sbrian 183426031Sbrian 183526031Sbrianstatic int 183631343SbrianAliasCommand(struct cmdargs const *arg) 183726031Sbrian{ 183836285Sbrian if (arg->argc > arg->argn) 183936285Sbrian FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv, 184036285Sbrian arg->prompt, arg->cx); 184136285Sbrian else if (arg->prompt) 184236285Sbrian prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help" 184336285Sbrian " <option>' for syntax help.\n"); 184426031Sbrian else 184536285Sbrian log_Printf(LogWARN, "alias command must have arguments\n"); 184626516Sbrian 184726516Sbrian return 0; 184826031Sbrian} 184926031Sbrian 185026031Sbrianstatic int 185131343SbrianAliasEnable(struct cmdargs const *arg) 185226031Sbrian{ 185336285Sbrian if (arg->argc == arg->argn+1) { 185436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 185537191Sbrian arg->bundle->AliasEnabled = 1; 185637191Sbrian return 0; 185736285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 185837191Sbrian arg->bundle->AliasEnabled = 0; 185926516Sbrian return 0; 186026142Sbrian } 186135449Sbrian } 186236285Sbrian 186326516Sbrian return -1; 186426031Sbrian} 186526031Sbrian 186626031Sbrian 186726031Sbrianstatic int 186831343SbrianAliasOption(struct cmdargs const *arg) 186926031Sbrian{ 187038559Sbrian long param = (long)arg->cmd->args; 187138559Sbrian 187236285Sbrian if (arg->argc == arg->argn+1) { 187336285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 187437191Sbrian if (arg->bundle->AliasEnabled) { 187537191Sbrian PacketAliasSetMode(param, param); 187628679Sbrian return 0; 187728679Sbrian } 187836285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 187936285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 188037191Sbrian if (arg->bundle->AliasEnabled) { 188137191Sbrian PacketAliasSetMode(0, param); 188228679Sbrian return 0; 188328679Sbrian } 188436285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 188528679Sbrian } 188635449Sbrian } 188728679Sbrian return -1; 188826031Sbrian} 188931343Sbrian#endif /* #ifndef NOALIAS */ 189031121Sbrian 189131121Sbrianstatic struct cmdtab const AllowCommands[] = { 189236285Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 189336285Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 189431121Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 189531121Sbrian "Allow users access to ppp", "allow users logname..."}, 189631121Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 189731343Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 189831121Sbrian {NULL, NULL, NULL}, 189931121Sbrian}; 190031121Sbrian 190131121Sbrianstatic int 190231343SbrianAllowCommand(struct cmdargs const *arg) 190331121Sbrian{ 190436285Sbrian /* arg->bundle may be NULL (see system_IsValid()) ! */ 190536285Sbrian if (arg->argc > arg->argn) 190636285Sbrian FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv, 190736285Sbrian arg->prompt, arg->cx); 190836285Sbrian else if (arg->prompt) 190936285Sbrian prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'" 191036285Sbrian " for syntax help.\n"); 191131121Sbrian else 191236285Sbrian log_Printf(LogWARN, "allow command must have arguments\n"); 191331121Sbrian 191431121Sbrian return 0; 191531121Sbrian} 191636285Sbrian 191736285Sbrianstatic int 191836285SbrianLinkCommand(struct cmdargs const *arg) 191936285Sbrian{ 192036285Sbrian if (arg->argc > arg->argn+1) { 192136285Sbrian char namelist[LINE_LEN]; 192236285Sbrian struct datalink *cx; 192336285Sbrian char *name; 192436285Sbrian int result = 0; 192536285Sbrian 192636285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 192736285Sbrian struct datalink *dl; 192836285Sbrian 192936285Sbrian cx = arg->bundle->links; 193036285Sbrian while (cx) { 193136285Sbrian /* Watch it, the command could be a ``remove'' */ 193236285Sbrian dl = cx->next; 193336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 193436285Sbrian arg->prompt, cx); 193536285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 193636285Sbrian if (cx == dl) 193736285Sbrian break; /* Pointer's still valid ! */ 193836285Sbrian } 193936285Sbrian } else { 194036285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 194136285Sbrian namelist[sizeof namelist - 1] = '\0'; 194236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 194336285Sbrian if (!bundle2datalink(arg->bundle, name)) { 194436285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 194536285Sbrian return 1; 194636285Sbrian } 194736285Sbrian 194836285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 194936285Sbrian namelist[sizeof namelist - 1] = '\0'; 195036285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 195136285Sbrian cx = bundle2datalink(arg->bundle, name); 195236285Sbrian if (cx) 195336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 195436285Sbrian arg->prompt, cx); 195536285Sbrian else { 195636285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 195736285Sbrian result++; 195836285Sbrian } 195936285Sbrian } 196036285Sbrian } 196136285Sbrian return result; 196236285Sbrian } 196336285Sbrian 196436285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 196536285Sbrian return 2; 196636285Sbrian} 196736285Sbrian 196836285Sbrianstruct link * 196936285Sbriancommand_ChooseLink(struct cmdargs const *arg) 197036285Sbrian{ 197136285Sbrian if (arg->cx) 197236285Sbrian return &arg->cx->physical->link; 197337210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 197436285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 197537210Sbrian if (dl) 197637210Sbrian return &dl->physical->link; 197736285Sbrian } 197837210Sbrian return &arg->bundle->ncp.mp.link; 197936285Sbrian} 198036285Sbrian 198136285Sbrianstatic const char * 198236285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 198336285Sbrian{ 198436285Sbrian const char *result; 198536285Sbrian 198636285Sbrian switch (*cmd) { 198736285Sbrian case 'A': 198836285Sbrian case 'a': 198936285Sbrian result = "accept"; 199036285Sbrian *keep = NEG_MYMASK; 199136285Sbrian *add = NEG_ACCEPTED; 199236285Sbrian break; 199336285Sbrian case 'D': 199436285Sbrian case 'd': 199536285Sbrian switch (cmd[1]) { 199636285Sbrian case 'E': 199736285Sbrian case 'e': 199836285Sbrian result = "deny"; 199936285Sbrian *keep = NEG_MYMASK; 200036285Sbrian *add = 0; 200136285Sbrian break; 200236285Sbrian case 'I': 200336285Sbrian case 'i': 200436285Sbrian result = "disable"; 200536285Sbrian *keep = NEG_HISMASK; 200636285Sbrian *add = 0; 200736285Sbrian break; 200836285Sbrian default: 200936285Sbrian return NULL; 201036285Sbrian } 201136285Sbrian break; 201236285Sbrian case 'E': 201336285Sbrian case 'e': 201436285Sbrian result = "enable"; 201536285Sbrian *keep = NEG_HISMASK; 201636285Sbrian *add = NEG_ENABLED; 201736285Sbrian break; 201836285Sbrian default: 201936285Sbrian return NULL; 202036285Sbrian } 202136285Sbrian 202236285Sbrian return result; 202336285Sbrian} 202436285Sbrian 202536285Sbrianstatic int 202636285SbrianOptSet(struct cmdargs const *arg) 202736285Sbrian{ 202837574Sbrian int bit = (int)(long)arg->cmd->args; 202936285Sbrian const char *cmd; 203036285Sbrian unsigned keep; /* Keep these bits */ 203136285Sbrian unsigned add; /* Add these bits */ 203236285Sbrian 203336285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 203436285Sbrian return 1; 203536285Sbrian 203636285Sbrian if (add) 203736285Sbrian arg->bundle->cfg.opt |= bit; 203836285Sbrian else 203936285Sbrian arg->bundle->cfg.opt &= ~bit; 204036285Sbrian return 0; 204136285Sbrian} 204236285Sbrian 204336285Sbrianstatic int 204436285SbrianNegotiateSet(struct cmdargs const *arg) 204536285Sbrian{ 204637210Sbrian long param = (long)arg->cmd->args; 204736285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 204836285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 204936285Sbrian const char *cmd; 205036285Sbrian unsigned keep; /* Keep these bits */ 205136285Sbrian unsigned add; /* Add these bits */ 205236285Sbrian 205336285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 205436285Sbrian return 1; 205536285Sbrian 205636285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 205736285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 205836285Sbrian cmd, arg->cmd->name); 205936285Sbrian return 2; 206036285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 206136285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 206236285Sbrian cmd, arg->cmd->name, cx->name); 206336285Sbrian cx = NULL; 206436285Sbrian } 206536285Sbrian 206636285Sbrian switch (param) { 206736285Sbrian case NEG_ACFCOMP: 206836285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 206936285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 207036285Sbrian break; 207136285Sbrian case NEG_CHAP: 207236285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 207336285Sbrian cx->physical->link.lcp.cfg.chap |= add; 207436285Sbrian break; 207536285Sbrian case NEG_DEFLATE: 207636285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 207736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 207836285Sbrian break; 207936285Sbrian case NEG_DNS: 208036285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 208136285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 208236285Sbrian break; 208336285Sbrian case NEG_LQR: 208436285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 208536285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 208636285Sbrian break; 208736285Sbrian case NEG_PAP: 208836285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 208936285Sbrian cx->physical->link.lcp.cfg.pap |= add; 209036285Sbrian break; 209136285Sbrian case NEG_PPPDDEFLATE: 209236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 209336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 209436285Sbrian break; 209536285Sbrian case NEG_PRED1: 209636285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 209736285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 209836285Sbrian break; 209936285Sbrian case NEG_PROTOCOMP: 210036285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 210136285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 210236285Sbrian break; 210336285Sbrian case NEG_SHORTSEQ: 210436285Sbrian if (bundle_Phase(arg->bundle) != PHASE_DEAD) 210536285Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); 210636285Sbrian else { 210736285Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 210836285Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 210936285Sbrian } 211036285Sbrian break; 211136285Sbrian case NEG_VJCOMP: 211236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 211336285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 211436285Sbrian break; 211536285Sbrian } 211636285Sbrian 211736285Sbrian return 0; 211836285Sbrian} 211936285Sbrian 212036285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 212136285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 212236285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 212336285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 212436285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 212536285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 212636285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 212736285Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", 212836285Sbrian "disable|enable", (const void *)OPT_PROXY}, 212936285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 213036285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 213136285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 213236285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 213336285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 213436285Sbrian "disable|enable", (const void *)OPT_UTMP}, 213536285Sbrian 213636285Sbrian#define OPT_MAX 7 /* accept/deny allowed below and not above */ 213736285Sbrian 213836285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 213936285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 214036285Sbrian (const void *)NEG_ACFCOMP}, 214136285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 214236285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 214336285Sbrian (const void *)NEG_CHAP}, 214436285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 214536285Sbrian "Deflate compression", "accept|deny|disable|enable", 214636285Sbrian (const void *)NEG_DEFLATE}, 214736285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 214836285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 214936285Sbrian (const void *)NEG_PPPDDEFLATE}, 215036285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 215136285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 215236285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 215336285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 215436285Sbrian (const void *)NEG_LQR}, 215536285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 215636285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 215736285Sbrian (const void *)NEG_PAP}, 215836285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 215936285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 216036285Sbrian (const void *)NEG_PRED1}, 216136285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 216236285Sbrian "Protocol field compression", "accept|deny|disable|enable", 216336285Sbrian (const void *)NEG_PROTOCOMP}, 216436285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 216536285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 216636285Sbrian (const void *)NEG_SHORTSEQ}, 216736285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 216836285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 216936285Sbrian (const void *)NEG_VJCOMP}, 217036285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 217136285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 217236285Sbrian NegotiateCommands}, 217336285Sbrian {NULL, NULL, NULL}, 217436285Sbrian}; 217536285Sbrian 217636285Sbrianstatic int 217736285SbrianNegotiateCommand(struct cmdargs const *arg) 217836285Sbrian{ 217936285Sbrian if (arg->argc > arg->argn) { 218036285Sbrian char const *argv[3]; 218136285Sbrian unsigned keep, add; 218236285Sbrian int n; 218336285Sbrian 218436285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 218536285Sbrian return -1; 218636285Sbrian argv[2] = NULL; 218736285Sbrian 218836285Sbrian for (n = arg->argn; n < arg->argc; n++) { 218936285Sbrian argv[1] = arg->argv[n]; 219036285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 219136285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 219236285Sbrian } 219336285Sbrian } else if (arg->prompt) 219436285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 219536285Sbrian arg->argv[arg->argn-1]); 219636285Sbrian else 219736285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 219836285Sbrian arg->argv[arg->argn] ); 219936285Sbrian 220036285Sbrian return 0; 220136285Sbrian} 220236285Sbrian 220336285Sbrianconst char * 220436285Sbriancommand_ShowNegval(unsigned val) 220536285Sbrian{ 220636285Sbrian switch (val&3) { 220736285Sbrian case 1: return "disabled & accepted"; 220836285Sbrian case 2: return "enabled & denied"; 220936285Sbrian case 3: return "enabled & accepted"; 221036285Sbrian } 221136285Sbrian return "disabled & denied"; 221236285Sbrian} 221336934Sbrian 221436934Sbrianstatic int 221536934SbrianClearCommand(struct cmdargs const *arg) 221636934Sbrian{ 221736934Sbrian struct pppThroughput *t; 221836934Sbrian struct datalink *cx; 221936934Sbrian int i, clear_type; 222036934Sbrian 222136934Sbrian if (arg->argc < arg->argn + 1) 222236934Sbrian return -1; 222336934Sbrian 222436934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 222536934Sbrian cx = arg->cx; 222636934Sbrian if (!cx) 222736934Sbrian cx = bundle2datalink(arg->bundle, NULL); 222836934Sbrian if (!cx) { 222936934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 223036934Sbrian return 1; 223136934Sbrian } 223236934Sbrian t = &cx->physical->link.throughput; 223336934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 223436934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 223536934Sbrian else 223636934Sbrian return -1; 223736934Sbrian 223836934Sbrian if (arg->argc > arg->argn + 1) { 223936934Sbrian clear_type = 0; 224036934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 224136934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 224236934Sbrian clear_type |= THROUGHPUT_OVERALL; 224336934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 224436934Sbrian clear_type |= THROUGHPUT_CURRENT; 224536934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 224636934Sbrian clear_type |= THROUGHPUT_PEAK; 224736934Sbrian else 224836934Sbrian return -1; 224936934Sbrian } else 225036934Sbrian clear_type = THROUGHPUT_ALL; 225136934Sbrian 225236934Sbrian throughput_clear(t, clear_type, arg->prompt); 225336934Sbrian return 0; 225436934Sbrian} 2255