command.c revision 81033
178189Sbrian/*- 278189Sbrian * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 378189Sbrian * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 478189Sbrian * Internet Initiative Japan, Inc (IIJ) 578189Sbrian * All rights reserved. 66059Samurai * 778189Sbrian * Redistribution and use in source and binary forms, with or without 878189Sbrian * modification, are permitted provided that the following conditions 978189Sbrian * are met: 1078189Sbrian * 1. Redistributions of source code must retain the above copyright 1178189Sbrian * notice, this list of conditions and the following disclaimer. 1278189Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1378189Sbrian * notice, this list of conditions and the following disclaimer in the 1478189Sbrian * documentation and/or other materials provided with the distribution. 156059Samurai * 1678189Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1778189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1878189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1978189Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2078189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2178189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2278189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2378189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2478189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2578189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2678189Sbrian * SUCH DAMAGE. 276059Samurai * 2850479Speter * $FreeBSD: head/usr.sbin/ppp/command.c 81033 2001-08-02 10:16:32Z brian $ 296059Samurai */ 3078189Sbrian 3143313Sbrian#include <sys/param.h> 3230715Sbrian#include <netinet/in_systm.h> 3326031Sbrian#include <netinet/in.h> 3430715Sbrian#include <netinet/ip.h> 3526031Sbrian#include <arpa/inet.h> 3630715Sbrian#include <sys/socket.h> 3726031Sbrian#include <net/route.h> 3830715Sbrian#include <netdb.h> 3936285Sbrian#include <sys/un.h> 4030715Sbrian 4138628Sbrian#include <ctype.h> 4230715Sbrian#include <errno.h> 4326516Sbrian#include <fcntl.h> 4430715Sbrian#include <paths.h> 4530715Sbrian#include <stdio.h> 4630715Sbrian#include <stdlib.h> 4730715Sbrian#include <string.h> 4830715Sbrian#include <sys/wait.h> 4930715Sbrian#include <termios.h> 5030715Sbrian#include <unistd.h> 5130715Sbrian 5250059Sbrian#ifndef NONAT 5358037Sbrian#ifdef LOCALNAT 5458037Sbrian#include "alias.h" 5558037Sbrian#else 5646086Sbrian#include <alias.h> 5739395Sbrian#endif 5839395Sbrian#endif 5958037Sbrian 6046686Sbrian#include "layer.h" 6137009Sbrian#include "defs.h" 6231343Sbrian#include "command.h" 6330715Sbrian#include "mbuf.h" 6430715Sbrian#include "log.h" 6530715Sbrian#include "timer.h" 666059Samurai#include "fsm.h" 6731690Sbrian#include "iplist.h" 6836285Sbrian#include "throughput.h" 6936285Sbrian#include "slcompress.h" 7038557Sbrian#include "lqr.h" 7138557Sbrian#include "hdlc.h" 7263484Sbrian#include "lcp.h" 736059Samurai#include "ipcp.h" 7450059Sbrian#ifndef NONAT 7551075Sbrian#include "nat_cmd.h" 7631343Sbrian#endif 7725630Sbrian#include "systems.h" 7836285Sbrian#include "filter.h" 7936285Sbrian#include "descriptor.h" 8030715Sbrian#include "main.h" 8130715Sbrian#include "route.h" 8230715Sbrian#include "ccp.h" 8331080Sbrian#include "auth.h" 8436285Sbrian#include "async.h" 8536285Sbrian#include "link.h" 8636285Sbrian#include "physical.h" 8736285Sbrian#include "mp.h" 8843313Sbrian#ifndef NORADIUS 8943313Sbrian#include "radius.h" 9043313Sbrian#endif 9136285Sbrian#include "bundle.h" 9236285Sbrian#include "server.h" 9336285Sbrian#include "prompt.h" 9436285Sbrian#include "chat.h" 9536285Sbrian#include "chap.h" 9638174Sbrian#include "cbcp.h" 9736285Sbrian#include "datalink.h" 9840561Sbrian#include "iface.h" 9953298Sbrian#include "id.h" 1006059Samurai 10136285Sbrian/* ``set'' values */ 10236285Sbrian#define VAR_AUTHKEY 0 10336285Sbrian#define VAR_DIAL 1 10436285Sbrian#define VAR_LOGIN 2 10536285Sbrian#define VAR_AUTHNAME 3 10636285Sbrian#define VAR_AUTOLOAD 4 10736285Sbrian#define VAR_WINSIZE 5 10836285Sbrian#define VAR_DEVICE 6 10936285Sbrian#define VAR_ACCMAP 7 11036285Sbrian#define VAR_MRRU 8 11136285Sbrian#define VAR_MRU 9 11236285Sbrian#define VAR_MTU 10 11336285Sbrian#define VAR_OPENMODE 11 11436285Sbrian#define VAR_PHONE 12 11536285Sbrian#define VAR_HANGUP 13 11636285Sbrian#define VAR_IDLETIMEOUT 14 11736285Sbrian#define VAR_LQRPERIOD 15 11836285Sbrian#define VAR_LCPRETRY 16 11936285Sbrian#define VAR_CHAPRETRY 17 12036285Sbrian#define VAR_PAPRETRY 18 12136285Sbrian#define VAR_CCPRETRY 19 12236285Sbrian#define VAR_IPCPRETRY 20 12336285Sbrian#define VAR_DNS 21 12436285Sbrian#define VAR_NBNS 22 12536285Sbrian#define VAR_MODE 23 12638174Sbrian#define VAR_CALLBACK 24 12738174Sbrian#define VAR_CBCP 25 12838544Sbrian#define VAR_CHOKED 26 12940665Sbrian#define VAR_SENDPIPE 27 13040665Sbrian#define VAR_RECVPIPE 28 13143313Sbrian#define VAR_RADIUS 29 13244073Sbrian#define VAR_CD 30 13346686Sbrian#define VAR_PARITY 31 13446686Sbrian#define VAR_CRTSCTS 32 13550867Sbrian#define VAR_URGENTPORTS 33 13652488Sbrian#define VAR_LOGOUT 34 13761534Sbrian#define VAR_IFQUEUE 35 13878411Sbrian#define VAR_MPPE 36 1396059Samurai 14036285Sbrian/* ``accept|deny|disable|enable'' masks */ 14136285Sbrian#define NEG_HISMASK (1) 14236285Sbrian#define NEG_MYMASK (2) 14336285Sbrian 14436285Sbrian/* ``accept|deny|disable|enable'' values */ 14536285Sbrian#define NEG_ACFCOMP 40 14644106Sbrian#define NEG_CHAP05 41 14744106Sbrian#define NEG_CHAP80 42 14844106Sbrian#define NEG_CHAP80LM 43 14944106Sbrian#define NEG_DEFLATE 44 15047858Sbrian#define NEG_DNS 45 15147858Sbrian#define NEG_ENDDISC 46 15247858Sbrian#define NEG_LQR 47 15347858Sbrian#define NEG_PAP 48 15447858Sbrian#define NEG_PPPDDEFLATE 49 15547858Sbrian#define NEG_PRED1 50 15647858Sbrian#define NEG_PROTOCOMP 51 15747858Sbrian#define NEG_SHORTSEQ 52 15847858Sbrian#define NEG_VJCOMP 53 15967910Sbrian#define NEG_MPPE 54 16067910Sbrian#define NEG_CHAP81 55 16136285Sbrian 16278410Sbrianconst char Version[] = "2.3.2"; 16336285Sbrian 16436285Sbrianstatic int ShowCommand(struct cmdargs const *); 16536285Sbrianstatic int TerminalCommand(struct cmdargs const *); 16636285Sbrianstatic int QuitCommand(struct cmdargs const *); 16736285Sbrianstatic int OpenCommand(struct cmdargs const *); 16836285Sbrianstatic int CloseCommand(struct cmdargs const *); 16936285Sbrianstatic int DownCommand(struct cmdargs const *); 17036285Sbrianstatic int SetCommand(struct cmdargs const *); 17136285Sbrianstatic int LinkCommand(struct cmdargs const *); 17236285Sbrianstatic int AddCommand(struct cmdargs const *); 17336285Sbrianstatic int DeleteCommand(struct cmdargs const *); 17436285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 17536934Sbrianstatic int ClearCommand(struct cmdargs const *); 17640561Sbrianstatic int RunListCommand(struct cmdargs const *); 17740561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 17840561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 17940561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 18040679Sbrianstatic int SetProcTitle(struct cmdargs const *); 18150059Sbrian#ifndef NONAT 18258867Sbrianstatic int NatEnable(struct cmdargs const *); 18358867Sbrianstatic int NatOption(struct cmdargs const *); 18431343Sbrian#endif 1856059Samurai 18636285Sbrianstatic const char * 18736285Sbrianshowcx(struct cmdtab const *cmd) 18836285Sbrian{ 18936285Sbrian if (cmd->lauth & LOCAL_CX) 19036285Sbrian return "(c)"; 19136285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 19236285Sbrian return "(o)"; 19336285Sbrian 19436285Sbrian return ""; 19536285Sbrian} 19636285Sbrian 1976059Samuraistatic int 19831343SbrianHelpCommand(struct cmdargs const *arg) 1996059Samurai{ 20028679Sbrian struct cmdtab const *cmd; 20136285Sbrian int n, cmax, dmax, cols, cxlen; 20236285Sbrian const char *cx; 2036059Samurai 20436285Sbrian if (!arg->prompt) { 20536285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 20626516Sbrian return 0; 20736285Sbrian } 20826516Sbrian 20936285Sbrian if (arg->argc > arg->argn) { 21036285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 21136285Sbrian if ((cmd->lauth & arg->prompt->auth) && 21236285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 21336285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 21436285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 21528679Sbrian return 0; 2166059Samurai } 21726516Sbrian return -1; 2186059Samurai } 21936285Sbrian 22031372Sbrian cmax = dmax = 0; 22136285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22236285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22336285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 22431372Sbrian cmax = n; 22531372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 22631372Sbrian dmax = n; 22731372Sbrian } 22831372Sbrian 22931372Sbrian cols = 80 / (dmax + cmax + 3); 2306059Samurai n = 0; 23136285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 23236285Sbrian " (c) = Context required\n"); 23336285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 23436285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 23536285Sbrian cx = showcx(cmd); 23636285Sbrian cxlen = cmax - strlen(cmd->name); 23740482Sbrian if (n % cols != 0) 23840482Sbrian prompt_Printf(arg->prompt, " "); 23940482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 24036285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 24131372Sbrian if (++n % cols == 0) 24236285Sbrian prompt_Printf(arg->prompt, "\n"); 2436059Samurai } 24431372Sbrian if (n % cols != 0) 24536285Sbrian prompt_Printf(arg->prompt, "\n"); 24626516Sbrian 24726516Sbrian return 0; 2486059Samurai} 2496059Samurai 25036285Sbrianstatic int 25163484SbrianIdentCommand(struct cmdargs const *arg) 25263484Sbrian{ 25363484Sbrian int f, pos; 25463484Sbrian 25563484Sbrian *arg->cx->physical->link.lcp.cfg.ident = '\0'; 25663484Sbrian 25763484Sbrian for (pos = 0, f = arg->argn; f < arg->argc; f++) 25863484Sbrian pos += snprintf(arg->cx->physical->link.lcp.cfg.ident + pos, 25963484Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident - pos, "%s%s", 26063484Sbrian f == arg->argn ? "" : " ", arg->argv[f]); 26163484Sbrian 26263484Sbrian return 0; 26363484Sbrian} 26463484Sbrian 26563484Sbrianstatic int 26663484SbrianSendIdentification(struct cmdargs const *arg) 26763484Sbrian{ 26863484Sbrian if (arg->cx->state < DATALINK_LCP) { 26963484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 27063484Sbrian return 2; 27163484Sbrian } 27263484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 27363484Sbrian} 27463484Sbrian 27563484Sbrianstatic int 27636285SbrianCloneCommand(struct cmdargs const *arg) 2776059Samurai{ 27836285Sbrian char namelist[LINE_LEN]; 27936285Sbrian char *name; 28036285Sbrian int f; 2816059Samurai 28236285Sbrian if (arg->argc == arg->argn) 28336285Sbrian return -1; 28436285Sbrian 28536285Sbrian namelist[sizeof namelist - 1] = '\0'; 28636285Sbrian for (f = arg->argn; f < arg->argc; f++) { 28736285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 28836285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 28936285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2906059Samurai } 29136285Sbrian 29236285Sbrian return 0; 2936059Samurai} 2946059Samurai 2956059Samuraistatic int 29636285SbrianRemoveCommand(struct cmdargs const *arg) 2976059Samurai{ 29836285Sbrian if (arg->argc != arg->argn) 29936285Sbrian return -1; 30011336Samurai 30136285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 30236285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 30336285Sbrian return 2; 3046059Samurai } 30526516Sbrian 30636285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 30736285Sbrian return 0; 30836285Sbrian} 30932711Sbrian 31036285Sbrianstatic int 31136285SbrianRenameCommand(struct cmdargs const *arg) 31236285Sbrian{ 31336285Sbrian if (arg->argc != arg->argn + 1) 31436285Sbrian return -1; 31531121Sbrian 31636285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 31736285Sbrian return 0; 31836285Sbrian 31936285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 32036285Sbrian arg->cx->name, arg->argv[arg->argn]); 32136285Sbrian return 1; 32236285Sbrian} 32336285Sbrian 32436285Sbrianint 32536285SbrianLoadCommand(struct cmdargs const *arg) 32636285Sbrian{ 32740797Sbrian const char *err; 32840797Sbrian int n, mode; 32936285Sbrian 33040797Sbrian mode = arg->bundle->phys_type.all; 33136285Sbrian 33240797Sbrian if (arg->argn < arg->argc) { 33340797Sbrian for (n = arg->argn; n < arg->argc; n++) 33440797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 33540797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 33640797Sbrian return 1; 33740797Sbrian } 33840797Sbrian 33940797Sbrian for (n = arg->argn; n < arg->argc; n++) { 34040797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34140797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 34240797Sbrian } 34340797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34440797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 34540797Sbrian log_Printf(LogWARN, "default: %s\n", err); 34636285Sbrian return 1; 34736285Sbrian } else { 34840797Sbrian bundle_SetLabel(arg->bundle, "default"); 34940797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 35040797Sbrian bundle_SetLabel(arg->bundle, "default"); 35136285Sbrian } 35240797Sbrian 35326516Sbrian return 0; 3546059Samurai} 3556059Samurai 35636285Sbrianint 35736285SbrianSaveCommand(struct cmdargs const *arg) 35836285Sbrian{ 35936285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 36036285Sbrian return 1; 36136285Sbrian} 36236285Sbrian 36310528Samuraistatic int 36436285SbrianDialCommand(struct cmdargs const *arg) 36528536Sbrian{ 36636285Sbrian int res; 36736285Sbrian 36836465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 36936465Sbrian || (!arg->cx && 37036928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 37136285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 37236285Sbrian " interactive links\n"); 37336285Sbrian return 1; 37434536Sbrian } 37536285Sbrian 37636285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 37736285Sbrian return res; 37836285Sbrian 37937993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 38036285Sbrian 38136285Sbrian return 0; 38228536Sbrian} 38328536Sbrian 38438628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 38538628Sbrian 38638628Sbrianstatic char * 38738628Sbrianstrstrword(char *big, const char *little) 38838628Sbrian{ 38938628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 39038628Sbrian char *pos; 39138628Sbrian int len; 39238628Sbrian 39338628Sbrian pos = big; 39438628Sbrian len = strlen(little); 39538628Sbrian 39638628Sbrian while ((pos = strstr(pos, little)) != NULL) 39747865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 39847865Sbrian pos++; 39947865Sbrian else if (pos != big && pos[-1] == '\\') 40047865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 40147865Sbrian else 40238628Sbrian break; 40338628Sbrian 40438628Sbrian return pos; 40538628Sbrian} 40638628Sbrian 40738628Sbrianstatic char * 40838628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 40938628Sbrian{ 41038628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 41138628Sbrian char *word, *ntgt; 41238628Sbrian int ltgt, loldstr, lnewstr, pos; 41338628Sbrian 41438628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 41538628Sbrian return tgt; 41638628Sbrian 41738628Sbrian ltgt = strlen(tgt) + 1; 41838628Sbrian loldstr = strlen(oldstr); 41938628Sbrian lnewstr = strlen(newstr); 42038628Sbrian do { 42138628Sbrian pos = word - tgt; 42238628Sbrian if (loldstr > lnewstr) 42338628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 42438628Sbrian if (loldstr != lnewstr) { 42538628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 42638628Sbrian if (ntgt == NULL) 42738628Sbrian break; /* Oh wonderful ! */ 42838628Sbrian word = ntgt + pos; 42938628Sbrian tgt = ntgt; 43038628Sbrian } 43138628Sbrian if (lnewstr > loldstr) 43238628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 43338628Sbrian bcopy(newstr, word, lnewstr); 43438628Sbrian } while ((word = strstrword(word, oldstr))); 43538628Sbrian 43638628Sbrian return tgt; 43738628Sbrian} 43838628Sbrian 43943888Sbrianvoid 44043888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 44147849Sbrian struct bundle *bundle, int inc0, pid_t pid) 44238628Sbrian{ 44338628Sbrian int arg; 44447849Sbrian char pidstr[12]; 44538628Sbrian 44641755Sbrian if (inc0) 44741755Sbrian arg = 0; /* Start at arg 0 */ 44841755Sbrian else { 44941755Sbrian nargv[0] = strdup(oargv[0]); 45041755Sbrian arg = 1; 45141755Sbrian } 45247849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 45341755Sbrian for (; arg < argc; arg++) { 45438629Sbrian nargv[arg] = strdup(oargv[arg]); 45538629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 45638628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 45738629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 45840561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 45938628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 46038629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 46138629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 46238629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 46338629Sbrian bundle->ncp.mp.peer.enddisc.address, 46438629Sbrian bundle->ncp.mp.peer.enddisc.len)); 46538629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 46638629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 46738629Sbrian bundle->ncp.mp.cfg.enddisc.address, 46838629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 46947849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 47038629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 47158044Sbrian nargv[arg] = subst(nargv[arg], "DNS0", 47258044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); 47358044Sbrian nargv[arg] = subst(nargv[arg], "DNS1", 47458044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); 47563484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 47663484Sbrian nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 47738628Sbrian } 47838628Sbrian nargv[arg] = NULL; 47938628Sbrian} 48038628Sbrian 48128536Sbrianstatic int 48231343SbrianShellCommand(struct cmdargs const *arg, int bg) 48310528Samurai{ 48410528Samurai const char *shell; 48547849Sbrian pid_t shpid, pid; 48620813Sjkh 48718856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 48826911Sbrian /* we're only allowed to shell when we run ppp interactively */ 48936285Sbrian if (arg->prompt && arg->prompt->owner) { 49036285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 49126516Sbrian return 1; 49210528Samurai } 49326911Sbrian#endif 49428679Sbrian 49536285Sbrian if (arg->argc == arg->argn) { 49636285Sbrian if (!arg->prompt) { 49736285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 49836285Sbrian " a config file\n"); 49928381Sbrian return 1; 50036285Sbrian } else if (arg->prompt->owner) { 50136285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 50236285Sbrian " a socket connection\n"); 50336285Sbrian return 1; 50428381Sbrian } else if (bg) { 50536285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 50628679Sbrian " the foreground mode\n"); 50728381Sbrian return 1; 50828381Sbrian } 50934536Sbrian } 51034536Sbrian 51147849Sbrian pid = getpid(); 51228679Sbrian if ((shpid = fork()) == 0) { 51336285Sbrian int i, fd; 51418531Sbde 51536285Sbrian if ((shell = getenv("SHELL")) == 0) 51636285Sbrian shell = _PATH_BSHELL; 51732017Sbrian 51836285Sbrian timer_TermService(); 51936285Sbrian 52036285Sbrian if (arg->prompt) 52136285Sbrian fd = arg->prompt->fd_out; 52236285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 52336285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 52436285Sbrian _PATH_DEVNULL, strerror(errno)); 52528679Sbrian exit(1); 52628679Sbrian } 52749976Sbrian dup2(fd, STDIN_FILENO); 52849976Sbrian dup2(fd, STDOUT_FILENO); 52949976Sbrian dup2(fd, STDERR_FILENO); 53049976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 53149976Sbrian fcntl(i, F_SETFD, 1); 53226516Sbrian 53364802Sbrian#ifndef NOSUID 53455252Sbrian setuid(ID0realuid()); 53564802Sbrian#endif 53636285Sbrian if (arg->argc > arg->argn) { 53728679Sbrian /* substitute pseudo args */ 53838628Sbrian char *argv[MAXARGS]; 53938628Sbrian int argc = arg->argc - arg->argn; 54038628Sbrian 54138628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 54238628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 54338628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 54431343Sbrian } 54547849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 54628679Sbrian if (bg) { 54728679Sbrian pid_t p; 54810528Samurai 54928679Sbrian p = getpid(); 55028679Sbrian if (daemon(1, 1) == -1) { 55136832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 55228679Sbrian exit(1); 55328679Sbrian } 55436285Sbrian } else if (arg->prompt) 55536285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 55631343Sbrian execvp(argv[0], argv); 55730316Sbrian } else { 55836285Sbrian if (arg->prompt) 55932017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 56036285Sbrian prompt_TtyOldMode(arg->prompt); 56179450Sbrian execl(shell, shell, (char *)NULL); 56230316Sbrian } 56320813Sjkh 56440665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 56540665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 56640665Sbrian strerror(errno)); 56749976Sbrian _exit(255); 56810528Samurai } 56936285Sbrian 57036285Sbrian if (shpid == (pid_t) - 1) 57136285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 57236285Sbrian else { 57310528Samurai int status; 57431343Sbrian waitpid(shpid, &status, 0); 57510528Samurai } 57620813Sjkh 57736285Sbrian if (arg->prompt && !arg->prompt->owner) 57836285Sbrian prompt_TtyCommandMode(arg->prompt); 57920813Sjkh 58036285Sbrian return 0; 58110528Samurai} 58210528Samurai 58331343Sbrianstatic int 58431343SbrianBgShellCommand(struct cmdargs const *arg) 58531343Sbrian{ 58636285Sbrian if (arg->argc == arg->argn) 58731343Sbrian return -1; 58831343Sbrian return ShellCommand(arg, 1); 58931343Sbrian} 59031343Sbrian 59131343Sbrianstatic int 59231343SbrianFgShellCommand(struct cmdargs const *arg) 59331343Sbrian{ 59431343Sbrian return ShellCommand(arg, 0); 59531343Sbrian} 59631343Sbrian 59758044Sbrianstatic int 59858044SbrianResolvCommand(struct cmdargs const *arg) 59958044Sbrian{ 60058044Sbrian if (arg->argc == arg->argn + 1) { 60158044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 60258044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 60358044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 60458044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 60558044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 60658044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 60758044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 60858044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 60958044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 61058044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 61158044Sbrian else 61258044Sbrian return -1; 61358044Sbrian 61458044Sbrian return 0; 61558044Sbrian } 61658044Sbrian 61758044Sbrian return -1; 61858044Sbrian} 61958044Sbrian 62050059Sbrian#ifndef NONAT 62158867Sbrianstatic struct cmdtab const NatCommands[] = 62240561Sbrian{ 62350059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 62450059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 62558867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 62650059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 62740561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 62858867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 62950059Sbrian "enable NAT", "nat enable yes|no"}, 63058867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 63150059Sbrian "log NAT link creation", "nat log yes|no", 63240561Sbrian (const void *) PKT_ALIAS_LOG}, 63350059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 63450059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 63579433Sbrian {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 63679433Sbrian "nat proto proto localIP [publicIP [remoteIP]]"}, 63750059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 63850059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 63981033Sbrian#ifndef NO_FW_PUNCH 64081033Sbrian {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 64181033Sbrian "firewall control", "nat punch_fw [base count]"}, 64281033Sbrian#endif 64358867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 64450059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 64540561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 64658867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 64758867Sbrian "Default address for incoming connections", "nat target addr" }, 64858867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 64950059Sbrian "translate unregistered (private) IP address space only", 65050059Sbrian "nat unregistered_only yes|no", 65140561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 65258867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 65350059Sbrian "allocate host sockets", "nat use_sockets yes|no", 65440561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 65540561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 65658867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 65740561Sbrian {NULL, NULL, NULL}, 65840561Sbrian}; 65940561Sbrian#endif 66040561Sbrian 66140561Sbrianstatic struct cmdtab const AllowCommands[] = { 66240561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 66340561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 66440561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 66540561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 66640561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 66740561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 66840561Sbrian {NULL, NULL, NULL}, 66940561Sbrian}; 67040561Sbrian 67140561Sbrianstatic struct cmdtab const IfaceCommands[] = 67240561Sbrian{ 67340561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 67440561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 67540561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 67640561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 67740561Sbrian (void *)1}, 67840561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 67940561Sbrian "Clear iface address(es)", "iface clear"}, 68040561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 68140561Sbrian "Delete iface address", "iface delete addr", NULL}, 68240561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 68340561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 68440561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 68540561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 68640561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 68740561Sbrian "Show iface address(es)", "iface show"}, 68840561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 68950059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 69040561Sbrian {NULL, NULL, NULL}, 69140561Sbrian}; 69240561Sbrian 69330715Sbrianstatic struct cmdtab const Commands[] = { 69436285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 69528679Sbrian "accept option request", "accept option .."}, 69628679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 69732109Sbrian "add route", "add dest mask gateway", NULL}, 69836285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 69932109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 70040561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 70140561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 70228679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 70331372Sbrian "Run a background command", "[!]bg command"}, 70436934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70546686Sbrian "Clear throughput statistics", 70646686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 70736285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 70836285Sbrian "Clone a link", "clone newname..."}, 70936285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71036285Sbrian "Close an FSM", "close [lcp|ccp]"}, 71128679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 71232109Sbrian "delete route", "delete dest", NULL}, 71336285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 71432109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 71536285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71628679Sbrian "Deny option request", "deny option .."}, 71736285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71840797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 71936285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 72028679Sbrian "Disable option", "disable option .."}, 72136285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 72246686Sbrian "Generate a down event", "down [ccp|lcp]"}, 72336285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 72428679Sbrian "Enable option", "enable option .."}, 72563484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 72663484Sbrian "Set the link identity", "ident text..."}, 72740561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 72840561Sbrian "interface control", "iface option ...", IfaceCommands}, 72936285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 73036285Sbrian "Link specific commands", "link name command ..."}, 73137008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 73240797Sbrian "Load settings", "load [system ...]"}, 73350059Sbrian#ifndef NONAT 73450059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 73558867Sbrian "NAT control", "nat option yes|no", NatCommands}, 73650059Sbrian#endif 73736285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 73837955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 73936285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 74036285Sbrian "Password for manipulation", "passwd LocalPassword"}, 74136285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 74236285Sbrian "Quit PPP program", "quit|bye [all]"}, 74336285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 74436285Sbrian "Remove a link", "remove"}, 74536285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 74636285Sbrian "Rename a link", "rename name"}, 74758044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 74858044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 74928679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 75028679Sbrian "Save settings", "save"}, 75163484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 75263484Sbrian "Transmit the link identity", "sendident"}, 75336285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 75428679Sbrian "Set parameters", "set[up] var value"}, 75528679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 75628679Sbrian "Run a subshell", "shell|! [sh command]"}, 75736285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 75831372Sbrian "Show status and stats", "show var"}, 75936285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 76031372Sbrian "Enter terminal mode", "term"}, 76128679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 76231343Sbrian "Display this message", "help|? [command]", Commands}, 76328679Sbrian {NULL, NULL, NULL}, 7646059Samurai}; 7656059Samurai 76628536Sbrianstatic int 76731343SbrianShowEscape(struct cmdargs const *arg) 7686059Samurai{ 76936285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 77036285Sbrian int code, bit; 77136285Sbrian const char *sep = ""; 7726059Samurai 77326516Sbrian for (code = 0; code < 32; code++) 77436285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 77528679Sbrian for (bit = 0; bit < 8; bit++) 77636285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 77736285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 77836285Sbrian sep = ", "; 77936285Sbrian } 78036285Sbrian prompt_Printf(arg->prompt, "\n"); 7816059Samurai } 78231077Sbrian return 0; 7836059Samurai} 7846059Samurai 78528679Sbrianstatic int 78636285SbrianShowTimerList(struct cmdargs const *arg) 7876059Samurai{ 78836285Sbrian timer_Show(0, arg->prompt); 78931077Sbrian return 0; 7906059Samurai} 7916059Samurai 79228679Sbrianstatic int 79331343SbrianShowStopped(struct cmdargs const *arg) 79428327Sbrian{ 79536285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 79636285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 79736285Sbrian prompt_Printf(arg->prompt, "Disabled"); 79828327Sbrian else 79936285Sbrian prompt_Printf(arg->prompt, "%ld secs", 80036285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 80128461Sbrian 80236285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 80336285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 80436285Sbrian prompt_Printf(arg->prompt, "Disabled"); 80528461Sbrian else 80636285Sbrian prompt_Printf(arg->prompt, "%ld secs", 80736285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 80828461Sbrian 80936285Sbrian prompt_Printf(arg->prompt, "\n"); 81028461Sbrian 81131077Sbrian return 0; 81228327Sbrian} 81328327Sbrian 81428679Sbrianstatic int 81531343SbrianShowVersion(struct cmdargs const *arg) 8166059Samurai{ 81751026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 81831077Sbrian return 0; 8196059Samurai} 8206059Samurai 82128679Sbrianstatic int 82236285SbrianShowProtocolStats(struct cmdargs const *arg) 82326326Sbrian{ 82436285Sbrian struct link *l = command_ChooseLink(arg); 82526326Sbrian 82636285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 82736285Sbrian link_ReportProtocolStatus(l, arg->prompt); 82831077Sbrian return 0; 82926326Sbrian} 83026326Sbrian 83130715Sbrianstatic struct cmdtab const ShowCommands[] = { 83236285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 83336285Sbrian "bundle details", "show bundle"}, 83436285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 83536285Sbrian "CCP status", "show cpp"}, 83636285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 83736285Sbrian "VJ compression stats", "show compress"}, 83836285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 83936285Sbrian "escape characters", "show escape"}, 84036285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 84136285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 84236285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 84336285Sbrian "HDLC errors", "show hdlc"}, 84440561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 84540561Sbrian "Interface status", "show iface"}, 84636285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 84736285Sbrian "IPCP status", "show ipcp"}, 84847211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 84947211Sbrian "Protocol layers", "show layers"}, 85036285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 85136285Sbrian "LCP status", "show lcp"}, 85236285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 85336285Sbrian "(high-level) link info", "show link"}, 85436285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 85536285Sbrian "available link names", "show links"}, 85636285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 85736285Sbrian "log levels", "show log"}, 85836285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 85936285Sbrian "mbuf allocations", "show mem"}, 86046686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 86146686Sbrian "(low-level) link info", "show physical"}, 86236285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 86336285Sbrian "multilink setup", "show mp"}, 86436285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 86536285Sbrian "protocol summary", "show proto"}, 86636285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 86736285Sbrian "routing table", "show route"}, 86836285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 86936285Sbrian "STOPPED timeout", "show stopped"}, 87036285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 87136285Sbrian "alarm timers", "show timers"}, 87228679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 87336285Sbrian "version string", "show version"}, 87436285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 87536285Sbrian "client list", "show who"}, 87628679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 87731343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 87828679Sbrian {NULL, NULL, NULL}, 8796059Samurai}; 8806059Samurai 88130715Sbrianstatic struct cmdtab const * 88231343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 8836059Samurai{ 88426516Sbrian int nmatch; 88526516Sbrian int len; 88628679Sbrian struct cmdtab const *found; 8876059Samurai 88826516Sbrian found = NULL; 88926516Sbrian len = strlen(str); 89026516Sbrian nmatch = 0; 8916059Samurai while (cmds->func) { 89225566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 89326516Sbrian if (cmds->name[len] == '\0') { 89428679Sbrian *pmatch = 1; 89528679Sbrian return cmds; 89626516Sbrian } 8976059Samurai nmatch++; 8986059Samurai found = cmds; 89928679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 90026516Sbrian if (cmds->alias[len] == '\0') { 90128679Sbrian *pmatch = 1; 90228679Sbrian return cmds; 90326516Sbrian } 9046059Samurai nmatch++; 9056059Samurai found = cmds; 9066059Samurai } 9076059Samurai cmds++; 9086059Samurai } 9096059Samurai *pmatch = nmatch; 91026516Sbrian return found; 9116059Samurai} 9126059Samurai 91336285Sbrianstatic const char * 91436285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 91536285Sbrian{ 91636285Sbrian int f, tlen, len; 91736285Sbrian 91836285Sbrian tlen = 0; 91936285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 92036285Sbrian if (f) 92136285Sbrian tgt[tlen++] = ' '; 92236285Sbrian len = strlen(argv[f]); 92336285Sbrian if (len > sz - tlen - 1) 92436285Sbrian len = sz - tlen - 1; 92536285Sbrian strncpy(tgt+tlen, argv[f], len); 92636285Sbrian tlen += len; 92736285Sbrian } 92836285Sbrian tgt[tlen] = '\0'; 92936285Sbrian return tgt; 93036285Sbrian} 93136285Sbrian 93230715Sbrianstatic int 93336285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 93436285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 9356059Samurai{ 93628679Sbrian struct cmdtab const *cmd; 9376059Samurai int val = 1; 9386059Samurai int nmatch; 93931343Sbrian struct cmdargs arg; 94036285Sbrian char prefix[100]; 9416059Samurai 94236285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 9436059Samurai if (nmatch > 1) 94436285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 94536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 94636285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 94736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 94836285Sbrian /* We've got no context, but we require it */ 94936285Sbrian cx = bundle2datalink(bundle, NULL); 95036285Sbrian 95136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 95236285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 95336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 95436285Sbrian else { 95536285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 95636285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 95736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 95836285Sbrian cx = NULL; 95936285Sbrian } 96036285Sbrian arg.cmdtab = cmds; 96136285Sbrian arg.cmd = cmd; 96236285Sbrian arg.argc = argc; 96336285Sbrian arg.argn = argn+1; 96436285Sbrian arg.argv = argv; 96536285Sbrian arg.bundle = bundle; 96636285Sbrian arg.cx = cx; 96736285Sbrian arg.prompt = prompt; 96836285Sbrian val = (*cmd->func) (&arg); 96936285Sbrian } 97031343Sbrian } else 97136285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 97236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 97326516Sbrian 97426516Sbrian if (val == -1) 97536285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 97628679Sbrian else if (val) 97736285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 97836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 97926516Sbrian 98026516Sbrian return val; 9816059Samurai} 9826059Samurai 98337009Sbrianint 98458045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 98558045Sbrian{ 98658045Sbrian char buff2[LINE_LEN-offset]; 98758045Sbrian 98858045Sbrian InterpretArg(buff, buff2); 98958045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 99058045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 99158045Sbrian 99258045Sbrian return command_Interpret(buff, nb, argv); 99358045Sbrian} 99458045Sbrian 99558045Sbrianint 99637009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 9976059Samurai{ 9986059Samurai char *cp; 9996059Samurai 10006059Samurai if (nb > 0) { 10016059Samurai cp = buff + strcspn(buff, "\r\n"); 10026059Samurai if (cp) 10036059Samurai *cp = '\0'; 100455145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 100537009Sbrian } 100637009Sbrian return 0; 100731121Sbrian} 10086059Samurai 100931822Sbrianstatic int 101031822Sbrianarghidden(int argc, char const *const *argv, int n) 101131822Sbrian{ 101231822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 101331828Sbrian 101431828Sbrian /* set authkey xxxxx */ 101531828Sbrian /* set key xxxxx */ 101631822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 101731822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 101831822Sbrian return 1; 101931822Sbrian 102031828Sbrian /* passwd xxxxx */ 102131828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 102231828Sbrian return 1; 102331828Sbrian 102436285Sbrian /* set server port xxxxx .... */ 102536285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 102636285Sbrian !strncasecmp(argv[1], "se", 2)) 102736285Sbrian return 1; 102836285Sbrian 102931822Sbrian return 0; 103031822Sbrian} 103131822Sbrian 103231121Sbrianvoid 103336285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 103437008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 103531121Sbrian{ 103631156Sbrian if (argc > 0) { 103736285Sbrian if (log_IsKept(LogCOMMAND)) { 103847844Sbrian char buf[LINE_LEN]; 103931156Sbrian int f, n; 104031156Sbrian 104131156Sbrian if (label) { 104231962Sbrian strncpy(buf, label, sizeof buf - 3); 104331962Sbrian buf[sizeof buf - 3] = '\0'; 104431156Sbrian strcat(buf, ": "); 104547844Sbrian n = strlen(buf); 104647844Sbrian } else { 104747844Sbrian *buf = '\0'; 104847844Sbrian n = 0; 104931156Sbrian } 105047844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 105147844Sbrian 105231156Sbrian for (f = 0; f < argc; f++) { 105331962Sbrian if (n < sizeof buf - 1 && f) 105431156Sbrian buf[n++] = ' '; 105531822Sbrian if (arghidden(argc, argv, f)) 105636285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 105731822Sbrian else 105831962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 105931156Sbrian n += strlen(buf+n); 106031156Sbrian } 106136285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 106231156Sbrian } 106337008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 106431156Sbrian } 10656059Samurai} 10666059Samurai 106754914Sbrianint 106836285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 106936285Sbrian const char *label) 107031121Sbrian{ 107131121Sbrian int argc; 107237009Sbrian char *argv[MAXARGS]; 107331121Sbrian 107458045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 107554914Sbrian return 0; 107654914Sbrian 107737008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 107854914Sbrian return 1; 107931121Sbrian} 108031121Sbrian 10816059Samuraistatic int 108231343SbrianShowCommand(struct cmdargs const *arg) 10836059Samurai{ 108436285Sbrian if (!arg->prompt) 108536285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 108636285Sbrian else if (arg->argc > arg->argn) 108736285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 108836285Sbrian arg->prompt, arg->cx); 10896059Samurai else 109036285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 109126516Sbrian 109226516Sbrian return 0; 10936059Samurai} 10946059Samurai 10956059Samuraistatic int 109631343SbrianTerminalCommand(struct cmdargs const *arg) 10976059Samurai{ 109836285Sbrian if (!arg->prompt) { 109936285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 110026516Sbrian return 1; 11016059Samurai } 110236285Sbrian 110336285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 110436285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 110536285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 110636285Sbrian return 1; 11076059Samurai } 110836285Sbrian 110936285Sbrian datalink_Up(arg->cx, 0, 0); 111036285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 111136285Sbrian return 0; 11126059Samurai} 11136059Samurai 11146059Samuraistatic int 111531343SbrianQuitCommand(struct cmdargs const *arg) 11166059Samurai{ 111736285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 111836285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 111936285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 112036285Sbrian Cleanup(EX_NORMAL); 112136285Sbrian if (arg->prompt) 112236285Sbrian prompt_Destroy(arg->prompt, 1); 112326516Sbrian 112426516Sbrian return 0; 11256059Samurai} 11266059Samurai 11276059Samuraistatic int 112836285SbrianOpenCommand(struct cmdargs const *arg) 11296059Samurai{ 113037160Sbrian if (arg->argc == arg->argn) 113137993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 113237160Sbrian else if (arg->argc == arg->argn + 1) { 113337160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 113437385Sbrian struct datalink *cx = arg->cx ? 113537385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 113637385Sbrian if (cx) { 113737385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 113837385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 113937160Sbrian else 114037993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 114137160Sbrian } else 114237160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 114337160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 114437160Sbrian struct fsm *fp; 11456059Samurai 114637210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 114737160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 114837160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 114937160Sbrian else if (fp->state == ST_OPENED) 115037160Sbrian fsm_Reopen(fp); 115137160Sbrian else { 115237160Sbrian fp->open_mode = 0; /* Not passive any more */ 115337160Sbrian if (fp->state == ST_STOPPED) { 115437160Sbrian fsm_Down(fp); 115537160Sbrian fsm_Up(fp); 115637160Sbrian } else { 115737160Sbrian fsm_Up(fp); 115837160Sbrian fsm_Open(fp); 115937160Sbrian } 116036285Sbrian } 116137160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 116237160Sbrian if (arg->cx) 116337160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 116437160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 116537160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 116637160Sbrian else 116737993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 116837160Sbrian } else 116937160Sbrian return -1; 117036285Sbrian } else 117136285Sbrian return -1; 117236285Sbrian 117326516Sbrian return 0; 11746059Samurai} 11756059Samurai 117625067Sbrianstatic int 117736285SbrianCloseCommand(struct cmdargs const *arg) 11786059Samurai{ 117937007Sbrian if (arg->argc == arg->argn) 118037007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 118137007Sbrian else if (arg->argc == arg->argn + 1) { 118237007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 118337007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 118437007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 118537007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 118637007Sbrian struct fsm *fp; 11876059Samurai 118837210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 118937007Sbrian if (fp->state == ST_OPENED) { 119037007Sbrian fsm_Close(fp); 119137007Sbrian if (arg->argv[arg->argn][3] == '!') 119237007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 119337007Sbrian else 119437007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 119537007Sbrian } 119637007Sbrian } else 119736285Sbrian return -1; 119836285Sbrian } else 119936285Sbrian return -1; 120036285Sbrian 120136285Sbrian return 0; 12026059Samurai} 12036059Samurai 120425067Sbrianstatic int 120536285SbrianDownCommand(struct cmdargs const *arg) 120611336Samurai{ 120737018Sbrian if (arg->argc == arg->argn) { 120837018Sbrian if (arg->cx) 120937018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 121037018Sbrian else 121137018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 121237018Sbrian } else if (arg->argc == arg->argn + 1) { 121337018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 121437018Sbrian if (arg->cx) 121537018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 121637018Sbrian else 121737018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 121837018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 121937018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 122037018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 122137060Sbrian fsm2initial(fp); 122237018Sbrian } else 122337018Sbrian return -1; 122436285Sbrian } else 122536285Sbrian return -1; 122636285Sbrian 122736285Sbrian return 0; 122825067Sbrian} 122925067Sbrian 123025067Sbrianstatic int 123136285SbrianSetModemSpeed(struct cmdargs const *arg) 123225067Sbrian{ 123336285Sbrian long speed; 123436285Sbrian char *end; 123511336Samurai 123636285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 123736285Sbrian if (arg->argc > arg->argn+1) { 123854917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 123936285Sbrian return -1; 124011336Samurai } 124136285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 124236285Sbrian physical_SetSync(arg->cx->physical); 124336285Sbrian return 0; 124436285Sbrian } 124536285Sbrian end = NULL; 124636285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 124736285Sbrian if (*end) { 124836285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 124936285Sbrian arg->argv[arg->argn]); 125036285Sbrian return -1; 125136285Sbrian } 125236285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 125336285Sbrian return 0; 125436285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 125536285Sbrian } else 125636285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 125724939Sbrian 125826516Sbrian return -1; 125911336Samurai} 126011336Samurai 126125067Sbrianstatic int 126231343SbrianSetStoppedTimeout(struct cmdargs const *arg) 126328327Sbrian{ 126436285Sbrian struct link *l = &arg->cx->physical->link; 126536285Sbrian 126636285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 126736285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 126836285Sbrian if (arg->argc <= arg->argn+2) { 126936285Sbrian if (arg->argc > arg->argn) { 127036285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 127136285Sbrian if (arg->argc > arg->argn+1) 127236285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 127328461Sbrian } 127428327Sbrian return 0; 127528327Sbrian } 127628327Sbrian return -1; 127728327Sbrian} 127828327Sbrian 127928327Sbrianstatic int 128031343SbrianSetServer(struct cmdargs const *arg) 128126940Sbrian{ 128226940Sbrian int res = -1; 128326940Sbrian 128436285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 128531081Sbrian const char *port, *passwd, *mask; 128653125Sbrian int mlen; 128731081Sbrian 128831081Sbrian /* What's what ? */ 128936285Sbrian port = arg->argv[arg->argn]; 129036285Sbrian if (arg->argc == arg->argn + 2) { 129136285Sbrian passwd = arg->argv[arg->argn+1]; 129236285Sbrian mask = NULL; 129336285Sbrian } else if (arg->argc == arg->argn + 3) { 129436285Sbrian passwd = arg->argv[arg->argn+1]; 129536285Sbrian mask = arg->argv[arg->argn+2]; 129653125Sbrian mlen = strlen(mask); 129753125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 129853125Sbrian (mlen == 4 && *mask != '0')) { 129953125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 130053125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 130131081Sbrian return -1; 130253125Sbrian } 130371764Sbrian } else if (arg->argc != arg->argn + 1) 130471764Sbrian return -1; 130571764Sbrian else if (strcasecmp(port, "none") == 0) { 130671657Sbrian if (server_Clear(arg->bundle)) 130771657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 130871657Sbrian return 0; 130971657Sbrian } else if (strcasecmp(port, "open") == 0) { 131071657Sbrian switch (server_Reopen(arg->bundle)) { 131171657Sbrian case SERVER_OK: 131271657Sbrian return 0; 131371657Sbrian case SERVER_FAILED: 131471764Sbrian log_Printf(LogWARN, "Failed to reopen server port\n"); 131571657Sbrian return 1; 131671657Sbrian case SERVER_UNSET: 131771764Sbrian log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 131871657Sbrian return 1; 131971657Sbrian default: 132071657Sbrian break; 132171657Sbrian } 132271657Sbrian return -1; 132371657Sbrian } else if (strcasecmp(port, "closed") == 0) { 132436285Sbrian if (server_Close(arg->bundle)) 132571657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 132671657Sbrian else 132771657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 132871657Sbrian 132936285Sbrian return 0; 133031081Sbrian } else 133136285Sbrian return -1; 133231081Sbrian 133371657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 133471657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 133531081Sbrian 133636285Sbrian if (*port == '/') { 133731081Sbrian mode_t imask; 133836285Sbrian char *ptr, name[LINE_LEN + 12]; 133928679Sbrian 134053125Sbrian if (mask == NULL) 134131081Sbrian imask = (mode_t)-1; 134253125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 134353125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 134436285Sbrian 134536285Sbrian ptr = strstr(port, "%d"); 134636285Sbrian if (ptr) { 134736285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 134837210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 134936285Sbrian port = name; 135036285Sbrian } 135136285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 135227346Sbrian } else { 135336285Sbrian int iport, add = 0; 135428679Sbrian 135531081Sbrian if (mask != NULL) 135631081Sbrian return -1; 135728679Sbrian 135836285Sbrian if (*port == '+') { 135936285Sbrian port++; 136036285Sbrian add = 1; 136136285Sbrian } 136231081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 136331081Sbrian struct servent *s; 136431081Sbrian 136531081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 136631081Sbrian iport = 0; 136736285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 136828679Sbrian } else 136931081Sbrian iport = ntohs(s->s_port); 137027346Sbrian } else 137131081Sbrian iport = atoi(port); 137236285Sbrian 137336285Sbrian if (iport) { 137436285Sbrian if (add) 137536285Sbrian iport += arg->bundle->unit; 137636285Sbrian res = server_TcpOpen(arg->bundle, iport); 137736285Sbrian } else 137836285Sbrian res = -1; 137927346Sbrian } 138031081Sbrian } 138126940Sbrian 138226940Sbrian return res; 138326940Sbrian} 138426940Sbrian 138526940Sbrianstatic int 138631343SbrianSetEscape(struct cmdargs const *arg) 13876059Samurai{ 13886059Samurai int code; 138936285Sbrian int argc = arg->argc - arg->argn; 139036285Sbrian char const *const *argv = arg->argv + arg->argn; 13916059Samurai 13926059Samurai for (code = 0; code < 33; code++) 139336285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 139431343Sbrian 13956059Samurai while (argc-- > 0) { 13966059Samurai sscanf(*argv++, "%x", &code); 13976059Samurai code &= 0xff; 139836285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 139936285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 14006059Samurai } 140126516Sbrian return 0; 14026059Samurai} 14036059Samurai 14046059Samuraistatic int 140531343SbrianSetInterfaceAddr(struct cmdargs const *arg) 14066059Samurai{ 140736285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 140832267Sbrian const char *hisaddr; 140932267Sbrian 141040561Sbrian if (arg->argc > arg->argn + 4) 141140561Sbrian return -1; 141240561Sbrian 141332267Sbrian hisaddr = NULL; 141444874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 141544874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 141636285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 141736285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 141836285Sbrian iplist_reset(&ipcp->cfg.peer_list); 141928394Sbrian 142036285Sbrian if (arg->argc > arg->argn) { 142143313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 142236285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 142336285Sbrian &ipcp->cfg.my_range.width)) 142428679Sbrian return 1; 142536285Sbrian if (arg->argc > arg->argn+1) { 142636285Sbrian hisaddr = arg->argv[arg->argn+1]; 142736285Sbrian if (arg->argc > arg->argn+2) { 142844455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 142936285Sbrian if (arg->argc > arg->argn+3) { 143036285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 143136285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 14329440Samurai } 14336059Samurai } 14346059Samurai } 14356059Samurai } 143628394Sbrian 143740561Sbrian /* 0.0.0.0 means any address (0 bits) */ 143836285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 143936285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 144036285Sbrian ipcp->cfg.my_range.width = 0; 14416059Samurai } 144236285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 144347648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 144436285Sbrian 144536285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 144636928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 144732267Sbrian return 4; 144831121Sbrian 144926516Sbrian return 0; 14506059Samurai} 14516059Samurai 145218752Sjkhstatic int 145344305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 145444305Sbrian u_int *maxtrm, int def) 145544305Sbrian{ 145644305Sbrian if (argc == 0) { 145744305Sbrian *timeout = DEF_FSMRETRY; 145844305Sbrian *maxreq = def; 145944305Sbrian if (maxtrm != NULL) 146044305Sbrian *maxtrm = def; 146144305Sbrian } else { 146244305Sbrian long l = atol(argv[0]); 146344305Sbrian 146444305Sbrian if (l < MIN_FSMRETRY) { 146544305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 146644305Sbrian l, MIN_FSMRETRY); 146744305Sbrian return 1; 146844305Sbrian } else 146944305Sbrian *timeout = l; 147044305Sbrian 147144305Sbrian if (argc > 1) { 147244305Sbrian l = atol(argv[1]); 147344305Sbrian if (l < 1) { 147444305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 147544305Sbrian l = 1; 147644305Sbrian } 147744305Sbrian *maxreq = l; 147844305Sbrian 147944305Sbrian if (argc > 2 && maxtrm != NULL) { 148044305Sbrian l = atol(argv[2]); 148144305Sbrian if (l < 1) { 148244305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 148344305Sbrian l = 1; 148444305Sbrian } 148544305Sbrian *maxtrm = l; 148644305Sbrian } 148744305Sbrian } 148844305Sbrian } 148944305Sbrian 149044305Sbrian return 0; 149144305Sbrian} 149244305Sbrian 149344305Sbrianstatic int 149431343SbrianSetVariable(struct cmdargs const *arg) 14956059Samurai{ 149637210Sbrian long long_val, param = (long)arg->cmd->args; 149779119Sbrian int mode, dummyint, f, first, res; 149878410Sbrian u_short *change; 149931343Sbrian const char *argp; 150036285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 150136285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 150236285Sbrian struct in_addr dummyaddr, *addr; 15036059Samurai 150436285Sbrian if (arg->argc > arg->argn) 150536285Sbrian argp = arg->argv[arg->argn]; 150626551Sbrian else 150731343Sbrian argp = ""; 150826551Sbrian 150979119Sbrian res = 0; 151079119Sbrian 151136285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 151236285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 151336285Sbrian arg->cmd->name); 151436285Sbrian return 1; 151536285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 151636285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 151736285Sbrian arg->cmd->name, cx->name); 151836285Sbrian cx = NULL; 151936285Sbrian } 152036285Sbrian 152126551Sbrian switch (param) { 152228679Sbrian case VAR_AUTHKEY: 152350139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 152450139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 152550139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 152628679Sbrian break; 152737210Sbrian 152828679Sbrian case VAR_AUTHNAME: 152940622Sbrian switch (bundle_Phase(arg->bundle)) { 153058880Sbrian default: 153158880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 153258880Sbrian bundle_PhaseName(arg->bundle)); 153358880Sbrian /* drop through */ 153440622Sbrian case PHASE_DEAD: 153540622Sbrian case PHASE_ESTABLISH: 153640622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 153740622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 153840622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 153940622Sbrian break; 154036285Sbrian } 154128679Sbrian break; 154237210Sbrian 154336285Sbrian case VAR_AUTOLOAD: 154449434Sbrian if (arg->argc == arg->argn + 3) { 154549434Sbrian int v1, v2, v3; 154649434Sbrian char *end; 154749434Sbrian 154849434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 154949434Sbrian if (v1 < 0 || *end) { 155049434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 155149434Sbrian arg->argv[arg->argn]); 155279119Sbrian res = 1; 155379119Sbrian break; 155436285Sbrian } 155549434Sbrian 155649434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 155749434Sbrian if (v2 < 0 || *end) { 155849434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 155949434Sbrian arg->argv[arg->argn + 1]); 156079119Sbrian res = 1; 156179119Sbrian break; 156249434Sbrian } 156349434Sbrian if (v2 < v1) { 156449434Sbrian v3 = v1; 156549434Sbrian v1 = v2; 156649434Sbrian v2 = v3; 156749434Sbrian } 156849434Sbrian 156949434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 157049434Sbrian if (v3 <= 0 || *end) { 157149434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 157249434Sbrian arg->argv[arg->argn + 2]); 157379119Sbrian res = 1; 157479119Sbrian break; 157549434Sbrian } 157649434Sbrian 157749434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 157849434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 157949434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 158049434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 158136285Sbrian } else { 158279119Sbrian log_Printf(LogWARN, "Set autoload requires three arguments\n"); 158379119Sbrian res = 1; 158436285Sbrian } 158536285Sbrian break; 158637210Sbrian 158728679Sbrian case VAR_DIAL: 158836285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 158936285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 159028679Sbrian break; 159137210Sbrian 159228679Sbrian case VAR_LOGIN: 159336285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 159436285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 159528679Sbrian break; 159637210Sbrian 159736285Sbrian case VAR_WINSIZE: 159836285Sbrian if (arg->argc > arg->argn) { 159936285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 160036285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 160136285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 160236285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 160336285Sbrian l->ccp.cfg.deflate.out.winsize); 160436285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 160536285Sbrian } 160636285Sbrian if (arg->argc > arg->argn+1) { 160736285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 160836285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 160936285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 161036285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 161136285Sbrian l->ccp.cfg.deflate.in.winsize); 161236285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 161336285Sbrian } 161436285Sbrian } else 161536285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 161636285Sbrian } else { 161779119Sbrian log_Printf(LogWARN, "No window size specified\n"); 161879119Sbrian res = 1; 161936285Sbrian } 162036285Sbrian break; 162137210Sbrian 162267910Sbrian#ifdef HAVE_DES 162378411Sbrian case VAR_MPPE: 162479119Sbrian if (arg->argc > arg->argn + 2) { 162579119Sbrian res = -1; 162679119Sbrian break; 162779119Sbrian } 162878411Sbrian 162978411Sbrian if (arg->argc == arg->argn) { 163078411Sbrian l->ccp.cfg.mppe.keybits = 0; 163178411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 163278411Sbrian l->ccp.cfg.mppe.required = 0; 163378411Sbrian break; 163478411Sbrian } 163578411Sbrian 163678411Sbrian if (!strcmp(argp, "*")) 163778411Sbrian long_val = 0; 163878411Sbrian else { 163978411Sbrian long_val = atol(argp); 164078411Sbrian if (long_val != 40 && long_val != 56 && long_val != 128) { 164178411Sbrian log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 164279119Sbrian res = -1; 164379119Sbrian break; 164467910Sbrian } 164567910Sbrian } 164678411Sbrian 164778411Sbrian if (arg->argc == arg->argn + 2) { 164878411Sbrian if (!strcmp(arg->argv[arg->argn + 1], "*")) 164978411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 165078411Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 165178411Sbrian l->ccp.cfg.mppe.state = MPPE_STATELESS; 165279370Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 165378411Sbrian l->ccp.cfg.mppe.state = MPPE_STATEFUL; 165478411Sbrian else { 165578411Sbrian log_Printf(LogWARN, "%s: Invalid state value\n", 165678411Sbrian arg->argv[arg->argn + 1]); 165779119Sbrian res = -1; 165879119Sbrian break; 165978411Sbrian } 166078411Sbrian } else 166178411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 166278411Sbrian l->ccp.cfg.mppe.keybits = long_val; 166378411Sbrian l->ccp.cfg.mppe.required = 1; 166467910Sbrian break; 166567910Sbrian#endif 166667910Sbrian 166728679Sbrian case VAR_DEVICE: 166836285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 166936285Sbrian arg->argv + arg->argn); 167036285Sbrian break; 167137210Sbrian 167236285Sbrian case VAR_ACCMAP: 167336285Sbrian if (arg->argc > arg->argn) { 167437210Sbrian u_long ulong_val; 167536285Sbrian sscanf(argp, "%lx", &ulong_val); 167637210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 167736285Sbrian } else { 167879119Sbrian log_Printf(LogWARN, "No accmap specified\n"); 167979119Sbrian res = 1; 168036285Sbrian } 168136285Sbrian break; 168237210Sbrian 168336285Sbrian case VAR_MODE: 168436285Sbrian mode = Nam2mode(argp); 168536285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 168636285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 168779119Sbrian res = -1; 168879119Sbrian break; 168936285Sbrian } 169036285Sbrian bundle_SetMode(arg->bundle, cx, mode); 169136285Sbrian break; 169237210Sbrian 169336285Sbrian case VAR_MRRU: 169440622Sbrian switch (bundle_Phase(arg->bundle)) { 169540622Sbrian case PHASE_DEAD: 169640622Sbrian break; 169740622Sbrian case PHASE_ESTABLISH: 169840622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 169940622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 170040622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 170179119Sbrian res = 1; 170279119Sbrian break; 170340622Sbrian } 170440622Sbrian break; 170540622Sbrian default: 170640622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 170779119Sbrian res = 1; 170879119Sbrian break; 170929696Sbrian } 171079119Sbrian if (res != 0) 171179119Sbrian break; 171237210Sbrian long_val = atol(argp); 171337210Sbrian if (long_val && long_val < MIN_MRU) { 171437210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 171579119Sbrian res = 1; 171679119Sbrian break; 171737210Sbrian } else if (long_val > MAX_MRU) { 171837210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 171979119Sbrian res = 1; 172079119Sbrian break; 172137210Sbrian } else 172237210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 172328679Sbrian break; 172437210Sbrian 172536285Sbrian case VAR_MRU: 172679163Sbrian long_val = 0; /* silence gcc */ 172779163Sbrian change = NULL; /* silence gcc */ 172878410Sbrian switch(arg->argc - arg->argn) { 172978410Sbrian case 1: 173079119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 173179119Sbrian res = -1; 173279119Sbrian break; 173379119Sbrian } 173479119Sbrian /*FALLTHRU*/ 173578410Sbrian case 0: 173678410Sbrian long_val = atol(argp); 173778410Sbrian change = &l->lcp.cfg.mru; 173878410Sbrian if (long_val > l->lcp.cfg.max_mru) { 173978410Sbrian log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 174078410Sbrian l->lcp.cfg.max_mru); 174179119Sbrian res = 1; 174279119Sbrian break; 174378410Sbrian } 174478410Sbrian break; 174578410Sbrian case 2: 174679119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 174779119Sbrian res = -1; 174879119Sbrian break; 174979119Sbrian } 175078410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 175178410Sbrian change = &l->lcp.cfg.max_mru; 175278410Sbrian if (long_val > MAX_MRU) { 175378410Sbrian log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 175478410Sbrian MAX_MRU); 175579119Sbrian res = 1; 175679119Sbrian break; 175778410Sbrian } 175878410Sbrian break; 175978410Sbrian default: 176079119Sbrian res = -1; 176179119Sbrian break; 176278410Sbrian } 176379119Sbrian if (res != 0) 176479119Sbrian break; 176578410Sbrian 176637210Sbrian if (long_val == 0) 176780385Sbrian *change = 0; 176837210Sbrian else if (long_val < MIN_MRU) { 176937210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 177079119Sbrian res = 1; 177179119Sbrian break; 177237210Sbrian } else if (long_val > MAX_MRU) { 177337210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 177479119Sbrian res = 1; 177579119Sbrian break; 177637210Sbrian } else 177778410Sbrian *change = long_val; 177878410Sbrian if (l->lcp.cfg.mru > *change) 177978410Sbrian l->lcp.cfg.mru = *change; 178028679Sbrian break; 178137210Sbrian 178236285Sbrian case VAR_MTU: 178379163Sbrian long_val = 0; /* silence gcc */ 178479163Sbrian change = NULL; /* silence gcc */ 178578410Sbrian switch(arg->argc - arg->argn) { 178678410Sbrian case 1: 178779119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 178879119Sbrian res = -1; 178979119Sbrian break; 179079119Sbrian } 179179119Sbrian /*FALLTHRU*/ 179278410Sbrian case 0: 179378410Sbrian long_val = atol(argp); 179478410Sbrian change = &l->lcp.cfg.mtu; 179578410Sbrian if (long_val > l->lcp.cfg.max_mtu) { 179678410Sbrian log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 179778410Sbrian l->lcp.cfg.max_mtu); 179879119Sbrian res = 1; 179979119Sbrian break; 180078410Sbrian } 180178410Sbrian break; 180278410Sbrian case 2: 180379119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 180479119Sbrian res = -1; 180579119Sbrian break; 180679119Sbrian } 180778410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 180878410Sbrian change = &l->lcp.cfg.max_mtu; 180978410Sbrian if (long_val > MAX_MTU) { 181078410Sbrian log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 181178410Sbrian MAX_MTU); 181279119Sbrian res = 1; 181379119Sbrian break; 181478410Sbrian } 181578410Sbrian break; 181678410Sbrian default: 181779119Sbrian res = -1; 181879119Sbrian break; 181978410Sbrian } 182078410Sbrian 182179119Sbrian if (res != 0) 182279119Sbrian break; 182379119Sbrian 182437210Sbrian if (long_val && long_val < MIN_MTU) { 182537210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 182679119Sbrian res = 1; 182779119Sbrian break; 182837210Sbrian } else if (long_val > MAX_MTU) { 182937210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 183079119Sbrian res = 1; 183179119Sbrian break; 183237210Sbrian } else 183378410Sbrian *change = long_val; 183478410Sbrian if (l->lcp.cfg.mtu > *change) 183578410Sbrian l->lcp.cfg.mtu = *change; 183636285Sbrian break; 183737210Sbrian 183836285Sbrian case VAR_OPENMODE: 183936285Sbrian if (strcasecmp(argp, "active") == 0) 184036285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 184136285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 184236285Sbrian else if (strcasecmp(argp, "passive") == 0) 184336285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 184436285Sbrian else { 184579119Sbrian log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 184679119Sbrian res = 1; 184736285Sbrian } 184836285Sbrian break; 184937210Sbrian 185028679Sbrian case VAR_PHONE: 185136285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 185236285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 185338174Sbrian cx->phone.alt = cx->phone.next = NULL; 185428679Sbrian break; 185537210Sbrian 185628679Sbrian case VAR_HANGUP: 185736285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 185836285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 185928679Sbrian break; 186037210Sbrian 186161534Sbrian case VAR_IFQUEUE: 186261534Sbrian long_val = atol(argp); 186361534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 186461534Sbrian break; 186561534Sbrian 186652488Sbrian case VAR_LOGOUT: 186752488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 186852488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 186952488Sbrian break; 187052488Sbrian 187136285Sbrian case VAR_IDLETIMEOUT: 187279119Sbrian if (arg->argc > arg->argn+2) { 187379119Sbrian log_Printf(LogWARN, "Too many idle timeout values\n"); 187479119Sbrian res = 1; 187579119Sbrian } else if (arg->argc == arg->argn) { 187679119Sbrian log_Printf(LogWARN, "Too few idle timeout values\n"); 187779119Sbrian res = 1; 187879119Sbrian } else { 187949978Sbrian int timeout, min; 188049978Sbrian 188149978Sbrian timeout = atoi(argp); 188249978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 188349978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 188449978Sbrian } 188529549Sbrian break; 188637210Sbrian 188736285Sbrian case VAR_LQRPERIOD: 188837210Sbrian long_val = atol(argp); 188937210Sbrian if (long_val < MIN_LQRPERIOD) { 189037210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 189137210Sbrian long_val, MIN_LQRPERIOD); 189279119Sbrian res = 1; 189336285Sbrian } else 189437210Sbrian l->lcp.cfg.lqrperiod = long_val; 189536285Sbrian break; 189637210Sbrian 189736285Sbrian case VAR_LCPRETRY: 189879119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 189979119Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 190079119Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 190179119Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 190236285Sbrian break; 190337210Sbrian 190436285Sbrian case VAR_CHAPRETRY: 190579119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 190679119Sbrian &cx->chap.auth.cfg.fsm.timeout, 190779119Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 190836285Sbrian break; 190937210Sbrian 191036285Sbrian case VAR_PAPRETRY: 191179119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 191279119Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 191379119Sbrian NULL, DEF_FSMAUTHTRIES); 191436285Sbrian break; 191537210Sbrian 191636285Sbrian case VAR_CCPRETRY: 191779119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 191879119Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 191979119Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 192036285Sbrian break; 192137210Sbrian 192236285Sbrian case VAR_IPCPRETRY: 192379119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 192479119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 192579119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 192679119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 192736285Sbrian break; 192837210Sbrian 192936285Sbrian case VAR_NBNS: 193036285Sbrian case VAR_DNS: 193158044Sbrian if (param == VAR_DNS) { 193236285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 193358044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_NONE; 193458044Sbrian } else { 193536285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 193658044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 193758044Sbrian } 193836285Sbrian 193936285Sbrian if (arg->argc > arg->argn) { 194043313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 194136285Sbrian addr, &dummyaddr, &dummyint); 194236285Sbrian if (arg->argc > arg->argn+1) 194343313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 194436285Sbrian addr + 1, &dummyaddr, &dummyint); 194536285Sbrian 194658044Sbrian if (addr[0].s_addr == INADDR_ANY) { 194736285Sbrian addr[0].s_addr = addr[1].s_addr; 194858044Sbrian addr[1].s_addr = INADDR_ANY; 194958044Sbrian } 195058044Sbrian if (addr[0].s_addr == INADDR_NONE) { 195158044Sbrian addr[0].s_addr = addr[1].s_addr; 195258044Sbrian addr[1].s_addr = INADDR_NONE; 195358044Sbrian } 195436285Sbrian } 195536285Sbrian break; 195638174Sbrian 195738174Sbrian case VAR_CALLBACK: 195838174Sbrian cx->cfg.callback.opmask = 0; 195938174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 196038174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 196138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 196238174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 196338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 196438174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 196538174Sbrian if (dummyint == arg->argc - 1) 196638174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 196738174Sbrian else { 196838174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 196938174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 197038174Sbrian sizeof cx->cfg.callback.msg - 1); 197138174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 197238174Sbrian } 197338174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 197438174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 197579119Sbrian else { 197679119Sbrian res = -1; 197779119Sbrian break; 197879119Sbrian } 197938174Sbrian } 198038174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 198138174Sbrian cx->cfg.callback.opmask = 0; 198238174Sbrian break; 198338174Sbrian 198438174Sbrian case VAR_CBCP: 198538174Sbrian cx->cfg.cbcp.delay = 0; 198638174Sbrian *cx->cfg.cbcp.phone = '\0'; 198738174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 198838174Sbrian if (arg->argc > arg->argn) { 198938174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 199038174Sbrian sizeof cx->cfg.cbcp.phone - 1); 199138174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 199238174Sbrian if (arg->argc > arg->argn + 1) { 199338174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 199438174Sbrian if (arg->argc > arg->argn + 2) { 199538174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 199638174Sbrian if (long_val < MIN_FSMRETRY) 199738174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 199838174Sbrian long_val, MIN_FSMRETRY); 199938174Sbrian else 200038174Sbrian cx->cfg.cbcp.fsmretry = long_val; 200138174Sbrian } 200238174Sbrian } 200338174Sbrian } 200438174Sbrian break; 200538544Sbrian 200638544Sbrian case VAR_CHOKED: 200738544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 200838544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 200938544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 201038544Sbrian break; 201140665Sbrian 201240665Sbrian case VAR_SENDPIPE: 201340665Sbrian long_val = atol(argp); 201440665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 201540665Sbrian break; 201640665Sbrian 201740665Sbrian case VAR_RECVPIPE: 201840665Sbrian long_val = atol(argp); 201940665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 202040665Sbrian break; 202143313Sbrian 202243313Sbrian#ifndef NORADIUS 202343313Sbrian case VAR_RADIUS: 202443313Sbrian if (!*argp) 202543313Sbrian *arg->bundle->radius.cfg.file = '\0'; 202643313Sbrian else if (access(argp, R_OK)) { 202743313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 202879119Sbrian res = 1; 202979119Sbrian break; 203043313Sbrian } else { 203143313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 203243313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 203343313Sbrian arg->bundle->radius.cfg.file 203443313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 203543313Sbrian } 203643313Sbrian break; 203743313Sbrian#endif 203844073Sbrian 203944073Sbrian case VAR_CD: 204044073Sbrian if (*argp) { 204151699Sbrian if (strcasecmp(argp, "off")) { 204251699Sbrian long_val = atol(argp); 204351699Sbrian if (long_val < 0) 204451699Sbrian long_val = 0; 204551699Sbrian cx->physical->cfg.cd.delay = long_val; 204651699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 204751699Sbrian CD_REQUIRED : CD_VARIABLE; 204851699Sbrian } else 204951699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 205044073Sbrian } else { 205153733Sbrian cx->physical->cfg.cd.delay = 0; 205253733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 205344073Sbrian } 205444073Sbrian break; 205536285Sbrian 205646686Sbrian case VAR_PARITY: 205746686Sbrian if (arg->argc == arg->argn + 1) 205879119Sbrian res = physical_SetParity(arg->cx->physical, argp); 205946686Sbrian else { 206079119Sbrian log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 206179119Sbrian res = 1; 206246686Sbrian } 206346686Sbrian break; 20646059Samurai 206546686Sbrian case VAR_CRTSCTS: 206646686Sbrian if (strcasecmp(argp, "on") == 0) 206736285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 206846686Sbrian else if (strcasecmp(argp, "off") == 0) 206936285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 207046686Sbrian else { 207179119Sbrian log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 207279119Sbrian res = 1; 207346686Sbrian } 207446686Sbrian break; 207550867Sbrian 207650867Sbrian case VAR_URGENTPORTS: 207751048Sbrian if (arg->argn == arg->argc) { 207861430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 207951048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 208051048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 208151048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 208261430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 208351048Sbrian if (arg->argn == arg->argc - 1) 208451048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 208551048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 208651048Sbrian if (*arg->argv[f] == '+') 208751048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 208851048Sbrian else if (*arg->argv[f] == '-') 208951048Sbrian ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp, 209051048Sbrian atoi(arg->argv[f] + 1)); 209151048Sbrian else { 209251048Sbrian if (f == arg->argn) 209351048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 209451048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 209551048Sbrian } 209661430Sbrian } else if (arg->argn == arg->argc - 1 && 209761430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 209861430Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 209961430Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 210061430Sbrian ipcp_ClearUrgentTOS(&arg->bundle->ncp.ipcp); 210151048Sbrian } else { 210261430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 210351048Sbrian first = arg->argn; 210451048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 210551048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 210651048Sbrian 210751048Sbrian for (f = first; f < arg->argc; f++) 210851048Sbrian if (*arg->argv[f] == '+') 210951048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 211051048Sbrian else if (*arg->argv[f] == '-') 211151048Sbrian ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp, 211251048Sbrian atoi(arg->argv[f] + 1)); 211351048Sbrian else { 211451048Sbrian if (f == first) 211551048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 211651048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 211751048Sbrian } 211851048Sbrian } 211950867Sbrian break; 212020812Sjkh } 212146686Sbrian 212279119Sbrian return res; 212320812Sjkh} 212420812Sjkh 212530715Sbrianstatic struct cmdtab const SetCommands[] = { 212636285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 212736285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 212828679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 212936285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 213028679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 213136285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 213236285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 213336285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 213436285Sbrian (const void *)VAR_AUTOLOAD}, 213550867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 213650867Sbrian "datalink bandwidth", "set bandwidth value"}, 213738174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 213838174Sbrian "callback control", "set callback [none|auth|cbcp|" 213938174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 214038174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 214138174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 214238174Sbrian (const void *)VAR_CBCP}, 214344305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 214444305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 214544073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 214644073Sbrian "set cd value[!]", (const void *)VAR_CD}, 214744305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 214844305Sbrian "CHAP retries", "set chapretry value [attempts]", 214944305Sbrian (const void *)VAR_CHAPRETRY}, 215038544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 215138544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 215246686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 215346686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 215446686Sbrian (const char *)VAR_CRTSCTS}, 215536285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 215636285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 215736285Sbrian (const void *) VAR_WINSIZE}, 215867910Sbrian#ifdef HAVE_DES 215967910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 216079370Sbrian "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 216178411Sbrian (const void *) VAR_MPPE}, 216267910Sbrian#endif 216336285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 216446686Sbrian "physical device name", "set device|line device-name[,device-name]", 216536285Sbrian (const void *) VAR_DEVICE}, 216636285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 216736285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 216836285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 216936285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 217036285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 217136285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 217236285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 217336285Sbrian "escape characters", "set escape hex-digit ..."}, 217436285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 217536285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 217649388Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 217748142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 217836285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 217936285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 218036285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 218131343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 218261534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 218361534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 218444305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 218544305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 218644305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 218744305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 218836712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 218967916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 219058033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 219136285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 219236285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 219352488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 219452488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 219536285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 219636285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 219736285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 219836285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 219936285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 220036285Sbrian "set mrru value", (const void *)VAR_MRRU}, 220136285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 220278410Sbrian "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 220378410Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 220478410Sbrian "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 220536285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 220636285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 220736285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 220836285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 220944305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 221044305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 221146686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 221246686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 221336285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 221436285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 221540679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 221640679Sbrian "Process title", "set proctitle [value]"}, 221743313Sbrian#ifndef NORADIUS 221843313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 221943313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 222043313Sbrian#endif 222136285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 222236285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 222340665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 222440665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 222536285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 222644468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 222740665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 222840665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 222971657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 223071657Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 223136285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 223246686Sbrian "physical speed", "set speed value|sync"}, 223336285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 223436285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 223536285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 223636285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 223751048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 223851048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 223936285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 224036285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 224128679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 224231343Sbrian "Display this message", "set help|? [command]", SetCommands}, 224328679Sbrian {NULL, NULL, NULL}, 22446059Samurai}; 22456059Samurai 22466059Samuraistatic int 224731343SbrianSetCommand(struct cmdargs const *arg) 22486059Samurai{ 224936285Sbrian if (arg->argc > arg->argn) 225036285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 225136285Sbrian arg->prompt, arg->cx); 225236285Sbrian else if (arg->prompt) 225336285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 225458044Sbrian " syntax help.\n"); 22556059Samurai else 225636285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 225726516Sbrian 225826516Sbrian return 0; 22596059Samurai} 22606059Samurai 22616059Samuraistatic int 226231343SbrianAddCommand(struct cmdargs const *arg) 22636059Samurai{ 22646059Samurai struct in_addr dest, gateway, netmask; 226536285Sbrian int gw, addrs; 22666059Samurai 226736285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 226831598Sbrian return -1; 226931598Sbrian 227036285Sbrian addrs = 0; 227136285Sbrian if (arg->argc == arg->argn+2) { 227236285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 227336285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 227431598Sbrian else { 227536285Sbrian int width; 227636285Sbrian 227743313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 227836285Sbrian &dest, &netmask, &width)) 227936285Sbrian return -1; 228036285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 228136285Sbrian addrs = ROUTE_DSTMYADDR; 228236285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 228336285Sbrian addrs = ROUTE_DSTHISADDR; 228458044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 228558044Sbrian addrs = ROUTE_DSTDNS0; 228658044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 228758044Sbrian addrs = ROUTE_DSTDNS1; 228831598Sbrian } 228936285Sbrian gw = 1; 229034536Sbrian } else { 229136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 229236285Sbrian addrs = ROUTE_DSTMYADDR; 229336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 229436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 229536285Sbrian addrs = ROUTE_DSTHISADDR; 229636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 229758044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 229858044Sbrian addrs = ROUTE_DSTDNS0; 229958044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 230058044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 230158044Sbrian addrs = ROUTE_DSTDNS1; 230258044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 230365263Sbrian } else { 230436285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 230565263Sbrian if (dest.s_addr == INADDR_NONE) { 230665263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 230765263Sbrian arg->argv[arg->argn]); 230865263Sbrian return -1; 230965263Sbrian } 231065263Sbrian } 231136285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 231231598Sbrian gw = 2; 23136059Samurai } 231436285Sbrian 231536285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 231636285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 231736285Sbrian addrs |= ROUTE_GWHISADDR; 231865263Sbrian } else { 231936285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 232065263Sbrian if (gateway.s_addr == INADDR_NONE) { 232165263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 232265263Sbrian arg->argv[arg->argn + gw]); 232365263Sbrian return -1; 232465263Sbrian } 232565263Sbrian } 232636285Sbrian 232775212Sbrian if (rt_Set(arg->bundle, RTM_ADD, dest, gateway, netmask, 232843313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 232943313Sbrian && addrs != ROUTE_STATIC) 233036285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 233136285Sbrian 233231598Sbrian return 0; 23336059Samurai} 23346059Samurai 23356059Samuraistatic int 233631343SbrianDeleteCommand(struct cmdargs const *arg) 23376059Samurai{ 233831598Sbrian struct in_addr dest, none; 233936285Sbrian int addrs; 23406059Samurai 234136285Sbrian if (arg->argc == arg->argn+1) { 234236285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 234336285Sbrian route_IfDelete(arg->bundle, 0); 234436285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 234536285Sbrian } else { 234636285Sbrian addrs = 0; 234736285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 234836285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 234936285Sbrian addrs = ROUTE_DSTMYADDR; 235036285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 235136285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 235236285Sbrian addrs = ROUTE_DSTHISADDR; 235358044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 235458044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 235558044Sbrian addrs = ROUTE_DSTDNS0; 235658044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 235758044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 235858044Sbrian addrs = ROUTE_DSTDNS1; 235936285Sbrian } else { 236044279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 236144279Sbrian if (dest.s_addr == INADDR_NONE) { 236244279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 236344279Sbrian return -1; 236444279Sbrian } 236536285Sbrian addrs = ROUTE_STATIC; 236636285Sbrian } 236731598Sbrian none.s_addr = INADDR_ANY; 236875212Sbrian rt_Set(arg->bundle, RTM_DELETE, dest, none, none, 236937927Sbrian arg->cmd->args ? 1 : 0, 0); 237036285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 237131598Sbrian } 237234536Sbrian } else 237326516Sbrian return -1; 237426516Sbrian 237526516Sbrian return 0; 23766059Samurai} 23776059Samurai 237850059Sbrian#ifndef NONAT 237926031Sbrianstatic int 238058867SbrianNatEnable(struct cmdargs const *arg) 238126031Sbrian{ 238236285Sbrian if (arg->argc == arg->argn+1) { 238336285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 238450059Sbrian if (!arg->bundle->NatEnabled) { 238546686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 238646686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 238750059Sbrian arg->bundle->NatEnabled = 1; 238846686Sbrian } 238937191Sbrian return 0; 239036285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 239150059Sbrian arg->bundle->NatEnabled = 0; 239240561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 239340561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 239426516Sbrian return 0; 239526142Sbrian } 239635449Sbrian } 239736285Sbrian 239826516Sbrian return -1; 239926031Sbrian} 240026031Sbrian 240126031Sbrian 240226031Sbrianstatic int 240358867SbrianNatOption(struct cmdargs const *arg) 240426031Sbrian{ 240538559Sbrian long param = (long)arg->cmd->args; 240638559Sbrian 240736285Sbrian if (arg->argc == arg->argn+1) { 240836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 240950059Sbrian if (arg->bundle->NatEnabled) { 241037191Sbrian PacketAliasSetMode(param, param); 241128679Sbrian return 0; 241228679Sbrian } 241350059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 241436285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 241550059Sbrian if (arg->bundle->NatEnabled) { 241637191Sbrian PacketAliasSetMode(0, param); 241728679Sbrian return 0; 241828679Sbrian } 241950059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 242028679Sbrian } 242135449Sbrian } 242228679Sbrian return -1; 242326031Sbrian} 242450059Sbrian#endif /* #ifndef NONAT */ 242531121Sbrian 242631121Sbrianstatic int 242736285SbrianLinkCommand(struct cmdargs const *arg) 242836285Sbrian{ 242936285Sbrian if (arg->argc > arg->argn+1) { 243036285Sbrian char namelist[LINE_LEN]; 243136285Sbrian struct datalink *cx; 243236285Sbrian char *name; 243336285Sbrian int result = 0; 243436285Sbrian 243536285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 243636285Sbrian struct datalink *dl; 243736285Sbrian 243836285Sbrian cx = arg->bundle->links; 243936285Sbrian while (cx) { 244036285Sbrian /* Watch it, the command could be a ``remove'' */ 244136285Sbrian dl = cx->next; 244236285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 244336285Sbrian arg->prompt, cx); 244436285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 244536285Sbrian if (cx == dl) 244636285Sbrian break; /* Pointer's still valid ! */ 244736285Sbrian } 244836285Sbrian } else { 244936285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 245036285Sbrian namelist[sizeof namelist - 1] = '\0'; 245136285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 245236285Sbrian if (!bundle2datalink(arg->bundle, name)) { 245336285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 245436285Sbrian return 1; 245536285Sbrian } 245636285Sbrian 245736285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 245836285Sbrian namelist[sizeof namelist - 1] = '\0'; 245936285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 246036285Sbrian cx = bundle2datalink(arg->bundle, name); 246136285Sbrian if (cx) 246236285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 246336285Sbrian arg->prompt, cx); 246436285Sbrian else { 246536285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 246636285Sbrian result++; 246736285Sbrian } 246836285Sbrian } 246936285Sbrian } 247036285Sbrian return result; 247136285Sbrian } 247236285Sbrian 247336285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 247436285Sbrian return 2; 247536285Sbrian} 247636285Sbrian 247736285Sbrianstruct link * 247836285Sbriancommand_ChooseLink(struct cmdargs const *arg) 247936285Sbrian{ 248036285Sbrian if (arg->cx) 248136285Sbrian return &arg->cx->physical->link; 248237210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 248336285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 248437210Sbrian if (dl) 248537210Sbrian return &dl->physical->link; 248636285Sbrian } 248737210Sbrian return &arg->bundle->ncp.mp.link; 248836285Sbrian} 248936285Sbrian 249036285Sbrianstatic const char * 249136285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 249236285Sbrian{ 249336285Sbrian const char *result; 249436285Sbrian 249536285Sbrian switch (*cmd) { 249636285Sbrian case 'A': 249736285Sbrian case 'a': 249836285Sbrian result = "accept"; 249936285Sbrian *keep = NEG_MYMASK; 250036285Sbrian *add = NEG_ACCEPTED; 250136285Sbrian break; 250236285Sbrian case 'D': 250336285Sbrian case 'd': 250436285Sbrian switch (cmd[1]) { 250536285Sbrian case 'E': 250636285Sbrian case 'e': 250736285Sbrian result = "deny"; 250836285Sbrian *keep = NEG_MYMASK; 250936285Sbrian *add = 0; 251036285Sbrian break; 251136285Sbrian case 'I': 251236285Sbrian case 'i': 251336285Sbrian result = "disable"; 251436285Sbrian *keep = NEG_HISMASK; 251536285Sbrian *add = 0; 251636285Sbrian break; 251736285Sbrian default: 251836285Sbrian return NULL; 251936285Sbrian } 252036285Sbrian break; 252136285Sbrian case 'E': 252236285Sbrian case 'e': 252336285Sbrian result = "enable"; 252436285Sbrian *keep = NEG_HISMASK; 252536285Sbrian *add = NEG_ENABLED; 252636285Sbrian break; 252736285Sbrian default: 252836285Sbrian return NULL; 252936285Sbrian } 253036285Sbrian 253136285Sbrian return result; 253236285Sbrian} 253336285Sbrian 253436285Sbrianstatic int 253536285SbrianOptSet(struct cmdargs const *arg) 253636285Sbrian{ 253737574Sbrian int bit = (int)(long)arg->cmd->args; 253836285Sbrian const char *cmd; 253936285Sbrian unsigned keep; /* Keep these bits */ 254036285Sbrian unsigned add; /* Add these bits */ 254136285Sbrian 254236285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 254336285Sbrian return 1; 254436285Sbrian 254536285Sbrian if (add) 254636285Sbrian arg->bundle->cfg.opt |= bit; 254736285Sbrian else 254836285Sbrian arg->bundle->cfg.opt &= ~bit; 254936285Sbrian return 0; 255036285Sbrian} 255136285Sbrian 255236285Sbrianstatic int 255340561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 255440561Sbrian{ 255540561Sbrian unsigned save = arg->bundle->cfg.opt; 255640561Sbrian int result = OptSet(arg); 255740561Sbrian 255840561Sbrian if (result == 0) 255950059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 256040561Sbrian arg->bundle->cfg.opt = save; 256150059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 256240561Sbrian result = 2; 256340561Sbrian } 256440561Sbrian 256540561Sbrian return result; 256640561Sbrian} 256740561Sbrian 256840561Sbrianstatic int 256936285SbrianNegotiateSet(struct cmdargs const *arg) 257036285Sbrian{ 257137210Sbrian long param = (long)arg->cmd->args; 257236285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 257336285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 257436285Sbrian const char *cmd; 257536285Sbrian unsigned keep; /* Keep these bits */ 257636285Sbrian unsigned add; /* Add these bits */ 257736285Sbrian 257836285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 257936285Sbrian return 1; 258036285Sbrian 258136285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 258236285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 258336285Sbrian cmd, arg->cmd->name); 258436285Sbrian return 2; 258536285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 258636285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 258736285Sbrian cmd, arg->cmd->name, cx->name); 258836285Sbrian cx = NULL; 258936285Sbrian } 259036285Sbrian 259136285Sbrian switch (param) { 259236285Sbrian case NEG_ACFCOMP: 259336285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 259436285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 259536285Sbrian break; 259644106Sbrian case NEG_CHAP05: 259744106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 259844106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 259936285Sbrian break; 260044106Sbrian#ifdef HAVE_DES 260144106Sbrian case NEG_CHAP80: 260244106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 260344106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 260444106Sbrian break; 260544106Sbrian case NEG_CHAP80LM: 260644106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 260744106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 260844106Sbrian break; 260967910Sbrian case NEG_CHAP81: 261067910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 261167910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 261267910Sbrian break; 261367910Sbrian case NEG_MPPE: 261467910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 261567910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 261667910Sbrian break; 261744106Sbrian#endif 261836285Sbrian case NEG_DEFLATE: 261936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 262036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 262136285Sbrian break; 262236285Sbrian case NEG_DNS: 262336285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 262436285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 262536285Sbrian break; 262647858Sbrian case NEG_ENDDISC: 262747858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 262847858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 262947858Sbrian break; 263036285Sbrian case NEG_LQR: 263136285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 263236285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 263336285Sbrian break; 263436285Sbrian case NEG_PAP: 263536285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 263636285Sbrian cx->physical->link.lcp.cfg.pap |= add; 263736285Sbrian break; 263836285Sbrian case NEG_PPPDDEFLATE: 263936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 264036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 264136285Sbrian break; 264236285Sbrian case NEG_PRED1: 264336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 264436285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 264536285Sbrian break; 264636285Sbrian case NEG_PROTOCOMP: 264736285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 264836285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 264936285Sbrian break; 265036285Sbrian case NEG_SHORTSEQ: 265140622Sbrian switch (bundle_Phase(arg->bundle)) { 265240622Sbrian case PHASE_DEAD: 265340622Sbrian break; 265440622Sbrian case PHASE_ESTABLISH: 265540622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 265640622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 265740622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 265840622Sbrian " LCP negotiations\n"); 265940622Sbrian return 1; 266040622Sbrian } 266140622Sbrian break; 266240622Sbrian default: 266340622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 266440622Sbrian " DEAD/ESTABLISH\n"); 266540622Sbrian return 1; 266636285Sbrian } 266740622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 266840622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 266936285Sbrian break; 267036285Sbrian case NEG_VJCOMP: 267136285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 267236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 267336285Sbrian break; 267436285Sbrian } 267536285Sbrian 267636285Sbrian return 0; 267736285Sbrian} 267836285Sbrian 267936285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 268062778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 268162778Sbrian "filter on PPPoUDP payloads", "disable|enable", 268262778Sbrian (const void *)OPT_FILTERDECAP}, 268336285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 268436285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 268540666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 268662778Sbrian "retain interface addresses", "disable|enable", 268762778Sbrian (const void *)OPT_IFACEALIAS}, 268847689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 268947689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 269036285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 269136285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 269236285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 269336285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 269440665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 269536285Sbrian "disable|enable", (const void *)OPT_PROXY}, 269640665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 269740665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 269836285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 269936285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 270069303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 270169303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 270236285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 270336285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 270436285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 270536285Sbrian "disable|enable", (const void *)OPT_UTMP}, 270636285Sbrian 270769303Sbrian#define OPT_MAX 11 /* accept/deny allowed below and not above */ 270836285Sbrian 270936285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 271036285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 271136285Sbrian (const void *)NEG_ACFCOMP}, 271244106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 271336285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 271444106Sbrian (const void *)NEG_CHAP05}, 271544106Sbrian#ifdef HAVE_DES 271644106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 271744106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 271844106Sbrian (const void *)NEG_CHAP80}, 271944106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 272044106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 272144106Sbrian (const void *)NEG_CHAP80LM}, 272267910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 272367910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 272467910Sbrian (const void *)NEG_CHAP81}, 272567910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 272667910Sbrian "MPPE encryption", "accept|deny|disable|enable", 272767910Sbrian (const void *)NEG_MPPE}, 272844106Sbrian#endif 272936285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 273036285Sbrian "Deflate compression", "accept|deny|disable|enable", 273136285Sbrian (const void *)NEG_DEFLATE}, 273236285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 273336285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 273436285Sbrian (const void *)NEG_PPPDDEFLATE}, 273536285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 273636285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 273747858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 273847858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 273936285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 274036285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 274136285Sbrian (const void *)NEG_LQR}, 274236285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 274336285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 274436285Sbrian (const void *)NEG_PAP}, 274536285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 274636285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 274736285Sbrian (const void *)NEG_PRED1}, 274836285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 274936285Sbrian "Protocol field compression", "accept|deny|disable|enable", 275036285Sbrian (const void *)NEG_PROTOCOMP}, 275136285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 275236285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 275336285Sbrian (const void *)NEG_SHORTSEQ}, 275436285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 275536285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 275636285Sbrian (const void *)NEG_VJCOMP}, 275736285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 275836285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 275936285Sbrian NegotiateCommands}, 276036285Sbrian {NULL, NULL, NULL}, 276136285Sbrian}; 276236285Sbrian 276336285Sbrianstatic int 276436285SbrianNegotiateCommand(struct cmdargs const *arg) 276536285Sbrian{ 276636285Sbrian if (arg->argc > arg->argn) { 276736285Sbrian char const *argv[3]; 276836285Sbrian unsigned keep, add; 276936285Sbrian int n; 277036285Sbrian 277136285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 277236285Sbrian return -1; 277336285Sbrian argv[2] = NULL; 277436285Sbrian 277536285Sbrian for (n = arg->argn; n < arg->argc; n++) { 277636285Sbrian argv[1] = arg->argv[n]; 277736285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 277836285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 277936285Sbrian } 278036285Sbrian } else if (arg->prompt) 278136285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 278236285Sbrian arg->argv[arg->argn-1]); 278336285Sbrian else 278436285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 278536285Sbrian arg->argv[arg->argn] ); 278636285Sbrian 278736285Sbrian return 0; 278836285Sbrian} 278936285Sbrian 279036285Sbrianconst char * 279136285Sbriancommand_ShowNegval(unsigned val) 279236285Sbrian{ 279336285Sbrian switch (val&3) { 279436285Sbrian case 1: return "disabled & accepted"; 279536285Sbrian case 2: return "enabled & denied"; 279636285Sbrian case 3: return "enabled & accepted"; 279736285Sbrian } 279836285Sbrian return "disabled & denied"; 279936285Sbrian} 280036934Sbrian 280136934Sbrianstatic int 280236934SbrianClearCommand(struct cmdargs const *arg) 280336934Sbrian{ 280436934Sbrian struct pppThroughput *t; 280536934Sbrian struct datalink *cx; 280636934Sbrian int i, clear_type; 280736934Sbrian 280836934Sbrian if (arg->argc < arg->argn + 1) 280936934Sbrian return -1; 281036934Sbrian 281146686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 281236934Sbrian cx = arg->cx; 281336934Sbrian if (!cx) 281436934Sbrian cx = bundle2datalink(arg->bundle, NULL); 281536934Sbrian if (!cx) { 281646686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 281736934Sbrian return 1; 281836934Sbrian } 281964652Sbrian t = &cx->physical->link.stats.total; 282036934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 282136934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 282236934Sbrian else 282336934Sbrian return -1; 282436934Sbrian 282536934Sbrian if (arg->argc > arg->argn + 1) { 282636934Sbrian clear_type = 0; 282736934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 282836934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 282936934Sbrian clear_type |= THROUGHPUT_OVERALL; 283036934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 283136934Sbrian clear_type |= THROUGHPUT_CURRENT; 283236934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 283336934Sbrian clear_type |= THROUGHPUT_PEAK; 283436934Sbrian else 283536934Sbrian return -1; 283636934Sbrian } else 283736934Sbrian clear_type = THROUGHPUT_ALL; 283836934Sbrian 283936934Sbrian throughput_clear(t, clear_type, arg->prompt); 284036934Sbrian return 0; 284136934Sbrian} 284240561Sbrian 284340561Sbrianstatic int 284440561SbrianRunListCommand(struct cmdargs const *arg) 284540561Sbrian{ 284640561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 284740561Sbrian 284864801Sbrian#ifndef NONAT 284964801Sbrian if (arg->cmd->args == NatCommands && 285064801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 285164801Sbrian if (arg->prompt) 285265550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 285364801Sbrian else 285465550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 285564801Sbrian } 285664801Sbrian#endif 285764801Sbrian 285840561Sbrian if (arg->argc > arg->argn) 285940561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 286040561Sbrian arg->prompt, arg->cx); 286140561Sbrian else if (arg->prompt) 286240561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 286340561Sbrian " <option>' for syntax help.\n", cmd, cmd); 286440561Sbrian else 286540561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 286640561Sbrian 286740561Sbrian return 0; 286840561Sbrian} 286940561Sbrian 287040561Sbrianstatic int 287140561SbrianIfaceAddCommand(struct cmdargs const *arg) 287240561Sbrian{ 287340561Sbrian int bits, n, how; 287440561Sbrian struct in_addr ifa, mask, brd; 287540561Sbrian 287640664Sbrian if (arg->argc == arg->argn + 1) { 287743313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 287840561Sbrian return -1; 287940664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 288040664Sbrian } else { 288140664Sbrian if (arg->argc == arg->argn + 2) { 288243313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 288340664Sbrian return -1; 288440664Sbrian n = 1; 288540664Sbrian } else if (arg->argc == arg->argn + 3) { 288643313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 288740664Sbrian return -1; 288843313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 288940664Sbrian return -1; 289040664Sbrian n = 2; 289140664Sbrian } else 289240561Sbrian return -1; 289340561Sbrian 289443313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 289540664Sbrian return -1; 289640664Sbrian } 289740561Sbrian 289840561Sbrian how = IFACE_ADD_LAST; 289940561Sbrian if (arg->cmd->args) 290040561Sbrian how |= IFACE_FORCE_ADD; 290140561Sbrian 290240561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 290340561Sbrian} 290440561Sbrian 290540561Sbrianstatic int 290640561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 290740561Sbrian{ 290840561Sbrian struct in_addr ifa; 290940561Sbrian int ok; 291040561Sbrian 291140561Sbrian if (arg->argc != arg->argn + 1) 291240561Sbrian return -1; 291340561Sbrian 291443313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 291540561Sbrian return -1; 291640561Sbrian 291740561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 291840561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 291940561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 292040561Sbrian inet_ntoa(ifa)); 292140561Sbrian return 1; 292240561Sbrian } 292340561Sbrian 292440561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 292540561Sbrian if (!ok) { 292640561Sbrian if (arg->cmd->args) 292740561Sbrian ok = 1; 292840561Sbrian else if (arg->prompt) 292940561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 293040561Sbrian else 293140561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 293240561Sbrian } 293340561Sbrian 293440561Sbrian return !ok; 293540561Sbrian} 293640561Sbrian 293740561Sbrianstatic int 293840561SbrianIfaceClearCommand(struct cmdargs const *arg) 293940561Sbrian{ 294040561Sbrian int how; 294140561Sbrian 294240561Sbrian if (arg->argc != arg->argn) 294340561Sbrian return -1; 294440561Sbrian 294540941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 294640941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 294740561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 294840561Sbrian iface_Clear(arg->bundle->iface, how); 294940561Sbrian 295040561Sbrian return 0; 295140561Sbrian} 295240679Sbrian 295340679Sbrianstatic int 295440679SbrianSetProcTitle(struct cmdargs const *arg) 295540679Sbrian{ 295640679Sbrian static char title[LINE_LEN]; 295740679Sbrian char *argv[MAXARGS], *ptr; 295840679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 295940679Sbrian 296040679Sbrian if (arg->argc == arg->argn) { 296164698Sbrian SetTitle(NULL); 296240679Sbrian return 0; 296340679Sbrian } 296440679Sbrian 296540679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 296640679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 296740679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 296840679Sbrian } 296947849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 297040679Sbrian 297140679Sbrian ptr = title; 297240679Sbrian remaining = sizeof title - 1; 297340679Sbrian for (f = 0; f < argc && remaining; f++) { 297440679Sbrian if (f) { 297540679Sbrian *ptr++ = ' '; 297640679Sbrian remaining--; 297740679Sbrian } 297840679Sbrian len = strlen(argv[f]); 297940679Sbrian if (len > remaining) 298040679Sbrian len = remaining; 298140679Sbrian memcpy(ptr, argv[f], len); 298240679Sbrian remaining -= len; 298340679Sbrian ptr += len; 298440679Sbrian } 298540679Sbrian *ptr = '\0'; 298640679Sbrian 298764698Sbrian SetTitle(title); 298840679Sbrian 298940679Sbrian return 0; 299040679Sbrian} 2991