command.c revision 62778
16059Samurai/* 26059Samurai * PPP User command processing module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2050479Speter * $FreeBSD: head/usr.sbin/ppp/command.c 62778 2000-07-07 14:22:08Z brian $ 218857Srgrimes * 226059Samurai */ 2343313Sbrian#include <sys/param.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3338628Sbrian#include <ctype.h> 3430715Sbrian#include <errno.h> 3526516Sbrian#include <fcntl.h> 3653298Sbrian#ifdef __OpenBSD__ 3753298Sbrian#include <util.h> 3853298Sbrian#else 3953298Sbrian#include <libutil.h> 4053298Sbrian#endif 4130715Sbrian#include <paths.h> 4230715Sbrian#include <stdio.h> 4330715Sbrian#include <stdlib.h> 4430715Sbrian#include <string.h> 4530715Sbrian#include <sys/wait.h> 4630715Sbrian#include <termios.h> 4730715Sbrian#include <unistd.h> 4830715Sbrian 4950059Sbrian#ifndef NONAT 5058037Sbrian#ifdef LOCALNAT 5158037Sbrian#include "alias.h" 5258037Sbrian#else 5346086Sbrian#include <alias.h> 5439395Sbrian#endif 5539395Sbrian#endif 5658037Sbrian 5746686Sbrian#include "layer.h" 5837009Sbrian#include "defs.h" 5931343Sbrian#include "command.h" 6030715Sbrian#include "mbuf.h" 6130715Sbrian#include "log.h" 6230715Sbrian#include "timer.h" 636059Samurai#include "fsm.h" 646059Samurai#include "lcp.h" 6531690Sbrian#include "iplist.h" 6636285Sbrian#include "throughput.h" 6736285Sbrian#include "slcompress.h" 6838557Sbrian#include "lqr.h" 6938557Sbrian#include "hdlc.h" 706059Samurai#include "ipcp.h" 7150059Sbrian#ifndef NONAT 7251075Sbrian#include "nat_cmd.h" 7331343Sbrian#endif 7425630Sbrian#include "systems.h" 7536285Sbrian#include "filter.h" 7636285Sbrian#include "descriptor.h" 7730715Sbrian#include "main.h" 7830715Sbrian#include "route.h" 7930715Sbrian#include "ccp.h" 8031080Sbrian#include "auth.h" 8136285Sbrian#include "async.h" 8236285Sbrian#include "link.h" 8336285Sbrian#include "physical.h" 8436285Sbrian#include "mp.h" 8543313Sbrian#ifndef NORADIUS 8643313Sbrian#include "radius.h" 8743313Sbrian#endif 8836285Sbrian#include "bundle.h" 8936285Sbrian#include "server.h" 9036285Sbrian#include "prompt.h" 9136285Sbrian#include "chat.h" 9236285Sbrian#include "chap.h" 9338174Sbrian#include "cbcp.h" 9436285Sbrian#include "datalink.h" 9540561Sbrian#include "iface.h" 9653298Sbrian#include "id.h" 976059Samurai 9836285Sbrian/* ``set'' values */ 9936285Sbrian#define VAR_AUTHKEY 0 10036285Sbrian#define VAR_DIAL 1 10136285Sbrian#define VAR_LOGIN 2 10236285Sbrian#define VAR_AUTHNAME 3 10336285Sbrian#define VAR_AUTOLOAD 4 10436285Sbrian#define VAR_WINSIZE 5 10536285Sbrian#define VAR_DEVICE 6 10636285Sbrian#define VAR_ACCMAP 7 10736285Sbrian#define VAR_MRRU 8 10836285Sbrian#define VAR_MRU 9 10936285Sbrian#define VAR_MTU 10 11036285Sbrian#define VAR_OPENMODE 11 11136285Sbrian#define VAR_PHONE 12 11236285Sbrian#define VAR_HANGUP 13 11336285Sbrian#define VAR_IDLETIMEOUT 14 11436285Sbrian#define VAR_LQRPERIOD 15 11536285Sbrian#define VAR_LCPRETRY 16 11636285Sbrian#define VAR_CHAPRETRY 17 11736285Sbrian#define VAR_PAPRETRY 18 11836285Sbrian#define VAR_CCPRETRY 19 11936285Sbrian#define VAR_IPCPRETRY 20 12036285Sbrian#define VAR_DNS 21 12136285Sbrian#define VAR_NBNS 22 12236285Sbrian#define VAR_MODE 23 12338174Sbrian#define VAR_CALLBACK 24 12438174Sbrian#define VAR_CBCP 25 12538544Sbrian#define VAR_CHOKED 26 12640665Sbrian#define VAR_SENDPIPE 27 12740665Sbrian#define VAR_RECVPIPE 28 12843313Sbrian#define VAR_RADIUS 29 12944073Sbrian#define VAR_CD 30 13046686Sbrian#define VAR_PARITY 31 13146686Sbrian#define VAR_CRTSCTS 32 13250867Sbrian#define VAR_URGENTPORTS 33 13352488Sbrian#define VAR_LOGOUT 34 13461534Sbrian#define VAR_IFQUEUE 35 1356059Samurai 13636285Sbrian/* ``accept|deny|disable|enable'' masks */ 13736285Sbrian#define NEG_HISMASK (1) 13836285Sbrian#define NEG_MYMASK (2) 13936285Sbrian 14036285Sbrian/* ``accept|deny|disable|enable'' values */ 14136285Sbrian#define NEG_ACFCOMP 40 14244106Sbrian#define NEG_CHAP05 41 14344106Sbrian#define NEG_CHAP80 42 14444106Sbrian#define NEG_CHAP80LM 43 14544106Sbrian#define NEG_DEFLATE 44 14647858Sbrian#define NEG_DNS 45 14747858Sbrian#define NEG_ENDDISC 46 14847858Sbrian#define NEG_LQR 47 14947858Sbrian#define NEG_PAP 48 15047858Sbrian#define NEG_PPPDDEFLATE 49 15147858Sbrian#define NEG_PRED1 50 15247858Sbrian#define NEG_PROTOCOMP 51 15347858Sbrian#define NEG_SHORTSEQ 52 15447858Sbrian#define NEG_VJCOMP 53 15536285Sbrian 15653970Sbrianconst char Version[] = "2.26"; 15736285Sbrian 15836285Sbrianstatic int ShowCommand(struct cmdargs const *); 15936285Sbrianstatic int TerminalCommand(struct cmdargs const *); 16036285Sbrianstatic int QuitCommand(struct cmdargs const *); 16136285Sbrianstatic int OpenCommand(struct cmdargs const *); 16236285Sbrianstatic int CloseCommand(struct cmdargs const *); 16336285Sbrianstatic int DownCommand(struct cmdargs const *); 16436285Sbrianstatic int SetCommand(struct cmdargs const *); 16536285Sbrianstatic int LinkCommand(struct cmdargs const *); 16636285Sbrianstatic int AddCommand(struct cmdargs const *); 16736285Sbrianstatic int DeleteCommand(struct cmdargs const *); 16836285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 16936934Sbrianstatic int ClearCommand(struct cmdargs const *); 17040561Sbrianstatic int RunListCommand(struct cmdargs const *); 17140561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 17240561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 17340561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 17440679Sbrianstatic int SetProcTitle(struct cmdargs const *); 17550059Sbrian#ifndef NONAT 17658867Sbrianstatic int NatEnable(struct cmdargs const *); 17758867Sbrianstatic int NatOption(struct cmdargs const *); 17831343Sbrian#endif 1796059Samurai 18036285Sbrianstatic const char * 18136285Sbrianshowcx(struct cmdtab const *cmd) 18236285Sbrian{ 18336285Sbrian if (cmd->lauth & LOCAL_CX) 18436285Sbrian return "(c)"; 18536285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 18636285Sbrian return "(o)"; 18736285Sbrian 18836285Sbrian return ""; 18936285Sbrian} 19036285Sbrian 1916059Samuraistatic int 19231343SbrianHelpCommand(struct cmdargs const *arg) 1936059Samurai{ 19428679Sbrian struct cmdtab const *cmd; 19536285Sbrian int n, cmax, dmax, cols, cxlen; 19636285Sbrian const char *cx; 1976059Samurai 19836285Sbrian if (!arg->prompt) { 19936285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 20026516Sbrian return 0; 20136285Sbrian } 20226516Sbrian 20336285Sbrian if (arg->argc > arg->argn) { 20436285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 20536285Sbrian if ((cmd->lauth & arg->prompt->auth) && 20636285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 20736285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 20836285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 20928679Sbrian return 0; 2106059Samurai } 21126516Sbrian return -1; 2126059Samurai } 21336285Sbrian 21431372Sbrian cmax = dmax = 0; 21536285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 21636285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 21736285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 21831372Sbrian cmax = n; 21931372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 22031372Sbrian dmax = n; 22131372Sbrian } 22231372Sbrian 22331372Sbrian cols = 80 / (dmax + cmax + 3); 2246059Samurai n = 0; 22536285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 22636285Sbrian " (c) = Context required\n"); 22736285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22836285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22936285Sbrian cx = showcx(cmd); 23036285Sbrian cxlen = cmax - strlen(cmd->name); 23140482Sbrian if (n % cols != 0) 23240482Sbrian prompt_Printf(arg->prompt, " "); 23340482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 23436285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 23531372Sbrian if (++n % cols == 0) 23636285Sbrian prompt_Printf(arg->prompt, "\n"); 2376059Samurai } 23831372Sbrian if (n % cols != 0) 23936285Sbrian prompt_Printf(arg->prompt, "\n"); 24026516Sbrian 24126516Sbrian return 0; 2426059Samurai} 2436059Samurai 24436285Sbrianstatic int 24536285SbrianCloneCommand(struct cmdargs const *arg) 2466059Samurai{ 24736285Sbrian char namelist[LINE_LEN]; 24836285Sbrian char *name; 24936285Sbrian int f; 2506059Samurai 25136285Sbrian if (arg->argc == arg->argn) 25236285Sbrian return -1; 25336285Sbrian 25436285Sbrian namelist[sizeof namelist - 1] = '\0'; 25536285Sbrian for (f = arg->argn; f < arg->argc; f++) { 25636285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 25736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 25836285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2596059Samurai } 26036285Sbrian 26136285Sbrian return 0; 2626059Samurai} 2636059Samurai 2646059Samuraistatic int 26536285SbrianRemoveCommand(struct cmdargs const *arg) 2666059Samurai{ 26736285Sbrian if (arg->argc != arg->argn) 26836285Sbrian return -1; 26911336Samurai 27036285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 27136285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 27236285Sbrian return 2; 2736059Samurai } 27426516Sbrian 27536285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 27636285Sbrian return 0; 27736285Sbrian} 27832711Sbrian 27936285Sbrianstatic int 28036285SbrianRenameCommand(struct cmdargs const *arg) 28136285Sbrian{ 28236285Sbrian if (arg->argc != arg->argn + 1) 28336285Sbrian return -1; 28431121Sbrian 28536285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 28636285Sbrian return 0; 28736285Sbrian 28836285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 28936285Sbrian arg->cx->name, arg->argv[arg->argn]); 29036285Sbrian return 1; 29136285Sbrian} 29236285Sbrian 29336285Sbrianint 29436285SbrianLoadCommand(struct cmdargs const *arg) 29536285Sbrian{ 29640797Sbrian const char *err; 29740797Sbrian int n, mode; 29836285Sbrian 29940797Sbrian mode = arg->bundle->phys_type.all; 30036285Sbrian 30140797Sbrian if (arg->argn < arg->argc) { 30240797Sbrian for (n = arg->argn; n < arg->argc; n++) 30340797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 30440797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 30540797Sbrian return 1; 30640797Sbrian } 30740797Sbrian 30840797Sbrian for (n = arg->argn; n < arg->argc; n++) { 30940797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 31040797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 31140797Sbrian } 31240797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 31340797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 31440797Sbrian log_Printf(LogWARN, "default: %s\n", err); 31536285Sbrian return 1; 31636285Sbrian } else { 31740797Sbrian bundle_SetLabel(arg->bundle, "default"); 31840797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 31940797Sbrian bundle_SetLabel(arg->bundle, "default"); 32036285Sbrian } 32140797Sbrian 32226516Sbrian return 0; 3236059Samurai} 3246059Samurai 32536285Sbrianint 32636285SbrianSaveCommand(struct cmdargs const *arg) 32736285Sbrian{ 32836285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 32936285Sbrian return 1; 33036285Sbrian} 33136285Sbrian 33210528Samuraistatic int 33336285SbrianDialCommand(struct cmdargs const *arg) 33428536Sbrian{ 33536285Sbrian int res; 33636285Sbrian 33736465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 33836465Sbrian || (!arg->cx && 33936928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 34036285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 34136285Sbrian " interactive links\n"); 34236285Sbrian return 1; 34334536Sbrian } 34436285Sbrian 34536285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 34636285Sbrian return res; 34736285Sbrian 34837993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 34936285Sbrian 35036285Sbrian return 0; 35128536Sbrian} 35228536Sbrian 35338628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 35438628Sbrian 35538628Sbrianstatic char * 35638628Sbrianstrstrword(char *big, const char *little) 35738628Sbrian{ 35838628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 35938628Sbrian char *pos; 36038628Sbrian int len; 36138628Sbrian 36238628Sbrian pos = big; 36338628Sbrian len = strlen(little); 36438628Sbrian 36538628Sbrian while ((pos = strstr(pos, little)) != NULL) 36647865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 36747865Sbrian pos++; 36847865Sbrian else if (pos != big && pos[-1] == '\\') 36947865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 37047865Sbrian else 37138628Sbrian break; 37238628Sbrian 37338628Sbrian return pos; 37438628Sbrian} 37538628Sbrian 37638628Sbrianstatic char * 37738628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 37838628Sbrian{ 37938628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 38038628Sbrian char *word, *ntgt; 38138628Sbrian int ltgt, loldstr, lnewstr, pos; 38238628Sbrian 38338628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 38438628Sbrian return tgt; 38538628Sbrian 38638628Sbrian ltgt = strlen(tgt) + 1; 38738628Sbrian loldstr = strlen(oldstr); 38838628Sbrian lnewstr = strlen(newstr); 38938628Sbrian do { 39038628Sbrian pos = word - tgt; 39138628Sbrian if (loldstr > lnewstr) 39238628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 39338628Sbrian if (loldstr != lnewstr) { 39438628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 39538628Sbrian if (ntgt == NULL) 39638628Sbrian break; /* Oh wonderful ! */ 39738628Sbrian word = ntgt + pos; 39838628Sbrian tgt = ntgt; 39938628Sbrian } 40038628Sbrian if (lnewstr > loldstr) 40138628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 40238628Sbrian bcopy(newstr, word, lnewstr); 40338628Sbrian } while ((word = strstrword(word, oldstr))); 40438628Sbrian 40538628Sbrian return tgt; 40638628Sbrian} 40738628Sbrian 40843888Sbrianvoid 40943888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 41047849Sbrian struct bundle *bundle, int inc0, pid_t pid) 41138628Sbrian{ 41238628Sbrian int arg; 41347849Sbrian char pidstr[12]; 41438628Sbrian 41541755Sbrian if (inc0) 41641755Sbrian arg = 0; /* Start at arg 0 */ 41741755Sbrian else { 41841755Sbrian nargv[0] = strdup(oargv[0]); 41941755Sbrian arg = 1; 42041755Sbrian } 42147849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 42241755Sbrian for (; arg < argc; arg++) { 42338629Sbrian nargv[arg] = strdup(oargv[arg]); 42438629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 42538628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 42638629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 42740561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 42838628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 42938629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 43038629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 43138629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 43238629Sbrian bundle->ncp.mp.peer.enddisc.address, 43338629Sbrian bundle->ncp.mp.peer.enddisc.len)); 43438629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 43538629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 43638629Sbrian bundle->ncp.mp.cfg.enddisc.address, 43738629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 43847849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 43938629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 44058044Sbrian nargv[arg] = subst(nargv[arg], "DNS0", 44158044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); 44258044Sbrian nargv[arg] = subst(nargv[arg], "DNS1", 44358044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); 44438628Sbrian } 44538628Sbrian nargv[arg] = NULL; 44638628Sbrian} 44738628Sbrian 44828536Sbrianstatic int 44931343SbrianShellCommand(struct cmdargs const *arg, int bg) 45010528Samurai{ 45110528Samurai const char *shell; 45247849Sbrian pid_t shpid, pid; 45320813Sjkh 45418856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 45526911Sbrian /* we're only allowed to shell when we run ppp interactively */ 45636285Sbrian if (arg->prompt && arg->prompt->owner) { 45736285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 45826516Sbrian return 1; 45910528Samurai } 46026911Sbrian#endif 46128679Sbrian 46236285Sbrian if (arg->argc == arg->argn) { 46336285Sbrian if (!arg->prompt) { 46436285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 46536285Sbrian " a config file\n"); 46628381Sbrian return 1; 46736285Sbrian } else if (arg->prompt->owner) { 46836285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 46936285Sbrian " a socket connection\n"); 47036285Sbrian return 1; 47128381Sbrian } else if (bg) { 47236285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 47328679Sbrian " the foreground mode\n"); 47428381Sbrian return 1; 47528381Sbrian } 47634536Sbrian } 47734536Sbrian 47847849Sbrian pid = getpid(); 47928679Sbrian if ((shpid = fork()) == 0) { 48036285Sbrian int i, fd; 48118531Sbde 48236285Sbrian if ((shell = getenv("SHELL")) == 0) 48336285Sbrian shell = _PATH_BSHELL; 48432017Sbrian 48536285Sbrian timer_TermService(); 48636285Sbrian 48736285Sbrian if (arg->prompt) 48836285Sbrian fd = arg->prompt->fd_out; 48936285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 49036285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 49136285Sbrian _PATH_DEVNULL, strerror(errno)); 49228679Sbrian exit(1); 49328679Sbrian } 49449976Sbrian dup2(fd, STDIN_FILENO); 49549976Sbrian dup2(fd, STDOUT_FILENO); 49649976Sbrian dup2(fd, STDERR_FILENO); 49749976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 49849976Sbrian fcntl(i, F_SETFD, 1); 49926516Sbrian 50055252Sbrian setuid(ID0realuid()); 50136285Sbrian if (arg->argc > arg->argn) { 50228679Sbrian /* substitute pseudo args */ 50338628Sbrian char *argv[MAXARGS]; 50438628Sbrian int argc = arg->argc - arg->argn; 50538628Sbrian 50638628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 50738628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 50838628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 50931343Sbrian } 51047849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 51128679Sbrian if (bg) { 51228679Sbrian pid_t p; 51310528Samurai 51428679Sbrian p = getpid(); 51528679Sbrian if (daemon(1, 1) == -1) { 51636832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 51728679Sbrian exit(1); 51828679Sbrian } 51936285Sbrian } else if (arg->prompt) 52036285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 52131343Sbrian execvp(argv[0], argv); 52230316Sbrian } else { 52336285Sbrian if (arg->prompt) 52432017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 52536285Sbrian prompt_TtyOldMode(arg->prompt); 52631343Sbrian execl(shell, shell, NULL); 52730316Sbrian } 52820813Sjkh 52940665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 53040665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 53140665Sbrian strerror(errno)); 53249976Sbrian _exit(255); 53310528Samurai } 53436285Sbrian 53536285Sbrian if (shpid == (pid_t) - 1) 53636285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 53736285Sbrian else { 53810528Samurai int status; 53931343Sbrian waitpid(shpid, &status, 0); 54010528Samurai } 54120813Sjkh 54236285Sbrian if (arg->prompt && !arg->prompt->owner) 54336285Sbrian prompt_TtyCommandMode(arg->prompt); 54420813Sjkh 54536285Sbrian return 0; 54610528Samurai} 54710528Samurai 54831343Sbrianstatic int 54931343SbrianBgShellCommand(struct cmdargs const *arg) 55031343Sbrian{ 55136285Sbrian if (arg->argc == arg->argn) 55231343Sbrian return -1; 55331343Sbrian return ShellCommand(arg, 1); 55431343Sbrian} 55531343Sbrian 55631343Sbrianstatic int 55731343SbrianFgShellCommand(struct cmdargs const *arg) 55831343Sbrian{ 55931343Sbrian return ShellCommand(arg, 0); 56031343Sbrian} 56131343Sbrian 56258044Sbrianstatic int 56358044SbrianResolvCommand(struct cmdargs const *arg) 56458044Sbrian{ 56558044Sbrian if (arg->argc == arg->argn + 1) { 56658044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 56758044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 56858044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 56958044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 57058044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 57158044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 57258044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 57358044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 57458044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 57558044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 57658044Sbrian else 57758044Sbrian return -1; 57858044Sbrian 57958044Sbrian return 0; 58058044Sbrian } 58158044Sbrian 58258044Sbrian return -1; 58358044Sbrian} 58458044Sbrian 58550059Sbrian#ifndef NONAT 58658867Sbrianstatic struct cmdtab const NatCommands[] = 58740561Sbrian{ 58850059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 58950059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 59058867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 59150059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 59240561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 59358867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 59450059Sbrian "enable NAT", "nat enable yes|no"}, 59558867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 59650059Sbrian "log NAT link creation", "nat log yes|no", 59740561Sbrian (const void *) PKT_ALIAS_LOG}, 59850059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 59950059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 60050059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 60150059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 60258867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 60350059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 60440561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 60558867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 60658867Sbrian "Default address for incoming connections", "nat target addr" }, 60758867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 60850059Sbrian "translate unregistered (private) IP address space only", 60950059Sbrian "nat unregistered_only yes|no", 61040561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 61158867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 61250059Sbrian "allocate host sockets", "nat use_sockets yes|no", 61340561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 61440561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 61558867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 61640561Sbrian {NULL, NULL, NULL}, 61740561Sbrian}; 61840561Sbrian#endif 61940561Sbrian 62040561Sbrianstatic struct cmdtab const AllowCommands[] = { 62140561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 62240561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 62340561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 62440561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 62540561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 62640561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 62740561Sbrian {NULL, NULL, NULL}, 62840561Sbrian}; 62940561Sbrian 63040561Sbrianstatic struct cmdtab const IfaceCommands[] = 63140561Sbrian{ 63240561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 63340561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 63440561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 63540561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 63640561Sbrian (void *)1}, 63740561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 63840561Sbrian "Clear iface address(es)", "iface clear"}, 63940561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 64040561Sbrian "Delete iface address", "iface delete addr", NULL}, 64140561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 64240561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 64340561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 64440561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 64540561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 64640561Sbrian "Show iface address(es)", "iface show"}, 64740561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 64850059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 64940561Sbrian {NULL, NULL, NULL}, 65040561Sbrian}; 65140561Sbrian 65230715Sbrianstatic struct cmdtab const Commands[] = { 65336285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65428679Sbrian "accept option request", "accept option .."}, 65528679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 65632109Sbrian "add route", "add dest mask gateway", NULL}, 65736285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 65832109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 65940561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 66040561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 66128679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 66231372Sbrian "Run a background command", "[!]bg command"}, 66336934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66446686Sbrian "Clear throughput statistics", 66546686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 66636285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 66736285Sbrian "Clone a link", "clone newname..."}, 66836285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66936285Sbrian "Close an FSM", "close [lcp|ccp]"}, 67028679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 67132109Sbrian "delete route", "delete dest", NULL}, 67236285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 67332109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 67436285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67528679Sbrian "Deny option request", "deny option .."}, 67636285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67740797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 67836285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67928679Sbrian "Disable option", "disable option .."}, 68036285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68146686Sbrian "Generate a down event", "down [ccp|lcp]"}, 68236285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68328679Sbrian "Enable option", "enable option .."}, 68440561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 68540561Sbrian "interface control", "iface option ...", IfaceCommands}, 68636285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 68736285Sbrian "Link specific commands", "link name command ..."}, 68837008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68940797Sbrian "Load settings", "load [system ...]"}, 69050059Sbrian#ifndef NONAT 69150059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 69258867Sbrian "NAT control", "nat option yes|no", NatCommands}, 69350059Sbrian#endif 69436285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 69537955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 69636285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 69736285Sbrian "Password for manipulation", "passwd LocalPassword"}, 69836285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 69936285Sbrian "Quit PPP program", "quit|bye [all]"}, 70036285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 70136285Sbrian "Remove a link", "remove"}, 70236285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 70336285Sbrian "Rename a link", "rename name"}, 70458044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 70558044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 70628679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 70728679Sbrian "Save settings", "save"}, 70836285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70928679Sbrian "Set parameters", "set[up] var value"}, 71028679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 71128679Sbrian "Run a subshell", "shell|! [sh command]"}, 71236285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71331372Sbrian "Show status and stats", "show var"}, 71436285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 71531372Sbrian "Enter terminal mode", "term"}, 71628679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 71731343Sbrian "Display this message", "help|? [command]", Commands}, 71828679Sbrian {NULL, NULL, NULL}, 7196059Samurai}; 7206059Samurai 72128536Sbrianstatic int 72231343SbrianShowEscape(struct cmdargs const *arg) 7236059Samurai{ 72436285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 72536285Sbrian int code, bit; 72636285Sbrian const char *sep = ""; 7276059Samurai 72826516Sbrian for (code = 0; code < 32; code++) 72936285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 73028679Sbrian for (bit = 0; bit < 8; bit++) 73136285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 73236285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 73336285Sbrian sep = ", "; 73436285Sbrian } 73536285Sbrian prompt_Printf(arg->prompt, "\n"); 7366059Samurai } 73731077Sbrian return 0; 7386059Samurai} 7396059Samurai 74028679Sbrianstatic int 74136285SbrianShowTimerList(struct cmdargs const *arg) 7426059Samurai{ 74336285Sbrian timer_Show(0, arg->prompt); 74431077Sbrian return 0; 7456059Samurai} 7466059Samurai 74728679Sbrianstatic int 74831343SbrianShowStopped(struct cmdargs const *arg) 74928327Sbrian{ 75036285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 75136285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 75236285Sbrian prompt_Printf(arg->prompt, "Disabled"); 75328327Sbrian else 75436285Sbrian prompt_Printf(arg->prompt, "%ld secs", 75536285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 75628461Sbrian 75736285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 75836285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 75936285Sbrian prompt_Printf(arg->prompt, "Disabled"); 76028461Sbrian else 76136285Sbrian prompt_Printf(arg->prompt, "%ld secs", 76236285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 76328461Sbrian 76436285Sbrian prompt_Printf(arg->prompt, "\n"); 76528461Sbrian 76631077Sbrian return 0; 76728327Sbrian} 76828327Sbrian 76928679Sbrianstatic int 77031343SbrianShowVersion(struct cmdargs const *arg) 7716059Samurai{ 77251026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 77331077Sbrian return 0; 7746059Samurai} 7756059Samurai 77628679Sbrianstatic int 77736285SbrianShowProtocolStats(struct cmdargs const *arg) 77826326Sbrian{ 77936285Sbrian struct link *l = command_ChooseLink(arg); 78026326Sbrian 78136285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 78236285Sbrian link_ReportProtocolStatus(l, arg->prompt); 78331077Sbrian return 0; 78426326Sbrian} 78526326Sbrian 78630715Sbrianstatic struct cmdtab const ShowCommands[] = { 78736285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 78836285Sbrian "bundle details", "show bundle"}, 78936285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 79036285Sbrian "CCP status", "show cpp"}, 79136285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 79236285Sbrian "VJ compression stats", "show compress"}, 79336285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 79436285Sbrian "escape characters", "show escape"}, 79536285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 79636285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 79736285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 79836285Sbrian "HDLC errors", "show hdlc"}, 79940561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 80040561Sbrian "Interface status", "show iface"}, 80136285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 80236285Sbrian "IPCP status", "show ipcp"}, 80347211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 80447211Sbrian "Protocol layers", "show layers"}, 80536285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 80636285Sbrian "LCP status", "show lcp"}, 80736285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 80836285Sbrian "(high-level) link info", "show link"}, 80936285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 81036285Sbrian "available link names", "show links"}, 81136285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 81236285Sbrian "log levels", "show log"}, 81336285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 81436285Sbrian "mbuf allocations", "show mem"}, 81546686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 81646686Sbrian "(low-level) link info", "show physical"}, 81736285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 81836285Sbrian "multilink setup", "show mp"}, 81936285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 82036285Sbrian "protocol summary", "show proto"}, 82136285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 82236285Sbrian "routing table", "show route"}, 82336285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 82436285Sbrian "STOPPED timeout", "show stopped"}, 82536285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 82636285Sbrian "alarm timers", "show timers"}, 82728679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 82836285Sbrian "version string", "show version"}, 82936285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 83036285Sbrian "client list", "show who"}, 83128679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 83231343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 83328679Sbrian {NULL, NULL, NULL}, 8346059Samurai}; 8356059Samurai 83630715Sbrianstatic struct cmdtab const * 83731343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 8386059Samurai{ 83926516Sbrian int nmatch; 84026516Sbrian int len; 84128679Sbrian struct cmdtab const *found; 8426059Samurai 84326516Sbrian found = NULL; 84426516Sbrian len = strlen(str); 84526516Sbrian nmatch = 0; 8466059Samurai while (cmds->func) { 84725566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 84826516Sbrian if (cmds->name[len] == '\0') { 84928679Sbrian *pmatch = 1; 85028679Sbrian return cmds; 85126516Sbrian } 8526059Samurai nmatch++; 8536059Samurai found = cmds; 85428679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 85526516Sbrian if (cmds->alias[len] == '\0') { 85628679Sbrian *pmatch = 1; 85728679Sbrian return cmds; 85826516Sbrian } 8596059Samurai nmatch++; 8606059Samurai found = cmds; 8616059Samurai } 8626059Samurai cmds++; 8636059Samurai } 8646059Samurai *pmatch = nmatch; 86526516Sbrian return found; 8666059Samurai} 8676059Samurai 86836285Sbrianstatic const char * 86936285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 87036285Sbrian{ 87136285Sbrian int f, tlen, len; 87236285Sbrian 87336285Sbrian tlen = 0; 87436285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 87536285Sbrian if (f) 87636285Sbrian tgt[tlen++] = ' '; 87736285Sbrian len = strlen(argv[f]); 87836285Sbrian if (len > sz - tlen - 1) 87936285Sbrian len = sz - tlen - 1; 88036285Sbrian strncpy(tgt+tlen, argv[f], len); 88136285Sbrian tlen += len; 88236285Sbrian } 88336285Sbrian tgt[tlen] = '\0'; 88436285Sbrian return tgt; 88536285Sbrian} 88636285Sbrian 88730715Sbrianstatic int 88836285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 88936285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8906059Samurai{ 89128679Sbrian struct cmdtab const *cmd; 8926059Samurai int val = 1; 8936059Samurai int nmatch; 89431343Sbrian struct cmdargs arg; 89536285Sbrian char prefix[100]; 8966059Samurai 89736285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8986059Samurai if (nmatch > 1) 89936285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 90036285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 90136285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 90236285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 90336285Sbrian /* We've got no context, but we require it */ 90436285Sbrian cx = bundle2datalink(bundle, NULL); 90536285Sbrian 90636285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 90736285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 90836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 90936285Sbrian else { 91036285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 91136285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 91236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 91336285Sbrian cx = NULL; 91436285Sbrian } 91536285Sbrian arg.cmdtab = cmds; 91636285Sbrian arg.cmd = cmd; 91736285Sbrian arg.argc = argc; 91836285Sbrian arg.argn = argn+1; 91936285Sbrian arg.argv = argv; 92036285Sbrian arg.bundle = bundle; 92136285Sbrian arg.cx = cx; 92236285Sbrian arg.prompt = prompt; 92336285Sbrian val = (*cmd->func) (&arg); 92436285Sbrian } 92531343Sbrian } else 92636285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 92736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 92826516Sbrian 92926516Sbrian if (val == -1) 93036285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 93128679Sbrian else if (val) 93236285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 93336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 93426516Sbrian 93526516Sbrian return val; 9366059Samurai} 9376059Samurai 93837009Sbrianint 93958045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 94058045Sbrian{ 94158045Sbrian char buff2[LINE_LEN-offset]; 94258045Sbrian 94358045Sbrian InterpretArg(buff, buff2); 94458045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 94558045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 94658045Sbrian 94758045Sbrian return command_Interpret(buff, nb, argv); 94858045Sbrian} 94958045Sbrian 95058045Sbrianint 95137009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 9526059Samurai{ 9536059Samurai char *cp; 9546059Samurai 9556059Samurai if (nb > 0) { 9566059Samurai cp = buff + strcspn(buff, "\r\n"); 9576059Samurai if (cp) 9586059Samurai *cp = '\0'; 95955145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 96037009Sbrian } 96137009Sbrian return 0; 96231121Sbrian} 9636059Samurai 96431822Sbrianstatic int 96531822Sbrianarghidden(int argc, char const *const *argv, int n) 96631822Sbrian{ 96731822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 96831828Sbrian 96931828Sbrian /* set authkey xxxxx */ 97031828Sbrian /* set key xxxxx */ 97131822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 97231822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 97331822Sbrian return 1; 97431822Sbrian 97531828Sbrian /* passwd xxxxx */ 97631828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 97731828Sbrian return 1; 97831828Sbrian 97936285Sbrian /* set server port xxxxx .... */ 98036285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 98136285Sbrian !strncasecmp(argv[1], "se", 2)) 98236285Sbrian return 1; 98336285Sbrian 98431822Sbrian return 0; 98531822Sbrian} 98631822Sbrian 98731121Sbrianvoid 98836285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 98937008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 99031121Sbrian{ 99131156Sbrian if (argc > 0) { 99236285Sbrian if (log_IsKept(LogCOMMAND)) { 99347844Sbrian char buf[LINE_LEN]; 99431156Sbrian int f, n; 99531156Sbrian 99631156Sbrian if (label) { 99731962Sbrian strncpy(buf, label, sizeof buf - 3); 99831962Sbrian buf[sizeof buf - 3] = '\0'; 99931156Sbrian strcat(buf, ": "); 100047844Sbrian n = strlen(buf); 100147844Sbrian } else { 100247844Sbrian *buf = '\0'; 100347844Sbrian n = 0; 100431156Sbrian } 100547844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 100647844Sbrian 100731156Sbrian for (f = 0; f < argc; f++) { 100831962Sbrian if (n < sizeof buf - 1 && f) 100931156Sbrian buf[n++] = ' '; 101031822Sbrian if (arghidden(argc, argv, f)) 101136285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 101231822Sbrian else 101331962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 101431156Sbrian n += strlen(buf+n); 101531156Sbrian } 101636285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 101731156Sbrian } 101837008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 101931156Sbrian } 10206059Samurai} 10216059Samurai 102254914Sbrianint 102336285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 102436285Sbrian const char *label) 102531121Sbrian{ 102631121Sbrian int argc; 102737009Sbrian char *argv[MAXARGS]; 102831121Sbrian 102958045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 103054914Sbrian return 0; 103154914Sbrian 103237008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 103354914Sbrian return 1; 103431121Sbrian} 103531121Sbrian 10366059Samuraistatic int 103731343SbrianShowCommand(struct cmdargs const *arg) 10386059Samurai{ 103936285Sbrian if (!arg->prompt) 104036285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 104136285Sbrian else if (arg->argc > arg->argn) 104236285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 104336285Sbrian arg->prompt, arg->cx); 10446059Samurai else 104536285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 104626516Sbrian 104726516Sbrian return 0; 10486059Samurai} 10496059Samurai 10506059Samuraistatic int 105131343SbrianTerminalCommand(struct cmdargs const *arg) 10526059Samurai{ 105336285Sbrian if (!arg->prompt) { 105436285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 105526516Sbrian return 1; 10566059Samurai } 105736285Sbrian 105836285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 105936285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 106036285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 106136285Sbrian return 1; 10626059Samurai } 106336285Sbrian 106436285Sbrian datalink_Up(arg->cx, 0, 0); 106536285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 106636285Sbrian return 0; 10676059Samurai} 10686059Samurai 10696059Samuraistatic int 107031343SbrianQuitCommand(struct cmdargs const *arg) 10716059Samurai{ 107236285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 107336285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 107436285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 107536285Sbrian Cleanup(EX_NORMAL); 107636285Sbrian if (arg->prompt) 107736285Sbrian prompt_Destroy(arg->prompt, 1); 107826516Sbrian 107926516Sbrian return 0; 10806059Samurai} 10816059Samurai 10826059Samuraistatic int 108336285SbrianOpenCommand(struct cmdargs const *arg) 10846059Samurai{ 108537160Sbrian if (arg->argc == arg->argn) 108637993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 108737160Sbrian else if (arg->argc == arg->argn + 1) { 108837160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 108937385Sbrian struct datalink *cx = arg->cx ? 109037385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 109137385Sbrian if (cx) { 109237385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 109337385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 109437160Sbrian else 109537993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 109637160Sbrian } else 109737160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 109837160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 109937160Sbrian struct fsm *fp; 11006059Samurai 110137210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 110237160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 110337160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 110437160Sbrian else if (fp->state == ST_OPENED) 110537160Sbrian fsm_Reopen(fp); 110637160Sbrian else { 110737160Sbrian fp->open_mode = 0; /* Not passive any more */ 110837160Sbrian if (fp->state == ST_STOPPED) { 110937160Sbrian fsm_Down(fp); 111037160Sbrian fsm_Up(fp); 111137160Sbrian } else { 111237160Sbrian fsm_Up(fp); 111337160Sbrian fsm_Open(fp); 111437160Sbrian } 111536285Sbrian } 111637160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 111737160Sbrian if (arg->cx) 111837160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 111937160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 112037160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 112137160Sbrian else 112237993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 112337160Sbrian } else 112437160Sbrian return -1; 112536285Sbrian } else 112636285Sbrian return -1; 112736285Sbrian 112826516Sbrian return 0; 11296059Samurai} 11306059Samurai 113125067Sbrianstatic int 113236285SbrianCloseCommand(struct cmdargs const *arg) 11336059Samurai{ 113437007Sbrian if (arg->argc == arg->argn) 113537007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 113637007Sbrian else if (arg->argc == arg->argn + 1) { 113737007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 113837007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 113937007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 114037007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 114137007Sbrian struct fsm *fp; 11426059Samurai 114337210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 114437007Sbrian if (fp->state == ST_OPENED) { 114537007Sbrian fsm_Close(fp); 114637007Sbrian if (arg->argv[arg->argn][3] == '!') 114737007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 114837007Sbrian else 114937007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 115037007Sbrian } 115137007Sbrian } else 115236285Sbrian return -1; 115336285Sbrian } else 115436285Sbrian return -1; 115536285Sbrian 115636285Sbrian return 0; 11576059Samurai} 11586059Samurai 115925067Sbrianstatic int 116036285SbrianDownCommand(struct cmdargs const *arg) 116111336Samurai{ 116237018Sbrian if (arg->argc == arg->argn) { 116337018Sbrian if (arg->cx) 116437018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 116537018Sbrian else 116637018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 116737018Sbrian } else if (arg->argc == arg->argn + 1) { 116837018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 116937018Sbrian if (arg->cx) 117037018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 117137018Sbrian else 117237018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 117337018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 117437018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 117537018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 117637060Sbrian fsm2initial(fp); 117737018Sbrian } else 117837018Sbrian return -1; 117936285Sbrian } else 118036285Sbrian return -1; 118136285Sbrian 118236285Sbrian return 0; 118325067Sbrian} 118425067Sbrian 118525067Sbrianstatic int 118636285SbrianSetModemSpeed(struct cmdargs const *arg) 118725067Sbrian{ 118836285Sbrian long speed; 118936285Sbrian char *end; 119011336Samurai 119136285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 119236285Sbrian if (arg->argc > arg->argn+1) { 119354917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 119436285Sbrian return -1; 119511336Samurai } 119636285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 119736285Sbrian physical_SetSync(arg->cx->physical); 119836285Sbrian return 0; 119936285Sbrian } 120036285Sbrian end = NULL; 120136285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 120236285Sbrian if (*end) { 120336285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 120436285Sbrian arg->argv[arg->argn]); 120536285Sbrian return -1; 120636285Sbrian } 120736285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 120836285Sbrian return 0; 120936285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 121036285Sbrian } else 121136285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 121224939Sbrian 121326516Sbrian return -1; 121411336Samurai} 121511336Samurai 121625067Sbrianstatic int 121731343SbrianSetStoppedTimeout(struct cmdargs const *arg) 121828327Sbrian{ 121936285Sbrian struct link *l = &arg->cx->physical->link; 122036285Sbrian 122136285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 122236285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 122336285Sbrian if (arg->argc <= arg->argn+2) { 122436285Sbrian if (arg->argc > arg->argn) { 122536285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 122636285Sbrian if (arg->argc > arg->argn+1) 122736285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 122828461Sbrian } 122928327Sbrian return 0; 123028327Sbrian } 123128327Sbrian return -1; 123228327Sbrian} 123328327Sbrian 123428327Sbrianstatic int 123531343SbrianSetServer(struct cmdargs const *arg) 123626940Sbrian{ 123726940Sbrian int res = -1; 123826940Sbrian 123936285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 124031081Sbrian const char *port, *passwd, *mask; 124153125Sbrian int mlen; 124231081Sbrian 124331081Sbrian /* What's what ? */ 124436285Sbrian port = arg->argv[arg->argn]; 124536285Sbrian if (arg->argc == arg->argn + 2) { 124636285Sbrian passwd = arg->argv[arg->argn+1]; 124736285Sbrian mask = NULL; 124836285Sbrian } else if (arg->argc == arg->argn + 3) { 124936285Sbrian passwd = arg->argv[arg->argn+1]; 125036285Sbrian mask = arg->argv[arg->argn+2]; 125153125Sbrian mlen = strlen(mask); 125253125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 125353125Sbrian (mlen == 4 && *mask != '0')) { 125453125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 125553125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 125631081Sbrian return -1; 125753125Sbrian } 125836285Sbrian } else if (strcasecmp(port, "none") == 0) { 125936285Sbrian if (server_Close(arg->bundle)) 126036285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 126136285Sbrian return 0; 126231081Sbrian } else 126336285Sbrian return -1; 126431081Sbrian 126536285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 126636285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 126731081Sbrian 126836285Sbrian if (*port == '/') { 126931081Sbrian mode_t imask; 127036285Sbrian char *ptr, name[LINE_LEN + 12]; 127128679Sbrian 127253125Sbrian if (mask == NULL) 127331081Sbrian imask = (mode_t)-1; 127453125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 127553125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 127636285Sbrian 127736285Sbrian ptr = strstr(port, "%d"); 127836285Sbrian if (ptr) { 127936285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 128037210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 128136285Sbrian port = name; 128236285Sbrian } 128336285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 128427346Sbrian } else { 128536285Sbrian int iport, add = 0; 128628679Sbrian 128731081Sbrian if (mask != NULL) 128831081Sbrian return -1; 128928679Sbrian 129036285Sbrian if (*port == '+') { 129136285Sbrian port++; 129236285Sbrian add = 1; 129336285Sbrian } 129431081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 129531081Sbrian struct servent *s; 129631081Sbrian 129731081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 129831081Sbrian iport = 0; 129936285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 130028679Sbrian } else 130131081Sbrian iport = ntohs(s->s_port); 130227346Sbrian } else 130331081Sbrian iport = atoi(port); 130436285Sbrian 130536285Sbrian if (iport) { 130636285Sbrian if (add) 130736285Sbrian iport += arg->bundle->unit; 130836285Sbrian res = server_TcpOpen(arg->bundle, iport); 130936285Sbrian } else 131036285Sbrian res = -1; 131127346Sbrian } 131231081Sbrian } 131326940Sbrian 131426940Sbrian return res; 131526940Sbrian} 131626940Sbrian 131726940Sbrianstatic int 131831343SbrianSetEscape(struct cmdargs const *arg) 13196059Samurai{ 13206059Samurai int code; 132136285Sbrian int argc = arg->argc - arg->argn; 132236285Sbrian char const *const *argv = arg->argv + arg->argn; 13236059Samurai 13246059Samurai for (code = 0; code < 33; code++) 132536285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 132631343Sbrian 13276059Samurai while (argc-- > 0) { 13286059Samurai sscanf(*argv++, "%x", &code); 13296059Samurai code &= 0xff; 133036285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 133136285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 13326059Samurai } 133326516Sbrian return 0; 13346059Samurai} 13356059Samurai 13366059Samuraistatic int 133731343SbrianSetInterfaceAddr(struct cmdargs const *arg) 13386059Samurai{ 133936285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 134032267Sbrian const char *hisaddr; 134132267Sbrian 134240561Sbrian if (arg->argc > arg->argn + 4) 134340561Sbrian return -1; 134440561Sbrian 134532267Sbrian hisaddr = NULL; 134644874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 134744874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 134836285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 134936285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 135036285Sbrian iplist_reset(&ipcp->cfg.peer_list); 135128394Sbrian 135236285Sbrian if (arg->argc > arg->argn) { 135343313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 135436285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 135536285Sbrian &ipcp->cfg.my_range.width)) 135628679Sbrian return 1; 135736285Sbrian if (arg->argc > arg->argn+1) { 135836285Sbrian hisaddr = arg->argv[arg->argn+1]; 135936285Sbrian if (arg->argc > arg->argn+2) { 136044455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 136136285Sbrian if (arg->argc > arg->argn+3) { 136236285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 136336285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 13649440Samurai } 13656059Samurai } 13666059Samurai } 13676059Samurai } 136828394Sbrian 136940561Sbrian /* 0.0.0.0 means any address (0 bits) */ 137036285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 137136285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 137236285Sbrian ipcp->cfg.my_range.width = 0; 13736059Samurai } 137436285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 137547648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 137636285Sbrian 137736285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 137836928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 137932267Sbrian return 4; 138031121Sbrian 138126516Sbrian return 0; 13826059Samurai} 13836059Samurai 138418752Sjkhstatic int 138544305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 138644305Sbrian u_int *maxtrm, int def) 138744305Sbrian{ 138844305Sbrian if (argc == 0) { 138944305Sbrian *timeout = DEF_FSMRETRY; 139044305Sbrian *maxreq = def; 139144305Sbrian if (maxtrm != NULL) 139244305Sbrian *maxtrm = def; 139344305Sbrian } else { 139444305Sbrian long l = atol(argv[0]); 139544305Sbrian 139644305Sbrian if (l < MIN_FSMRETRY) { 139744305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 139844305Sbrian l, MIN_FSMRETRY); 139944305Sbrian return 1; 140044305Sbrian } else 140144305Sbrian *timeout = l; 140244305Sbrian 140344305Sbrian if (argc > 1) { 140444305Sbrian l = atol(argv[1]); 140544305Sbrian if (l < 1) { 140644305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 140744305Sbrian l = 1; 140844305Sbrian } 140944305Sbrian *maxreq = l; 141044305Sbrian 141144305Sbrian if (argc > 2 && maxtrm != NULL) { 141244305Sbrian l = atol(argv[2]); 141344305Sbrian if (l < 1) { 141444305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 141544305Sbrian l = 1; 141644305Sbrian } 141744305Sbrian *maxtrm = l; 141844305Sbrian } 141944305Sbrian } 142044305Sbrian } 142144305Sbrian 142244305Sbrian return 0; 142344305Sbrian} 142444305Sbrian 142544305Sbrianstatic int 142631343SbrianSetVariable(struct cmdargs const *arg) 14276059Samurai{ 142837210Sbrian long long_val, param = (long)arg->cmd->args; 142951048Sbrian int mode, dummyint, f, first; 143031343Sbrian const char *argp; 143136285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 143236285Sbrian const char *err = NULL; 143336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 143436285Sbrian struct in_addr dummyaddr, *addr; 14356059Samurai 143636285Sbrian if (arg->argc > arg->argn) 143736285Sbrian argp = arg->argv[arg->argn]; 143826551Sbrian else 143931343Sbrian argp = ""; 144026551Sbrian 144136285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 144236285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 144336285Sbrian arg->cmd->name); 144436285Sbrian return 1; 144536285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 144636285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 144736285Sbrian arg->cmd->name, cx->name); 144836285Sbrian cx = NULL; 144936285Sbrian } 145036285Sbrian 145126551Sbrian switch (param) { 145228679Sbrian case VAR_AUTHKEY: 145350139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 145450139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 145550139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 145628679Sbrian break; 145737210Sbrian 145828679Sbrian case VAR_AUTHNAME: 145940622Sbrian switch (bundle_Phase(arg->bundle)) { 146058880Sbrian default: 146158880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 146258880Sbrian bundle_PhaseName(arg->bundle)); 146358880Sbrian /* drop through */ 146440622Sbrian case PHASE_DEAD: 146540622Sbrian case PHASE_ESTABLISH: 146640622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 146740622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 146840622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 146940622Sbrian break; 147036285Sbrian } 147128679Sbrian break; 147237210Sbrian 147336285Sbrian case VAR_AUTOLOAD: 147449434Sbrian if (arg->argc == arg->argn + 3) { 147549434Sbrian int v1, v2, v3; 147649434Sbrian char *end; 147749434Sbrian 147849434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 147949434Sbrian if (v1 < 0 || *end) { 148049434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 148149434Sbrian arg->argv[arg->argn]); 148249434Sbrian return 1; 148336285Sbrian } 148449434Sbrian 148549434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 148649434Sbrian if (v2 < 0 || *end) { 148749434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 148849434Sbrian arg->argv[arg->argn + 1]); 148949434Sbrian return 1; 149049434Sbrian } 149149434Sbrian if (v2 < v1) { 149249434Sbrian v3 = v1; 149349434Sbrian v1 = v2; 149449434Sbrian v2 = v3; 149549434Sbrian } 149649434Sbrian 149749434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 149849434Sbrian if (v3 <= 0 || *end) { 149949434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 150049434Sbrian arg->argv[arg->argn + 2]); 150149434Sbrian return 1; 150249434Sbrian } 150349434Sbrian 150449434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 150549434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 150649434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 150749434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 150836285Sbrian } else { 150949434Sbrian err = "Set autoload requires three arguments\n"; 151036285Sbrian log_Printf(LogWARN, err); 151136285Sbrian } 151236285Sbrian break; 151337210Sbrian 151428679Sbrian case VAR_DIAL: 151536285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 151636285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 151728679Sbrian break; 151837210Sbrian 151928679Sbrian case VAR_LOGIN: 152036285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 152136285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 152228679Sbrian break; 152337210Sbrian 152436285Sbrian case VAR_WINSIZE: 152536285Sbrian if (arg->argc > arg->argn) { 152636285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 152736285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 152836285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 152936285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 153036285Sbrian l->ccp.cfg.deflate.out.winsize); 153136285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 153236285Sbrian } 153336285Sbrian if (arg->argc > arg->argn+1) { 153436285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 153536285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 153636285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 153736285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 153836285Sbrian l->ccp.cfg.deflate.in.winsize); 153936285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 154036285Sbrian } 154136285Sbrian } else 154236285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 154336285Sbrian } else { 154436285Sbrian err = "No window size specified\n"; 154536285Sbrian log_Printf(LogWARN, err); 154636285Sbrian } 154736285Sbrian break; 154837210Sbrian 154928679Sbrian case VAR_DEVICE: 155036285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 155136285Sbrian arg->argv + arg->argn); 155236285Sbrian break; 155337210Sbrian 155436285Sbrian case VAR_ACCMAP: 155536285Sbrian if (arg->argc > arg->argn) { 155637210Sbrian u_long ulong_val; 155736285Sbrian sscanf(argp, "%lx", &ulong_val); 155837210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 155936285Sbrian } else { 156036285Sbrian err = "No accmap specified\n"; 156136285Sbrian log_Printf(LogWARN, err); 156236285Sbrian } 156336285Sbrian break; 156437210Sbrian 156536285Sbrian case VAR_MODE: 156636285Sbrian mode = Nam2mode(argp); 156736285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 156836285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 156936285Sbrian return -1; 157036285Sbrian } 157136285Sbrian bundle_SetMode(arg->bundle, cx, mode); 157236285Sbrian break; 157337210Sbrian 157436285Sbrian case VAR_MRRU: 157540622Sbrian switch (bundle_Phase(arg->bundle)) { 157640622Sbrian case PHASE_DEAD: 157740622Sbrian break; 157840622Sbrian case PHASE_ESTABLISH: 157940622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 158040622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 158140622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 158240622Sbrian return 1; 158340622Sbrian } 158440622Sbrian break; 158540622Sbrian default: 158640622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 158740622Sbrian return 1; 158829696Sbrian } 158937210Sbrian long_val = atol(argp); 159037210Sbrian if (long_val && long_val < MIN_MRU) { 159137210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 159237210Sbrian return 1; 159337210Sbrian } else if (long_val > MAX_MRU) { 159437210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 159537210Sbrian return 1; 159637210Sbrian } else 159737210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 159828679Sbrian break; 159937210Sbrian 160036285Sbrian case VAR_MRU: 160137210Sbrian long_val = atol(argp); 160237210Sbrian if (long_val == 0) 160337210Sbrian l->lcp.cfg.mru = DEF_MRU; 160437210Sbrian else if (long_val < MIN_MRU) { 160537210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 160637210Sbrian return 1; 160737210Sbrian } else if (long_val > MAX_MRU) { 160837210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 160937210Sbrian return 1; 161037210Sbrian } else 161137210Sbrian l->lcp.cfg.mru = long_val; 161228679Sbrian break; 161337210Sbrian 161436285Sbrian case VAR_MTU: 161537210Sbrian long_val = atol(argp); 161637210Sbrian if (long_val && long_val < MIN_MTU) { 161737210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 161837210Sbrian return 1; 161937210Sbrian } else if (long_val > MAX_MTU) { 162037210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 162137210Sbrian return 1; 162237210Sbrian } else 162337210Sbrian arg->bundle->cfg.mtu = long_val; 162436285Sbrian break; 162537210Sbrian 162636285Sbrian case VAR_OPENMODE: 162736285Sbrian if (strcasecmp(argp, "active") == 0) 162836285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 162936285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 163036285Sbrian else if (strcasecmp(argp, "passive") == 0) 163136285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 163236285Sbrian else { 163336285Sbrian err = "%s: Invalid openmode\n"; 163436285Sbrian log_Printf(LogWARN, err, argp); 163536285Sbrian } 163636285Sbrian break; 163737210Sbrian 163828679Sbrian case VAR_PHONE: 163936285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 164036285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 164138174Sbrian cx->phone.alt = cx->phone.next = NULL; 164228679Sbrian break; 164337210Sbrian 164428679Sbrian case VAR_HANGUP: 164536285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 164636285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 164728679Sbrian break; 164837210Sbrian 164961534Sbrian case VAR_IFQUEUE: 165061534Sbrian long_val = atol(argp); 165161534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 165261534Sbrian break; 165361534Sbrian 165452488Sbrian case VAR_LOGOUT: 165552488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 165652488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 165752488Sbrian break; 165852488Sbrian 165936285Sbrian case VAR_IDLETIMEOUT: 166049978Sbrian if (arg->argc > arg->argn+2) 166136285Sbrian err = "Too many idle timeout values\n"; 166249978Sbrian else if (arg->argc == arg->argn) 166349978Sbrian err = "Too few idle timeout values\n"; 166449978Sbrian else { 166549978Sbrian int timeout, min; 166649978Sbrian 166749978Sbrian timeout = atoi(argp); 166849978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 166949978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 167049978Sbrian } 167136285Sbrian if (err) 167236285Sbrian log_Printf(LogWARN, err); 167329549Sbrian break; 167437210Sbrian 167536285Sbrian case VAR_LQRPERIOD: 167637210Sbrian long_val = atol(argp); 167737210Sbrian if (long_val < MIN_LQRPERIOD) { 167837210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 167937210Sbrian long_val, MIN_LQRPERIOD); 168037210Sbrian return 1; 168136285Sbrian } else 168237210Sbrian l->lcp.cfg.lqrperiod = long_val; 168336285Sbrian break; 168437210Sbrian 168536285Sbrian case VAR_LCPRETRY: 168644305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 168744305Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 168844305Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 168944305Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 169036285Sbrian break; 169137210Sbrian 169236285Sbrian case VAR_CHAPRETRY: 169344305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 169444305Sbrian &cx->chap.auth.cfg.fsm.timeout, 169544305Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 169636285Sbrian break; 169737210Sbrian 169836285Sbrian case VAR_PAPRETRY: 169944305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 170044305Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 170144305Sbrian NULL, DEF_FSMAUTHTRIES); 170236285Sbrian break; 170337210Sbrian 170436285Sbrian case VAR_CCPRETRY: 170544305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 170644305Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 170744305Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 170836285Sbrian break; 170937210Sbrian 171036285Sbrian case VAR_IPCPRETRY: 171144305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 171244305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 171344305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 171444305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 171536285Sbrian break; 171637210Sbrian 171736285Sbrian case VAR_NBNS: 171836285Sbrian case VAR_DNS: 171958044Sbrian if (param == VAR_DNS) { 172036285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 172158044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_NONE; 172258044Sbrian } else { 172336285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 172458044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 172558044Sbrian } 172636285Sbrian 172736285Sbrian if (arg->argc > arg->argn) { 172843313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 172936285Sbrian addr, &dummyaddr, &dummyint); 173036285Sbrian if (arg->argc > arg->argn+1) 173143313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 173236285Sbrian addr + 1, &dummyaddr, &dummyint); 173336285Sbrian 173458044Sbrian if (addr[0].s_addr == INADDR_ANY) { 173536285Sbrian addr[0].s_addr = addr[1].s_addr; 173658044Sbrian addr[1].s_addr = INADDR_ANY; 173758044Sbrian } 173858044Sbrian if (addr[0].s_addr == INADDR_NONE) { 173958044Sbrian addr[0].s_addr = addr[1].s_addr; 174058044Sbrian addr[1].s_addr = INADDR_NONE; 174158044Sbrian } 174236285Sbrian } 174336285Sbrian break; 174438174Sbrian 174538174Sbrian case VAR_CALLBACK: 174638174Sbrian cx->cfg.callback.opmask = 0; 174738174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 174838174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 174938174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 175038174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 175138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 175238174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 175338174Sbrian if (dummyint == arg->argc - 1) 175438174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 175538174Sbrian else { 175638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 175738174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 175838174Sbrian sizeof cx->cfg.callback.msg - 1); 175938174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 176038174Sbrian } 176138174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 176238174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 176338174Sbrian else 176438174Sbrian return -1; 176538174Sbrian } 176638174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 176738174Sbrian cx->cfg.callback.opmask = 0; 176838174Sbrian break; 176938174Sbrian 177038174Sbrian case VAR_CBCP: 177138174Sbrian cx->cfg.cbcp.delay = 0; 177238174Sbrian *cx->cfg.cbcp.phone = '\0'; 177338174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 177438174Sbrian if (arg->argc > arg->argn) { 177538174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 177638174Sbrian sizeof cx->cfg.cbcp.phone - 1); 177738174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 177838174Sbrian if (arg->argc > arg->argn + 1) { 177938174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 178038174Sbrian if (arg->argc > arg->argn + 2) { 178138174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 178238174Sbrian if (long_val < MIN_FSMRETRY) 178338174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 178438174Sbrian long_val, MIN_FSMRETRY); 178538174Sbrian else 178638174Sbrian cx->cfg.cbcp.fsmretry = long_val; 178738174Sbrian } 178838174Sbrian } 178938174Sbrian } 179038174Sbrian break; 179138544Sbrian 179238544Sbrian case VAR_CHOKED: 179338544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 179438544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 179538544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 179638544Sbrian break; 179740665Sbrian 179840665Sbrian case VAR_SENDPIPE: 179940665Sbrian long_val = atol(argp); 180040665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 180140665Sbrian break; 180240665Sbrian 180340665Sbrian case VAR_RECVPIPE: 180440665Sbrian long_val = atol(argp); 180540665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 180640665Sbrian break; 180743313Sbrian 180843313Sbrian#ifndef NORADIUS 180943313Sbrian case VAR_RADIUS: 181043313Sbrian if (!*argp) 181143313Sbrian *arg->bundle->radius.cfg.file = '\0'; 181243313Sbrian else if (access(argp, R_OK)) { 181343313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 181443313Sbrian return 1; 181543313Sbrian } else { 181643313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 181743313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 181843313Sbrian arg->bundle->radius.cfg.file 181943313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 182043313Sbrian } 182143313Sbrian break; 182243313Sbrian#endif 182344073Sbrian 182444073Sbrian case VAR_CD: 182544073Sbrian if (*argp) { 182651699Sbrian if (strcasecmp(argp, "off")) { 182751699Sbrian long_val = atol(argp); 182851699Sbrian if (long_val < 0) 182951699Sbrian long_val = 0; 183051699Sbrian cx->physical->cfg.cd.delay = long_val; 183151699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 183251699Sbrian CD_REQUIRED : CD_VARIABLE; 183351699Sbrian } else 183451699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 183544073Sbrian } else { 183653733Sbrian cx->physical->cfg.cd.delay = 0; 183753733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 183844073Sbrian } 183944073Sbrian break; 184036285Sbrian 184146686Sbrian case VAR_PARITY: 184246686Sbrian if (arg->argc == arg->argn + 1) 184346686Sbrian return physical_SetParity(arg->cx->physical, argp); 184446686Sbrian else { 184546686Sbrian err = "Parity value must be odd, even or none\n"; 184646686Sbrian log_Printf(LogWARN, err); 184746686Sbrian } 184846686Sbrian break; 18496059Samurai 185046686Sbrian case VAR_CRTSCTS: 185146686Sbrian if (strcasecmp(argp, "on") == 0) 185236285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 185346686Sbrian else if (strcasecmp(argp, "off") == 0) 185436285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 185546686Sbrian else { 185646686Sbrian err = "RTS/CTS value must be on or off\n"; 185746686Sbrian log_Printf(LogWARN, err); 185846686Sbrian } 185946686Sbrian break; 186050867Sbrian 186150867Sbrian case VAR_URGENTPORTS: 186251048Sbrian if (arg->argn == arg->argc) { 186361430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 186451048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 186551048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 186651048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 186761430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 186851048Sbrian if (arg->argn == arg->argc - 1) 186951048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 187051048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 187151048Sbrian if (*arg->argv[f] == '+') 187251048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 187351048Sbrian else if (*arg->argv[f] == '-') 187451048Sbrian ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp, 187551048Sbrian atoi(arg->argv[f] + 1)); 187651048Sbrian else { 187751048Sbrian if (f == arg->argn) 187851048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 187951048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 188051048Sbrian } 188161430Sbrian } else if (arg->argn == arg->argc - 1 && 188261430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 188361430Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 188461430Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 188561430Sbrian ipcp_ClearUrgentTOS(&arg->bundle->ncp.ipcp); 188651048Sbrian } else { 188761430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 188851048Sbrian first = arg->argn; 188951048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 189051048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 189151048Sbrian 189251048Sbrian for (f = first; f < arg->argc; f++) 189351048Sbrian if (*arg->argv[f] == '+') 189451048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 189551048Sbrian else if (*arg->argv[f] == '-') 189651048Sbrian ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp, 189751048Sbrian atoi(arg->argv[f] + 1)); 189851048Sbrian else { 189951048Sbrian if (f == first) 190051048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 190151048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 190251048Sbrian } 190351048Sbrian } 190450867Sbrian break; 190520812Sjkh } 190646686Sbrian 190746686Sbrian return err ? 1 : 0; 190820812Sjkh} 190920812Sjkh 191030715Sbrianstatic struct cmdtab const SetCommands[] = { 191136285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 191236285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 191328679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 191436285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 191528679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 191636285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 191736285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 191836285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 191936285Sbrian (const void *)VAR_AUTOLOAD}, 192050867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 192150867Sbrian "datalink bandwidth", "set bandwidth value"}, 192238174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 192338174Sbrian "callback control", "set callback [none|auth|cbcp|" 192438174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 192538174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 192638174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 192738174Sbrian (const void *)VAR_CBCP}, 192844305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 192944305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 193044073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 193144073Sbrian "set cd value[!]", (const void *)VAR_CD}, 193244305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 193344305Sbrian "CHAP retries", "set chapretry value [attempts]", 193444305Sbrian (const void *)VAR_CHAPRETRY}, 193538544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 193638544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 193746686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 193846686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 193946686Sbrian (const char *)VAR_CRTSCTS}, 194036285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 194136285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 194236285Sbrian (const void *) VAR_WINSIZE}, 194336285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 194446686Sbrian "physical device name", "set device|line device-name[,device-name]", 194536285Sbrian (const void *) VAR_DEVICE}, 194636285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 194736285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 194836285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 194936285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 195036285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 195136285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 195236285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 195336285Sbrian "escape characters", "set escape hex-digit ..."}, 195436285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 195536285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 195649388Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 195748142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 195836285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 195936285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 196036285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 196131343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 196261534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 196361534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 196444305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 196544305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 196644305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 196744305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 196836712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 196958033Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 197058033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 197136285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 197236285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 197352488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 197452488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 197536285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 197636285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 197736285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 197836285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 197936285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 198036285Sbrian "set mrru value", (const void *)VAR_MRRU}, 198136285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 198236285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 198336285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 198436285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 198536285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 198636285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 198736285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 198836285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 198944305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 199044305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 199146686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 199246686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 199336285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 199436285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 199540679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 199640679Sbrian "Process title", "set proctitle [value]"}, 199743313Sbrian#ifndef NORADIUS 199843313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 199943313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 200043313Sbrian#endif 200136285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 200236285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 200340665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 200440665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 200536285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 200644468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 200740665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 200840665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 200928679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 201036774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 201136285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 201246686Sbrian "physical speed", "set speed value|sync"}, 201336285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 201436285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 201536285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 201636285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 201751048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 201851048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 201936285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 202036285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 202128679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 202231343Sbrian "Display this message", "set help|? [command]", SetCommands}, 202328679Sbrian {NULL, NULL, NULL}, 20246059Samurai}; 20256059Samurai 20266059Samuraistatic int 202731343SbrianSetCommand(struct cmdargs const *arg) 20286059Samurai{ 202936285Sbrian if (arg->argc > arg->argn) 203036285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 203136285Sbrian arg->prompt, arg->cx); 203236285Sbrian else if (arg->prompt) 203336285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 203458044Sbrian " syntax help.\n"); 20356059Samurai else 203636285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 203726516Sbrian 203826516Sbrian return 0; 20396059Samurai} 20406059Samurai 20416059Samuraistatic int 204231343SbrianAddCommand(struct cmdargs const *arg) 20436059Samurai{ 20446059Samurai struct in_addr dest, gateway, netmask; 204536285Sbrian int gw, addrs; 20466059Samurai 204736285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 204831598Sbrian return -1; 204931598Sbrian 205036285Sbrian addrs = 0; 205136285Sbrian if (arg->argc == arg->argn+2) { 205236285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 205336285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 205431598Sbrian else { 205536285Sbrian int width; 205636285Sbrian 205743313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 205836285Sbrian &dest, &netmask, &width)) 205936285Sbrian return -1; 206036285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 206136285Sbrian addrs = ROUTE_DSTMYADDR; 206236285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 206336285Sbrian addrs = ROUTE_DSTHISADDR; 206458044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 206558044Sbrian addrs = ROUTE_DSTDNS0; 206658044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 206758044Sbrian addrs = ROUTE_DSTDNS1; 206831598Sbrian } 206936285Sbrian gw = 1; 207034536Sbrian } else { 207136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 207236285Sbrian addrs = ROUTE_DSTMYADDR; 207336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 207436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 207536285Sbrian addrs = ROUTE_DSTHISADDR; 207636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 207758044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 207858044Sbrian addrs = ROUTE_DSTDNS0; 207958044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 208058044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 208158044Sbrian addrs = ROUTE_DSTDNS1; 208258044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 208336285Sbrian } else 208436285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 208536285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 208631598Sbrian gw = 2; 20876059Samurai } 208836285Sbrian 208936285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 209036285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 209136285Sbrian addrs |= ROUTE_GWHISADDR; 209240561Sbrian } else 209336285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 209436285Sbrian 209536285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 209643313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 209743313Sbrian && addrs != ROUTE_STATIC) 209836285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 209936285Sbrian 210031598Sbrian return 0; 21016059Samurai} 21026059Samurai 21036059Samuraistatic int 210431343SbrianDeleteCommand(struct cmdargs const *arg) 21056059Samurai{ 210631598Sbrian struct in_addr dest, none; 210736285Sbrian int addrs; 21086059Samurai 210936285Sbrian if (arg->argc == arg->argn+1) { 211036285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 211136285Sbrian route_IfDelete(arg->bundle, 0); 211236285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 211336285Sbrian } else { 211436285Sbrian addrs = 0; 211536285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 211636285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 211736285Sbrian addrs = ROUTE_DSTMYADDR; 211836285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 211936285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 212036285Sbrian addrs = ROUTE_DSTHISADDR; 212158044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 212258044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 212358044Sbrian addrs = ROUTE_DSTDNS0; 212458044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 212558044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 212658044Sbrian addrs = ROUTE_DSTDNS1; 212736285Sbrian } else { 212844279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 212944279Sbrian if (dest.s_addr == INADDR_NONE) { 213044279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 213144279Sbrian return -1; 213244279Sbrian } 213336285Sbrian addrs = ROUTE_STATIC; 213436285Sbrian } 213531598Sbrian none.s_addr = INADDR_ANY; 213636285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 213737927Sbrian arg->cmd->args ? 1 : 0, 0); 213836285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 213931598Sbrian } 214034536Sbrian } else 214126516Sbrian return -1; 214226516Sbrian 214326516Sbrian return 0; 21446059Samurai} 21456059Samurai 214650059Sbrian#ifndef NONAT 214726031Sbrianstatic int 214858867SbrianNatEnable(struct cmdargs const *arg) 214926031Sbrian{ 215036285Sbrian if (arg->argc == arg->argn+1) { 215136285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 215250059Sbrian if (!arg->bundle->NatEnabled) { 215346686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 215446686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 215550059Sbrian arg->bundle->NatEnabled = 1; 215646686Sbrian } 215737191Sbrian return 0; 215836285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 215950059Sbrian arg->bundle->NatEnabled = 0; 216040561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 216140561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 216226516Sbrian return 0; 216326142Sbrian } 216435449Sbrian } 216536285Sbrian 216626516Sbrian return -1; 216726031Sbrian} 216826031Sbrian 216926031Sbrian 217026031Sbrianstatic int 217158867SbrianNatOption(struct cmdargs const *arg) 217226031Sbrian{ 217338559Sbrian long param = (long)arg->cmd->args; 217438559Sbrian 217536285Sbrian if (arg->argc == arg->argn+1) { 217636285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 217750059Sbrian if (arg->bundle->NatEnabled) { 217837191Sbrian PacketAliasSetMode(param, param); 217928679Sbrian return 0; 218028679Sbrian } 218150059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 218236285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 218350059Sbrian if (arg->bundle->NatEnabled) { 218437191Sbrian PacketAliasSetMode(0, param); 218528679Sbrian return 0; 218628679Sbrian } 218750059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 218828679Sbrian } 218935449Sbrian } 219028679Sbrian return -1; 219126031Sbrian} 219250059Sbrian#endif /* #ifndef NONAT */ 219331121Sbrian 219431121Sbrianstatic int 219536285SbrianLinkCommand(struct cmdargs const *arg) 219636285Sbrian{ 219736285Sbrian if (arg->argc > arg->argn+1) { 219836285Sbrian char namelist[LINE_LEN]; 219936285Sbrian struct datalink *cx; 220036285Sbrian char *name; 220136285Sbrian int result = 0; 220236285Sbrian 220336285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 220436285Sbrian struct datalink *dl; 220536285Sbrian 220636285Sbrian cx = arg->bundle->links; 220736285Sbrian while (cx) { 220836285Sbrian /* Watch it, the command could be a ``remove'' */ 220936285Sbrian dl = cx->next; 221036285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 221136285Sbrian arg->prompt, cx); 221236285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 221336285Sbrian if (cx == dl) 221436285Sbrian break; /* Pointer's still valid ! */ 221536285Sbrian } 221636285Sbrian } else { 221736285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 221836285Sbrian namelist[sizeof namelist - 1] = '\0'; 221936285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 222036285Sbrian if (!bundle2datalink(arg->bundle, name)) { 222136285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 222236285Sbrian return 1; 222336285Sbrian } 222436285Sbrian 222536285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 222636285Sbrian namelist[sizeof namelist - 1] = '\0'; 222736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 222836285Sbrian cx = bundle2datalink(arg->bundle, name); 222936285Sbrian if (cx) 223036285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 223136285Sbrian arg->prompt, cx); 223236285Sbrian else { 223336285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 223436285Sbrian result++; 223536285Sbrian } 223636285Sbrian } 223736285Sbrian } 223836285Sbrian return result; 223936285Sbrian } 224036285Sbrian 224136285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 224236285Sbrian return 2; 224336285Sbrian} 224436285Sbrian 224536285Sbrianstruct link * 224636285Sbriancommand_ChooseLink(struct cmdargs const *arg) 224736285Sbrian{ 224836285Sbrian if (arg->cx) 224936285Sbrian return &arg->cx->physical->link; 225037210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 225136285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 225237210Sbrian if (dl) 225337210Sbrian return &dl->physical->link; 225436285Sbrian } 225537210Sbrian return &arg->bundle->ncp.mp.link; 225636285Sbrian} 225736285Sbrian 225836285Sbrianstatic const char * 225936285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 226036285Sbrian{ 226136285Sbrian const char *result; 226236285Sbrian 226336285Sbrian switch (*cmd) { 226436285Sbrian case 'A': 226536285Sbrian case 'a': 226636285Sbrian result = "accept"; 226736285Sbrian *keep = NEG_MYMASK; 226836285Sbrian *add = NEG_ACCEPTED; 226936285Sbrian break; 227036285Sbrian case 'D': 227136285Sbrian case 'd': 227236285Sbrian switch (cmd[1]) { 227336285Sbrian case 'E': 227436285Sbrian case 'e': 227536285Sbrian result = "deny"; 227636285Sbrian *keep = NEG_MYMASK; 227736285Sbrian *add = 0; 227836285Sbrian break; 227936285Sbrian case 'I': 228036285Sbrian case 'i': 228136285Sbrian result = "disable"; 228236285Sbrian *keep = NEG_HISMASK; 228336285Sbrian *add = 0; 228436285Sbrian break; 228536285Sbrian default: 228636285Sbrian return NULL; 228736285Sbrian } 228836285Sbrian break; 228936285Sbrian case 'E': 229036285Sbrian case 'e': 229136285Sbrian result = "enable"; 229236285Sbrian *keep = NEG_HISMASK; 229336285Sbrian *add = NEG_ENABLED; 229436285Sbrian break; 229536285Sbrian default: 229636285Sbrian return NULL; 229736285Sbrian } 229836285Sbrian 229936285Sbrian return result; 230036285Sbrian} 230136285Sbrian 230236285Sbrianstatic int 230336285SbrianOptSet(struct cmdargs const *arg) 230436285Sbrian{ 230537574Sbrian int bit = (int)(long)arg->cmd->args; 230636285Sbrian const char *cmd; 230736285Sbrian unsigned keep; /* Keep these bits */ 230836285Sbrian unsigned add; /* Add these bits */ 230936285Sbrian 231036285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 231136285Sbrian return 1; 231236285Sbrian 231336285Sbrian if (add) 231436285Sbrian arg->bundle->cfg.opt |= bit; 231536285Sbrian else 231636285Sbrian arg->bundle->cfg.opt &= ~bit; 231736285Sbrian return 0; 231836285Sbrian} 231936285Sbrian 232036285Sbrianstatic int 232140561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 232240561Sbrian{ 232340561Sbrian unsigned save = arg->bundle->cfg.opt; 232440561Sbrian int result = OptSet(arg); 232540561Sbrian 232640561Sbrian if (result == 0) 232750059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 232840561Sbrian arg->bundle->cfg.opt = save; 232950059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 233040561Sbrian result = 2; 233140561Sbrian } 233240561Sbrian 233340561Sbrian return result; 233440561Sbrian} 233540561Sbrian 233640561Sbrianstatic int 233736285SbrianNegotiateSet(struct cmdargs const *arg) 233836285Sbrian{ 233937210Sbrian long param = (long)arg->cmd->args; 234036285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 234136285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 234236285Sbrian const char *cmd; 234336285Sbrian unsigned keep; /* Keep these bits */ 234436285Sbrian unsigned add; /* Add these bits */ 234536285Sbrian 234636285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 234736285Sbrian return 1; 234836285Sbrian 234936285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 235036285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 235136285Sbrian cmd, arg->cmd->name); 235236285Sbrian return 2; 235336285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 235436285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 235536285Sbrian cmd, arg->cmd->name, cx->name); 235636285Sbrian cx = NULL; 235736285Sbrian } 235836285Sbrian 235936285Sbrian switch (param) { 236036285Sbrian case NEG_ACFCOMP: 236136285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 236236285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 236336285Sbrian break; 236444106Sbrian case NEG_CHAP05: 236544106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 236644106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 236736285Sbrian break; 236844106Sbrian#ifdef HAVE_DES 236944106Sbrian case NEG_CHAP80: 237044106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 237144106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 237244106Sbrian break; 237344106Sbrian case NEG_CHAP80LM: 237444106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 237544106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 237644106Sbrian break; 237744106Sbrian#endif 237836285Sbrian case NEG_DEFLATE: 237936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 238036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 238136285Sbrian break; 238236285Sbrian case NEG_DNS: 238336285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 238436285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 238536285Sbrian break; 238647858Sbrian case NEG_ENDDISC: 238747858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 238847858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 238947858Sbrian break; 239036285Sbrian case NEG_LQR: 239136285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 239236285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 239336285Sbrian break; 239436285Sbrian case NEG_PAP: 239536285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 239636285Sbrian cx->physical->link.lcp.cfg.pap |= add; 239736285Sbrian break; 239836285Sbrian case NEG_PPPDDEFLATE: 239936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 240036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 240136285Sbrian break; 240236285Sbrian case NEG_PRED1: 240336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 240436285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 240536285Sbrian break; 240636285Sbrian case NEG_PROTOCOMP: 240736285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 240836285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 240936285Sbrian break; 241036285Sbrian case NEG_SHORTSEQ: 241140622Sbrian switch (bundle_Phase(arg->bundle)) { 241240622Sbrian case PHASE_DEAD: 241340622Sbrian break; 241440622Sbrian case PHASE_ESTABLISH: 241540622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 241640622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 241740622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 241840622Sbrian " LCP negotiations\n"); 241940622Sbrian return 1; 242040622Sbrian } 242140622Sbrian break; 242240622Sbrian default: 242340622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 242440622Sbrian " DEAD/ESTABLISH\n"); 242540622Sbrian return 1; 242636285Sbrian } 242740622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 242840622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 242936285Sbrian break; 243036285Sbrian case NEG_VJCOMP: 243136285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 243236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 243336285Sbrian break; 243436285Sbrian } 243536285Sbrian 243636285Sbrian return 0; 243736285Sbrian} 243836285Sbrian 243936285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 244062778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 244162778Sbrian "filter on PPPoUDP payloads", "disable|enable", 244262778Sbrian (const void *)OPT_FILTERDECAP}, 244336285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 244436285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 244540666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 244662778Sbrian "retain interface addresses", "disable|enable", 244762778Sbrian (const void *)OPT_IFACEALIAS}, 244847689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 244947689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 245036285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 245136285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 245236285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 245336285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 245440665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 245536285Sbrian "disable|enable", (const void *)OPT_PROXY}, 245640665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 245740665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 245836285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 245936285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 246036285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 246136285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 246236285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 246336285Sbrian "disable|enable", (const void *)OPT_UTMP}, 246436285Sbrian 246547689Sbrian#define OPT_MAX 10 /* accept/deny allowed below and not above */ 246636285Sbrian 246736285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 246836285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 246936285Sbrian (const void *)NEG_ACFCOMP}, 247044106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 247136285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 247244106Sbrian (const void *)NEG_CHAP05}, 247344106Sbrian#ifdef HAVE_DES 247444106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 247544106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 247644106Sbrian (const void *)NEG_CHAP80}, 247744106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 247844106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 247944106Sbrian (const void *)NEG_CHAP80LM}, 248044106Sbrian#endif 248136285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 248236285Sbrian "Deflate compression", "accept|deny|disable|enable", 248336285Sbrian (const void *)NEG_DEFLATE}, 248436285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 248536285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 248636285Sbrian (const void *)NEG_PPPDDEFLATE}, 248736285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 248836285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 248947858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 249047858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 249136285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 249236285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 249336285Sbrian (const void *)NEG_LQR}, 249436285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 249536285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 249636285Sbrian (const void *)NEG_PAP}, 249736285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 249836285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 249936285Sbrian (const void *)NEG_PRED1}, 250036285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 250136285Sbrian "Protocol field compression", "accept|deny|disable|enable", 250236285Sbrian (const void *)NEG_PROTOCOMP}, 250336285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 250436285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 250536285Sbrian (const void *)NEG_SHORTSEQ}, 250636285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 250736285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 250836285Sbrian (const void *)NEG_VJCOMP}, 250936285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 251036285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 251136285Sbrian NegotiateCommands}, 251236285Sbrian {NULL, NULL, NULL}, 251336285Sbrian}; 251436285Sbrian 251536285Sbrianstatic int 251636285SbrianNegotiateCommand(struct cmdargs const *arg) 251736285Sbrian{ 251836285Sbrian if (arg->argc > arg->argn) { 251936285Sbrian char const *argv[3]; 252036285Sbrian unsigned keep, add; 252136285Sbrian int n; 252236285Sbrian 252336285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 252436285Sbrian return -1; 252536285Sbrian argv[2] = NULL; 252636285Sbrian 252736285Sbrian for (n = arg->argn; n < arg->argc; n++) { 252836285Sbrian argv[1] = arg->argv[n]; 252936285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 253036285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 253136285Sbrian } 253236285Sbrian } else if (arg->prompt) 253336285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 253436285Sbrian arg->argv[arg->argn-1]); 253536285Sbrian else 253636285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 253736285Sbrian arg->argv[arg->argn] ); 253836285Sbrian 253936285Sbrian return 0; 254036285Sbrian} 254136285Sbrian 254236285Sbrianconst char * 254336285Sbriancommand_ShowNegval(unsigned val) 254436285Sbrian{ 254536285Sbrian switch (val&3) { 254636285Sbrian case 1: return "disabled & accepted"; 254736285Sbrian case 2: return "enabled & denied"; 254836285Sbrian case 3: return "enabled & accepted"; 254936285Sbrian } 255036285Sbrian return "disabled & denied"; 255136285Sbrian} 255236934Sbrian 255336934Sbrianstatic int 255436934SbrianClearCommand(struct cmdargs const *arg) 255536934Sbrian{ 255636934Sbrian struct pppThroughput *t; 255736934Sbrian struct datalink *cx; 255836934Sbrian int i, clear_type; 255936934Sbrian 256036934Sbrian if (arg->argc < arg->argn + 1) 256136934Sbrian return -1; 256236934Sbrian 256346686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 256436934Sbrian cx = arg->cx; 256536934Sbrian if (!cx) 256636934Sbrian cx = bundle2datalink(arg->bundle, NULL); 256736934Sbrian if (!cx) { 256846686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 256936934Sbrian return 1; 257036934Sbrian } 257136934Sbrian t = &cx->physical->link.throughput; 257236934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 257336934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 257436934Sbrian else 257536934Sbrian return -1; 257636934Sbrian 257736934Sbrian if (arg->argc > arg->argn + 1) { 257836934Sbrian clear_type = 0; 257936934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 258036934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 258136934Sbrian clear_type |= THROUGHPUT_OVERALL; 258236934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 258336934Sbrian clear_type |= THROUGHPUT_CURRENT; 258436934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 258536934Sbrian clear_type |= THROUGHPUT_PEAK; 258636934Sbrian else 258736934Sbrian return -1; 258836934Sbrian } else 258936934Sbrian clear_type = THROUGHPUT_ALL; 259036934Sbrian 259136934Sbrian throughput_clear(t, clear_type, arg->prompt); 259236934Sbrian return 0; 259336934Sbrian} 259440561Sbrian 259540561Sbrianstatic int 259640561SbrianRunListCommand(struct cmdargs const *arg) 259740561Sbrian{ 259840561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 259940561Sbrian 260040561Sbrian if (arg->argc > arg->argn) 260140561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 260240561Sbrian arg->prompt, arg->cx); 260340561Sbrian else if (arg->prompt) 260440561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 260540561Sbrian " <option>' for syntax help.\n", cmd, cmd); 260640561Sbrian else 260740561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 260840561Sbrian 260940561Sbrian return 0; 261040561Sbrian} 261140561Sbrian 261240561Sbrianstatic int 261340561SbrianIfaceAddCommand(struct cmdargs const *arg) 261440561Sbrian{ 261540561Sbrian int bits, n, how; 261640561Sbrian struct in_addr ifa, mask, brd; 261740561Sbrian 261840664Sbrian if (arg->argc == arg->argn + 1) { 261943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 262040561Sbrian return -1; 262140664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 262240664Sbrian } else { 262340664Sbrian if (arg->argc == arg->argn + 2) { 262443313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 262540664Sbrian return -1; 262640664Sbrian n = 1; 262740664Sbrian } else if (arg->argc == arg->argn + 3) { 262843313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 262940664Sbrian return -1; 263043313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 263140664Sbrian return -1; 263240664Sbrian n = 2; 263340664Sbrian } else 263440561Sbrian return -1; 263540561Sbrian 263643313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 263740664Sbrian return -1; 263840664Sbrian } 263940561Sbrian 264040561Sbrian how = IFACE_ADD_LAST; 264140561Sbrian if (arg->cmd->args) 264240561Sbrian how |= IFACE_FORCE_ADD; 264340561Sbrian 264440561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 264540561Sbrian} 264640561Sbrian 264740561Sbrianstatic int 264840561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 264940561Sbrian{ 265040561Sbrian struct in_addr ifa; 265140561Sbrian int ok; 265240561Sbrian 265340561Sbrian if (arg->argc != arg->argn + 1) 265440561Sbrian return -1; 265540561Sbrian 265643313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 265740561Sbrian return -1; 265840561Sbrian 265940561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 266040561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 266140561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 266240561Sbrian inet_ntoa(ifa)); 266340561Sbrian return 1; 266440561Sbrian } 266540561Sbrian 266640561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 266740561Sbrian if (!ok) { 266840561Sbrian if (arg->cmd->args) 266940561Sbrian ok = 1; 267040561Sbrian else if (arg->prompt) 267140561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 267240561Sbrian else 267340561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 267440561Sbrian } 267540561Sbrian 267640561Sbrian return !ok; 267740561Sbrian} 267840561Sbrian 267940561Sbrianstatic int 268040561SbrianIfaceClearCommand(struct cmdargs const *arg) 268140561Sbrian{ 268240561Sbrian int how; 268340561Sbrian 268440561Sbrian if (arg->argc != arg->argn) 268540561Sbrian return -1; 268640561Sbrian 268740941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 268840941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 268940561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 269040561Sbrian iface_Clear(arg->bundle->iface, how); 269140561Sbrian 269240561Sbrian return 0; 269340561Sbrian} 269440679Sbrian 269540679Sbrianstatic int 269640679SbrianSetProcTitle(struct cmdargs const *arg) 269740679Sbrian{ 269840679Sbrian static char title[LINE_LEN]; 269940679Sbrian char *argv[MAXARGS], *ptr; 270040679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 270140679Sbrian 270240679Sbrian if (arg->argc == arg->argn) { 270353298Sbrian ID0setproctitle(NULL); 270440679Sbrian return 0; 270540679Sbrian } 270640679Sbrian 270740679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 270840679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 270940679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 271040679Sbrian } 271147849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 271240679Sbrian 271340679Sbrian ptr = title; 271440679Sbrian remaining = sizeof title - 1; 271540679Sbrian for (f = 0; f < argc && remaining; f++) { 271640679Sbrian if (f) { 271740679Sbrian *ptr++ = ' '; 271840679Sbrian remaining--; 271940679Sbrian } 272040679Sbrian len = strlen(argv[f]); 272140679Sbrian if (len > remaining) 272240679Sbrian len = remaining; 272340679Sbrian memcpy(ptr, argv[f], len); 272440679Sbrian remaining -= len; 272540679Sbrian ptr += len; 272640679Sbrian } 272740679Sbrian *ptr = '\0'; 272840679Sbrian 272953298Sbrian ID0setproctitle(title); 273040679Sbrian 273140679Sbrian return 0; 273240679Sbrian} 2733