command.c revision 120372
178189Sbrian/*- 278189Sbrian * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 378189Sbrian * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 478189Sbrian * Internet Initiative Japan, Inc (IIJ) 578189Sbrian * All rights reserved. 66059Samurai * 778189Sbrian * Redistribution and use in source and binary forms, with or without 878189Sbrian * modification, are permitted provided that the following conditions 978189Sbrian * are met: 1078189Sbrian * 1. Redistributions of source code must retain the above copyright 1178189Sbrian * notice, this list of conditions and the following disclaimer. 1278189Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1378189Sbrian * notice, this list of conditions and the following disclaimer in the 1478189Sbrian * documentation and/or other materials provided with the distribution. 156059Samurai * 1678189Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1778189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1878189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1978189Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2078189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2178189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2278189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2378189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2478189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2578189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2678189Sbrian * SUCH DAMAGE. 276059Samurai * 2850479Speter * $FreeBSD: head/usr.sbin/ppp/command.c 120372 2003-09-23 07:41:55Z marcus $ 296059Samurai */ 3078189Sbrian 3143313Sbrian#include <sys/param.h> 3230715Sbrian#include <netinet/in_systm.h> 3326031Sbrian#include <netinet/in.h> 3430715Sbrian#include <netinet/ip.h> 3526031Sbrian#include <arpa/inet.h> 3630715Sbrian#include <sys/socket.h> 3726031Sbrian#include <net/route.h> 3830715Sbrian#include <netdb.h> 3936285Sbrian#include <sys/un.h> 4030715Sbrian 4138628Sbrian#include <ctype.h> 4230715Sbrian#include <errno.h> 4326516Sbrian#include <fcntl.h> 4430715Sbrian#include <paths.h> 45102500Sbrian#include <stdarg.h> 4630715Sbrian#include <stdio.h> 4730715Sbrian#include <stdlib.h> 4830715Sbrian#include <string.h> 4930715Sbrian#include <sys/wait.h> 5030715Sbrian#include <termios.h> 5130715Sbrian#include <unistd.h> 5230715Sbrian 5350059Sbrian#ifndef NONAT 5458037Sbrian#ifdef LOCALNAT 5558037Sbrian#include "alias.h" 5658037Sbrian#else 5746086Sbrian#include <alias.h> 5839395Sbrian#endif 5939395Sbrian#endif 6058037Sbrian 6146686Sbrian#include "layer.h" 6237009Sbrian#include "defs.h" 6331343Sbrian#include "command.h" 6430715Sbrian#include "mbuf.h" 6530715Sbrian#include "log.h" 6630715Sbrian#include "timer.h" 676059Samurai#include "fsm.h" 6831690Sbrian#include "iplist.h" 6936285Sbrian#include "throughput.h" 7036285Sbrian#include "slcompress.h" 7138557Sbrian#include "lqr.h" 7238557Sbrian#include "hdlc.h" 7363484Sbrian#include "lcp.h" 7481634Sbrian#include "ncpaddr.h" 756059Samurai#include "ipcp.h" 7650059Sbrian#ifndef NONAT 7751075Sbrian#include "nat_cmd.h" 7831343Sbrian#endif 7925630Sbrian#include "systems.h" 8036285Sbrian#include "filter.h" 8136285Sbrian#include "descriptor.h" 8230715Sbrian#include "main.h" 8330715Sbrian#include "route.h" 8430715Sbrian#include "ccp.h" 8531080Sbrian#include "auth.h" 8636285Sbrian#include "async.h" 8736285Sbrian#include "link.h" 8836285Sbrian#include "physical.h" 8936285Sbrian#include "mp.h" 9043313Sbrian#ifndef NORADIUS 9143313Sbrian#include "radius.h" 9243313Sbrian#endif 9381634Sbrian#include "ipv6cp.h" 9481634Sbrian#include "ncp.h" 9536285Sbrian#include "bundle.h" 9636285Sbrian#include "server.h" 9736285Sbrian#include "prompt.h" 9836285Sbrian#include "chat.h" 9936285Sbrian#include "chap.h" 10038174Sbrian#include "cbcp.h" 10136285Sbrian#include "datalink.h" 10240561Sbrian#include "iface.h" 10353298Sbrian#include "id.h" 10481697Sbrian#include "probe.h" 1056059Samurai 10636285Sbrian/* ``set'' values */ 10736285Sbrian#define VAR_AUTHKEY 0 10836285Sbrian#define VAR_DIAL 1 10936285Sbrian#define VAR_LOGIN 2 11036285Sbrian#define VAR_AUTHNAME 3 11136285Sbrian#define VAR_AUTOLOAD 4 11236285Sbrian#define VAR_WINSIZE 5 11336285Sbrian#define VAR_DEVICE 6 11436285Sbrian#define VAR_ACCMAP 7 11536285Sbrian#define VAR_MRRU 8 11636285Sbrian#define VAR_MRU 9 11736285Sbrian#define VAR_MTU 10 11836285Sbrian#define VAR_OPENMODE 11 11936285Sbrian#define VAR_PHONE 12 12036285Sbrian#define VAR_HANGUP 13 12136285Sbrian#define VAR_IDLETIMEOUT 14 12236285Sbrian#define VAR_LQRPERIOD 15 12336285Sbrian#define VAR_LCPRETRY 16 12436285Sbrian#define VAR_CHAPRETRY 17 12536285Sbrian#define VAR_PAPRETRY 18 12636285Sbrian#define VAR_CCPRETRY 19 12736285Sbrian#define VAR_IPCPRETRY 20 12836285Sbrian#define VAR_DNS 21 12936285Sbrian#define VAR_NBNS 22 13036285Sbrian#define VAR_MODE 23 13138174Sbrian#define VAR_CALLBACK 24 13238174Sbrian#define VAR_CBCP 25 13338544Sbrian#define VAR_CHOKED 26 13440665Sbrian#define VAR_SENDPIPE 27 13540665Sbrian#define VAR_RECVPIPE 28 13643313Sbrian#define VAR_RADIUS 29 13744073Sbrian#define VAR_CD 30 13846686Sbrian#define VAR_PARITY 31 13946686Sbrian#define VAR_CRTSCTS 32 14050867Sbrian#define VAR_URGENTPORTS 33 14152488Sbrian#define VAR_LOGOUT 34 14261534Sbrian#define VAR_IFQUEUE 35 14378411Sbrian#define VAR_MPPE 36 144102558Sbrian#define VAR_IPV6CPRETRY 37 1456059Samurai 14636285Sbrian/* ``accept|deny|disable|enable'' masks */ 14736285Sbrian#define NEG_HISMASK (1) 14836285Sbrian#define NEG_MYMASK (2) 14936285Sbrian 15036285Sbrian/* ``accept|deny|disable|enable'' values */ 15136285Sbrian#define NEG_ACFCOMP 40 15244106Sbrian#define NEG_CHAP05 41 15344106Sbrian#define NEG_CHAP80 42 15444106Sbrian#define NEG_CHAP80LM 43 15544106Sbrian#define NEG_DEFLATE 44 15647858Sbrian#define NEG_DNS 45 15747858Sbrian#define NEG_ENDDISC 46 15847858Sbrian#define NEG_LQR 47 15947858Sbrian#define NEG_PAP 48 16047858Sbrian#define NEG_PPPDDEFLATE 49 16147858Sbrian#define NEG_PRED1 50 16247858Sbrian#define NEG_PROTOCOMP 51 16347858Sbrian#define NEG_SHORTSEQ 52 16447858Sbrian#define NEG_VJCOMP 53 16567910Sbrian#define NEG_MPPE 54 16667910Sbrian#define NEG_CHAP81 55 16736285Sbrian 16898150Sbrianconst char Version[] = "3.1"; 16936285Sbrian 17036285Sbrianstatic int ShowCommand(struct cmdargs const *); 17136285Sbrianstatic int TerminalCommand(struct cmdargs const *); 17236285Sbrianstatic int QuitCommand(struct cmdargs const *); 17336285Sbrianstatic int OpenCommand(struct cmdargs const *); 17436285Sbrianstatic int CloseCommand(struct cmdargs const *); 17536285Sbrianstatic int DownCommand(struct cmdargs const *); 17636285Sbrianstatic int SetCommand(struct cmdargs const *); 17736285Sbrianstatic int LinkCommand(struct cmdargs const *); 17836285Sbrianstatic int AddCommand(struct cmdargs const *); 17936285Sbrianstatic int DeleteCommand(struct cmdargs const *); 18036285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 18136934Sbrianstatic int ClearCommand(struct cmdargs const *); 18240561Sbrianstatic int RunListCommand(struct cmdargs const *); 18340561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 18440561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 18540561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 18640679Sbrianstatic int SetProcTitle(struct cmdargs const *); 18750059Sbrian#ifndef NONAT 18858867Sbrianstatic int NatEnable(struct cmdargs const *); 18958867Sbrianstatic int NatOption(struct cmdargs const *); 19031343Sbrian#endif 1916059Samurai 19236285Sbrianstatic const char * 19336285Sbrianshowcx(struct cmdtab const *cmd) 19436285Sbrian{ 19536285Sbrian if (cmd->lauth & LOCAL_CX) 19636285Sbrian return "(c)"; 19736285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 19836285Sbrian return "(o)"; 19936285Sbrian 20036285Sbrian return ""; 20136285Sbrian} 20236285Sbrian 2036059Samuraistatic int 20431343SbrianHelpCommand(struct cmdargs const *arg) 2056059Samurai{ 20628679Sbrian struct cmdtab const *cmd; 20736285Sbrian int n, cmax, dmax, cols, cxlen; 20836285Sbrian const char *cx; 2096059Samurai 21036285Sbrian if (!arg->prompt) { 21136285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 21226516Sbrian return 0; 21336285Sbrian } 21426516Sbrian 21536285Sbrian if (arg->argc > arg->argn) { 21636285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 21736285Sbrian if ((cmd->lauth & arg->prompt->auth) && 21836285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 21936285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 22036285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 22128679Sbrian return 0; 2226059Samurai } 22326516Sbrian return -1; 2246059Samurai } 22536285Sbrian 22631372Sbrian cmax = dmax = 0; 22736285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22836285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22936285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 23031372Sbrian cmax = n; 23131372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 23231372Sbrian dmax = n; 23331372Sbrian } 23431372Sbrian 23531372Sbrian cols = 80 / (dmax + cmax + 3); 2366059Samurai n = 0; 23736285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 23836285Sbrian " (c) = Context required\n"); 23936285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 24036285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 24136285Sbrian cx = showcx(cmd); 24236285Sbrian cxlen = cmax - strlen(cmd->name); 24340482Sbrian if (n % cols != 0) 24440482Sbrian prompt_Printf(arg->prompt, " "); 24540482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 24636285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 24731372Sbrian if (++n % cols == 0) 24836285Sbrian prompt_Printf(arg->prompt, "\n"); 2496059Samurai } 25031372Sbrian if (n % cols != 0) 25136285Sbrian prompt_Printf(arg->prompt, "\n"); 25226516Sbrian 25326516Sbrian return 0; 2546059Samurai} 2556059Samurai 25636285Sbrianstatic int 25763484SbrianIdentCommand(struct cmdargs const *arg) 25863484Sbrian{ 25985991Sbrian Concatinate(arg->cx->physical->link.lcp.cfg.ident, 26085991Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident, 26185991Sbrian arg->argc - arg->argn, arg->argv + arg->argn); 26263484Sbrian return 0; 26363484Sbrian} 26463484Sbrian 26563484Sbrianstatic int 26663484SbrianSendIdentification(struct cmdargs const *arg) 26763484Sbrian{ 26863484Sbrian if (arg->cx->state < DATALINK_LCP) { 26963484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 27063484Sbrian return 2; 27163484Sbrian } 27263484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 27363484Sbrian} 27463484Sbrian 27563484Sbrianstatic int 27636285SbrianCloneCommand(struct cmdargs const *arg) 2776059Samurai{ 27836285Sbrian char namelist[LINE_LEN]; 27936285Sbrian char *name; 28036285Sbrian int f; 2816059Samurai 28236285Sbrian if (arg->argc == arg->argn) 28336285Sbrian return -1; 28436285Sbrian 28536285Sbrian namelist[sizeof namelist - 1] = '\0'; 28636285Sbrian for (f = arg->argn; f < arg->argc; f++) { 28736285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 28836285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 28936285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2906059Samurai } 29136285Sbrian 29236285Sbrian return 0; 2936059Samurai} 2946059Samurai 2956059Samuraistatic int 29636285SbrianRemoveCommand(struct cmdargs const *arg) 2976059Samurai{ 29836285Sbrian if (arg->argc != arg->argn) 29936285Sbrian return -1; 30011336Samurai 30136285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 30236285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 30336285Sbrian return 2; 3046059Samurai } 30526516Sbrian 30636285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 30736285Sbrian return 0; 30836285Sbrian} 30932711Sbrian 31036285Sbrianstatic int 31136285SbrianRenameCommand(struct cmdargs const *arg) 31236285Sbrian{ 31336285Sbrian if (arg->argc != arg->argn + 1) 31436285Sbrian return -1; 31531121Sbrian 31636285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 31736285Sbrian return 0; 31836285Sbrian 31998243Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 32036285Sbrian arg->cx->name, arg->argv[arg->argn]); 32136285Sbrian return 1; 32236285Sbrian} 32336285Sbrian 32485991Sbrianstatic int 32536285SbrianLoadCommand(struct cmdargs const *arg) 32636285Sbrian{ 32740797Sbrian const char *err; 32840797Sbrian int n, mode; 32936285Sbrian 33040797Sbrian mode = arg->bundle->phys_type.all; 33136285Sbrian 33240797Sbrian if (arg->argn < arg->argc) { 33340797Sbrian for (n = arg->argn; n < arg->argc; n++) 33440797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 33540797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 33640797Sbrian return 1; 33740797Sbrian } 33840797Sbrian 33940797Sbrian for (n = arg->argn; n < arg->argc; n++) { 34040797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34140797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 34240797Sbrian } 34340797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34440797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 34540797Sbrian log_Printf(LogWARN, "default: %s\n", err); 34636285Sbrian return 1; 34736285Sbrian } else { 34840797Sbrian bundle_SetLabel(arg->bundle, "default"); 34940797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 35040797Sbrian bundle_SetLabel(arg->bundle, "default"); 35136285Sbrian } 35240797Sbrian 35326516Sbrian return 0; 3546059Samurai} 3556059Samurai 35685991Sbrianstatic int 35785991SbrianLogCommand(struct cmdargs const *arg) 35885991Sbrian{ 35985991Sbrian char buf[LINE_LEN]; 36085991Sbrian 36185991Sbrian if (arg->argn < arg->argc) { 36285991Sbrian char *argv[MAXARGS]; 36385991Sbrian int argc = arg->argc - arg->argn; 36485991Sbrian 36585991Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 36685991Sbrian argc = sizeof argv / sizeof argv[0] - 1; 36785991Sbrian log_Printf(LogWARN, "Truncating log command to %d args\n", argc); 36885991Sbrian } 36986760Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 37085991Sbrian Concatinate(buf, sizeof buf, argc, (const char *const *)argv); 37185991Sbrian log_Printf(LogLOG, "%s\n", buf); 37285991Sbrian command_Free(argc, argv); 37385991Sbrian return 0; 37485991Sbrian } 37585991Sbrian 37685991Sbrian return -1; 37785991Sbrian} 37885991Sbrian 37985991Sbrianstatic int 38036285SbrianSaveCommand(struct cmdargs const *arg) 38136285Sbrian{ 38285991Sbrian log_Printf(LogWARN, "save command is not yet implemented.\n"); 38336285Sbrian return 1; 38436285Sbrian} 38536285Sbrian 38610528Samuraistatic int 38736285SbrianDialCommand(struct cmdargs const *arg) 38828536Sbrian{ 38936285Sbrian int res; 39036285Sbrian 39136465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 39236465Sbrian || (!arg->cx && 39336928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 39436285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 39536285Sbrian " interactive links\n"); 39636285Sbrian return 1; 39734536Sbrian } 39836285Sbrian 39936285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 40036285Sbrian return res; 40136285Sbrian 40237993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 40336285Sbrian 40436285Sbrian return 0; 40528536Sbrian} 40628536Sbrian 40738628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 40838628Sbrian 40938628Sbrianstatic char * 41038628Sbrianstrstrword(char *big, const char *little) 41138628Sbrian{ 41238628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 41338628Sbrian char *pos; 41438628Sbrian int len; 41538628Sbrian 41638628Sbrian pos = big; 41738628Sbrian len = strlen(little); 41838628Sbrian 41938628Sbrian while ((pos = strstr(pos, little)) != NULL) 42047865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 42147865Sbrian pos++; 42247865Sbrian else if (pos != big && pos[-1] == '\\') 42347865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 42447865Sbrian else 42538628Sbrian break; 42638628Sbrian 42738628Sbrian return pos; 42838628Sbrian} 42938628Sbrian 43038628Sbrianstatic char * 43138628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 43238628Sbrian{ 43338628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 43438628Sbrian char *word, *ntgt; 43538628Sbrian int ltgt, loldstr, lnewstr, pos; 43638628Sbrian 43738628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 43838628Sbrian return tgt; 43938628Sbrian 44038628Sbrian ltgt = strlen(tgt) + 1; 44138628Sbrian loldstr = strlen(oldstr); 44238628Sbrian lnewstr = strlen(newstr); 44338628Sbrian do { 44438628Sbrian pos = word - tgt; 44538628Sbrian if (loldstr > lnewstr) 44638628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 44738628Sbrian if (loldstr != lnewstr) { 44838628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 44938628Sbrian if (ntgt == NULL) 45038628Sbrian break; /* Oh wonderful ! */ 45138628Sbrian word = ntgt + pos; 45238628Sbrian tgt = ntgt; 45338628Sbrian } 45438628Sbrian if (lnewstr > loldstr) 45538628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 45638628Sbrian bcopy(newstr, word, lnewstr); 45738628Sbrian } while ((word = strstrword(word, oldstr))); 45838628Sbrian 45938628Sbrian return tgt; 46038628Sbrian} 46138628Sbrian 46294934Sbrianstatic char * 46394934Sbriansubstip(char *tgt, const char *oldstr, struct in_addr ip) 46494934Sbrian{ 46594934Sbrian return subst(tgt, oldstr, inet_ntoa(ip)); 46694934Sbrian} 46794934Sbrian 46894934Sbrianstatic char * 46997360Sbriansubstlong(char *tgt, const char *oldstr, long l) 47094934Sbrian{ 47197360Sbrian char buf[23]; 47294934Sbrian 47397360Sbrian snprintf(buf, sizeof buf, "%ld", l); 47494934Sbrian 47594934Sbrian return subst(tgt, oldstr, buf); 47694934Sbrian} 47794934Sbrian 47894934Sbrianstatic char * 47994934Sbriansubstull(char *tgt, const char *oldstr, unsigned long long ull) 48094934Sbrian{ 48194934Sbrian char buf[21]; 48294934Sbrian 48394934Sbrian snprintf(buf, sizeof buf, "%llu", ull); 48494934Sbrian 48594934Sbrian return subst(tgt, oldstr, buf); 48694934Sbrian} 48794934Sbrian 48894934Sbrian 48994934Sbrian#ifndef NOINET6 49094934Sbrianstatic char * 49194934Sbriansubstipv6(char *tgt, const char *oldstr, const struct ncpaddr *ip) 49294934Sbrian{ 49394934Sbrian return subst(tgt, oldstr, ncpaddr_ntoa(ip)); 49494934Sbrian} 495116622Sume 496116622Sume#ifndef NORADIUS 497116622Sumestatic char * 498116622Sumesubstipv6prefix(char *tgt, const char *oldstr, const uint8_t *ipv6prefix) 499116622Sume{ 500116622Sume uint8_t ipv6addr[INET6_ADDRSTRLEN]; 501116622Sume uint8_t prefix[INET6_ADDRSTRLEN + sizeof("/128") - 1]; 502116622Sume 503116622Sume if (ipv6prefix) { 504116622Sume inet_ntop(AF_INET6, &ipv6prefix[2], ipv6addr, sizeof(ipv6addr)); 505116622Sume snprintf(prefix, sizeof(prefix), "%s/%d", ipv6addr, ipv6prefix[1]); 506116622Sume } else 507116622Sume prefix[0] = '\0'; 508116622Sume return subst(tgt, oldstr, prefix); 509116622Sume} 51094934Sbrian#endif 511116622Sume#endif 51294934Sbrian 51343888Sbrianvoid 51443888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 51547849Sbrian struct bundle *bundle, int inc0, pid_t pid) 51638628Sbrian{ 51785991Sbrian int arg, secs; 51894934Sbrian char uptime[20]; 51994934Sbrian unsigned long long oin, oout, pin, pout; 52038628Sbrian 52141755Sbrian if (inc0) 52241755Sbrian arg = 0; /* Start at arg 0 */ 52341755Sbrian else { 52441755Sbrian nargv[0] = strdup(oargv[0]); 52541755Sbrian arg = 1; 52641755Sbrian } 52794934Sbrian 52894934Sbrian secs = bundle_Uptime(bundle); 52994934Sbrian snprintf(uptime, sizeof uptime, "%d:%02d:%02d", 53094934Sbrian secs / 3600, (secs / 60) % 60, secs % 60); 53194934Sbrian oin = bundle->ncp.ipcp.throughput.OctetsIn; 53294934Sbrian oout = bundle->ncp.ipcp.throughput.OctetsOut; 53394934Sbrian pin = bundle->ncp.ipcp.throughput.PacketsIn; 53494934Sbrian pout = bundle->ncp.ipcp.throughput.PacketsOut; 53594934Sbrian#ifndef NOINET6 53694934Sbrian oin += bundle->ncp.ipv6cp.throughput.OctetsIn; 53794934Sbrian oout += bundle->ncp.ipv6cp.throughput.OctetsOut; 53894934Sbrian pin += bundle->ncp.ipv6cp.throughput.PacketsIn; 53994934Sbrian pout += bundle->ncp.ipv6cp.throughput.PacketsOut; 54094934Sbrian#endif 54194934Sbrian 54241755Sbrian for (; arg < argc; arg++) { 54338629Sbrian nargv[arg] = strdup(oargv[arg]); 54494934Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 54594934Sbrian nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 54694934Sbrian nargv[arg] = substip(nargv[arg], "DNS0", bundle->ncp.ipcp.ns.dns[0]); 54794934Sbrian nargv[arg] = substip(nargv[arg], "DNS1", bundle->ncp.ipcp.ns.dns[1]); 54898243Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 54994934Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 55094934Sbrian bundle->ncp.mp.cfg.enddisc.address, 55194934Sbrian bundle->ncp.mp.cfg.enddisc.len)); 55294934Sbrian nargv[arg] = substip(nargv[arg], "HISADDR", bundle->ncp.ipcp.peer_ip); 55381634Sbrian#ifndef NOINET6 55494934Sbrian nargv[arg] = substipv6(nargv[arg], "HISADDR6", &bundle->ncp.ipv6cp.hisaddr); 55581634Sbrian#endif 55640561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 55794934Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSIN", 55894934Sbrian bundle->ncp.ipcp.throughput.OctetsIn); 55998243Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSOUT", 56094934Sbrian bundle->ncp.ipcp.throughput.OctetsOut); 56198243Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSIN", 56294934Sbrian bundle->ncp.ipcp.throughput.PacketsIn); 56398243Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSOUT", 56494934Sbrian bundle->ncp.ipcp.throughput.PacketsOut); 56581634Sbrian#ifndef NOINET6 56698243Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSIN", 56794934Sbrian bundle->ncp.ipv6cp.throughput.OctetsIn); 56898243Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSOUT", 56994934Sbrian bundle->ncp.ipv6cp.throughput.OctetsOut); 57098243Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSIN", 57194934Sbrian bundle->ncp.ipv6cp.throughput.PacketsIn); 57298243Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSOUT", 57394934Sbrian bundle->ncp.ipv6cp.throughput.PacketsOut); 57481634Sbrian#endif 57594934Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 57694934Sbrian nargv[arg] = substip(nargv[arg], "MYADDR", bundle->ncp.ipcp.my_ip); 57794934Sbrian#ifndef NOINET6 57894934Sbrian nargv[arg] = substipv6(nargv[arg], "MYADDR6", &bundle->ncp.ipv6cp.myaddr); 579116622Sume#ifndef NORADIUS 580116622Sume nargv[arg] = substipv6prefix(nargv[arg], "IPV6PREFIX", 581116622Sume bundle->radius.ipv6prefix); 58294934Sbrian#endif 583116622Sume#endif 58494934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSIN", oin); 58594934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSOUT", oout); 58694934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSIN", pin); 58794934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSOUT", pout); 58838629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 58938629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 59038629Sbrian bundle->ncp.mp.peer.enddisc.address, 59138629Sbrian bundle->ncp.mp.peer.enddisc.len)); 59297360Sbrian nargv[arg] = substlong(nargv[arg], "PROCESSID", pid); 59394934Sbrian if (server.cfg.port) 59497360Sbrian nargv[arg] = substlong(nargv[arg], "SOCKNAME", server.cfg.port); 59594934Sbrian else 59694934Sbrian nargv[arg] = subst(nargv[arg], "SOCKNAME", server.cfg.sockname); 59794934Sbrian nargv[arg] = subst(nargv[arg], "UPTIME", uptime); 59894934Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 59963484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 60038628Sbrian } 60138628Sbrian nargv[arg] = NULL; 60238628Sbrian} 60338628Sbrian 60485991Sbrianvoid 60585991Sbriancommand_Free(int argc, char **argv) 60685991Sbrian{ 60785991Sbrian while (argc) { 60885991Sbrian free(*argv); 60985991Sbrian argc--; 61085991Sbrian argv++; 61185991Sbrian } 61285991Sbrian} 61385991Sbrian 61428536Sbrianstatic int 61531343SbrianShellCommand(struct cmdargs const *arg, int bg) 61610528Samurai{ 61710528Samurai const char *shell; 61847849Sbrian pid_t shpid, pid; 61920813Sjkh 62018856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 62126911Sbrian /* we're only allowed to shell when we run ppp interactively */ 62236285Sbrian if (arg->prompt && arg->prompt->owner) { 62336285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 62426516Sbrian return 1; 62510528Samurai } 62626911Sbrian#endif 62728679Sbrian 62836285Sbrian if (arg->argc == arg->argn) { 62936285Sbrian if (!arg->prompt) { 63036285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 63136285Sbrian " a config file\n"); 63228381Sbrian return 1; 63336285Sbrian } else if (arg->prompt->owner) { 63436285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 63536285Sbrian " a socket connection\n"); 63636285Sbrian return 1; 63728381Sbrian } else if (bg) { 63836285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 63928679Sbrian " the foreground mode\n"); 64028381Sbrian return 1; 64128381Sbrian } 64234536Sbrian } 64334536Sbrian 64447849Sbrian pid = getpid(); 64528679Sbrian if ((shpid = fork()) == 0) { 64636285Sbrian int i, fd; 64718531Sbde 64836285Sbrian if ((shell = getenv("SHELL")) == 0) 64936285Sbrian shell = _PATH_BSHELL; 65032017Sbrian 65136285Sbrian timer_TermService(); 65236285Sbrian 65336285Sbrian if (arg->prompt) 65436285Sbrian fd = arg->prompt->fd_out; 65536285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 65636285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 65736285Sbrian _PATH_DEVNULL, strerror(errno)); 65828679Sbrian exit(1); 65928679Sbrian } 66049976Sbrian dup2(fd, STDIN_FILENO); 66149976Sbrian dup2(fd, STDOUT_FILENO); 66249976Sbrian dup2(fd, STDERR_FILENO); 66349976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 66449976Sbrian fcntl(i, F_SETFD, 1); 66526516Sbrian 66664802Sbrian#ifndef NOSUID 66755252Sbrian setuid(ID0realuid()); 66864802Sbrian#endif 66936285Sbrian if (arg->argc > arg->argn) { 67028679Sbrian /* substitute pseudo args */ 67138628Sbrian char *argv[MAXARGS]; 67238628Sbrian int argc = arg->argc - arg->argn; 67338628Sbrian 67438628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 67538628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 67638628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 67731343Sbrian } 67847849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 67928679Sbrian if (bg) { 68028679Sbrian pid_t p; 68110528Samurai 68228679Sbrian p = getpid(); 68328679Sbrian if (daemon(1, 1) == -1) { 68497360Sbrian log_Printf(LogERROR, "%ld: daemon: %s\n", (long)p, strerror(errno)); 68528679Sbrian exit(1); 68628679Sbrian } 68736285Sbrian } else if (arg->prompt) 68836285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 68931343Sbrian execvp(argv[0], argv); 69030316Sbrian } else { 69136285Sbrian if (arg->prompt) 69232017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 69336285Sbrian prompt_TtyOldMode(arg->prompt); 69479450Sbrian execl(shell, shell, (char *)NULL); 69530316Sbrian } 69620813Sjkh 69740665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 69840665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 69940665Sbrian strerror(errno)); 70049976Sbrian _exit(255); 70110528Samurai } 70236285Sbrian 70397360Sbrian if (shpid == (pid_t)-1) 70436285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 70536285Sbrian else { 70610528Samurai int status; 70731343Sbrian waitpid(shpid, &status, 0); 70810528Samurai } 70920813Sjkh 71036285Sbrian if (arg->prompt && !arg->prompt->owner) 71136285Sbrian prompt_TtyCommandMode(arg->prompt); 71220813Sjkh 71336285Sbrian return 0; 71410528Samurai} 71510528Samurai 71631343Sbrianstatic int 71731343SbrianBgShellCommand(struct cmdargs const *arg) 71831343Sbrian{ 71936285Sbrian if (arg->argc == arg->argn) 72031343Sbrian return -1; 72131343Sbrian return ShellCommand(arg, 1); 72231343Sbrian} 72331343Sbrian 72431343Sbrianstatic int 72531343SbrianFgShellCommand(struct cmdargs const *arg) 72631343Sbrian{ 72731343Sbrian return ShellCommand(arg, 0); 72831343Sbrian} 72931343Sbrian 73058044Sbrianstatic int 73158044SbrianResolvCommand(struct cmdargs const *arg) 73258044Sbrian{ 73358044Sbrian if (arg->argc == arg->argn + 1) { 73458044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 73558044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 73658044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 73758044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 73858044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 73958044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 74058044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 74158044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 74258044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 74358044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 74458044Sbrian else 74558044Sbrian return -1; 74658044Sbrian 74758044Sbrian return 0; 74858044Sbrian } 74958044Sbrian 75058044Sbrian return -1; 75158044Sbrian} 75258044Sbrian 75350059Sbrian#ifndef NONAT 75458867Sbrianstatic struct cmdtab const NatCommands[] = 75540561Sbrian{ 75650059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 75750059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 75858867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 75950059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 76040561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 76158867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 76250059Sbrian "enable NAT", "nat enable yes|no"}, 76358867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 76450059Sbrian "log NAT link creation", "nat log yes|no", 76540561Sbrian (const void *) PKT_ALIAS_LOG}, 76650059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 76750059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 76879433Sbrian {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 76979433Sbrian "nat proto proto localIP [publicIP [remoteIP]]"}, 77050059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 77150059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 77281033Sbrian#ifndef NO_FW_PUNCH 77381033Sbrian {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 77481033Sbrian "firewall control", "nat punch_fw [base count]"}, 77581033Sbrian#endif 776120372Smarcus {"skinny_port", NULL, nat_SkinnyPort, LOCAL_AUTH, 777120372Smarcus "TCP port used by Skinny Station protocol", "nat skinny_port [port]"}, 77858867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 77950059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 78040561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 78158867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 78258867Sbrian "Default address for incoming connections", "nat target addr" }, 78358867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 78450059Sbrian "translate unregistered (private) IP address space only", 78550059Sbrian "nat unregistered_only yes|no", 78640561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 78758867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 78850059Sbrian "allocate host sockets", "nat use_sockets yes|no", 78940561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 79040561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 79158867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 79240561Sbrian {NULL, NULL, NULL}, 79340561Sbrian}; 79440561Sbrian#endif 79540561Sbrian 79640561Sbrianstatic struct cmdtab const AllowCommands[] = { 79740561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 79840561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 79940561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 80040561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 80140561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 80240561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 80340561Sbrian {NULL, NULL, NULL}, 80440561Sbrian}; 80540561Sbrian 80640561Sbrianstatic struct cmdtab const IfaceCommands[] = 80740561Sbrian{ 80840561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 80940561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 81040561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 81140561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 81240561Sbrian (void *)1}, 81340561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 81481634Sbrian "Clear iface address(es)", "iface clear [INET | INET6]"}, 81540561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 81640561Sbrian "Delete iface address", "iface delete addr", NULL}, 81740561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 81840561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 81940561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 82040561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 82140561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 82240561Sbrian "Show iface address(es)", "iface show"}, 82340561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 82450059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 82540561Sbrian {NULL, NULL, NULL}, 82640561Sbrian}; 82740561Sbrian 82830715Sbrianstatic struct cmdtab const Commands[] = { 82936285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 83028679Sbrian "accept option request", "accept option .."}, 83128679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 83232109Sbrian "add route", "add dest mask gateway", NULL}, 83336285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 83432109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 83540561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 83640561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 83728679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 83831372Sbrian "Run a background command", "[!]bg command"}, 83936934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 84046686Sbrian "Clear throughput statistics", 84181634Sbrian "clear ipcp|ipv6cp|physical [current|overall|peak]..."}, 84236285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 84336285Sbrian "Clone a link", "clone newname..."}, 84436285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 84536285Sbrian "Close an FSM", "close [lcp|ccp]"}, 84628679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 84732109Sbrian "delete route", "delete dest", NULL}, 84836285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 84932109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 85036285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85128679Sbrian "Deny option request", "deny option .."}, 85236285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85340797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 85436285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85528679Sbrian "Disable option", "disable option .."}, 85636285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85746686Sbrian "Generate a down event", "down [ccp|lcp]"}, 85836285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85928679Sbrian "Enable option", "enable option .."}, 86063484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 86163484Sbrian "Set the link identity", "ident text..."}, 86240561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 86340561Sbrian "interface control", "iface option ...", IfaceCommands}, 86436285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 86536285Sbrian "Link specific commands", "link name command ..."}, 86637008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 86740797Sbrian "Load settings", "load [system ...]"}, 86885991Sbrian {"log", NULL, LogCommand, LOCAL_AUTH | LOCAL_CX_OPT, 86985991Sbrian "log information", "log word ..."}, 87050059Sbrian#ifndef NONAT 87150059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 87258867Sbrian "NAT control", "nat option yes|no", NatCommands}, 87350059Sbrian#endif 87436285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 87537955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 87636285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 87736285Sbrian "Password for manipulation", "passwd LocalPassword"}, 87836285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 87936285Sbrian "Quit PPP program", "quit|bye [all]"}, 88036285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 88136285Sbrian "Remove a link", "remove"}, 88236285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 88336285Sbrian "Rename a link", "rename name"}, 88458044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 88558044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 88628679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 88728679Sbrian "Save settings", "save"}, 88863484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 88963484Sbrian "Transmit the link identity", "sendident"}, 89036285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 89128679Sbrian "Set parameters", "set[up] var value"}, 89228679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 89328679Sbrian "Run a subshell", "shell|! [sh command]"}, 89436285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 89531372Sbrian "Show status and stats", "show var"}, 89636285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 89731372Sbrian "Enter terminal mode", "term"}, 89828679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 89931343Sbrian "Display this message", "help|? [command]", Commands}, 90028679Sbrian {NULL, NULL, NULL}, 9016059Samurai}; 9026059Samurai 90328536Sbrianstatic int 90431343SbrianShowEscape(struct cmdargs const *arg) 9056059Samurai{ 90636285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 90736285Sbrian int code, bit; 90836285Sbrian const char *sep = ""; 9096059Samurai 91026516Sbrian for (code = 0; code < 32; code++) 91136285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 91228679Sbrian for (bit = 0; bit < 8; bit++) 91336285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 91436285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 91536285Sbrian sep = ", "; 91636285Sbrian } 91736285Sbrian prompt_Printf(arg->prompt, "\n"); 9186059Samurai } 91931077Sbrian return 0; 9206059Samurai} 9216059Samurai 92228679Sbrianstatic int 92336285SbrianShowTimerList(struct cmdargs const *arg) 9246059Samurai{ 92536285Sbrian timer_Show(0, arg->prompt); 92631077Sbrian return 0; 9276059Samurai} 9286059Samurai 92928679Sbrianstatic int 93031343SbrianShowStopped(struct cmdargs const *arg) 93128327Sbrian{ 93236285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 93336285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 93436285Sbrian prompt_Printf(arg->prompt, "Disabled"); 93528327Sbrian else 93636285Sbrian prompt_Printf(arg->prompt, "%ld secs", 93736285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 93828461Sbrian 93936285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 94036285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 94136285Sbrian prompt_Printf(arg->prompt, "Disabled"); 94228461Sbrian else 94336285Sbrian prompt_Printf(arg->prompt, "%ld secs", 94436285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 94528461Sbrian 94636285Sbrian prompt_Printf(arg->prompt, "\n"); 94728461Sbrian 94831077Sbrian return 0; 94928327Sbrian} 95028327Sbrian 95128679Sbrianstatic int 95231343SbrianShowVersion(struct cmdargs const *arg) 9536059Samurai{ 95451026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 95531077Sbrian return 0; 9566059Samurai} 9576059Samurai 95828679Sbrianstatic int 95936285SbrianShowProtocolStats(struct cmdargs const *arg) 96026326Sbrian{ 96136285Sbrian struct link *l = command_ChooseLink(arg); 96226326Sbrian 96336285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 96436285Sbrian link_ReportProtocolStatus(l, arg->prompt); 96531077Sbrian return 0; 96626326Sbrian} 96726326Sbrian 96830715Sbrianstatic struct cmdtab const ShowCommands[] = { 96936285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 97036285Sbrian "bundle details", "show bundle"}, 97136285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 97236285Sbrian "CCP status", "show cpp"}, 97336285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 97436285Sbrian "VJ compression stats", "show compress"}, 97536285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 97636285Sbrian "escape characters", "show escape"}, 97736285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 97836285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 97936285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 98036285Sbrian "HDLC errors", "show hdlc"}, 98140561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 98240561Sbrian "Interface status", "show iface"}, 98336285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 98436285Sbrian "IPCP status", "show ipcp"}, 98581634Sbrian#ifndef NOINET6 98681634Sbrian {"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH, 98781634Sbrian "IPV6CP status", "show ipv6cp"}, 98881634Sbrian#endif 98947211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 99047211Sbrian "Protocol layers", "show layers"}, 99136285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 99236285Sbrian "LCP status", "show lcp"}, 99336285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 99436285Sbrian "(high-level) link info", "show link"}, 99536285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 99636285Sbrian "available link names", "show links"}, 99736285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 99836285Sbrian "log levels", "show log"}, 99936285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 100036285Sbrian "mbuf allocations", "show mem"}, 100181634Sbrian {"ncp", NULL, ncp_Show, LOCAL_AUTH, 100281634Sbrian "NCP status", "show ncp"}, 100346686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 100446686Sbrian "(low-level) link info", "show physical"}, 100536285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 100636285Sbrian "multilink setup", "show mp"}, 100736285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 100836285Sbrian "protocol summary", "show proto"}, 100936285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 101036285Sbrian "routing table", "show route"}, 101136285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 101236285Sbrian "STOPPED timeout", "show stopped"}, 101336285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 101436285Sbrian "alarm timers", "show timers"}, 101528679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 101636285Sbrian "version string", "show version"}, 101736285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 101836285Sbrian "client list", "show who"}, 101928679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 102031343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 102128679Sbrian {NULL, NULL, NULL}, 10226059Samurai}; 10236059Samurai 102430715Sbrianstatic struct cmdtab const * 102531343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 10266059Samurai{ 102726516Sbrian int nmatch; 102826516Sbrian int len; 102928679Sbrian struct cmdtab const *found; 10306059Samurai 103126516Sbrian found = NULL; 103226516Sbrian len = strlen(str); 103326516Sbrian nmatch = 0; 10346059Samurai while (cmds->func) { 103525566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 103626516Sbrian if (cmds->name[len] == '\0') { 103728679Sbrian *pmatch = 1; 103828679Sbrian return cmds; 103926516Sbrian } 10406059Samurai nmatch++; 10416059Samurai found = cmds; 104228679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 104326516Sbrian if (cmds->alias[len] == '\0') { 104428679Sbrian *pmatch = 1; 104528679Sbrian return cmds; 104626516Sbrian } 10476059Samurai nmatch++; 10486059Samurai found = cmds; 10496059Samurai } 10506059Samurai cmds++; 10516059Samurai } 10526059Samurai *pmatch = nmatch; 105326516Sbrian return found; 10546059Samurai} 10556059Samurai 105636285Sbrianstatic const char * 105736285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 105836285Sbrian{ 105936285Sbrian int f, tlen, len; 106036285Sbrian 106136285Sbrian tlen = 0; 106236285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 106336285Sbrian if (f) 106436285Sbrian tgt[tlen++] = ' '; 106536285Sbrian len = strlen(argv[f]); 106636285Sbrian if (len > sz - tlen - 1) 106736285Sbrian len = sz - tlen - 1; 106836285Sbrian strncpy(tgt+tlen, argv[f], len); 106936285Sbrian tlen += len; 107036285Sbrian } 107136285Sbrian tgt[tlen] = '\0'; 107236285Sbrian return tgt; 107336285Sbrian} 107436285Sbrian 107530715Sbrianstatic int 107636285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 107736285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 10786059Samurai{ 107928679Sbrian struct cmdtab const *cmd; 10806059Samurai int val = 1; 10816059Samurai int nmatch; 108231343Sbrian struct cmdargs arg; 108336285Sbrian char prefix[100]; 10846059Samurai 108536285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 10866059Samurai if (nmatch > 1) 108736285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 108836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 108936285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 109036285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 109136285Sbrian /* We've got no context, but we require it */ 109236285Sbrian cx = bundle2datalink(bundle, NULL); 109336285Sbrian 109436285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 109536285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 109636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 109736285Sbrian else { 109836285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 109936285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 110036285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 110136285Sbrian cx = NULL; 110236285Sbrian } 110336285Sbrian arg.cmdtab = cmds; 110436285Sbrian arg.cmd = cmd; 110536285Sbrian arg.argc = argc; 110636285Sbrian arg.argn = argn+1; 110736285Sbrian arg.argv = argv; 110836285Sbrian arg.bundle = bundle; 110936285Sbrian arg.cx = cx; 111036285Sbrian arg.prompt = prompt; 111136285Sbrian val = (*cmd->func) (&arg); 111236285Sbrian } 111331343Sbrian } else 111436285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 111536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 111626516Sbrian 111726516Sbrian if (val == -1) 111895258Sdes log_Printf(LogWARN, "usage: %s\n", cmd->syntax); 111928679Sbrian else if (val) 112036285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 112136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 112226516Sbrian 112326516Sbrian return val; 11246059Samurai} 11256059Samurai 112637009Sbrianint 112758045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 112858045Sbrian{ 112958045Sbrian char buff2[LINE_LEN-offset]; 113058045Sbrian 113158045Sbrian InterpretArg(buff, buff2); 113258045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 113358045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 113458045Sbrian 113558045Sbrian return command_Interpret(buff, nb, argv); 113658045Sbrian} 113758045Sbrian 113858045Sbrianint 113937009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 11406059Samurai{ 11416059Samurai char *cp; 11426059Samurai 11436059Samurai if (nb > 0) { 11446059Samurai cp = buff + strcspn(buff, "\r\n"); 11456059Samurai if (cp) 11466059Samurai *cp = '\0'; 114755145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 114837009Sbrian } 114937009Sbrian return 0; 115031121Sbrian} 11516059Samurai 115231822Sbrianstatic int 115331822Sbrianarghidden(int argc, char const *const *argv, int n) 115431822Sbrian{ 115531822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 115631828Sbrian 115731828Sbrian /* set authkey xxxxx */ 115831828Sbrian /* set key xxxxx */ 115931822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 116031822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 116131822Sbrian return 1; 116231822Sbrian 116331828Sbrian /* passwd xxxxx */ 116431828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 116531828Sbrian return 1; 116631828Sbrian 116736285Sbrian /* set server port xxxxx .... */ 116836285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 116936285Sbrian !strncasecmp(argv[1], "se", 2)) 117036285Sbrian return 1; 117136285Sbrian 117231822Sbrian return 0; 117331822Sbrian} 117431822Sbrian 117531121Sbrianvoid 117636285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 117737008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 117831121Sbrian{ 117931156Sbrian if (argc > 0) { 118036285Sbrian if (log_IsKept(LogCOMMAND)) { 118147844Sbrian char buf[LINE_LEN]; 118231156Sbrian int f, n; 118331156Sbrian 118431156Sbrian if (label) { 118531962Sbrian strncpy(buf, label, sizeof buf - 3); 118631962Sbrian buf[sizeof buf - 3] = '\0'; 118731156Sbrian strcat(buf, ": "); 118847844Sbrian n = strlen(buf); 118947844Sbrian } else { 119047844Sbrian *buf = '\0'; 119147844Sbrian n = 0; 119231156Sbrian } 119347844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 119447844Sbrian 119531156Sbrian for (f = 0; f < argc; f++) { 119631962Sbrian if (n < sizeof buf - 1 && f) 119731156Sbrian buf[n++] = ' '; 119831822Sbrian if (arghidden(argc, argv, f)) 119936285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 120031822Sbrian else 120131962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 120231156Sbrian n += strlen(buf+n); 120331156Sbrian } 120436285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 120531156Sbrian } 120637008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 120731156Sbrian } 12086059Samurai} 12096059Samurai 121054914Sbrianint 121136285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 121236285Sbrian const char *label) 121331121Sbrian{ 121431121Sbrian int argc; 121537009Sbrian char *argv[MAXARGS]; 121631121Sbrian 121758045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 121854914Sbrian return 0; 121954914Sbrian 122037008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 122154914Sbrian return 1; 122231121Sbrian} 122331121Sbrian 12246059Samuraistatic int 122531343SbrianShowCommand(struct cmdargs const *arg) 12266059Samurai{ 122736285Sbrian if (!arg->prompt) 122836285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 122936285Sbrian else if (arg->argc > arg->argn) 123036285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 123136285Sbrian arg->prompt, arg->cx); 12326059Samurai else 123336285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 123426516Sbrian 123526516Sbrian return 0; 12366059Samurai} 12376059Samurai 12386059Samuraistatic int 123931343SbrianTerminalCommand(struct cmdargs const *arg) 12406059Samurai{ 124136285Sbrian if (!arg->prompt) { 124236285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 124326516Sbrian return 1; 12446059Samurai } 124536285Sbrian 124636285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 124736285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 124836285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 124936285Sbrian return 1; 12506059Samurai } 125136285Sbrian 125236285Sbrian datalink_Up(arg->cx, 0, 0); 125336285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 125436285Sbrian return 0; 12556059Samurai} 12566059Samurai 12576059Samuraistatic int 125831343SbrianQuitCommand(struct cmdargs const *arg) 12596059Samurai{ 126036285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 126136285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 126236285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 126336285Sbrian Cleanup(EX_NORMAL); 126436285Sbrian if (arg->prompt) 126536285Sbrian prompt_Destroy(arg->prompt, 1); 126626516Sbrian 126726516Sbrian return 0; 12686059Samurai} 12696059Samurai 12706059Samuraistatic int 127136285SbrianOpenCommand(struct cmdargs const *arg) 12726059Samurai{ 127337160Sbrian if (arg->argc == arg->argn) 127437993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 127537160Sbrian else if (arg->argc == arg->argn + 1) { 127637160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 127737385Sbrian struct datalink *cx = arg->cx ? 127837385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 127937385Sbrian if (cx) { 128037385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 128137385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 128237160Sbrian else 128337993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 128437160Sbrian } else 128537160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 128637160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 128737160Sbrian struct fsm *fp; 12886059Samurai 128937210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 129037160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 129137160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 129237160Sbrian else if (fp->state == ST_OPENED) 129337160Sbrian fsm_Reopen(fp); 129437160Sbrian else { 129537160Sbrian fp->open_mode = 0; /* Not passive any more */ 129637160Sbrian if (fp->state == ST_STOPPED) { 129737160Sbrian fsm_Down(fp); 129837160Sbrian fsm_Up(fp); 129937160Sbrian } else { 130037160Sbrian fsm_Up(fp); 130137160Sbrian fsm_Open(fp); 130237160Sbrian } 130336285Sbrian } 130437160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 130537160Sbrian if (arg->cx) 130637160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 130737160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 130837160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 130937160Sbrian else 131037993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 131137160Sbrian } else 131237160Sbrian return -1; 131336285Sbrian } else 131436285Sbrian return -1; 131536285Sbrian 131626516Sbrian return 0; 13176059Samurai} 13186059Samurai 131925067Sbrianstatic int 132036285SbrianCloseCommand(struct cmdargs const *arg) 13216059Samurai{ 132237007Sbrian if (arg->argc == arg->argn) 132337007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 132437007Sbrian else if (arg->argc == arg->argn + 1) { 132537007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 132637007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 132737007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 132837007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 132937007Sbrian struct fsm *fp; 13306059Samurai 133137210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 133237007Sbrian if (fp->state == ST_OPENED) { 133337007Sbrian fsm_Close(fp); 133437007Sbrian if (arg->argv[arg->argn][3] == '!') 133537007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 133637007Sbrian else 133737007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 133837007Sbrian } 133937007Sbrian } else 134036285Sbrian return -1; 134136285Sbrian } else 134236285Sbrian return -1; 134336285Sbrian 134436285Sbrian return 0; 13456059Samurai} 13466059Samurai 134725067Sbrianstatic int 134836285SbrianDownCommand(struct cmdargs const *arg) 134911336Samurai{ 135037018Sbrian if (arg->argc == arg->argn) { 135137018Sbrian if (arg->cx) 135237018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 135337018Sbrian else 135437018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 135537018Sbrian } else if (arg->argc == arg->argn + 1) { 135637018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 135737018Sbrian if (arg->cx) 135837018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 135937018Sbrian else 136037018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 136137018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 136237018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 136337018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 136437060Sbrian fsm2initial(fp); 136537018Sbrian } else 136637018Sbrian return -1; 136736285Sbrian } else 136836285Sbrian return -1; 136936285Sbrian 137036285Sbrian return 0; 137125067Sbrian} 137225067Sbrian 137325067Sbrianstatic int 137436285SbrianSetModemSpeed(struct cmdargs const *arg) 137525067Sbrian{ 137636285Sbrian long speed; 137736285Sbrian char *end; 137811336Samurai 137936285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 138036285Sbrian if (arg->argc > arg->argn+1) { 138154917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 138236285Sbrian return -1; 138311336Samurai } 138436285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 138536285Sbrian physical_SetSync(arg->cx->physical); 138636285Sbrian return 0; 138736285Sbrian } 138836285Sbrian end = NULL; 138936285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 139036285Sbrian if (*end) { 139136285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 139236285Sbrian arg->argv[arg->argn]); 139336285Sbrian return -1; 139436285Sbrian } 139536285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 139636285Sbrian return 0; 139736285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 139836285Sbrian } else 139936285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 140024939Sbrian 140126516Sbrian return -1; 140211336Samurai} 140311336Samurai 140425067Sbrianstatic int 140531343SbrianSetStoppedTimeout(struct cmdargs const *arg) 140628327Sbrian{ 140736285Sbrian struct link *l = &arg->cx->physical->link; 140836285Sbrian 140936285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 141036285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 141136285Sbrian if (arg->argc <= arg->argn+2) { 141236285Sbrian if (arg->argc > arg->argn) { 141336285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 141436285Sbrian if (arg->argc > arg->argn+1) 141536285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 141628461Sbrian } 141728327Sbrian return 0; 141828327Sbrian } 141928327Sbrian return -1; 142028327Sbrian} 142128327Sbrian 142228327Sbrianstatic int 142331343SbrianSetServer(struct cmdargs const *arg) 142426940Sbrian{ 142526940Sbrian int res = -1; 142626940Sbrian 142736285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 142831081Sbrian const char *port, *passwd, *mask; 142953125Sbrian int mlen; 143031081Sbrian 143131081Sbrian /* What's what ? */ 143236285Sbrian port = arg->argv[arg->argn]; 143336285Sbrian if (arg->argc == arg->argn + 2) { 143436285Sbrian passwd = arg->argv[arg->argn+1]; 143536285Sbrian mask = NULL; 143636285Sbrian } else if (arg->argc == arg->argn + 3) { 143736285Sbrian passwd = arg->argv[arg->argn+1]; 143836285Sbrian mask = arg->argv[arg->argn+2]; 143953125Sbrian mlen = strlen(mask); 144053125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 144153125Sbrian (mlen == 4 && *mask != '0')) { 144253125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 144353125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 144431081Sbrian return -1; 144553125Sbrian } 144671764Sbrian } else if (arg->argc != arg->argn + 1) 144771764Sbrian return -1; 144871764Sbrian else if (strcasecmp(port, "none") == 0) { 144971657Sbrian if (server_Clear(arg->bundle)) 145071657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 145171657Sbrian return 0; 145271657Sbrian } else if (strcasecmp(port, "open") == 0) { 145371657Sbrian switch (server_Reopen(arg->bundle)) { 145471657Sbrian case SERVER_OK: 145571657Sbrian return 0; 145671657Sbrian case SERVER_FAILED: 145771764Sbrian log_Printf(LogWARN, "Failed to reopen server port\n"); 145871657Sbrian return 1; 145971657Sbrian case SERVER_UNSET: 146071764Sbrian log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 146171657Sbrian return 1; 146271657Sbrian default: 146371657Sbrian break; 146471657Sbrian } 146571657Sbrian return -1; 146671657Sbrian } else if (strcasecmp(port, "closed") == 0) { 146736285Sbrian if (server_Close(arg->bundle)) 146871657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 146971657Sbrian else 147071657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 147171657Sbrian 147236285Sbrian return 0; 147331081Sbrian } else 147436285Sbrian return -1; 147531081Sbrian 147671657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 147771657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 147831081Sbrian 147936285Sbrian if (*port == '/') { 148031081Sbrian mode_t imask; 148136285Sbrian char *ptr, name[LINE_LEN + 12]; 148228679Sbrian 148353125Sbrian if (mask == NULL) 148431081Sbrian imask = (mode_t)-1; 148553125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 148653125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 148736285Sbrian 148836285Sbrian ptr = strstr(port, "%d"); 148936285Sbrian if (ptr) { 149036285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 149137210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 149236285Sbrian port = name; 149336285Sbrian } 149436285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 149527346Sbrian } else { 149636285Sbrian int iport, add = 0; 149728679Sbrian 149831081Sbrian if (mask != NULL) 149931081Sbrian return -1; 150028679Sbrian 150136285Sbrian if (*port == '+') { 150236285Sbrian port++; 150336285Sbrian add = 1; 150436285Sbrian } 150531081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 150631081Sbrian struct servent *s; 150731081Sbrian 150831081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 150931081Sbrian iport = 0; 151036285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 151128679Sbrian } else 151231081Sbrian iport = ntohs(s->s_port); 151327346Sbrian } else 151431081Sbrian iport = atoi(port); 151536285Sbrian 151636285Sbrian if (iport) { 151736285Sbrian if (add) 151836285Sbrian iport += arg->bundle->unit; 151936285Sbrian res = server_TcpOpen(arg->bundle, iport); 152036285Sbrian } else 152136285Sbrian res = -1; 152227346Sbrian } 152331081Sbrian } 152426940Sbrian 152526940Sbrian return res; 152626940Sbrian} 152726940Sbrian 152826940Sbrianstatic int 152931343SbrianSetEscape(struct cmdargs const *arg) 15306059Samurai{ 15316059Samurai int code; 153236285Sbrian int argc = arg->argc - arg->argn; 153336285Sbrian char const *const *argv = arg->argv + arg->argn; 15346059Samurai 15356059Samurai for (code = 0; code < 33; code++) 153636285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 153731343Sbrian 15386059Samurai while (argc-- > 0) { 15396059Samurai sscanf(*argv++, "%x", &code); 15406059Samurai code &= 0xff; 154136285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 154236285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 15436059Samurai } 154426516Sbrian return 0; 15456059Samurai} 15466059Samurai 15476059Samuraistatic int 154831343SbrianSetInterfaceAddr(struct cmdargs const *arg) 15496059Samurai{ 155081634Sbrian struct ncp *ncp = &arg->bundle->ncp; 155181634Sbrian struct ncpaddr ncpaddr; 155232267Sbrian const char *hisaddr; 155332267Sbrian 155440561Sbrian if (arg->argc > arg->argn + 4) 155540561Sbrian return -1; 155640561Sbrian 155732267Sbrian hisaddr = NULL; 155881634Sbrian memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range); 155981634Sbrian memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range); 156081634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 0; 156181634Sbrian ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY; 156281634Sbrian iplist_reset(&ncp->ipcp.cfg.peer_list); 156328394Sbrian 156436285Sbrian if (arg->argc > arg->argn) { 156581634Sbrian if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn])) 156628679Sbrian return 1; 156736285Sbrian if (arg->argc > arg->argn+1) { 156836285Sbrian hisaddr = arg->argv[arg->argn+1]; 156936285Sbrian if (arg->argc > arg->argn+2) { 157081634Sbrian ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask = 157181634Sbrian GetIpAddr(arg->argv[arg->argn+2]); 157236285Sbrian if (arg->argc > arg->argn+3) { 157381634Sbrian ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 157481634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 1; 15759440Samurai } 15766059Samurai } 15776059Samurai } 15786059Samurai } 157928394Sbrian 158040561Sbrian /* 0.0.0.0 means any address (0 bits) */ 158181634Sbrian ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip); 158281634Sbrian ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr); 158381634Sbrian if (ncp->ipcp.my_ip.s_addr == INADDR_ANY) 158481634Sbrian ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0); 158581634Sbrian bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL); 158636285Sbrian 158736285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 158836928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 158932267Sbrian return 4; 159031121Sbrian 159126516Sbrian return 0; 15926059Samurai} 15936059Samurai 159418752Sjkhstatic int 159544305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 159644305Sbrian u_int *maxtrm, int def) 159744305Sbrian{ 159844305Sbrian if (argc == 0) { 159944305Sbrian *timeout = DEF_FSMRETRY; 160044305Sbrian *maxreq = def; 160144305Sbrian if (maxtrm != NULL) 160244305Sbrian *maxtrm = def; 160344305Sbrian } else { 160444305Sbrian long l = atol(argv[0]); 160544305Sbrian 160644305Sbrian if (l < MIN_FSMRETRY) { 160744305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 160844305Sbrian l, MIN_FSMRETRY); 160944305Sbrian return 1; 161044305Sbrian } else 161144305Sbrian *timeout = l; 161244305Sbrian 161344305Sbrian if (argc > 1) { 161444305Sbrian l = atol(argv[1]); 161544305Sbrian if (l < 1) { 161644305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 161744305Sbrian l = 1; 161844305Sbrian } 161944305Sbrian *maxreq = l; 162044305Sbrian 162144305Sbrian if (argc > 2 && maxtrm != NULL) { 162244305Sbrian l = atol(argv[2]); 162344305Sbrian if (l < 1) { 162444305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 162544305Sbrian l = 1; 162644305Sbrian } 162744305Sbrian *maxtrm = l; 162844305Sbrian } 162944305Sbrian } 163044305Sbrian } 163144305Sbrian 163244305Sbrian return 0; 163344305Sbrian} 163444305Sbrian 163544305Sbrianstatic int 163631343SbrianSetVariable(struct cmdargs const *arg) 16376059Samurai{ 163837210Sbrian long long_val, param = (long)arg->cmd->args; 163979119Sbrian int mode, dummyint, f, first, res; 164078410Sbrian u_short *change; 164131343Sbrian const char *argp; 164236285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 164336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 164481634Sbrian struct in_addr *ipaddr; 164581634Sbrian struct ncpaddr ncpaddr[2]; 16466059Samurai 164736285Sbrian if (arg->argc > arg->argn) 164836285Sbrian argp = arg->argv[arg->argn]; 164926551Sbrian else 165031343Sbrian argp = ""; 165126551Sbrian 165279119Sbrian res = 0; 165379119Sbrian 165436285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 165536285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 165636285Sbrian arg->cmd->name); 165736285Sbrian return 1; 165836285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 165936285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 166036285Sbrian arg->cmd->name, cx->name); 166136285Sbrian cx = NULL; 166236285Sbrian } 166336285Sbrian 166426551Sbrian switch (param) { 166528679Sbrian case VAR_AUTHKEY: 166650139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 166750139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 166850139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 166928679Sbrian break; 167037210Sbrian 167128679Sbrian case VAR_AUTHNAME: 167240622Sbrian switch (bundle_Phase(arg->bundle)) { 167358880Sbrian default: 167458880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 167558880Sbrian bundle_PhaseName(arg->bundle)); 167658880Sbrian /* drop through */ 167740622Sbrian case PHASE_DEAD: 167840622Sbrian case PHASE_ESTABLISH: 167940622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 168040622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 168140622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 168240622Sbrian break; 168336285Sbrian } 168428679Sbrian break; 168537210Sbrian 168636285Sbrian case VAR_AUTOLOAD: 168749434Sbrian if (arg->argc == arg->argn + 3) { 168898243Sbrian int v1, v2, v3; 168949434Sbrian char *end; 169049434Sbrian 169149434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 169249434Sbrian if (v1 < 0 || *end) { 169349434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 169449434Sbrian arg->argv[arg->argn]); 169579119Sbrian res = 1; 169679119Sbrian break; 169736285Sbrian } 169849434Sbrian 169949434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 170049434Sbrian if (v2 < 0 || *end) { 170149434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 170249434Sbrian arg->argv[arg->argn + 1]); 170379119Sbrian res = 1; 170479119Sbrian break; 170549434Sbrian } 170649434Sbrian if (v2 < v1) { 170749434Sbrian v3 = v1; 170849434Sbrian v1 = v2; 170949434Sbrian v2 = v3; 171049434Sbrian } 171149434Sbrian 171249434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 171349434Sbrian if (v3 <= 0 || *end) { 171449434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 171549434Sbrian arg->argv[arg->argn + 2]); 171679119Sbrian res = 1; 171779119Sbrian break; 171849434Sbrian } 171949434Sbrian 172049434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 172149434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 172249434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 172349434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 172436285Sbrian } else { 172579119Sbrian log_Printf(LogWARN, "Set autoload requires three arguments\n"); 172679119Sbrian res = 1; 172736285Sbrian } 172836285Sbrian break; 172937210Sbrian 173028679Sbrian case VAR_DIAL: 173136285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 173236285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 173328679Sbrian break; 173437210Sbrian 173528679Sbrian case VAR_LOGIN: 173636285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 173736285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 173828679Sbrian break; 173937210Sbrian 174036285Sbrian case VAR_WINSIZE: 174136285Sbrian if (arg->argc > arg->argn) { 174236285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 174336285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 174436285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 174536285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 174636285Sbrian l->ccp.cfg.deflate.out.winsize); 174736285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 174836285Sbrian } 174936285Sbrian if (arg->argc > arg->argn+1) { 175036285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 175136285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 175236285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 175336285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 175436285Sbrian l->ccp.cfg.deflate.in.winsize); 175536285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 175636285Sbrian } 175736285Sbrian } else 175836285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 175936285Sbrian } else { 176079119Sbrian log_Printf(LogWARN, "No window size specified\n"); 176179119Sbrian res = 1; 176236285Sbrian } 176336285Sbrian break; 176437210Sbrian 176593418Sbrian#ifndef NODES 176678411Sbrian case VAR_MPPE: 176779119Sbrian if (arg->argc > arg->argn + 2) { 176879119Sbrian res = -1; 176979119Sbrian break; 177079119Sbrian } 177178411Sbrian 177278411Sbrian if (arg->argc == arg->argn) { 177378411Sbrian l->ccp.cfg.mppe.keybits = 0; 177478411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 177578411Sbrian l->ccp.cfg.mppe.required = 0; 177678411Sbrian break; 177778411Sbrian } 177878411Sbrian 177978411Sbrian if (!strcmp(argp, "*")) 178078411Sbrian long_val = 0; 178178411Sbrian else { 178278411Sbrian long_val = atol(argp); 178378411Sbrian if (long_val != 40 && long_val != 56 && long_val != 128) { 178478411Sbrian log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 178579119Sbrian res = -1; 178679119Sbrian break; 178767910Sbrian } 178867910Sbrian } 178978411Sbrian 179078411Sbrian if (arg->argc == arg->argn + 2) { 179178411Sbrian if (!strcmp(arg->argv[arg->argn + 1], "*")) 179278411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 179378411Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 179478411Sbrian l->ccp.cfg.mppe.state = MPPE_STATELESS; 179579370Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 179678411Sbrian l->ccp.cfg.mppe.state = MPPE_STATEFUL; 179778411Sbrian else { 179878411Sbrian log_Printf(LogWARN, "%s: Invalid state value\n", 179978411Sbrian arg->argv[arg->argn + 1]); 180079119Sbrian res = -1; 180179119Sbrian break; 180278411Sbrian } 180378411Sbrian } else 180478411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 180578411Sbrian l->ccp.cfg.mppe.keybits = long_val; 180678411Sbrian l->ccp.cfg.mppe.required = 1; 180767910Sbrian break; 180867910Sbrian#endif 180967910Sbrian 181028679Sbrian case VAR_DEVICE: 181136285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 181236285Sbrian arg->argv + arg->argn); 181336285Sbrian break; 181437210Sbrian 181536285Sbrian case VAR_ACCMAP: 181636285Sbrian if (arg->argc > arg->argn) { 181737210Sbrian u_long ulong_val; 181836285Sbrian sscanf(argp, "%lx", &ulong_val); 181937210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 182036285Sbrian } else { 182179119Sbrian log_Printf(LogWARN, "No accmap specified\n"); 182279119Sbrian res = 1; 182336285Sbrian } 182436285Sbrian break; 182537210Sbrian 182636285Sbrian case VAR_MODE: 182736285Sbrian mode = Nam2mode(argp); 182836285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 182936285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 183079119Sbrian res = -1; 183179119Sbrian break; 183236285Sbrian } 183336285Sbrian bundle_SetMode(arg->bundle, cx, mode); 183436285Sbrian break; 183537210Sbrian 183636285Sbrian case VAR_MRRU: 183740622Sbrian switch (bundle_Phase(arg->bundle)) { 183840622Sbrian case PHASE_DEAD: 183940622Sbrian break; 184040622Sbrian case PHASE_ESTABLISH: 184140622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 184240622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 184340622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 184479119Sbrian res = 1; 184579119Sbrian break; 184640622Sbrian } 184740622Sbrian break; 184840622Sbrian default: 184940622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 185079119Sbrian res = 1; 185179119Sbrian break; 185229696Sbrian } 185379119Sbrian if (res != 0) 185479119Sbrian break; 185537210Sbrian long_val = atol(argp); 185637210Sbrian if (long_val && long_val < MIN_MRU) { 185737210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 185879119Sbrian res = 1; 185979119Sbrian break; 186037210Sbrian } else if (long_val > MAX_MRU) { 186137210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 186279119Sbrian res = 1; 186379119Sbrian break; 186437210Sbrian } else 186537210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 186628679Sbrian break; 186737210Sbrian 186836285Sbrian case VAR_MRU: 186979163Sbrian long_val = 0; /* silence gcc */ 187079163Sbrian change = NULL; /* silence gcc */ 187178410Sbrian switch(arg->argc - arg->argn) { 187278410Sbrian case 1: 187379119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 187479119Sbrian res = -1; 187579119Sbrian break; 187679119Sbrian } 187779119Sbrian /*FALLTHRU*/ 187878410Sbrian case 0: 187978410Sbrian long_val = atol(argp); 188078410Sbrian change = &l->lcp.cfg.mru; 188178410Sbrian if (long_val > l->lcp.cfg.max_mru) { 188278410Sbrian log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 188378410Sbrian l->lcp.cfg.max_mru); 188479119Sbrian res = 1; 188579119Sbrian break; 188678410Sbrian } 188778410Sbrian break; 188878410Sbrian case 2: 188979119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 189079119Sbrian res = -1; 189179119Sbrian break; 189279119Sbrian } 189378410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 189478410Sbrian change = &l->lcp.cfg.max_mru; 189578410Sbrian if (long_val > MAX_MRU) { 189678410Sbrian log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 189778410Sbrian MAX_MRU); 189879119Sbrian res = 1; 189979119Sbrian break; 190078410Sbrian } 190178410Sbrian break; 190278410Sbrian default: 190379119Sbrian res = -1; 190479119Sbrian break; 190578410Sbrian } 190679119Sbrian if (res != 0) 190779119Sbrian break; 190878410Sbrian 190937210Sbrian if (long_val == 0) 191080385Sbrian *change = 0; 191137210Sbrian else if (long_val < MIN_MRU) { 191237210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 191379119Sbrian res = 1; 191479119Sbrian break; 191537210Sbrian } else if (long_val > MAX_MRU) { 191637210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 191779119Sbrian res = 1; 191879119Sbrian break; 191937210Sbrian } else 192078410Sbrian *change = long_val; 192178410Sbrian if (l->lcp.cfg.mru > *change) 192278410Sbrian l->lcp.cfg.mru = *change; 192328679Sbrian break; 192437210Sbrian 192536285Sbrian case VAR_MTU: 192679163Sbrian long_val = 0; /* silence gcc */ 192779163Sbrian change = NULL; /* silence gcc */ 192878410Sbrian switch(arg->argc - arg->argn) { 192978410Sbrian case 1: 193079119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 193179119Sbrian res = -1; 193279119Sbrian break; 193379119Sbrian } 193479119Sbrian /*FALLTHRU*/ 193578410Sbrian case 0: 193678410Sbrian long_val = atol(argp); 193778410Sbrian change = &l->lcp.cfg.mtu; 193878410Sbrian if (long_val > l->lcp.cfg.max_mtu) { 193978410Sbrian log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 194078410Sbrian l->lcp.cfg.max_mtu); 194179119Sbrian res = 1; 194279119Sbrian break; 194378410Sbrian } 194478410Sbrian break; 194578410Sbrian case 2: 194679119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 194779119Sbrian res = -1; 194879119Sbrian break; 194979119Sbrian } 195078410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 195178410Sbrian change = &l->lcp.cfg.max_mtu; 195278410Sbrian if (long_val > MAX_MTU) { 195378410Sbrian log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 195478410Sbrian MAX_MTU); 195579119Sbrian res = 1; 195679119Sbrian break; 195778410Sbrian } 195878410Sbrian break; 195978410Sbrian default: 196079119Sbrian res = -1; 196179119Sbrian break; 196278410Sbrian } 196378410Sbrian 196479119Sbrian if (res != 0) 196579119Sbrian break; 196679119Sbrian 196737210Sbrian if (long_val && long_val < MIN_MTU) { 196837210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 196979119Sbrian res = 1; 197079119Sbrian break; 197137210Sbrian } else if (long_val > MAX_MTU) { 197237210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 197379119Sbrian res = 1; 197479119Sbrian break; 197537210Sbrian } else 197678410Sbrian *change = long_val; 197778410Sbrian if (l->lcp.cfg.mtu > *change) 197878410Sbrian l->lcp.cfg.mtu = *change; 197936285Sbrian break; 198037210Sbrian 198136285Sbrian case VAR_OPENMODE: 198236285Sbrian if (strcasecmp(argp, "active") == 0) 198336285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 198436285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 198536285Sbrian else if (strcasecmp(argp, "passive") == 0) 198636285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 198736285Sbrian else { 198879119Sbrian log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 198979119Sbrian res = 1; 199036285Sbrian } 199136285Sbrian break; 199237210Sbrian 199328679Sbrian case VAR_PHONE: 199436285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 199536285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 199638174Sbrian cx->phone.alt = cx->phone.next = NULL; 199728679Sbrian break; 199837210Sbrian 199928679Sbrian case VAR_HANGUP: 200036285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 200136285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 200228679Sbrian break; 200337210Sbrian 200461534Sbrian case VAR_IFQUEUE: 200561534Sbrian long_val = atol(argp); 200661534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 200761534Sbrian break; 200861534Sbrian 200952488Sbrian case VAR_LOGOUT: 201052488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 201152488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 201252488Sbrian break; 201352488Sbrian 201436285Sbrian case VAR_IDLETIMEOUT: 201579119Sbrian if (arg->argc > arg->argn+2) { 201679119Sbrian log_Printf(LogWARN, "Too many idle timeout values\n"); 201779119Sbrian res = 1; 201879119Sbrian } else if (arg->argc == arg->argn) { 201979119Sbrian log_Printf(LogWARN, "Too few idle timeout values\n"); 202079119Sbrian res = 1; 202179119Sbrian } else { 202249978Sbrian int timeout, min; 202349978Sbrian 202449978Sbrian timeout = atoi(argp); 202549978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 202649978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 202749978Sbrian } 202829549Sbrian break; 202937210Sbrian 203036285Sbrian case VAR_LQRPERIOD: 203137210Sbrian long_val = atol(argp); 203237210Sbrian if (long_val < MIN_LQRPERIOD) { 203337210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 203437210Sbrian long_val, MIN_LQRPERIOD); 203579119Sbrian res = 1; 203636285Sbrian } else 203737210Sbrian l->lcp.cfg.lqrperiod = long_val; 203836285Sbrian break; 203937210Sbrian 204036285Sbrian case VAR_LCPRETRY: 204179119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 204279119Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 204379119Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 204479119Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 204536285Sbrian break; 204637210Sbrian 204736285Sbrian case VAR_CHAPRETRY: 204879119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 204979119Sbrian &cx->chap.auth.cfg.fsm.timeout, 205079119Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 205136285Sbrian break; 205237210Sbrian 205336285Sbrian case VAR_PAPRETRY: 205479119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 205579119Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 205679119Sbrian NULL, DEF_FSMAUTHTRIES); 205736285Sbrian break; 205837210Sbrian 205936285Sbrian case VAR_CCPRETRY: 206079119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 206179119Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 206279119Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 206336285Sbrian break; 206437210Sbrian 206536285Sbrian case VAR_IPCPRETRY: 206679119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 206779119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 206879119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 206979119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 207036285Sbrian break; 207137210Sbrian 2072102855Sbrian#ifndef NOINET6 2073102558Sbrian case VAR_IPV6CPRETRY: 2074102558Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 2075102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.timeout, 2076102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.maxreq, 2077102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.maxtrm, DEF_FSMTRIES); 2078102558Sbrian break; 2079102855Sbrian#endif 2080102558Sbrian 208136285Sbrian case VAR_NBNS: 208236285Sbrian case VAR_DNS: 208358044Sbrian if (param == VAR_DNS) { 208481634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns; 208581634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE; 208658044Sbrian } else { 208781634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 208881634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY; 208958044Sbrian } 209036285Sbrian 209136285Sbrian if (arg->argc > arg->argn) { 209281634Sbrian ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]); 209381634Sbrian if (!ncpaddr_getip4(ncpaddr, ipaddr)) 209481634Sbrian return -1; 209581634Sbrian if (arg->argc > arg->argn+1) { 209681634Sbrian ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]); 209781634Sbrian if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1)) 209881634Sbrian return -1; 209981634Sbrian } 210036285Sbrian 210181634Sbrian if (ipaddr[0].s_addr == INADDR_ANY) { 210281634Sbrian ipaddr[0] = ipaddr[1]; 210381634Sbrian ipaddr[1].s_addr = INADDR_ANY; 210458044Sbrian } 210581634Sbrian if (ipaddr[0].s_addr == INADDR_NONE) { 210681634Sbrian ipaddr[0] = ipaddr[1]; 210781634Sbrian ipaddr[1].s_addr = INADDR_NONE; 210858044Sbrian } 210936285Sbrian } 211036285Sbrian break; 211138174Sbrian 211238174Sbrian case VAR_CALLBACK: 211338174Sbrian cx->cfg.callback.opmask = 0; 211438174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 211538174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 211638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 211738174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 211838174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 211938174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 212038174Sbrian if (dummyint == arg->argc - 1) 212138174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 212238174Sbrian else { 212338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 212438174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 212538174Sbrian sizeof cx->cfg.callback.msg - 1); 212638174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 212738174Sbrian } 212838174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 212938174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 213079119Sbrian else { 213179119Sbrian res = -1; 213279119Sbrian break; 213379119Sbrian } 213438174Sbrian } 213538174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 213638174Sbrian cx->cfg.callback.opmask = 0; 213738174Sbrian break; 213838174Sbrian 213938174Sbrian case VAR_CBCP: 214038174Sbrian cx->cfg.cbcp.delay = 0; 214138174Sbrian *cx->cfg.cbcp.phone = '\0'; 214238174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 214338174Sbrian if (arg->argc > arg->argn) { 214438174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 214538174Sbrian sizeof cx->cfg.cbcp.phone - 1); 214638174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 214738174Sbrian if (arg->argc > arg->argn + 1) { 214838174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 214938174Sbrian if (arg->argc > arg->argn + 2) { 215038174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 215138174Sbrian if (long_val < MIN_FSMRETRY) 215238174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 215338174Sbrian long_val, MIN_FSMRETRY); 215438174Sbrian else 215538174Sbrian cx->cfg.cbcp.fsmretry = long_val; 215638174Sbrian } 215738174Sbrian } 215838174Sbrian } 215938174Sbrian break; 216038544Sbrian 216138544Sbrian case VAR_CHOKED: 216238544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 216338544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 216438544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 216538544Sbrian break; 216640665Sbrian 216740665Sbrian case VAR_SENDPIPE: 216840665Sbrian long_val = atol(argp); 216981634Sbrian arg->bundle->ncp.cfg.sendpipe = long_val; 217040665Sbrian break; 217140665Sbrian 217240665Sbrian case VAR_RECVPIPE: 217340665Sbrian long_val = atol(argp); 217481634Sbrian arg->bundle->ncp.cfg.recvpipe = long_val; 217540665Sbrian break; 217643313Sbrian 217743313Sbrian#ifndef NORADIUS 217843313Sbrian case VAR_RADIUS: 217943313Sbrian if (!*argp) 218043313Sbrian *arg->bundle->radius.cfg.file = '\0'; 218143313Sbrian else if (access(argp, R_OK)) { 218243313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 218379119Sbrian res = 1; 218479119Sbrian break; 218543313Sbrian } else { 218643313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 218743313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 218843313Sbrian arg->bundle->radius.cfg.file 218943313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 219043313Sbrian } 219143313Sbrian break; 219243313Sbrian#endif 219344073Sbrian 219444073Sbrian case VAR_CD: 219544073Sbrian if (*argp) { 219651699Sbrian if (strcasecmp(argp, "off")) { 219751699Sbrian long_val = atol(argp); 219851699Sbrian if (long_val < 0) 219951699Sbrian long_val = 0; 220051699Sbrian cx->physical->cfg.cd.delay = long_val; 220151699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 220251699Sbrian CD_REQUIRED : CD_VARIABLE; 220351699Sbrian } else 220451699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 220544073Sbrian } else { 220653733Sbrian cx->physical->cfg.cd.delay = 0; 220753733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 220844073Sbrian } 220944073Sbrian break; 221036285Sbrian 221146686Sbrian case VAR_PARITY: 221246686Sbrian if (arg->argc == arg->argn + 1) 221379119Sbrian res = physical_SetParity(arg->cx->physical, argp); 221446686Sbrian else { 221579119Sbrian log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 221679119Sbrian res = 1; 221746686Sbrian } 221846686Sbrian break; 22196059Samurai 222046686Sbrian case VAR_CRTSCTS: 222146686Sbrian if (strcasecmp(argp, "on") == 0) 222236285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 222346686Sbrian else if (strcasecmp(argp, "off") == 0) 222436285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 222546686Sbrian else { 222679119Sbrian log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 222779119Sbrian res = 1; 222846686Sbrian } 222946686Sbrian break; 223050867Sbrian 223150867Sbrian case VAR_URGENTPORTS: 223251048Sbrian if (arg->argn == arg->argc) { 223381634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 223481634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 223581634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 223651048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 223781634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 223851048Sbrian if (arg->argn == arg->argc - 1) 223981634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 224051048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 224151048Sbrian if (*arg->argv[f] == '+') 224281634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 224351048Sbrian else if (*arg->argv[f] == '-') 224481634Sbrian ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 224551048Sbrian else { 224651048Sbrian if (f == arg->argn) 224781634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 224881634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 224951048Sbrian } 225061430Sbrian } else if (arg->argn == arg->argc - 1 && 225161430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 225281634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 225381634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 225481634Sbrian ncp_ClearUrgentTOS(&arg->bundle->ncp); 225551048Sbrian } else { 225681634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 225751048Sbrian first = arg->argn; 225851048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 225981634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 226051048Sbrian 226151048Sbrian for (f = first; f < arg->argc; f++) 226251048Sbrian if (*arg->argv[f] == '+') 226381634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 226451048Sbrian else if (*arg->argv[f] == '-') 226581634Sbrian ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 226651048Sbrian else { 226751048Sbrian if (f == first) 226881634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 226981634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 227051048Sbrian } 227151048Sbrian } 227250867Sbrian break; 227320812Sjkh } 227446686Sbrian 227579119Sbrian return res; 227620812Sjkh} 227720812Sjkh 227830715Sbrianstatic struct cmdtab const SetCommands[] = { 227936285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 228036285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 228128679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 228236285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 228328679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 228436285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 228536285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 228636285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 228736285Sbrian (const void *)VAR_AUTOLOAD}, 228850867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 228950867Sbrian "datalink bandwidth", "set bandwidth value"}, 229038174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 229138174Sbrian "callback control", "set callback [none|auth|cbcp|" 229238174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 229338174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 229498243Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 229538174Sbrian (const void *)VAR_CBCP}, 229644305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 229744305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 229844073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 229944073Sbrian "set cd value[!]", (const void *)VAR_CD}, 230044305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 230144305Sbrian "CHAP retries", "set chapretry value [attempts]", 230244305Sbrian (const void *)VAR_CHAPRETRY}, 230338544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 230438544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 230546686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 230646686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 230746686Sbrian (const char *)VAR_CRTSCTS}, 230836285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 230936285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 231036285Sbrian (const void *) VAR_WINSIZE}, 231193418Sbrian#ifndef NODES 231267910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 231398243Sbrian "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 231478411Sbrian (const void *) VAR_MPPE}, 231567910Sbrian#endif 231636285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 231746686Sbrian "physical device name", "set device|line device-name[,device-name]", 231836285Sbrian (const void *) VAR_DEVICE}, 231936285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 232036285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 232136285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 232236285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 232336285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 232436285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 232536285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 232636285Sbrian "escape characters", "set escape hex-digit ..."}, 232736285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 232836285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 232981634Sbrian "[src_addr[/width]] [dst_addr[/width]] [proto " 233048142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 233136285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 233236285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 233336285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 233431343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 233561534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 233661534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 233744305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 233844305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 2339102558Sbrian {"ipv6cpretry", "ipv6cpretries", SetVariable, LOCAL_AUTH, "IPV6CP retries", 2340102558Sbrian "set ipv6cpretry value [attempts]", (const void *)VAR_IPV6CPRETRY}, 234144305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 234244305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 234336712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 234467916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 234558033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 234636285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 234736285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 234852488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 234952488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 235036285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 235136285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 235236285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 235336285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 235436285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 235536285Sbrian "set mrru value", (const void *)VAR_MRRU}, 235696038Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 235778410Sbrian "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 235878410Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 235978410Sbrian "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 236036285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 236136285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 236236285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 236336285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 236444305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 236544305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 236646686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 236746686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 236836285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 236936285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 237040679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 237140679Sbrian "Process title", "set proctitle [value]"}, 237243313Sbrian#ifndef NORADIUS 237343313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 237443313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 237543313Sbrian#endif 237636285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 237736285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 237840665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 237940665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 238036285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 238144468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 238240665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 238340665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 238471657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 238571657Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 238636285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 238746686Sbrian "physical speed", "set speed value|sync"}, 238836285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 238936285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 239036285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 239136285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 239251048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 239351048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 239436285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 239536285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 239628679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 239731343Sbrian "Display this message", "set help|? [command]", SetCommands}, 239828679Sbrian {NULL, NULL, NULL}, 23996059Samurai}; 24006059Samurai 24016059Samuraistatic int 240231343SbrianSetCommand(struct cmdargs const *arg) 24036059Samurai{ 240436285Sbrian if (arg->argc > arg->argn) 240536285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 240636285Sbrian arg->prompt, arg->cx); 240736285Sbrian else if (arg->prompt) 240836285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 240958044Sbrian " syntax help.\n"); 24106059Samurai else 241136285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 241226516Sbrian 241326516Sbrian return 0; 24146059Samurai} 24156059Samurai 24166059Samuraistatic int 241731343SbrianAddCommand(struct cmdargs const *arg) 24186059Samurai{ 241981634Sbrian struct ncpaddr gw; 242081634Sbrian struct ncprange dest; 242181634Sbrian struct in_addr host; 2422112673Sume#ifndef NOINET6 2423112673Sume struct in6_addr host6; 2424112673Sume#endif 242581634Sbrian int dest_default, gw_arg, addrs; 24266059Samurai 242736285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 242831598Sbrian return -1; 242931598Sbrian 243036285Sbrian addrs = 0; 243181634Sbrian dest_default = 0; 243281634Sbrian if (arg->argc == arg->argn + 2) { 243336285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 243481634Sbrian dest_default = 1; 243531598Sbrian else { 243681634Sbrian if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn])) 243736285Sbrian return -1; 243836285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 243936285Sbrian addrs = ROUTE_DSTMYADDR; 244081634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7)) 244181634Sbrian addrs = ROUTE_DSTMYADDR6; 244236285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 244336285Sbrian addrs = ROUTE_DSTHISADDR; 244481634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8)) 244581634Sbrian addrs = ROUTE_DSTHISADDR6; 244658044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 244758044Sbrian addrs = ROUTE_DSTDNS0; 244858044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 244958044Sbrian addrs = ROUTE_DSTDNS1; 245031598Sbrian } 245181634Sbrian gw_arg = 1; 245234536Sbrian } else { 245336285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 245436285Sbrian addrs = ROUTE_DSTMYADDR; 245581634Sbrian host = arg->bundle->ncp.ipcp.my_ip; 245636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 245736285Sbrian addrs = ROUTE_DSTHISADDR; 245881634Sbrian host = arg->bundle->ncp.ipcp.peer_ip; 245958044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 246058044Sbrian addrs = ROUTE_DSTDNS0; 246181634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[0]; 246258044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 246358044Sbrian addrs = ROUTE_DSTDNS1; 246481634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[1]; 246565263Sbrian } else { 246681634Sbrian host = GetIpAddr(arg->argv[arg->argn]); 246781634Sbrian if (host.s_addr == INADDR_NONE) { 246865263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 246965263Sbrian arg->argv[arg->argn]); 247065263Sbrian return -1; 247165263Sbrian } 247265263Sbrian } 247381634Sbrian ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1])); 247481634Sbrian gw_arg = 2; 24756059Samurai } 247636285Sbrian 247781634Sbrian if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) { 247881634Sbrian ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip); 247936285Sbrian addrs |= ROUTE_GWHISADDR; 248081634Sbrian#ifndef NOINET6 248181897Sbrian } else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) { 2482112673Sume if (!ncpaddr_getip6(&arg->bundle->ncp.ipv6cp.hisaddr, &host6)) 2483112673Sume memset(&host6, '\0', sizeof host6); 2484112673Sume ncpaddr_setip6(&gw, &host6); 248581634Sbrian addrs |= ROUTE_GWHISADDR6; 248681634Sbrian#endif 248765263Sbrian } else { 248881634Sbrian if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) { 248965263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 249081634Sbrian arg->argv[arg->argn + gw_arg]); 249165263Sbrian return -1; 249265263Sbrian } 249365263Sbrian } 249436285Sbrian 249581634Sbrian if (dest_default) 249681634Sbrian ncprange_setdefault(&dest, ncpaddr_family(&gw)); 249781634Sbrian 249881634Sbrian if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0, 249981634Sbrian ((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0) 250043313Sbrian && addrs != ROUTE_STATIC) 250181634Sbrian route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw); 250236285Sbrian 250331598Sbrian return 0; 25046059Samurai} 25056059Samurai 25066059Samuraistatic int 250731343SbrianDeleteCommand(struct cmdargs const *arg) 25086059Samurai{ 250981634Sbrian struct ncprange dest; 251036285Sbrian int addrs; 25116059Samurai 251236285Sbrian if (arg->argc == arg->argn+1) { 251336285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 251436285Sbrian route_IfDelete(arg->bundle, 0); 251581634Sbrian route_DeleteAll(&arg->bundle->ncp.route); 251636285Sbrian } else { 251736285Sbrian addrs = 0; 251836285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 251981634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip); 252036285Sbrian addrs = ROUTE_DSTMYADDR; 252181634Sbrian#ifndef NOINET6 252281897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) { 252381634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr); 252481634Sbrian addrs = ROUTE_DSTMYADDR6; 252581634Sbrian#endif 252636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 252781634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip); 252836285Sbrian addrs = ROUTE_DSTHISADDR; 252981634Sbrian#ifndef NOINET6 253081897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) { 253181634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr); 253281634Sbrian addrs = ROUTE_DSTHISADDR6; 253381634Sbrian#endif 253458044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 253581634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]); 253658044Sbrian addrs = ROUTE_DSTDNS0; 253758044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 253881634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]); 253958044Sbrian addrs = ROUTE_DSTDNS1; 254036285Sbrian } else { 254181634Sbrian ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]); 254236285Sbrian addrs = ROUTE_STATIC; 254336285Sbrian } 254481634Sbrian rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0); 254581634Sbrian route_Delete(&arg->bundle->ncp.route, addrs, &dest); 254631598Sbrian } 254734536Sbrian } else 254826516Sbrian return -1; 254926516Sbrian 255026516Sbrian return 0; 25516059Samurai} 25526059Samurai 255350059Sbrian#ifndef NONAT 255426031Sbrianstatic int 255558867SbrianNatEnable(struct cmdargs const *arg) 255626031Sbrian{ 255736285Sbrian if (arg->argc == arg->argn+1) { 255836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 255950059Sbrian if (!arg->bundle->NatEnabled) { 256046686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 256146686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 256250059Sbrian arg->bundle->NatEnabled = 1; 256346686Sbrian } 256437191Sbrian return 0; 256536285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 256650059Sbrian arg->bundle->NatEnabled = 0; 256740561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 256840561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 256926516Sbrian return 0; 257026142Sbrian } 257135449Sbrian } 257236285Sbrian 257326516Sbrian return -1; 257426031Sbrian} 257526031Sbrian 257626031Sbrian 257726031Sbrianstatic int 257858867SbrianNatOption(struct cmdargs const *arg) 257926031Sbrian{ 258038559Sbrian long param = (long)arg->cmd->args; 258138559Sbrian 258236285Sbrian if (arg->argc == arg->argn+1) { 258336285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 258450059Sbrian if (arg->bundle->NatEnabled) { 258537191Sbrian PacketAliasSetMode(param, param); 258628679Sbrian return 0; 258728679Sbrian } 258850059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 258936285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 259050059Sbrian if (arg->bundle->NatEnabled) { 259137191Sbrian PacketAliasSetMode(0, param); 259228679Sbrian return 0; 259328679Sbrian } 259450059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 259528679Sbrian } 259635449Sbrian } 259728679Sbrian return -1; 259826031Sbrian} 259950059Sbrian#endif /* #ifndef NONAT */ 260031121Sbrian 260131121Sbrianstatic int 260236285SbrianLinkCommand(struct cmdargs const *arg) 260336285Sbrian{ 260436285Sbrian if (arg->argc > arg->argn+1) { 260536285Sbrian char namelist[LINE_LEN]; 260636285Sbrian struct datalink *cx; 260736285Sbrian char *name; 260836285Sbrian int result = 0; 260936285Sbrian 261036285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 261136285Sbrian struct datalink *dl; 261236285Sbrian 261336285Sbrian cx = arg->bundle->links; 261436285Sbrian while (cx) { 261536285Sbrian /* Watch it, the command could be a ``remove'' */ 261636285Sbrian dl = cx->next; 261736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 261836285Sbrian arg->prompt, cx); 261936285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 262036285Sbrian if (cx == dl) 262136285Sbrian break; /* Pointer's still valid ! */ 262236285Sbrian } 262336285Sbrian } else { 262436285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 262536285Sbrian namelist[sizeof namelist - 1] = '\0'; 262636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 262736285Sbrian if (!bundle2datalink(arg->bundle, name)) { 262836285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 262936285Sbrian return 1; 263036285Sbrian } 263136285Sbrian 263236285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 263336285Sbrian namelist[sizeof namelist - 1] = '\0'; 263436285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 263536285Sbrian cx = bundle2datalink(arg->bundle, name); 263636285Sbrian if (cx) 263736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 263836285Sbrian arg->prompt, cx); 263936285Sbrian else { 264036285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 264136285Sbrian result++; 264236285Sbrian } 264336285Sbrian } 264436285Sbrian } 264536285Sbrian return result; 264636285Sbrian } 264736285Sbrian 264895258Sdes log_Printf(LogWARN, "usage: %s\n", arg->cmd->syntax); 264936285Sbrian return 2; 265036285Sbrian} 265136285Sbrian 265236285Sbrianstruct link * 265336285Sbriancommand_ChooseLink(struct cmdargs const *arg) 265436285Sbrian{ 265536285Sbrian if (arg->cx) 265636285Sbrian return &arg->cx->physical->link; 265737210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 265836285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 265937210Sbrian if (dl) 266037210Sbrian return &dl->physical->link; 266136285Sbrian } 266237210Sbrian return &arg->bundle->ncp.mp.link; 266336285Sbrian} 266436285Sbrian 266536285Sbrianstatic const char * 266636285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 266736285Sbrian{ 266836285Sbrian const char *result; 266936285Sbrian 267036285Sbrian switch (*cmd) { 267136285Sbrian case 'A': 267236285Sbrian case 'a': 267336285Sbrian result = "accept"; 267436285Sbrian *keep = NEG_MYMASK; 267536285Sbrian *add = NEG_ACCEPTED; 267636285Sbrian break; 267736285Sbrian case 'D': 267836285Sbrian case 'd': 267936285Sbrian switch (cmd[1]) { 268036285Sbrian case 'E': 268136285Sbrian case 'e': 268236285Sbrian result = "deny"; 268336285Sbrian *keep = NEG_MYMASK; 268436285Sbrian *add = 0; 268536285Sbrian break; 268636285Sbrian case 'I': 268736285Sbrian case 'i': 268836285Sbrian result = "disable"; 268936285Sbrian *keep = NEG_HISMASK; 269036285Sbrian *add = 0; 269136285Sbrian break; 269236285Sbrian default: 269336285Sbrian return NULL; 269436285Sbrian } 269536285Sbrian break; 269636285Sbrian case 'E': 269736285Sbrian case 'e': 269836285Sbrian result = "enable"; 269936285Sbrian *keep = NEG_HISMASK; 270036285Sbrian *add = NEG_ENABLED; 270136285Sbrian break; 270236285Sbrian default: 270336285Sbrian return NULL; 270436285Sbrian } 270536285Sbrian 270636285Sbrian return result; 270736285Sbrian} 270836285Sbrian 270936285Sbrianstatic int 271036285SbrianOptSet(struct cmdargs const *arg) 271136285Sbrian{ 271237574Sbrian int bit = (int)(long)arg->cmd->args; 271336285Sbrian unsigned keep; /* Keep these bits */ 271436285Sbrian unsigned add; /* Add these bits */ 271536285Sbrian 271681697Sbrian if (ident_cmd(arg->argv[arg->argn - 2], &keep, &add) == NULL) 271736285Sbrian return 1; 271836285Sbrian 271981885Sbrian#ifndef NOINET6 272081697Sbrian if (add == NEG_ENABLED && bit == OPT_IPV6CP && !probe.ipv6_available) { 272181697Sbrian log_Printf(LogWARN, "IPv6 is not available on this machine\n"); 272281697Sbrian return 1; 272381697Sbrian } 272481885Sbrian#endif 272581697Sbrian 272636285Sbrian if (add) 272736285Sbrian arg->bundle->cfg.opt |= bit; 272836285Sbrian else 272936285Sbrian arg->bundle->cfg.opt &= ~bit; 273081697Sbrian 273136285Sbrian return 0; 273236285Sbrian} 273336285Sbrian 273436285Sbrianstatic int 273540561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 273640561Sbrian{ 273740561Sbrian unsigned save = arg->bundle->cfg.opt; 273840561Sbrian int result = OptSet(arg); 273940561Sbrian 274040561Sbrian if (result == 0) 274150059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 274240561Sbrian arg->bundle->cfg.opt = save; 274350059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 274440561Sbrian result = 2; 274540561Sbrian } 274640561Sbrian 274740561Sbrian return result; 274840561Sbrian} 274940561Sbrian 275040561Sbrianstatic int 275136285SbrianNegotiateSet(struct cmdargs const *arg) 275236285Sbrian{ 275337210Sbrian long param = (long)arg->cmd->args; 275436285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 275536285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 275636285Sbrian const char *cmd; 275736285Sbrian unsigned keep; /* Keep these bits */ 275836285Sbrian unsigned add; /* Add these bits */ 275936285Sbrian 276036285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 276136285Sbrian return 1; 276236285Sbrian 276336285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 276436285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 276536285Sbrian cmd, arg->cmd->name); 276636285Sbrian return 2; 276736285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 276836285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 276936285Sbrian cmd, arg->cmd->name, cx->name); 277036285Sbrian cx = NULL; 277136285Sbrian } 277236285Sbrian 277336285Sbrian switch (param) { 277436285Sbrian case NEG_ACFCOMP: 277536285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 277636285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 277736285Sbrian break; 277844106Sbrian case NEG_CHAP05: 277944106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 278044106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 278136285Sbrian break; 278293418Sbrian#ifndef NODES 278344106Sbrian case NEG_CHAP80: 278444106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 278544106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 278644106Sbrian break; 278744106Sbrian case NEG_CHAP80LM: 278844106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 278944106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 279044106Sbrian break; 279167910Sbrian case NEG_CHAP81: 279267910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 279367910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 279467910Sbrian break; 279567910Sbrian case NEG_MPPE: 279667910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 279767910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 279867910Sbrian break; 279944106Sbrian#endif 280036285Sbrian case NEG_DEFLATE: 280136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 280236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 280336285Sbrian break; 280436285Sbrian case NEG_DNS: 280536285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 280636285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 280736285Sbrian break; 280847858Sbrian case NEG_ENDDISC: 280947858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 281047858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 281147858Sbrian break; 281236285Sbrian case NEG_LQR: 281336285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 281436285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 281536285Sbrian break; 281636285Sbrian case NEG_PAP: 281736285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 281836285Sbrian cx->physical->link.lcp.cfg.pap |= add; 281936285Sbrian break; 282036285Sbrian case NEG_PPPDDEFLATE: 282136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 282236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 282336285Sbrian break; 282436285Sbrian case NEG_PRED1: 282536285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 282636285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 282736285Sbrian break; 282836285Sbrian case NEG_PROTOCOMP: 282936285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 283036285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 283136285Sbrian break; 283236285Sbrian case NEG_SHORTSEQ: 283340622Sbrian switch (bundle_Phase(arg->bundle)) { 283440622Sbrian case PHASE_DEAD: 283540622Sbrian break; 283640622Sbrian case PHASE_ESTABLISH: 283740622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 283840622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 283940622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 284040622Sbrian " LCP negotiations\n"); 284140622Sbrian return 1; 284240622Sbrian } 284340622Sbrian break; 284440622Sbrian default: 284540622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 284640622Sbrian " DEAD/ESTABLISH\n"); 284740622Sbrian return 1; 284836285Sbrian } 284940622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 285040622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 285136285Sbrian break; 285236285Sbrian case NEG_VJCOMP: 285336285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 285436285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 285536285Sbrian break; 285636285Sbrian } 285736285Sbrian 285836285Sbrian return 0; 285936285Sbrian} 286036285Sbrian 286136285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 286262778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 286362778Sbrian "filter on PPPoUDP payloads", "disable|enable", 286462778Sbrian (const void *)OPT_FILTERDECAP}, 2865112659Sbrian {"force-scripts", NULL, OptSet, LOCAL_AUTH, 2866112659Sbrian "Force execution of the configured chat scripts", "disable|enable", 2867112659Sbrian (const void *)OPT_FORCE_SCRIPTS}, 286836285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 286936285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 287040666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 287162778Sbrian "retain interface addresses", "disable|enable", 287262778Sbrian (const void *)OPT_IFACEALIAS}, 287381634Sbrian#ifndef NOINET6 287481634Sbrian {"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol", 287581634Sbrian "disable|enable", (const void *)OPT_IPCP}, 287681634Sbrian {"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol", 287781634Sbrian "disable|enable", (const void *)OPT_IPV6CP}, 287881634Sbrian#endif 287947689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 288047689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 288136285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 288236285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 288336285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 288436285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 288540665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 288636285Sbrian "disable|enable", (const void *)OPT_PROXY}, 288740665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 288840665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 288936285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 289036285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 289169303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 289269303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 289336285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 289436285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 289536285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 289636285Sbrian "disable|enable", (const void *)OPT_UTMP}, 289736285Sbrian 289881634Sbrian#ifndef NOINET6 2899112659Sbrian#define OPT_MAX 14 /* accept/deny allowed below and not above */ 290081634Sbrian#else 2901112659Sbrian#define OPT_MAX 12 290281634Sbrian#endif 290336285Sbrian 290436285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 290536285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 290636285Sbrian (const void *)NEG_ACFCOMP}, 290744106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 290836285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 290944106Sbrian (const void *)NEG_CHAP05}, 291093418Sbrian#ifndef NODES 291144106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 291244106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 291344106Sbrian (const void *)NEG_CHAP80}, 291444106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 291544106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 291644106Sbrian (const void *)NEG_CHAP80LM}, 291767910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 291867910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 291967910Sbrian (const void *)NEG_CHAP81}, 292067910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 292167910Sbrian "MPPE encryption", "accept|deny|disable|enable", 292267910Sbrian (const void *)NEG_MPPE}, 292344106Sbrian#endif 292436285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 292536285Sbrian "Deflate compression", "accept|deny|disable|enable", 292636285Sbrian (const void *)NEG_DEFLATE}, 292736285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 292836285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 292936285Sbrian (const void *)NEG_PPPDDEFLATE}, 293036285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 293136285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 293247858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 293347858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 293436285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 293536285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 293636285Sbrian (const void *)NEG_LQR}, 293736285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 293836285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 293936285Sbrian (const void *)NEG_PAP}, 294036285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 294136285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 294236285Sbrian (const void *)NEG_PRED1}, 294336285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 294436285Sbrian "Protocol field compression", "accept|deny|disable|enable", 294536285Sbrian (const void *)NEG_PROTOCOMP}, 294636285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 294736285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 294836285Sbrian (const void *)NEG_SHORTSEQ}, 294936285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 295036285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 295136285Sbrian (const void *)NEG_VJCOMP}, 295236285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 295336285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 295436285Sbrian NegotiateCommands}, 295536285Sbrian {NULL, NULL, NULL}, 295636285Sbrian}; 295736285Sbrian 295836285Sbrianstatic int 295936285SbrianNegotiateCommand(struct cmdargs const *arg) 296036285Sbrian{ 296136285Sbrian if (arg->argc > arg->argn) { 296236285Sbrian char const *argv[3]; 296336285Sbrian unsigned keep, add; 296436285Sbrian int n; 296536285Sbrian 296636285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 296736285Sbrian return -1; 296836285Sbrian argv[2] = NULL; 296936285Sbrian 297036285Sbrian for (n = arg->argn; n < arg->argc; n++) { 297136285Sbrian argv[1] = arg->argv[n]; 297236285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 297336285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 297436285Sbrian } 297536285Sbrian } else if (arg->prompt) 297636285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 297736285Sbrian arg->argv[arg->argn-1]); 297836285Sbrian else 297936285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 298036285Sbrian arg->argv[arg->argn] ); 298136285Sbrian 298236285Sbrian return 0; 298336285Sbrian} 298436285Sbrian 298536285Sbrianconst char * 298636285Sbriancommand_ShowNegval(unsigned val) 298736285Sbrian{ 298836285Sbrian switch (val&3) { 298936285Sbrian case 1: return "disabled & accepted"; 299036285Sbrian case 2: return "enabled & denied"; 299136285Sbrian case 3: return "enabled & accepted"; 299236285Sbrian } 299336285Sbrian return "disabled & denied"; 299436285Sbrian} 299536934Sbrian 299636934Sbrianstatic int 299736934SbrianClearCommand(struct cmdargs const *arg) 299836934Sbrian{ 299936934Sbrian struct pppThroughput *t; 300036934Sbrian struct datalink *cx; 300136934Sbrian int i, clear_type; 300236934Sbrian 300336934Sbrian if (arg->argc < arg->argn + 1) 300436934Sbrian return -1; 300536934Sbrian 300646686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 300736934Sbrian cx = arg->cx; 300836934Sbrian if (!cx) 300936934Sbrian cx = bundle2datalink(arg->bundle, NULL); 301036934Sbrian if (!cx) { 301146686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 301236934Sbrian return 1; 301336934Sbrian } 301464652Sbrian t = &cx->physical->link.stats.total; 301536934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 301636934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 301781634Sbrian#ifndef NOINET6 301881897Sbrian else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0) 301981634Sbrian t = &arg->bundle->ncp.ipv6cp.throughput; 302081634Sbrian#endif 302136934Sbrian else 302236934Sbrian return -1; 302336934Sbrian 302436934Sbrian if (arg->argc > arg->argn + 1) { 302536934Sbrian clear_type = 0; 302636934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 302736934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 302836934Sbrian clear_type |= THROUGHPUT_OVERALL; 302936934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 303036934Sbrian clear_type |= THROUGHPUT_CURRENT; 303136934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 303236934Sbrian clear_type |= THROUGHPUT_PEAK; 303336934Sbrian else 303436934Sbrian return -1; 303598243Sbrian } else 303636934Sbrian clear_type = THROUGHPUT_ALL; 303736934Sbrian 303836934Sbrian throughput_clear(t, clear_type, arg->prompt); 303936934Sbrian return 0; 304036934Sbrian} 304140561Sbrian 304240561Sbrianstatic int 304340561SbrianRunListCommand(struct cmdargs const *arg) 304440561Sbrian{ 304540561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 304640561Sbrian 304764801Sbrian#ifndef NONAT 304864801Sbrian if (arg->cmd->args == NatCommands && 304964801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 305064801Sbrian if (arg->prompt) 305165550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 305264801Sbrian else 305365550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 305464801Sbrian } 305564801Sbrian#endif 305664801Sbrian 305740561Sbrian if (arg->argc > arg->argn) 305840561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 305940561Sbrian arg->prompt, arg->cx); 306040561Sbrian else if (arg->prompt) 306140561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 306240561Sbrian " <option>' for syntax help.\n", cmd, cmd); 306340561Sbrian else 306440561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 306540561Sbrian 306640561Sbrian return 0; 306740561Sbrian} 306840561Sbrian 306940561Sbrianstatic int 307040561SbrianIfaceAddCommand(struct cmdargs const *arg) 307140561Sbrian{ 307281634Sbrian struct ncpaddr peer, addr; 307381634Sbrian struct ncprange ifa; 307481634Sbrian struct in_addr mask; 307581634Sbrian int n, how; 307640561Sbrian 307740664Sbrian if (arg->argc == arg->argn + 1) { 307881634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 307940561Sbrian return -1; 308081634Sbrian ncpaddr_init(&peer); 308140664Sbrian } else { 308240664Sbrian if (arg->argc == arg->argn + 2) { 308381634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 308440664Sbrian return -1; 308540664Sbrian n = 1; 308640664Sbrian } else if (arg->argc == arg->argn + 3) { 308781634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn])) 308840664Sbrian return -1; 308981634Sbrian if (ncpaddr_family(&addr) != AF_INET) 309040664Sbrian return -1; 309181634Sbrian ncprange_sethost(&ifa, &addr); 309281634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1])) 309381634Sbrian return -1; 309481634Sbrian if (!ncpaddr_getip4(&addr, &mask)) 309581634Sbrian return -1; 309681634Sbrian if (!ncprange_setip4mask(&ifa, mask)) 309781634Sbrian return -1; 309840664Sbrian n = 2; 309940664Sbrian } else 310040561Sbrian return -1; 310140561Sbrian 310281634Sbrian if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n])) 310340664Sbrian return -1; 310481634Sbrian 310581634Sbrian if (ncprange_family(&ifa) != ncpaddr_family(&peer)) { 310681634Sbrian log_Printf(LogWARN, "IfaceAddCommand: src and dst address families" 310781634Sbrian " differ\n"); 310881634Sbrian return -1; 310981634Sbrian } 311040664Sbrian } 311140561Sbrian 311240561Sbrian how = IFACE_ADD_LAST; 311340561Sbrian if (arg->cmd->args) 311440561Sbrian how |= IFACE_FORCE_ADD; 311540561Sbrian 311681634Sbrian return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how); 311740561Sbrian} 311840561Sbrian 311940561Sbrianstatic int 312040561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 312140561Sbrian{ 312281634Sbrian struct ncpaddr ifa; 312381634Sbrian struct in_addr ifa4; 312440561Sbrian int ok; 312540561Sbrian 312640561Sbrian if (arg->argc != arg->argn + 1) 312740561Sbrian return -1; 312840561Sbrian 312981634Sbrian if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn])) 313040561Sbrian return -1; 313140561Sbrian 313240561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 313381634Sbrian ncpaddr_getip4(&ifa, &ifa4) && 313481634Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) { 313540561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 313681634Sbrian ncpaddr_ntoa(&ifa)); 313740561Sbrian return 1; 313840561Sbrian } 313940561Sbrian 314081634Sbrian ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa); 314140561Sbrian if (!ok) { 314240561Sbrian if (arg->cmd->args) 314340561Sbrian ok = 1; 314440561Sbrian else if (arg->prompt) 314581634Sbrian prompt_Printf(arg->prompt, "%s: No such interface address\n", 314681634Sbrian ncpaddr_ntoa(&ifa)); 314740561Sbrian else 314881634Sbrian log_Printf(LogWARN, "%s: No such interface address\n", 314981634Sbrian ncpaddr_ntoa(&ifa)); 315040561Sbrian } 315140561Sbrian 315240561Sbrian return !ok; 315340561Sbrian} 315440561Sbrian 315540561Sbrianstatic int 315640561SbrianIfaceClearCommand(struct cmdargs const *arg) 315740561Sbrian{ 315881634Sbrian int family, how; 315940561Sbrian 316081634Sbrian family = 0; 316181634Sbrian if (arg->argc == arg->argn + 1) { 316281634Sbrian if (strcasecmp(arg->argv[arg->argn], "inet") == 0) 316381634Sbrian family = AF_INET; 316481634Sbrian#ifndef NOINET6 316581897Sbrian else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0) 316681634Sbrian family = AF_INET6; 316781634Sbrian#endif 316881634Sbrian else 316981634Sbrian return -1; 317081634Sbrian } else if (arg->argc != arg->argn) 317140561Sbrian return -1; 317240561Sbrian 317340941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 317440941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 317540561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 317681634Sbrian iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how); 317740561Sbrian 317840561Sbrian return 0; 317940561Sbrian} 318040679Sbrian 318140679Sbrianstatic int 318240679SbrianSetProcTitle(struct cmdargs const *arg) 318340679Sbrian{ 318440679Sbrian static char title[LINE_LEN]; 318586028Sbrian char *argv[MAXARGS]; 318686028Sbrian int argc = arg->argc - arg->argn; 318740679Sbrian 318840679Sbrian if (arg->argc == arg->argn) { 318964698Sbrian SetTitle(NULL); 319040679Sbrian return 0; 319140679Sbrian } 319240679Sbrian 319340679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 319440679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 319540679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 319640679Sbrian } 319747849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 319885991Sbrian Concatinate(title, sizeof title, argc, (const char *const *)argv); 319964698Sbrian SetTitle(title); 320085991Sbrian command_Free(argc, argv); 320140679Sbrian 320240679Sbrian return 0; 320340679Sbrian} 3204