command.c revision 249582
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 249582 2013-04-17 11:40:10Z gabor $ 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 145132273Sbrian#define VAR_RAD_ALIVE 38 146132818Sglebius#define VAR_PPPOE 39 147169986Snovel#define VAR_PORT_ID 40 1486059Samurai 14936285Sbrian/* ``accept|deny|disable|enable'' masks */ 15036285Sbrian#define NEG_HISMASK (1) 15136285Sbrian#define NEG_MYMASK (2) 15236285Sbrian 15336285Sbrian/* ``accept|deny|disable|enable'' values */ 15436285Sbrian#define NEG_ACFCOMP 40 15544106Sbrian#define NEG_CHAP05 41 15644106Sbrian#define NEG_CHAP80 42 15744106Sbrian#define NEG_CHAP80LM 43 15844106Sbrian#define NEG_DEFLATE 44 15947858Sbrian#define NEG_DNS 45 160138799Sbrian#define NEG_ECHO 46 161138799Sbrian#define NEG_ENDDISC 47 162138799Sbrian#define NEG_LQR 48 163138799Sbrian#define NEG_PAP 49 164138799Sbrian#define NEG_PPPDDEFLATE 50 165138799Sbrian#define NEG_PRED1 51 166138799Sbrian#define NEG_PROTOCOMP 52 167138799Sbrian#define NEG_SHORTSEQ 53 168138799Sbrian#define NEG_VJCOMP 54 169138799Sbrian#define NEG_MPPE 55 170138799Sbrian#define NEG_CHAP81 56 17136285Sbrian 172138799Sbrianconst char Version[] = "3.4.2"; 17336285Sbrian 17436285Sbrianstatic int ShowCommand(struct cmdargs const *); 17536285Sbrianstatic int TerminalCommand(struct cmdargs const *); 17636285Sbrianstatic int QuitCommand(struct cmdargs const *); 17736285Sbrianstatic int OpenCommand(struct cmdargs const *); 17836285Sbrianstatic int CloseCommand(struct cmdargs const *); 17936285Sbrianstatic int DownCommand(struct cmdargs const *); 18036285Sbrianstatic int SetCommand(struct cmdargs const *); 18136285Sbrianstatic int LinkCommand(struct cmdargs const *); 18236285Sbrianstatic int AddCommand(struct cmdargs const *); 18336285Sbrianstatic int DeleteCommand(struct cmdargs const *); 18436285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 18536934Sbrianstatic int ClearCommand(struct cmdargs const *); 18640561Sbrianstatic int RunListCommand(struct cmdargs const *); 187218397Sbrianstatic int IfaceNameCommand(struct cmdargs const *arg); 18840561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 18940561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 19040561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 19140679Sbrianstatic int SetProcTitle(struct cmdargs const *); 19250059Sbrian#ifndef NONAT 19358867Sbrianstatic int NatEnable(struct cmdargs const *); 19458867Sbrianstatic int NatOption(struct cmdargs const *); 19531343Sbrian#endif 1966059Samurai 197177100Spisoextern struct libalias *la; 198177100Spiso 19936285Sbrianstatic const char * 20036285Sbrianshowcx(struct cmdtab const *cmd) 20136285Sbrian{ 20236285Sbrian if (cmd->lauth & LOCAL_CX) 20336285Sbrian return "(c)"; 20436285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 20536285Sbrian return "(o)"; 20636285Sbrian 20736285Sbrian return ""; 20836285Sbrian} 20936285Sbrian 2106059Samuraistatic int 21131343SbrianHelpCommand(struct cmdargs const *arg) 2126059Samurai{ 21328679Sbrian struct cmdtab const *cmd; 21436285Sbrian int n, cmax, dmax, cols, cxlen; 21536285Sbrian const char *cx; 2166059Samurai 21736285Sbrian if (!arg->prompt) { 21836285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 21926516Sbrian return 0; 22036285Sbrian } 22126516Sbrian 22236285Sbrian if (arg->argc > arg->argn) { 22336285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 22436285Sbrian if ((cmd->lauth & arg->prompt->auth) && 22536285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 22636285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 22736285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 22828679Sbrian return 0; 2296059Samurai } 23026516Sbrian return -1; 2316059Samurai } 23236285Sbrian 23331372Sbrian cmax = dmax = 0; 23436285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 23536285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 23636285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 23731372Sbrian cmax = n; 23831372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 23931372Sbrian dmax = n; 24031372Sbrian } 24131372Sbrian 24231372Sbrian cols = 80 / (dmax + cmax + 3); 2436059Samurai n = 0; 24436285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 24536285Sbrian " (c) = Context required\n"); 24636285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 24736285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 24836285Sbrian cx = showcx(cmd); 24936285Sbrian cxlen = cmax - strlen(cmd->name); 25040482Sbrian if (n % cols != 0) 25140482Sbrian prompt_Printf(arg->prompt, " "); 25240482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 25336285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 25431372Sbrian if (++n % cols == 0) 25536285Sbrian prompt_Printf(arg->prompt, "\n"); 2566059Samurai } 25731372Sbrian if (n % cols != 0) 25836285Sbrian prompt_Printf(arg->prompt, "\n"); 25926516Sbrian 26026516Sbrian return 0; 2616059Samurai} 2626059Samurai 26336285Sbrianstatic int 26463484SbrianIdentCommand(struct cmdargs const *arg) 26563484Sbrian{ 26685991Sbrian Concatinate(arg->cx->physical->link.lcp.cfg.ident, 26785991Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident, 26885991Sbrian arg->argc - arg->argn, arg->argv + arg->argn); 26963484Sbrian return 0; 27063484Sbrian} 27163484Sbrian 27263484Sbrianstatic int 27363484SbrianSendIdentification(struct cmdargs const *arg) 27463484Sbrian{ 27563484Sbrian if (arg->cx->state < DATALINK_LCP) { 27663484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 27763484Sbrian return 2; 27863484Sbrian } 27963484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 28063484Sbrian} 28163484Sbrian 28263484Sbrianstatic int 28336285SbrianCloneCommand(struct cmdargs const *arg) 2846059Samurai{ 28536285Sbrian char namelist[LINE_LEN]; 28636285Sbrian char *name; 28736285Sbrian int f; 2886059Samurai 28936285Sbrian if (arg->argc == arg->argn) 29036285Sbrian return -1; 29136285Sbrian 29236285Sbrian namelist[sizeof namelist - 1] = '\0'; 29336285Sbrian for (f = arg->argn; f < arg->argc; f++) { 29436285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 29536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 29636285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2976059Samurai } 29836285Sbrian 29936285Sbrian return 0; 3006059Samurai} 3016059Samurai 3026059Samuraistatic int 30336285SbrianRemoveCommand(struct cmdargs const *arg) 3046059Samurai{ 30536285Sbrian if (arg->argc != arg->argn) 30636285Sbrian return -1; 30711336Samurai 30836285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 30936285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 31036285Sbrian return 2; 3116059Samurai } 31226516Sbrian 31336285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 31436285Sbrian return 0; 31536285Sbrian} 31632711Sbrian 31736285Sbrianstatic int 31836285SbrianRenameCommand(struct cmdargs const *arg) 31936285Sbrian{ 32036285Sbrian if (arg->argc != arg->argn + 1) 32136285Sbrian return -1; 32231121Sbrian 32336285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 32436285Sbrian return 0; 32536285Sbrian 32698243Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 32736285Sbrian arg->cx->name, arg->argv[arg->argn]); 32836285Sbrian return 1; 32936285Sbrian} 33036285Sbrian 33185991Sbrianstatic int 33236285SbrianLoadCommand(struct cmdargs const *arg) 33336285Sbrian{ 33440797Sbrian const char *err; 33540797Sbrian int n, mode; 33636285Sbrian 33740797Sbrian mode = arg->bundle->phys_type.all; 33836285Sbrian 33940797Sbrian if (arg->argn < arg->argc) { 34040797Sbrian for (n = arg->argn; n < arg->argc; n++) 34140797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 34240797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 34340797Sbrian return 1; 34440797Sbrian } 34540797Sbrian 34640797Sbrian for (n = arg->argn; n < arg->argc; n++) { 34740797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34840797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 34940797Sbrian } 35040797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 35140797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 35240797Sbrian log_Printf(LogWARN, "default: %s\n", err); 35336285Sbrian return 1; 35436285Sbrian } else { 35540797Sbrian bundle_SetLabel(arg->bundle, "default"); 35640797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 35740797Sbrian bundle_SetLabel(arg->bundle, "default"); 35836285Sbrian } 35940797Sbrian 36026516Sbrian return 0; 3616059Samurai} 3626059Samurai 36385991Sbrianstatic int 36485991SbrianLogCommand(struct cmdargs const *arg) 36585991Sbrian{ 36685991Sbrian char buf[LINE_LEN]; 36785991Sbrian 36885991Sbrian if (arg->argn < arg->argc) { 36985991Sbrian char *argv[MAXARGS]; 37085991Sbrian int argc = arg->argc - arg->argn; 37185991Sbrian 372134789Sbrian if (argc >= (int)(sizeof argv / sizeof argv[0])) { 37385991Sbrian argc = sizeof argv / sizeof argv[0] - 1; 37485991Sbrian log_Printf(LogWARN, "Truncating log command to %d args\n", argc); 37585991Sbrian } 37686760Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 37785991Sbrian Concatinate(buf, sizeof buf, argc, (const char *const *)argv); 37885991Sbrian log_Printf(LogLOG, "%s\n", buf); 37985991Sbrian command_Free(argc, argv); 38085991Sbrian return 0; 38185991Sbrian } 38285991Sbrian 38385991Sbrian return -1; 38485991Sbrian} 38585991Sbrian 38685991Sbrianstatic int 387134789SbrianSaveCommand(struct cmdargs const *arg __unused) 38836285Sbrian{ 38985991Sbrian log_Printf(LogWARN, "save command is not yet implemented.\n"); 39036285Sbrian return 1; 39136285Sbrian} 39236285Sbrian 39310528Samuraistatic int 39436285SbrianDialCommand(struct cmdargs const *arg) 39528536Sbrian{ 39636285Sbrian int res; 39736285Sbrian 39836465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 39936465Sbrian || (!arg->cx && 40036928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 40136285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 40236285Sbrian " interactive links\n"); 40336285Sbrian return 1; 40434536Sbrian } 40536285Sbrian 40636285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 40736285Sbrian return res; 40836285Sbrian 40937993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 41036285Sbrian 41136285Sbrian return 0; 41228536Sbrian} 41328536Sbrian 41438628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 41538628Sbrian 41638628Sbrianstatic char * 41738628Sbrianstrstrword(char *big, const char *little) 41838628Sbrian{ 419249582Sgabor /* Get the first occurrence of the word ``little'' in ``big'' */ 42038628Sbrian char *pos; 42138628Sbrian int len; 42238628Sbrian 42338628Sbrian pos = big; 42438628Sbrian len = strlen(little); 42538628Sbrian 42638628Sbrian while ((pos = strstr(pos, little)) != NULL) 42747865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 42847865Sbrian pos++; 42947865Sbrian else if (pos != big && pos[-1] == '\\') 43047865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 43147865Sbrian else 43238628Sbrian break; 43338628Sbrian 43438628Sbrian return pos; 43538628Sbrian} 43638628Sbrian 43738628Sbrianstatic char * 43838628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 43938628Sbrian{ 44038628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 44138628Sbrian char *word, *ntgt; 44238628Sbrian int ltgt, loldstr, lnewstr, pos; 44338628Sbrian 44438628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 44538628Sbrian return tgt; 44638628Sbrian 44738628Sbrian ltgt = strlen(tgt) + 1; 44838628Sbrian loldstr = strlen(oldstr); 44938628Sbrian lnewstr = strlen(newstr); 45038628Sbrian do { 45138628Sbrian pos = word - tgt; 45238628Sbrian if (loldstr > lnewstr) 45338628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 45438628Sbrian if (loldstr != lnewstr) { 45538628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 45638628Sbrian if (ntgt == NULL) 45738628Sbrian break; /* Oh wonderful ! */ 45838628Sbrian word = ntgt + pos; 45938628Sbrian tgt = ntgt; 46038628Sbrian } 46138628Sbrian if (lnewstr > loldstr) 462141504Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - lnewstr); 46338628Sbrian bcopy(newstr, word, lnewstr); 46438628Sbrian } while ((word = strstrword(word, oldstr))); 46538628Sbrian 46638628Sbrian return tgt; 46738628Sbrian} 46838628Sbrian 46994934Sbrianstatic char * 47094934Sbriansubstip(char *tgt, const char *oldstr, struct in_addr ip) 47194934Sbrian{ 47294934Sbrian return subst(tgt, oldstr, inet_ntoa(ip)); 47394934Sbrian} 47494934Sbrian 47594934Sbrianstatic char * 47697360Sbriansubstlong(char *tgt, const char *oldstr, long l) 47794934Sbrian{ 47897360Sbrian char buf[23]; 47994934Sbrian 48097360Sbrian snprintf(buf, sizeof buf, "%ld", l); 48194934Sbrian 48294934Sbrian return subst(tgt, oldstr, buf); 48394934Sbrian} 48494934Sbrian 48594934Sbrianstatic char * 48694934Sbriansubstull(char *tgt, const char *oldstr, unsigned long long ull) 48794934Sbrian{ 48894934Sbrian char buf[21]; 48994934Sbrian 49094934Sbrian snprintf(buf, sizeof buf, "%llu", ull); 49194934Sbrian 49294934Sbrian return subst(tgt, oldstr, buf); 49394934Sbrian} 49494934Sbrian 49594934Sbrian 49694934Sbrian#ifndef NOINET6 49794934Sbrianstatic char * 49894934Sbriansubstipv6(char *tgt, const char *oldstr, const struct ncpaddr *ip) 49994934Sbrian{ 50094934Sbrian return subst(tgt, oldstr, ncpaddr_ntoa(ip)); 50194934Sbrian} 502116622Sume 503116622Sume#ifndef NORADIUS 504116622Sumestatic char * 505116622Sumesubstipv6prefix(char *tgt, const char *oldstr, const uint8_t *ipv6prefix) 506116622Sume{ 507116622Sume uint8_t ipv6addr[INET6_ADDRSTRLEN]; 508116622Sume uint8_t prefix[INET6_ADDRSTRLEN + sizeof("/128") - 1]; 509116622Sume 510116622Sume if (ipv6prefix) { 511116622Sume inet_ntop(AF_INET6, &ipv6prefix[2], ipv6addr, sizeof(ipv6addr)); 512116622Sume snprintf(prefix, sizeof(prefix), "%s/%d", ipv6addr, ipv6prefix[1]); 513116622Sume } else 514116622Sume prefix[0] = '\0'; 515116622Sume return subst(tgt, oldstr, prefix); 516116622Sume} 51794934Sbrian#endif 518116622Sume#endif 51994934Sbrian 52043888Sbrianvoid 52143888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 52247849Sbrian struct bundle *bundle, int inc0, pid_t pid) 52338628Sbrian{ 52485991Sbrian int arg, secs; 52594934Sbrian char uptime[20]; 52694934Sbrian unsigned long long oin, oout, pin, pout; 52738628Sbrian 52841755Sbrian if (inc0) 52941755Sbrian arg = 0; /* Start at arg 0 */ 53041755Sbrian else { 53141755Sbrian nargv[0] = strdup(oargv[0]); 53241755Sbrian arg = 1; 53341755Sbrian } 53494934Sbrian 53594934Sbrian secs = bundle_Uptime(bundle); 53694934Sbrian snprintf(uptime, sizeof uptime, "%d:%02d:%02d", 53794934Sbrian secs / 3600, (secs / 60) % 60, secs % 60); 53894934Sbrian oin = bundle->ncp.ipcp.throughput.OctetsIn; 53994934Sbrian oout = bundle->ncp.ipcp.throughput.OctetsOut; 54094934Sbrian pin = bundle->ncp.ipcp.throughput.PacketsIn; 54194934Sbrian pout = bundle->ncp.ipcp.throughput.PacketsOut; 54294934Sbrian#ifndef NOINET6 54394934Sbrian oin += bundle->ncp.ipv6cp.throughput.OctetsIn; 54494934Sbrian oout += bundle->ncp.ipv6cp.throughput.OctetsOut; 54594934Sbrian pin += bundle->ncp.ipv6cp.throughput.PacketsIn; 54694934Sbrian pout += bundle->ncp.ipv6cp.throughput.PacketsOut; 54794934Sbrian#endif 54894934Sbrian 54941755Sbrian for (; arg < argc; arg++) { 55038629Sbrian nargv[arg] = strdup(oargv[arg]); 55194934Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 55294934Sbrian nargv[arg] = substip(nargv[arg], "DNS0", bundle->ncp.ipcp.ns.dns[0]); 55394934Sbrian nargv[arg] = substip(nargv[arg], "DNS1", bundle->ncp.ipcp.ns.dns[1]); 55498243Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 55594934Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 55694934Sbrian bundle->ncp.mp.cfg.enddisc.address, 55794934Sbrian bundle->ncp.mp.cfg.enddisc.len)); 55894934Sbrian nargv[arg] = substip(nargv[arg], "HISADDR", bundle->ncp.ipcp.peer_ip); 55981634Sbrian#ifndef NOINET6 56094934Sbrian nargv[arg] = substipv6(nargv[arg], "HISADDR6", &bundle->ncp.ipv6cp.hisaddr); 56181634Sbrian#endif 56240561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 56394934Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSIN", 56494934Sbrian bundle->ncp.ipcp.throughput.OctetsIn); 56598243Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSOUT", 56694934Sbrian bundle->ncp.ipcp.throughput.OctetsOut); 56798243Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSIN", 56894934Sbrian bundle->ncp.ipcp.throughput.PacketsIn); 56998243Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSOUT", 57094934Sbrian bundle->ncp.ipcp.throughput.PacketsOut); 57181634Sbrian#ifndef NOINET6 57298243Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSIN", 57394934Sbrian bundle->ncp.ipv6cp.throughput.OctetsIn); 57498243Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSOUT", 57594934Sbrian bundle->ncp.ipv6cp.throughput.OctetsOut); 57698243Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSIN", 57794934Sbrian bundle->ncp.ipv6cp.throughput.PacketsIn); 57898243Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSOUT", 57994934Sbrian bundle->ncp.ipv6cp.throughput.PacketsOut); 58081634Sbrian#endif 58194934Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 58294934Sbrian nargv[arg] = substip(nargv[arg], "MYADDR", bundle->ncp.ipcp.my_ip); 58394934Sbrian#ifndef NOINET6 58494934Sbrian nargv[arg] = substipv6(nargv[arg], "MYADDR6", &bundle->ncp.ipv6cp.myaddr); 585116622Sume#ifndef NORADIUS 586116622Sume nargv[arg] = substipv6prefix(nargv[arg], "IPV6PREFIX", 587116622Sume bundle->radius.ipv6prefix); 58894934Sbrian#endif 589116622Sume#endif 59094934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSIN", oin); 59194934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSOUT", oout); 59294934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSIN", pin); 59394934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSOUT", pout); 59438629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 59538629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 59638629Sbrian bundle->ncp.mp.peer.enddisc.address, 59738629Sbrian bundle->ncp.mp.peer.enddisc.len)); 59897360Sbrian nargv[arg] = substlong(nargv[arg], "PROCESSID", pid); 59994934Sbrian if (server.cfg.port) 60097360Sbrian nargv[arg] = substlong(nargv[arg], "SOCKNAME", server.cfg.port); 60194934Sbrian else 60294934Sbrian nargv[arg] = subst(nargv[arg], "SOCKNAME", server.cfg.sockname); 60394934Sbrian nargv[arg] = subst(nargv[arg], "UPTIME", uptime); 60494934Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 60563484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 60638628Sbrian } 60738628Sbrian nargv[arg] = NULL; 60838628Sbrian} 60938628Sbrian 61085991Sbrianvoid 61185991Sbriancommand_Free(int argc, char **argv) 61285991Sbrian{ 61385991Sbrian while (argc) { 61485991Sbrian free(*argv); 61585991Sbrian argc--; 61685991Sbrian argv++; 61785991Sbrian } 61885991Sbrian} 61985991Sbrian 62028536Sbrianstatic int 62131343SbrianShellCommand(struct cmdargs const *arg, int bg) 62210528Samurai{ 62310528Samurai const char *shell; 62447849Sbrian pid_t shpid, pid; 62520813Sjkh 62618856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 62726911Sbrian /* we're only allowed to shell when we run ppp interactively */ 62836285Sbrian if (arg->prompt && arg->prompt->owner) { 62936285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 63026516Sbrian return 1; 63110528Samurai } 63226911Sbrian#endif 63328679Sbrian 63436285Sbrian if (arg->argc == arg->argn) { 63536285Sbrian if (!arg->prompt) { 63636285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 63736285Sbrian " a config file\n"); 63828381Sbrian return 1; 63936285Sbrian } else if (arg->prompt->owner) { 64036285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 64136285Sbrian " a socket connection\n"); 64236285Sbrian return 1; 64328381Sbrian } else if (bg) { 64436285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 64528679Sbrian " the foreground mode\n"); 64628381Sbrian return 1; 64728381Sbrian } 64834536Sbrian } 64934536Sbrian 65047849Sbrian pid = getpid(); 65128679Sbrian if ((shpid = fork()) == 0) { 65236285Sbrian int i, fd; 65318531Sbde 65436285Sbrian if ((shell = getenv("SHELL")) == 0) 65536285Sbrian shell = _PATH_BSHELL; 65632017Sbrian 65736285Sbrian timer_TermService(); 65836285Sbrian 65936285Sbrian if (arg->prompt) 66036285Sbrian fd = arg->prompt->fd_out; 66136285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 66236285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 66336285Sbrian _PATH_DEVNULL, strerror(errno)); 66428679Sbrian exit(1); 66528679Sbrian } 66649976Sbrian dup2(fd, STDIN_FILENO); 66749976Sbrian dup2(fd, STDOUT_FILENO); 66849976Sbrian dup2(fd, STDERR_FILENO); 66949976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 67049976Sbrian fcntl(i, F_SETFD, 1); 67126516Sbrian 67264802Sbrian#ifndef NOSUID 67355252Sbrian setuid(ID0realuid()); 67464802Sbrian#endif 67536285Sbrian if (arg->argc > arg->argn) { 67628679Sbrian /* substitute pseudo args */ 67738628Sbrian char *argv[MAXARGS]; 67838628Sbrian int argc = arg->argc - arg->argn; 67938628Sbrian 680134789Sbrian if (argc >= (int)(sizeof argv / sizeof argv[0])) { 68138628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 68238628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 68331343Sbrian } 68447849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 68528679Sbrian if (bg) { 68628679Sbrian pid_t p; 68710528Samurai 68828679Sbrian p = getpid(); 68928679Sbrian if (daemon(1, 1) == -1) { 69097360Sbrian log_Printf(LogERROR, "%ld: daemon: %s\n", (long)p, strerror(errno)); 69128679Sbrian exit(1); 69228679Sbrian } 69336285Sbrian } else if (arg->prompt) 69436285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 69531343Sbrian execvp(argv[0], argv); 69630316Sbrian } else { 69736285Sbrian if (arg->prompt) 69832017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 69936285Sbrian prompt_TtyOldMode(arg->prompt); 70079450Sbrian execl(shell, shell, (char *)NULL); 70130316Sbrian } 70220813Sjkh 70340665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 70440665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 70540665Sbrian strerror(errno)); 70649976Sbrian _exit(255); 70710528Samurai } 70836285Sbrian 70997360Sbrian if (shpid == (pid_t)-1) 71036285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 71136285Sbrian else { 71210528Samurai int status; 71331343Sbrian waitpid(shpid, &status, 0); 71410528Samurai } 71520813Sjkh 71636285Sbrian if (arg->prompt && !arg->prompt->owner) 71736285Sbrian prompt_TtyCommandMode(arg->prompt); 71820813Sjkh 71936285Sbrian return 0; 72010528Samurai} 72110528Samurai 72231343Sbrianstatic int 72331343SbrianBgShellCommand(struct cmdargs const *arg) 72431343Sbrian{ 72536285Sbrian if (arg->argc == arg->argn) 72631343Sbrian return -1; 72731343Sbrian return ShellCommand(arg, 1); 72831343Sbrian} 72931343Sbrian 73031343Sbrianstatic int 73131343SbrianFgShellCommand(struct cmdargs const *arg) 73231343Sbrian{ 73331343Sbrian return ShellCommand(arg, 0); 73431343Sbrian} 73531343Sbrian 73658044Sbrianstatic int 73758044SbrianResolvCommand(struct cmdargs const *arg) 73858044Sbrian{ 73958044Sbrian if (arg->argc == arg->argn + 1) { 74058044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 74158044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 74258044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 74358044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 74458044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 74558044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 74658044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 74758044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 74858044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 74958044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 75058044Sbrian else 75158044Sbrian return -1; 75258044Sbrian 75358044Sbrian return 0; 75458044Sbrian } 75558044Sbrian 75658044Sbrian return -1; 75758044Sbrian} 75858044Sbrian 75950059Sbrian#ifndef NONAT 76058867Sbrianstatic struct cmdtab const NatCommands[] = 76140561Sbrian{ 76250059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 763134789Sbrian "static address translation", "nat addr [addr_local addr_alias]", NULL}, 76458867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 76550059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 76640561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 76758867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 768134789Sbrian "enable NAT", "nat enable yes|no", NULL}, 76958867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 77050059Sbrian "log NAT link creation", "nat log yes|no", 77140561Sbrian (const void *) PKT_ALIAS_LOG}, 77250059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 773134789Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]", NULL}, 77479433Sbrian {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 775134789Sbrian "nat proto proto localIP [publicIP [remoteIP]]", NULL}, 77650059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 777134789Sbrian "proxy control", "nat proxy server host[:port] ...", NULL}, 77881033Sbrian#ifndef NO_FW_PUNCH 77981033Sbrian {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 780134789Sbrian "firewall control", "nat punch_fw [base count]", NULL}, 78181033Sbrian#endif 782120372Smarcus {"skinny_port", NULL, nat_SkinnyPort, LOCAL_AUTH, 783134789Sbrian "TCP port used by Skinny Station protocol", "nat skinny_port [port]", NULL}, 78458867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 78550059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 78640561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 78758867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 788134789Sbrian "Default address for incoming connections", "nat target addr", NULL}, 78958867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 79050059Sbrian "translate unregistered (private) IP address space only", 79150059Sbrian "nat unregistered_only yes|no", 79240561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 79358867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 79450059Sbrian "allocate host sockets", "nat use_sockets yes|no", 79540561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 79640561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 79758867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 798134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 79940561Sbrian}; 80040561Sbrian#endif 80140561Sbrian 80240561Sbrianstatic struct cmdtab const AllowCommands[] = { 80340561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 804134789Sbrian "Only allow certain ppp modes", "allow modes mode...", NULL}, 80540561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 806134789Sbrian "Only allow ppp access to certain users", "allow users logname...", NULL}, 80740561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 80840561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 809134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 81040561Sbrian}; 81140561Sbrian 81240561Sbrianstatic struct cmdtab const IfaceCommands[] = 81340561Sbrian{ 81440561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 81540561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 81640561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 81740561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 81840561Sbrian (void *)1}, 81940561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 820134789Sbrian "Clear iface address(es)", "iface clear [INET | INET6]", NULL}, 82140561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 82240561Sbrian "Delete iface address", "iface delete addr", NULL}, 82340561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 82440561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 82540561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 82640561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 827218397Sbrian {"name", NULL, IfaceNameCommand, LOCAL_AUTH, 828218397Sbrian "Set iface name", "iface name name", NULL}, 829218397Sbrian {"description", NULL, iface_Descr, LOCAL_AUTH, 830218397Sbrian "Set iface description", "iface description text", NULL}, 83140561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 832134789Sbrian "Show iface address(es)", "iface show", NULL}, 83340561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 83450059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 835134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 83640561Sbrian}; 83740561Sbrian 83830715Sbrianstatic struct cmdtab const Commands[] = { 83936285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 840134789Sbrian "accept option request", "accept option ..", NULL}, 84128679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 84232109Sbrian "add route", "add dest mask gateway", NULL}, 84336285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 84432109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 84540561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 84640561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 84728679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 848134789Sbrian "Run a background command", "[!]bg command", NULL}, 84936934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85046686Sbrian "Clear throughput statistics", 851134789Sbrian "clear ipcp|ipv6cp|physical [current|overall|peak]...", NULL}, 85236285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 853134789Sbrian "Clone a link", "clone newname...", NULL}, 85436285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 855134789Sbrian "Close an FSM", "close [lcp|ccp]", NULL}, 85628679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 85732109Sbrian "delete route", "delete dest", NULL}, 85836285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 85932109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 86036285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 861134789Sbrian "Deny option request", "deny option ..", NULL}, 86236285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 86340797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 86436285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 865134789Sbrian "Disable option", "disable option ..", NULL}, 86636285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 867134789Sbrian "Generate a down event", "down [ccp|lcp]", NULL}, 86836285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 869134789Sbrian "Enable option", "enable option ..", NULL}, 87063484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 871134789Sbrian "Set the link identity", "ident text...", NULL}, 87240561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 87340561Sbrian "interface control", "iface option ...", IfaceCommands}, 87436285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 875134789Sbrian "Link specific commands", "link name command ...", NULL}, 87637008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 877134789Sbrian "Load settings", "load [system ...]", NULL}, 87885991Sbrian {"log", NULL, LogCommand, LOCAL_AUTH | LOCAL_CX_OPT, 879134789Sbrian "log information", "log word ...", NULL}, 88050059Sbrian#ifndef NONAT 88150059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 88258867Sbrian "NAT control", "nat option yes|no", NatCommands}, 88350059Sbrian#endif 88436285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 88537955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 88636285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 887134789Sbrian "Password for manipulation", "passwd LocalPassword", NULL}, 88836285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 889134789Sbrian "Quit PPP program", "quit|bye [all]", NULL}, 89036285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 891134789Sbrian "Remove a link", "remove", NULL}, 89236285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 893134789Sbrian "Rename a link", "rename name", NULL}, 89458044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 895134789Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable", 896134789Sbrian NULL}, 89728679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 898134789Sbrian "Save settings", "save", NULL}, 89963484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 900134789Sbrian "Transmit the link identity", "sendident", NULL}, 90136285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 902134789Sbrian "Set parameters", "set[up] var value", NULL}, 90328679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 904134789Sbrian "Run a subshell", "shell|! [sh command]", NULL}, 90536285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 906134789Sbrian "Show status and stats", "show var", NULL}, 90736285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 908134789Sbrian "Enter terminal mode", "term", NULL}, 90928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 91031343Sbrian "Display this message", "help|? [command]", Commands}, 911134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 9126059Samurai}; 9136059Samurai 91428536Sbrianstatic int 91531343SbrianShowEscape(struct cmdargs const *arg) 9166059Samurai{ 91736285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 91836285Sbrian int code, bit; 91936285Sbrian const char *sep = ""; 9206059Samurai 92126516Sbrian for (code = 0; code < 32; code++) 92236285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 92328679Sbrian for (bit = 0; bit < 8; bit++) 92436285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 92536285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 92636285Sbrian sep = ", "; 92736285Sbrian } 92836285Sbrian prompt_Printf(arg->prompt, "\n"); 9296059Samurai } 93031077Sbrian return 0; 9316059Samurai} 9326059Samurai 93328679Sbrianstatic int 93436285SbrianShowTimerList(struct cmdargs const *arg) 9356059Samurai{ 93636285Sbrian timer_Show(0, arg->prompt); 93731077Sbrian return 0; 9386059Samurai} 9396059Samurai 94028679Sbrianstatic int 94131343SbrianShowStopped(struct cmdargs const *arg) 94228327Sbrian{ 94336285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 94436285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 94536285Sbrian prompt_Printf(arg->prompt, "Disabled"); 94628327Sbrian else 94736285Sbrian prompt_Printf(arg->prompt, "%ld secs", 94836285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 94928461Sbrian 95036285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 95136285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 95236285Sbrian prompt_Printf(arg->prompt, "Disabled"); 95328461Sbrian else 95436285Sbrian prompt_Printf(arg->prompt, "%ld secs", 95536285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 95628461Sbrian 95736285Sbrian prompt_Printf(arg->prompt, "\n"); 95828461Sbrian 95931077Sbrian return 0; 96028327Sbrian} 96128327Sbrian 96228679Sbrianstatic int 96331343SbrianShowVersion(struct cmdargs const *arg) 9646059Samurai{ 965162063Sbrian prompt_Printf(arg->prompt, "PPP Version %s\n", Version); 96631077Sbrian return 0; 9676059Samurai} 9686059Samurai 96928679Sbrianstatic int 97036285SbrianShowProtocolStats(struct cmdargs const *arg) 97126326Sbrian{ 97236285Sbrian struct link *l = command_ChooseLink(arg); 97326326Sbrian 97436285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 97536285Sbrian link_ReportProtocolStatus(l, arg->prompt); 97631077Sbrian return 0; 97726326Sbrian} 97826326Sbrian 97930715Sbrianstatic struct cmdtab const ShowCommands[] = { 98036285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 981134789Sbrian "bundle details", "show bundle", NULL}, 98236285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 983134789Sbrian "CCP status", "show cpp", NULL}, 98436285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 985134789Sbrian "VJ compression stats", "show compress", NULL}, 98636285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 987134789Sbrian "escape characters", "show escape", NULL}, 98836285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 989134789Sbrian "packet filters", "show filter [in|out|dial|alive]", NULL}, 99036285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 991134789Sbrian "HDLC errors", "show hdlc", NULL}, 99240561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 993134789Sbrian "Interface status", "show iface", NULL}, 99436285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 995134789Sbrian "IPCP status", "show ipcp", NULL}, 99681634Sbrian#ifndef NOINET6 99781634Sbrian {"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH, 998134789Sbrian "IPV6CP status", "show ipv6cp", NULL}, 99981634Sbrian#endif 100047211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 1001134789Sbrian "Protocol layers", "show layers", NULL}, 100236285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 1003134789Sbrian "LCP status", "show lcp", NULL}, 100436285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 1005134789Sbrian "(high-level) link info", "show link", NULL}, 100636285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 1007134789Sbrian "available link names", "show links", NULL}, 100836285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 1009134789Sbrian "log levels", "show log", NULL}, 101036285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 1011134789Sbrian "mbuf allocations", "show mem", NULL}, 101281634Sbrian {"ncp", NULL, ncp_Show, LOCAL_AUTH, 1013134789Sbrian "NCP status", "show ncp", NULL}, 101446686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 1015134789Sbrian "(low-level) link info", "show physical", NULL}, 101636285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 1017134789Sbrian "multilink setup", "show mp", NULL}, 101836285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 1019134789Sbrian "protocol summary", "show proto", NULL}, 102036285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 1021134789Sbrian "routing table", "show route", NULL}, 102236285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 1023134789Sbrian "STOPPED timeout", "show stopped", NULL}, 102436285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 1025134789Sbrian "alarm timers", "show timers", NULL}, 102628679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 1027134789Sbrian "version string", "show version", NULL}, 102836285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 1029134789Sbrian "client list", "show who", NULL}, 103028679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 103131343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 1032134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 10336059Samurai}; 10346059Samurai 103530715Sbrianstatic struct cmdtab const * 103631343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 10376059Samurai{ 103826516Sbrian int nmatch; 103926516Sbrian int len; 104028679Sbrian struct cmdtab const *found; 10416059Samurai 104226516Sbrian found = NULL; 104326516Sbrian len = strlen(str); 104426516Sbrian nmatch = 0; 10456059Samurai while (cmds->func) { 104625566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 104726516Sbrian if (cmds->name[len] == '\0') { 104828679Sbrian *pmatch = 1; 104928679Sbrian return cmds; 105026516Sbrian } 10516059Samurai nmatch++; 10526059Samurai found = cmds; 105328679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 105426516Sbrian if (cmds->alias[len] == '\0') { 105528679Sbrian *pmatch = 1; 105628679Sbrian return cmds; 105726516Sbrian } 10586059Samurai nmatch++; 10596059Samurai found = cmds; 10606059Samurai } 10616059Samurai cmds++; 10626059Samurai } 10636059Samurai *pmatch = nmatch; 106426516Sbrian return found; 10656059Samurai} 10666059Samurai 106736285Sbrianstatic const char * 106836285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 106936285Sbrian{ 107036285Sbrian int f, tlen, len; 107136285Sbrian 107236285Sbrian tlen = 0; 107336285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 107436285Sbrian if (f) 107536285Sbrian tgt[tlen++] = ' '; 107636285Sbrian len = strlen(argv[f]); 107736285Sbrian if (len > sz - tlen - 1) 107836285Sbrian len = sz - tlen - 1; 107936285Sbrian strncpy(tgt+tlen, argv[f], len); 108036285Sbrian tlen += len; 108136285Sbrian } 108236285Sbrian tgt[tlen] = '\0'; 108336285Sbrian return tgt; 108436285Sbrian} 108536285Sbrian 108630715Sbrianstatic int 108736285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 108836285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 10896059Samurai{ 109028679Sbrian struct cmdtab const *cmd; 10916059Samurai int val = 1; 10926059Samurai int nmatch; 109331343Sbrian struct cmdargs arg; 109436285Sbrian char prefix[100]; 10956059Samurai 109636285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 10976059Samurai if (nmatch > 1) 109836285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 109936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 110036285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 110136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 110236285Sbrian /* We've got no context, but we require it */ 110336285Sbrian cx = bundle2datalink(bundle, NULL); 110436285Sbrian 110536285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 110636285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 110736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 110836285Sbrian else { 110936285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 111036285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 111136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 111236285Sbrian cx = NULL; 111336285Sbrian } 111436285Sbrian arg.cmdtab = cmds; 111536285Sbrian arg.cmd = cmd; 111636285Sbrian arg.argc = argc; 111736285Sbrian arg.argn = argn+1; 111836285Sbrian arg.argv = argv; 111936285Sbrian arg.bundle = bundle; 112036285Sbrian arg.cx = cx; 112136285Sbrian arg.prompt = prompt; 112236285Sbrian val = (*cmd->func) (&arg); 112336285Sbrian } 112431343Sbrian } else 112536285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 112636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 112726516Sbrian 112826516Sbrian if (val == -1) 112995258Sdes log_Printf(LogWARN, "usage: %s\n", cmd->syntax); 113028679Sbrian else if (val) 113136285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 113236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 113326516Sbrian 113426516Sbrian return val; 11356059Samurai} 11366059Samurai 113737009Sbrianint 113858045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 113958045Sbrian{ 114058045Sbrian char buff2[LINE_LEN-offset]; 114158045Sbrian 114258045Sbrian InterpretArg(buff, buff2); 114358045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 114458045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 114558045Sbrian 114658045Sbrian return command_Interpret(buff, nb, argv); 114758045Sbrian} 114858045Sbrian 114958045Sbrianint 115037009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 11516059Samurai{ 11526059Samurai char *cp; 11536059Samurai 11546059Samurai if (nb > 0) { 11556059Samurai cp = buff + strcspn(buff, "\r\n"); 11566059Samurai if (cp) 11576059Samurai *cp = '\0'; 115855145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 115937009Sbrian } 116037009Sbrian return 0; 116131121Sbrian} 11626059Samurai 116331822Sbrianstatic int 1164134789Sbrianarghidden(char const *const *argv, int n) 116531822Sbrian{ 116631822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 116731828Sbrian 116831828Sbrian /* set authkey xxxxx */ 116931828Sbrian /* set key xxxxx */ 117031822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 117131822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 117231822Sbrian return 1; 117331822Sbrian 117431828Sbrian /* passwd xxxxx */ 117531828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 117631828Sbrian return 1; 117731828Sbrian 117836285Sbrian /* set server port xxxxx .... */ 117936285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 118036285Sbrian !strncasecmp(argv[1], "se", 2)) 118136285Sbrian return 1; 118236285Sbrian 118331822Sbrian return 0; 118431822Sbrian} 118531822Sbrian 118631121Sbrianvoid 118736285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 118837008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 118931121Sbrian{ 119031156Sbrian if (argc > 0) { 119136285Sbrian if (log_IsKept(LogCOMMAND)) { 119247844Sbrian char buf[LINE_LEN]; 1193134789Sbrian int f; 1194134789Sbrian size_t n; 119531156Sbrian 119631156Sbrian if (label) { 119731962Sbrian strncpy(buf, label, sizeof buf - 3); 119831962Sbrian buf[sizeof buf - 3] = '\0'; 119931156Sbrian strcat(buf, ": "); 120047844Sbrian n = strlen(buf); 120147844Sbrian } else { 120247844Sbrian *buf = '\0'; 120347844Sbrian n = 0; 120431156Sbrian } 120547844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 120647844Sbrian 120731156Sbrian for (f = 0; f < argc; f++) { 120831962Sbrian if (n < sizeof buf - 1 && f) 120931156Sbrian buf[n++] = ' '; 1210134789Sbrian if (arghidden(argv, f)) 121136285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 121231822Sbrian else 121331962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 121431156Sbrian n += strlen(buf+n); 121531156Sbrian } 121636285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 121731156Sbrian } 121837008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 121931156Sbrian } 12206059Samurai} 12216059Samurai 122254914Sbrianint 122336285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 122436285Sbrian const char *label) 122531121Sbrian{ 122631121Sbrian int argc; 122737009Sbrian char *argv[MAXARGS]; 122831121Sbrian 122958045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 123054914Sbrian return 0; 123154914Sbrian 123237008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 123354914Sbrian return 1; 123431121Sbrian} 123531121Sbrian 12366059Samuraistatic int 123731343SbrianShowCommand(struct cmdargs const *arg) 12386059Samurai{ 123936285Sbrian if (!arg->prompt) 124036285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 124136285Sbrian else if (arg->argc > arg->argn) 124236285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 124336285Sbrian arg->prompt, arg->cx); 12446059Samurai else 124536285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 124626516Sbrian 124726516Sbrian return 0; 12486059Samurai} 12496059Samurai 12506059Samuraistatic int 125131343SbrianTerminalCommand(struct cmdargs const *arg) 12526059Samurai{ 125336285Sbrian if (!arg->prompt) { 125436285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 125526516Sbrian return 1; 12566059Samurai } 125736285Sbrian 125836285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 125936285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 126036285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 126136285Sbrian return 1; 12626059Samurai } 126336285Sbrian 126436285Sbrian datalink_Up(arg->cx, 0, 0); 126536285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 126636285Sbrian return 0; 12676059Samurai} 12686059Samurai 12696059Samuraistatic int 127031343SbrianQuitCommand(struct cmdargs const *arg) 12716059Samurai{ 127236285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 127336285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 127436285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 1275134789Sbrian Cleanup(); 127636285Sbrian if (arg->prompt) 127736285Sbrian prompt_Destroy(arg->prompt, 1); 127826516Sbrian 127926516Sbrian return 0; 12806059Samurai} 12816059Samurai 12826059Samuraistatic int 128336285SbrianOpenCommand(struct cmdargs const *arg) 12846059Samurai{ 128537160Sbrian if (arg->argc == arg->argn) 128637993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 128737160Sbrian else if (arg->argc == arg->argn + 1) { 128837160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 128937385Sbrian struct datalink *cx = arg->cx ? 129037385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 129137385Sbrian if (cx) { 129237385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 129337385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 129437160Sbrian else 129537993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 129637160Sbrian } else 129737160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 129837160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 129937160Sbrian struct fsm *fp; 13006059Samurai 130137210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 130237160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 130337160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 130437160Sbrian else if (fp->state == ST_OPENED) 130537160Sbrian fsm_Reopen(fp); 130637160Sbrian else { 130737160Sbrian fp->open_mode = 0; /* Not passive any more */ 130837160Sbrian if (fp->state == ST_STOPPED) { 130937160Sbrian fsm_Down(fp); 131037160Sbrian fsm_Up(fp); 131137160Sbrian } else { 131237160Sbrian fsm_Up(fp); 131337160Sbrian fsm_Open(fp); 131437160Sbrian } 131536285Sbrian } 131637160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 131737160Sbrian if (arg->cx) 131837160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 131937160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 132037160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 132137160Sbrian else 132237993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 132337160Sbrian } else 132437160Sbrian return -1; 132536285Sbrian } else 132636285Sbrian return -1; 132736285Sbrian 132826516Sbrian return 0; 13296059Samurai} 13306059Samurai 133125067Sbrianstatic int 133236285SbrianCloseCommand(struct cmdargs const *arg) 13336059Samurai{ 133437007Sbrian if (arg->argc == arg->argn) 133537007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 133637007Sbrian else if (arg->argc == arg->argn + 1) { 133737007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 133837007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 133937007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 134037007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 134137007Sbrian struct fsm *fp; 13426059Samurai 134337210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 134437007Sbrian if (fp->state == ST_OPENED) { 134537007Sbrian fsm_Close(fp); 134637007Sbrian if (arg->argv[arg->argn][3] == '!') 134737007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 134837007Sbrian else 134937007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 135037007Sbrian } 135137007Sbrian } else 135236285Sbrian return -1; 135336285Sbrian } else 135436285Sbrian return -1; 135536285Sbrian 135636285Sbrian return 0; 13576059Samurai} 13586059Samurai 135925067Sbrianstatic int 136036285SbrianDownCommand(struct cmdargs const *arg) 136111336Samurai{ 136237018Sbrian if (arg->argc == arg->argn) { 136337018Sbrian if (arg->cx) 136437018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 136537018Sbrian else 136637018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 136737018Sbrian } else if (arg->argc == arg->argn + 1) { 136837018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 136937018Sbrian if (arg->cx) 137037018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 137137018Sbrian else 137237018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 137337018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 137437018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 137537018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 137637060Sbrian fsm2initial(fp); 137737018Sbrian } else 137837018Sbrian return -1; 137936285Sbrian } else 138036285Sbrian return -1; 138136285Sbrian 138236285Sbrian return 0; 138325067Sbrian} 138425067Sbrian 138525067Sbrianstatic int 138636285SbrianSetModemSpeed(struct cmdargs const *arg) 138725067Sbrian{ 138836285Sbrian long speed; 138936285Sbrian char *end; 139011336Samurai 139136285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 139236285Sbrian if (arg->argc > arg->argn+1) { 139354917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 139436285Sbrian return -1; 139511336Samurai } 139636285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 139736285Sbrian physical_SetSync(arg->cx->physical); 139836285Sbrian return 0; 139936285Sbrian } 140036285Sbrian end = NULL; 140136285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 1402134789Sbrian if (*end || speed < 0) { 140336285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 140436285Sbrian arg->argv[arg->argn]); 140536285Sbrian return -1; 140636285Sbrian } 140736285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 140836285Sbrian return 0; 140936285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 141036285Sbrian } else 141136285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 141224939Sbrian 141326516Sbrian return -1; 141411336Samurai} 141511336Samurai 141625067Sbrianstatic int 141731343SbrianSetStoppedTimeout(struct cmdargs const *arg) 141828327Sbrian{ 141936285Sbrian struct link *l = &arg->cx->physical->link; 142036285Sbrian 142136285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 142236285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 142336285Sbrian if (arg->argc <= arg->argn+2) { 142436285Sbrian if (arg->argc > arg->argn) { 142536285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 142636285Sbrian if (arg->argc > arg->argn+1) 142736285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 142828461Sbrian } 142928327Sbrian return 0; 143028327Sbrian } 143128327Sbrian return -1; 143228327Sbrian} 143328327Sbrian 143428327Sbrianstatic int 143531343SbrianSetServer(struct cmdargs const *arg) 143626940Sbrian{ 143726940Sbrian int res = -1; 143826940Sbrian 143936285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 144031081Sbrian const char *port, *passwd, *mask; 1441134789Sbrian size_t mlen; 144231081Sbrian 144331081Sbrian /* What's what ? */ 144436285Sbrian port = arg->argv[arg->argn]; 144536285Sbrian if (arg->argc == arg->argn + 2) { 144636285Sbrian passwd = arg->argv[arg->argn+1]; 144736285Sbrian mask = NULL; 144836285Sbrian } else if (arg->argc == arg->argn + 3) { 144936285Sbrian passwd = arg->argv[arg->argn+1]; 145036285Sbrian mask = arg->argv[arg->argn+2]; 145153125Sbrian mlen = strlen(mask); 145253125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 145353125Sbrian (mlen == 4 && *mask != '0')) { 145453125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 145553125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 145631081Sbrian return -1; 145753125Sbrian } 145871764Sbrian } else if (arg->argc != arg->argn + 1) 145971764Sbrian return -1; 146071764Sbrian else if (strcasecmp(port, "none") == 0) { 146171657Sbrian if (server_Clear(arg->bundle)) 146271657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 146371657Sbrian return 0; 146471657Sbrian } else if (strcasecmp(port, "open") == 0) { 146571657Sbrian switch (server_Reopen(arg->bundle)) { 146671657Sbrian case SERVER_OK: 146771657Sbrian return 0; 146871657Sbrian case SERVER_FAILED: 146971764Sbrian log_Printf(LogWARN, "Failed to reopen server port\n"); 147071657Sbrian return 1; 147171657Sbrian case SERVER_UNSET: 147271764Sbrian log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 147371657Sbrian return 1; 147471657Sbrian default: 147571657Sbrian break; 147671657Sbrian } 147771657Sbrian return -1; 147871657Sbrian } else if (strcasecmp(port, "closed") == 0) { 147936285Sbrian if (server_Close(arg->bundle)) 148071657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 148171657Sbrian else 148271657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 148371657Sbrian 148436285Sbrian return 0; 148531081Sbrian } else 148636285Sbrian return -1; 148731081Sbrian 148871657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 148971657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 149031081Sbrian 149136285Sbrian if (*port == '/') { 149231081Sbrian mode_t imask; 149336285Sbrian char *ptr, name[LINE_LEN + 12]; 149428679Sbrian 149553125Sbrian if (mask == NULL) 149631081Sbrian imask = (mode_t)-1; 149753125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 149853125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 149936285Sbrian 150036285Sbrian ptr = strstr(port, "%d"); 150136285Sbrian if (ptr) { 150236285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 150337210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 150436285Sbrian port = name; 150536285Sbrian } 150636285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 150727346Sbrian } else { 150836285Sbrian int iport, add = 0; 150928679Sbrian 151031081Sbrian if (mask != NULL) 151131081Sbrian return -1; 151228679Sbrian 151336285Sbrian if (*port == '+') { 151436285Sbrian port++; 151536285Sbrian add = 1; 151636285Sbrian } 151731081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 151831081Sbrian struct servent *s; 151931081Sbrian 152031081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 152131081Sbrian iport = 0; 152236285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 152328679Sbrian } else 152431081Sbrian iport = ntohs(s->s_port); 152527346Sbrian } else 152631081Sbrian iport = atoi(port); 152736285Sbrian 152836285Sbrian if (iport) { 152936285Sbrian if (add) 153036285Sbrian iport += arg->bundle->unit; 153136285Sbrian res = server_TcpOpen(arg->bundle, iport); 153236285Sbrian } else 153336285Sbrian res = -1; 153427346Sbrian } 153531081Sbrian } 153626940Sbrian 153726940Sbrian return res; 153826940Sbrian} 153926940Sbrian 154026940Sbrianstatic int 154131343SbrianSetEscape(struct cmdargs const *arg) 15426059Samurai{ 15436059Samurai int code; 154436285Sbrian int argc = arg->argc - arg->argn; 154536285Sbrian char const *const *argv = arg->argv + arg->argn; 15466059Samurai 15476059Samurai for (code = 0; code < 33; code++) 154836285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 154931343Sbrian 15506059Samurai while (argc-- > 0) { 15516059Samurai sscanf(*argv++, "%x", &code); 15526059Samurai code &= 0xff; 155336285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 155436285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 15556059Samurai } 155626516Sbrian return 0; 15576059Samurai} 15586059Samurai 15596059Samuraistatic int 156031343SbrianSetInterfaceAddr(struct cmdargs const *arg) 15616059Samurai{ 156281634Sbrian struct ncp *ncp = &arg->bundle->ncp; 156381634Sbrian struct ncpaddr ncpaddr; 156432267Sbrian const char *hisaddr; 156532267Sbrian 156640561Sbrian if (arg->argc > arg->argn + 4) 156740561Sbrian return -1; 156840561Sbrian 156932267Sbrian hisaddr = NULL; 157081634Sbrian memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range); 157181634Sbrian memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range); 157281634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 0; 157381634Sbrian ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY; 157481634Sbrian iplist_reset(&ncp->ipcp.cfg.peer_list); 157528394Sbrian 157636285Sbrian if (arg->argc > arg->argn) { 157781634Sbrian if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn])) 157828679Sbrian return 1; 157936285Sbrian if (arg->argc > arg->argn+1) { 158036285Sbrian hisaddr = arg->argv[arg->argn+1]; 158136285Sbrian if (arg->argc > arg->argn+2) { 158281634Sbrian ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask = 158381634Sbrian GetIpAddr(arg->argv[arg->argn+2]); 158436285Sbrian if (arg->argc > arg->argn+3) { 158581634Sbrian ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 158681634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 1; 15879440Samurai } 15886059Samurai } 15896059Samurai } 15906059Samurai } 159128394Sbrian 159240561Sbrian /* 0.0.0.0 means any address (0 bits) */ 1593132204Sbrian ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr); 159481634Sbrian ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip); 159581634Sbrian if (ncp->ipcp.my_ip.s_addr == INADDR_ANY) 159681634Sbrian ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0); 159781634Sbrian bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL); 159836285Sbrian 159936285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 160036928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 160132267Sbrian return 4; 160231121Sbrian 160326516Sbrian return 0; 16046059Samurai} 16056059Samurai 160618752Sjkhstatic int 160744305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 160844305Sbrian u_int *maxtrm, int def) 160944305Sbrian{ 161044305Sbrian if (argc == 0) { 161144305Sbrian *timeout = DEF_FSMRETRY; 161244305Sbrian *maxreq = def; 161344305Sbrian if (maxtrm != NULL) 161444305Sbrian *maxtrm = def; 161544305Sbrian } else { 161644305Sbrian long l = atol(argv[0]); 161744305Sbrian 161844305Sbrian if (l < MIN_FSMRETRY) { 161944305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 162044305Sbrian l, MIN_FSMRETRY); 162144305Sbrian return 1; 162244305Sbrian } else 162344305Sbrian *timeout = l; 162444305Sbrian 162544305Sbrian if (argc > 1) { 162644305Sbrian l = atol(argv[1]); 162744305Sbrian if (l < 1) { 162844305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 162944305Sbrian l = 1; 163044305Sbrian } 163144305Sbrian *maxreq = l; 163244305Sbrian 163344305Sbrian if (argc > 2 && maxtrm != NULL) { 163444305Sbrian l = atol(argv[2]); 163544305Sbrian if (l < 1) { 163644305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 163744305Sbrian l = 1; 163844305Sbrian } 163944305Sbrian *maxtrm = l; 164044305Sbrian } 164144305Sbrian } 164244305Sbrian } 164344305Sbrian 164444305Sbrian return 0; 164544305Sbrian} 164644305Sbrian 164744305Sbrianstatic int 164831343SbrianSetVariable(struct cmdargs const *arg) 16496059Samurai{ 165037210Sbrian long long_val, param = (long)arg->cmd->args; 165179119Sbrian int mode, dummyint, f, first, res; 165278410Sbrian u_short *change; 165331343Sbrian const char *argp; 165436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 165536285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 165681634Sbrian struct in_addr *ipaddr; 165781634Sbrian struct ncpaddr ncpaddr[2]; 16586059Samurai 165936285Sbrian if (arg->argc > arg->argn) 166036285Sbrian argp = arg->argv[arg->argn]; 166126551Sbrian else 166231343Sbrian argp = ""; 166326551Sbrian 166479119Sbrian res = 0; 166579119Sbrian 166636285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 166736285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 166836285Sbrian arg->cmd->name); 166936285Sbrian return 1; 167036285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 167136285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 167236285Sbrian arg->cmd->name, cx->name); 167336285Sbrian cx = NULL; 167436285Sbrian } 167536285Sbrian 167626551Sbrian switch (param) { 167728679Sbrian case VAR_AUTHKEY: 167850139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 167950139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 168050139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 168128679Sbrian break; 168237210Sbrian 168328679Sbrian case VAR_AUTHNAME: 168440622Sbrian switch (bundle_Phase(arg->bundle)) { 168558880Sbrian default: 168658880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 168758880Sbrian bundle_PhaseName(arg->bundle)); 168858880Sbrian /* drop through */ 168940622Sbrian case PHASE_DEAD: 169040622Sbrian case PHASE_ESTABLISH: 169140622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 169240622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 169340622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 169440622Sbrian break; 169536285Sbrian } 169628679Sbrian break; 169737210Sbrian 169836285Sbrian case VAR_AUTOLOAD: 169949434Sbrian if (arg->argc == arg->argn + 3) { 170098243Sbrian int v1, v2, v3; 170149434Sbrian char *end; 170249434Sbrian 170349434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 170449434Sbrian if (v1 < 0 || *end) { 170549434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 170649434Sbrian arg->argv[arg->argn]); 170779119Sbrian res = 1; 170879119Sbrian break; 170936285Sbrian } 171049434Sbrian 171149434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 171249434Sbrian if (v2 < 0 || *end) { 171349434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 171449434Sbrian arg->argv[arg->argn + 1]); 171579119Sbrian res = 1; 171679119Sbrian break; 171749434Sbrian } 171849434Sbrian if (v2 < v1) { 171949434Sbrian v3 = v1; 172049434Sbrian v1 = v2; 172149434Sbrian v2 = v3; 172249434Sbrian } 172349434Sbrian 172449434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 172549434Sbrian if (v3 <= 0 || *end) { 172649434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 172749434Sbrian arg->argv[arg->argn + 2]); 172879119Sbrian res = 1; 172979119Sbrian break; 173049434Sbrian } 173149434Sbrian 173249434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 173349434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 173449434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 173549434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 173636285Sbrian } else { 173779119Sbrian log_Printf(LogWARN, "Set autoload requires three arguments\n"); 173879119Sbrian res = 1; 173936285Sbrian } 174036285Sbrian break; 174137210Sbrian 174228679Sbrian case VAR_DIAL: 174336285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 174436285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 174528679Sbrian break; 174637210Sbrian 174728679Sbrian case VAR_LOGIN: 174836285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 174936285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 175028679Sbrian break; 175137210Sbrian 175236285Sbrian case VAR_WINSIZE: 175336285Sbrian if (arg->argc > arg->argn) { 175436285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 175536285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 175636285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 175736285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 175836285Sbrian l->ccp.cfg.deflate.out.winsize); 175936285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 176036285Sbrian } 176136285Sbrian if (arg->argc > arg->argn+1) { 176236285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 176336285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 176436285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 176536285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 176636285Sbrian l->ccp.cfg.deflate.in.winsize); 176736285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 176836285Sbrian } 176936285Sbrian } else 177036285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 177136285Sbrian } else { 177279119Sbrian log_Printf(LogWARN, "No window size specified\n"); 177379119Sbrian res = 1; 177436285Sbrian } 177536285Sbrian break; 177637210Sbrian 177793418Sbrian#ifndef NODES 177878411Sbrian case VAR_MPPE: 177979119Sbrian if (arg->argc > arg->argn + 2) { 178079119Sbrian res = -1; 178179119Sbrian break; 178279119Sbrian } 178378411Sbrian 178478411Sbrian if (arg->argc == arg->argn) { 178578411Sbrian l->ccp.cfg.mppe.keybits = 0; 178678411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 178778411Sbrian l->ccp.cfg.mppe.required = 0; 178878411Sbrian break; 178978411Sbrian } 179078411Sbrian 179178411Sbrian if (!strcmp(argp, "*")) 179278411Sbrian long_val = 0; 179378411Sbrian else { 179478411Sbrian long_val = atol(argp); 179578411Sbrian if (long_val != 40 && long_val != 56 && long_val != 128) { 179678411Sbrian log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 179779119Sbrian res = -1; 179879119Sbrian break; 179967910Sbrian } 180067910Sbrian } 180178411Sbrian 180278411Sbrian if (arg->argc == arg->argn + 2) { 180378411Sbrian if (!strcmp(arg->argv[arg->argn + 1], "*")) 180478411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 180578411Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 180678411Sbrian l->ccp.cfg.mppe.state = MPPE_STATELESS; 180779370Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 180878411Sbrian l->ccp.cfg.mppe.state = MPPE_STATEFUL; 180978411Sbrian else { 181078411Sbrian log_Printf(LogWARN, "%s: Invalid state value\n", 181178411Sbrian arg->argv[arg->argn + 1]); 181279119Sbrian res = -1; 181379119Sbrian break; 181478411Sbrian } 181578411Sbrian } else 181678411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 181778411Sbrian l->ccp.cfg.mppe.keybits = long_val; 181878411Sbrian l->ccp.cfg.mppe.required = 1; 181967910Sbrian break; 182067910Sbrian#endif 182167910Sbrian 182228679Sbrian case VAR_DEVICE: 182336285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 182436285Sbrian arg->argv + arg->argn); 182536285Sbrian break; 182637210Sbrian 182736285Sbrian case VAR_ACCMAP: 182836285Sbrian if (arg->argc > arg->argn) { 182937210Sbrian u_long ulong_val; 183036285Sbrian sscanf(argp, "%lx", &ulong_val); 183137210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 183236285Sbrian } else { 183379119Sbrian log_Printf(LogWARN, "No accmap specified\n"); 183479119Sbrian res = 1; 183536285Sbrian } 183636285Sbrian break; 183737210Sbrian 183836285Sbrian case VAR_MODE: 183936285Sbrian mode = Nam2mode(argp); 184036285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 184136285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 184279119Sbrian res = -1; 184379119Sbrian break; 184436285Sbrian } 184536285Sbrian bundle_SetMode(arg->bundle, cx, mode); 184636285Sbrian break; 184737210Sbrian 184836285Sbrian case VAR_MRRU: 184940622Sbrian switch (bundle_Phase(arg->bundle)) { 185040622Sbrian case PHASE_DEAD: 185140622Sbrian break; 185240622Sbrian case PHASE_ESTABLISH: 185340622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 185440622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 1855228990Suqs log_Printf(LogWARN, "mrru: Only changeable before LCP negotiations\n"); 185679119Sbrian res = 1; 185779119Sbrian break; 185840622Sbrian } 185940622Sbrian break; 186040622Sbrian default: 1861228990Suqs log_Printf(LogWARN, "mrru: Only changeable at phase DEAD/ESTABLISH\n"); 186279119Sbrian res = 1; 186379119Sbrian break; 186429696Sbrian } 186579119Sbrian if (res != 0) 186679119Sbrian break; 186737210Sbrian long_val = atol(argp); 186837210Sbrian if (long_val && long_val < MIN_MRU) { 186937210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 187079119Sbrian res = 1; 187179119Sbrian break; 187237210Sbrian } else if (long_val > MAX_MRU) { 187337210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 187479119Sbrian res = 1; 187579119Sbrian break; 187637210Sbrian } else 187737210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 187828679Sbrian break; 187937210Sbrian 188036285Sbrian case VAR_MRU: 188179163Sbrian long_val = 0; /* silence gcc */ 188279163Sbrian change = NULL; /* silence gcc */ 188378410Sbrian switch(arg->argc - arg->argn) { 188478410Sbrian case 1: 188579119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 188679119Sbrian res = -1; 188779119Sbrian break; 188879119Sbrian } 188979119Sbrian /*FALLTHRU*/ 189078410Sbrian case 0: 189178410Sbrian long_val = atol(argp); 189278410Sbrian change = &l->lcp.cfg.mru; 189378410Sbrian if (long_val > l->lcp.cfg.max_mru) { 189478410Sbrian log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 189578410Sbrian l->lcp.cfg.max_mru); 189679119Sbrian res = 1; 189779119Sbrian break; 189878410Sbrian } 189978410Sbrian break; 190078410Sbrian case 2: 190179119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 190279119Sbrian res = -1; 190379119Sbrian break; 190479119Sbrian } 190578410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 190678410Sbrian change = &l->lcp.cfg.max_mru; 190778410Sbrian if (long_val > MAX_MRU) { 190878410Sbrian log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 190978410Sbrian MAX_MRU); 191079119Sbrian res = 1; 191179119Sbrian break; 191278410Sbrian } 191378410Sbrian break; 191478410Sbrian default: 191579119Sbrian res = -1; 191679119Sbrian break; 191778410Sbrian } 191879119Sbrian if (res != 0) 191979119Sbrian break; 192078410Sbrian 192137210Sbrian if (long_val == 0) 192280385Sbrian *change = 0; 192337210Sbrian else if (long_val < MIN_MRU) { 192437210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 192579119Sbrian res = 1; 192679119Sbrian break; 192737210Sbrian } else if (long_val > MAX_MRU) { 192837210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 192979119Sbrian res = 1; 193079119Sbrian break; 193137210Sbrian } else 193278410Sbrian *change = long_val; 193378410Sbrian if (l->lcp.cfg.mru > *change) 193478410Sbrian l->lcp.cfg.mru = *change; 193528679Sbrian break; 193637210Sbrian 193736285Sbrian case VAR_MTU: 193879163Sbrian long_val = 0; /* silence gcc */ 193979163Sbrian change = NULL; /* silence gcc */ 194078410Sbrian switch(arg->argc - arg->argn) { 194178410Sbrian case 1: 194279119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 194379119Sbrian res = -1; 194479119Sbrian break; 194579119Sbrian } 194679119Sbrian /*FALLTHRU*/ 194778410Sbrian case 0: 194878410Sbrian long_val = atol(argp); 194978410Sbrian change = &l->lcp.cfg.mtu; 195078410Sbrian if (long_val > l->lcp.cfg.max_mtu) { 195178410Sbrian log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 195278410Sbrian l->lcp.cfg.max_mtu); 195379119Sbrian res = 1; 195479119Sbrian break; 195578410Sbrian } 195678410Sbrian break; 195778410Sbrian case 2: 195879119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 195979119Sbrian res = -1; 196079119Sbrian break; 196179119Sbrian } 196278410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 196378410Sbrian change = &l->lcp.cfg.max_mtu; 196478410Sbrian if (long_val > MAX_MTU) { 196578410Sbrian log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 196678410Sbrian MAX_MTU); 196779119Sbrian res = 1; 196879119Sbrian break; 196978410Sbrian } 197078410Sbrian break; 197178410Sbrian default: 197279119Sbrian res = -1; 197379119Sbrian break; 197478410Sbrian } 197578410Sbrian 197679119Sbrian if (res != 0) 197779119Sbrian break; 197879119Sbrian 197937210Sbrian if (long_val && long_val < MIN_MTU) { 198037210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 198179119Sbrian res = 1; 198279119Sbrian break; 198337210Sbrian } else if (long_val > MAX_MTU) { 198437210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 198579119Sbrian res = 1; 198679119Sbrian break; 198737210Sbrian } else 198878410Sbrian *change = long_val; 198978410Sbrian if (l->lcp.cfg.mtu > *change) 199078410Sbrian l->lcp.cfg.mtu = *change; 199136285Sbrian break; 199237210Sbrian 199336285Sbrian case VAR_OPENMODE: 199436285Sbrian if (strcasecmp(argp, "active") == 0) 199536285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 199636285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 199736285Sbrian else if (strcasecmp(argp, "passive") == 0) 199836285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 199936285Sbrian else { 200079119Sbrian log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 200179119Sbrian res = 1; 200236285Sbrian } 200336285Sbrian break; 200437210Sbrian 200528679Sbrian case VAR_PHONE: 200636285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 200736285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 200838174Sbrian cx->phone.alt = cx->phone.next = NULL; 200928679Sbrian break; 201037210Sbrian 201128679Sbrian case VAR_HANGUP: 201236285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 201336285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 201428679Sbrian break; 201537210Sbrian 201661534Sbrian case VAR_IFQUEUE: 201761534Sbrian long_val = atol(argp); 201861534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 201961534Sbrian break; 202061534Sbrian 202152488Sbrian case VAR_LOGOUT: 202252488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 202352488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 202452488Sbrian break; 202552488Sbrian 202636285Sbrian case VAR_IDLETIMEOUT: 202779119Sbrian if (arg->argc > arg->argn+2) { 202879119Sbrian log_Printf(LogWARN, "Too many idle timeout values\n"); 202979119Sbrian res = 1; 203079119Sbrian } else if (arg->argc == arg->argn) { 203179119Sbrian log_Printf(LogWARN, "Too few idle timeout values\n"); 203279119Sbrian res = 1; 203379119Sbrian } else { 2034134789Sbrian unsigned long timeout, min; 203549978Sbrian 2036134789Sbrian timeout = strtoul(argp, NULL, 10); 2037134789Sbrian min = arg->bundle->cfg.idle.min_timeout; 2038134789Sbrian if (arg->argc == arg->argn + 2) 2039134789Sbrian min = strtoul(arg->argv[arg->argn + 1], NULL, 10); 204049978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 204149978Sbrian } 204229549Sbrian break; 2043132273Sbrian 2044132273Sbrian#ifndef NORADIUS 2045132273Sbrian case VAR_RAD_ALIVE: 2046132273Sbrian if (arg->argc > arg->argn + 2) { 2047132273Sbrian log_Printf(LogWARN, "Too many RADIUS alive interval values\n"); 2048132273Sbrian res = 1; 2049132273Sbrian } else if (arg->argc == arg->argn) { 2050132273Sbrian log_Printf(LogWARN, "Too few RADIUS alive interval values\n"); 2051132273Sbrian res = 1; 2052132273Sbrian } else { 2053132273Sbrian arg->bundle->radius.alive.interval = atoi(argp); 2054132273Sbrian if (arg->bundle->radius.alive.interval && !arg->bundle->radius.cfg.file) { 2055132273Sbrian log_Printf(LogWARN, "rad_alive requires radius to be configured\n"); 2056132273Sbrian res = 1; 2057132273Sbrian } else if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) { 2058132273Sbrian if (arg->bundle->radius.alive.interval) 2059132273Sbrian radius_StartTimer(arg->bundle); 2060132273Sbrian else 2061132273Sbrian radius_StopTimer(&arg->bundle->radius); 2062132273Sbrian } 2063132273Sbrian } 2064132273Sbrian break; 2065132273Sbrian#endif 2066132273Sbrian 206736285Sbrian case VAR_LQRPERIOD: 206837210Sbrian long_val = atol(argp); 206937210Sbrian if (long_val < MIN_LQRPERIOD) { 207037210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 207137210Sbrian long_val, MIN_LQRPERIOD); 207279119Sbrian res = 1; 207336285Sbrian } else 207437210Sbrian l->lcp.cfg.lqrperiod = long_val; 207536285Sbrian break; 207637210Sbrian 207736285Sbrian case VAR_LCPRETRY: 207879119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 207979119Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 208079119Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 208179119Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 208236285Sbrian break; 208337210Sbrian 208436285Sbrian case VAR_CHAPRETRY: 208579119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 208679119Sbrian &cx->chap.auth.cfg.fsm.timeout, 208779119Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 208836285Sbrian break; 208937210Sbrian 209036285Sbrian case VAR_PAPRETRY: 209179119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 209279119Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 209379119Sbrian NULL, DEF_FSMAUTHTRIES); 209436285Sbrian break; 209537210Sbrian 209636285Sbrian case VAR_CCPRETRY: 209779119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 209879119Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 209979119Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 210036285Sbrian break; 210137210Sbrian 210236285Sbrian case VAR_IPCPRETRY: 210379119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 210479119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 210579119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 210679119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 210736285Sbrian break; 210837210Sbrian 2109102855Sbrian#ifndef NOINET6 2110102558Sbrian case VAR_IPV6CPRETRY: 2111102558Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 2112102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.timeout, 2113102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.maxreq, 2114102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.maxtrm, DEF_FSMTRIES); 2115102558Sbrian break; 2116102855Sbrian#endif 2117102558Sbrian 211836285Sbrian case VAR_NBNS: 211936285Sbrian case VAR_DNS: 212058044Sbrian if (param == VAR_DNS) { 212181634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns; 212281634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE; 212358044Sbrian } else { 212481634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 212581634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY; 212658044Sbrian } 212736285Sbrian 212836285Sbrian if (arg->argc > arg->argn) { 212981634Sbrian ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]); 213081634Sbrian if (!ncpaddr_getip4(ncpaddr, ipaddr)) 213181634Sbrian return -1; 213281634Sbrian if (arg->argc > arg->argn+1) { 213381634Sbrian ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]); 213481634Sbrian if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1)) 213581634Sbrian return -1; 213681634Sbrian } 213736285Sbrian 213881634Sbrian if (ipaddr[0].s_addr == INADDR_ANY) { 213981634Sbrian ipaddr[0] = ipaddr[1]; 214081634Sbrian ipaddr[1].s_addr = INADDR_ANY; 214158044Sbrian } 214281634Sbrian if (ipaddr[0].s_addr == INADDR_NONE) { 214381634Sbrian ipaddr[0] = ipaddr[1]; 214481634Sbrian ipaddr[1].s_addr = INADDR_NONE; 214558044Sbrian } 214636285Sbrian } 214736285Sbrian break; 214838174Sbrian 214938174Sbrian case VAR_CALLBACK: 215038174Sbrian cx->cfg.callback.opmask = 0; 215138174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 215238174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 215338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 215438174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 215538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 215638174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 215738174Sbrian if (dummyint == arg->argc - 1) 215838174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 215938174Sbrian else { 216038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 216138174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 216238174Sbrian sizeof cx->cfg.callback.msg - 1); 216338174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 216438174Sbrian } 216538174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 216638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 216779119Sbrian else { 216879119Sbrian res = -1; 216979119Sbrian break; 217079119Sbrian } 217138174Sbrian } 217238174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 217338174Sbrian cx->cfg.callback.opmask = 0; 217438174Sbrian break; 217538174Sbrian 217638174Sbrian case VAR_CBCP: 217738174Sbrian cx->cfg.cbcp.delay = 0; 217838174Sbrian *cx->cfg.cbcp.phone = '\0'; 217938174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 218038174Sbrian if (arg->argc > arg->argn) { 218138174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 218238174Sbrian sizeof cx->cfg.cbcp.phone - 1); 218338174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 218438174Sbrian if (arg->argc > arg->argn + 1) { 218538174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 218638174Sbrian if (arg->argc > arg->argn + 2) { 218738174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 218838174Sbrian if (long_val < MIN_FSMRETRY) 218938174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 219038174Sbrian long_val, MIN_FSMRETRY); 219138174Sbrian else 219238174Sbrian cx->cfg.cbcp.fsmretry = long_val; 219338174Sbrian } 219438174Sbrian } 219538174Sbrian } 219638174Sbrian break; 219738544Sbrian 219838544Sbrian case VAR_CHOKED: 219938544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 220038544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 220138544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 220238544Sbrian break; 220340665Sbrian 220440665Sbrian case VAR_SENDPIPE: 220540665Sbrian long_val = atol(argp); 220681634Sbrian arg->bundle->ncp.cfg.sendpipe = long_val; 220740665Sbrian break; 220840665Sbrian 220940665Sbrian case VAR_RECVPIPE: 221040665Sbrian long_val = atol(argp); 221181634Sbrian arg->bundle->ncp.cfg.recvpipe = long_val; 221240665Sbrian break; 221343313Sbrian 221443313Sbrian#ifndef NORADIUS 221543313Sbrian case VAR_RADIUS: 221643313Sbrian if (!*argp) 221743313Sbrian *arg->bundle->radius.cfg.file = '\0'; 221843313Sbrian else if (access(argp, R_OK)) { 221943313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 222079119Sbrian res = 1; 222179119Sbrian break; 222243313Sbrian } else { 222343313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 222443313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 222543313Sbrian arg->bundle->radius.cfg.file 222643313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 222743313Sbrian } 222843313Sbrian break; 222943313Sbrian#endif 223044073Sbrian 223144073Sbrian case VAR_CD: 223244073Sbrian if (*argp) { 223351699Sbrian if (strcasecmp(argp, "off")) { 223451699Sbrian long_val = atol(argp); 223551699Sbrian if (long_val < 0) 223651699Sbrian long_val = 0; 223751699Sbrian cx->physical->cfg.cd.delay = long_val; 223851699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 223951699Sbrian CD_REQUIRED : CD_VARIABLE; 224051699Sbrian } else 224151699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 224244073Sbrian } else { 224353733Sbrian cx->physical->cfg.cd.delay = 0; 224453733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 224544073Sbrian } 224644073Sbrian break; 224736285Sbrian 224846686Sbrian case VAR_PARITY: 224946686Sbrian if (arg->argc == arg->argn + 1) 225079119Sbrian res = physical_SetParity(arg->cx->physical, argp); 225146686Sbrian else { 225279119Sbrian log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 225379119Sbrian res = 1; 225446686Sbrian } 225546686Sbrian break; 22566059Samurai 225746686Sbrian case VAR_CRTSCTS: 225846686Sbrian if (strcasecmp(argp, "on") == 0) 225936285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 226046686Sbrian else if (strcasecmp(argp, "off") == 0) 226136285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 226246686Sbrian else { 226379119Sbrian log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 226479119Sbrian res = 1; 226546686Sbrian } 226646686Sbrian break; 226750867Sbrian 226850867Sbrian case VAR_URGENTPORTS: 226951048Sbrian if (arg->argn == arg->argc) { 227081634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 227181634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 227281634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 227351048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 227481634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 227551048Sbrian if (arg->argn == arg->argc - 1) 227681634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 227751048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 227851048Sbrian if (*arg->argv[f] == '+') 227981634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 228051048Sbrian else if (*arg->argv[f] == '-') 228181634Sbrian ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 228251048Sbrian else { 228351048Sbrian if (f == arg->argn) 228481634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 228581634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 228651048Sbrian } 228761430Sbrian } else if (arg->argn == arg->argc - 1 && 228861430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 228981634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 229081634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 229181634Sbrian ncp_ClearUrgentTOS(&arg->bundle->ncp); 229251048Sbrian } else { 229381634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 229451048Sbrian first = arg->argn; 229551048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 229681634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 229751048Sbrian 229851048Sbrian for (f = first; f < arg->argc; f++) 229951048Sbrian if (*arg->argv[f] == '+') 230081634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 230151048Sbrian else if (*arg->argv[f] == '-') 230281634Sbrian ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 230351048Sbrian else { 230451048Sbrian if (f == first) 230581634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 230681634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 230751048Sbrian } 230851048Sbrian } 230950867Sbrian break; 2310132818Sglebius 2311132818Sglebius case VAR_PPPOE: 2312132818Sglebius if (strcasecmp(argp, "3Com") == 0) 2313132818Sglebius physical_SetPPPoEnonstandard(arg->cx->physical, 1); 2314132818Sglebius else if (strcasecmp(argp, "standard") == 0) 2315132818Sglebius physical_SetPPPoEnonstandard(arg->cx->physical, 0); 2316132818Sglebius else { 2317132818Sglebius log_Printf(LogWARN, "PPPoE standard value must be \"standard\" or \"3Com\"\n"); 2318132818Sglebius res = 1; 2319132818Sglebius } 2320132818Sglebius break; 2321132818Sglebius 2322169986Snovel#ifndef NORADIUS 2323169986Snovel case VAR_PORT_ID: 2324169986Snovel if (strcasecmp(argp, "default") == 0) 2325169986Snovel arg->bundle->radius.port_id_type = RPI_DEFAULT; 2326169986Snovel else if (strcasecmp(argp, "pid") == 0) 2327169986Snovel arg->bundle->radius.port_id_type = RPI_PID; 2328169986Snovel else if (strcasecmp(argp, "ifnum") == 0) 2329169986Snovel arg->bundle->radius.port_id_type = RPI_IFNUM; 2330169986Snovel else if (strcasecmp(argp, "tunnum") == 0) 2331169986Snovel arg->bundle->radius.port_id_type = RPI_TUNNUM; 2332169986Snovel else { 2333169986Snovel log_Printf(LogWARN, 2334169986Snovel "RADIUS port id must be one of \"default\", \"pid\", \"ifnum\" or \"tunnum\"\n"); 2335169986Snovel res = 1; 2336169986Snovel } 2337169986Snovel 2338169986Snovel if (arg->bundle->radius.port_id_type && !arg->bundle->radius.cfg.file) { 2339169986Snovel log_Printf(LogWARN, "rad_port_id requires radius to be configured\n"); 2340169986Snovel res = 1; 2341169986Snovel } 2342169986Snovel 2343169986Snovel break; 2344169986Snovel#endif 234520812Sjkh } 234646686Sbrian 234779119Sbrian return res; 234820812Sjkh} 234920812Sjkh 235030715Sbrianstatic struct cmdtab const SetCommands[] = { 235136285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 235236285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 235328679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 235436285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 235528679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 235636285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 235736285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 235836285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 235936285Sbrian (const void *)VAR_AUTOLOAD}, 236050867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 2361134789Sbrian "datalink bandwidth", "set bandwidth value", NULL}, 236238174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 236338174Sbrian "callback control", "set callback [none|auth|cbcp|" 236438174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 236538174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 236698243Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 236738174Sbrian (const void *)VAR_CBCP}, 236844305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 236944305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 237044073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 237144073Sbrian "set cd value[!]", (const void *)VAR_CD}, 237244305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 237344305Sbrian "CHAP retries", "set chapretry value [attempts]", 237444305Sbrian (const void *)VAR_CHAPRETRY}, 237538544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 237638544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 237746686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 237846686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 237946686Sbrian (const char *)VAR_CRTSCTS}, 238036285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 238136285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 238236285Sbrian (const void *) VAR_WINSIZE}, 238393418Sbrian#ifndef NODES 238467910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 238598243Sbrian "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 238678411Sbrian (const void *) VAR_MPPE}, 238767910Sbrian#endif 238836285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 238946686Sbrian "physical device name", "set device|line device-name[,device-name]", 239036285Sbrian (const void *) VAR_DEVICE}, 239136285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 239236285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 239336285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 239436285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 239536285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 2396134789Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]", NULL}, 239736285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 2398134789Sbrian "escape characters", "set escape hex-digit ...", NULL}, 239936285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 240036285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 240181634Sbrian "[src_addr[/width]] [dst_addr[/width]] [proto " 2402134789Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]", NULL}, 240336285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 240436285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 240536285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 2406134789Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]", NULL}, 240761534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 240861534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 240944305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 241044305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 2411102558Sbrian {"ipv6cpretry", "ipv6cpretries", SetVariable, LOCAL_AUTH, "IPV6CP retries", 2412102558Sbrian "set ipv6cpretry value [attempts]", (const void *)VAR_IPV6CPRETRY}, 241344305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 241444305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 241536712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 241667916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 2417134789Sbrian "id0|ipcp|lcp|lqm|phase|physical|radius|sync|tcp/ip|timer|tun...", NULL}, 241836285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 241936285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 242052488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 242152488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 2422138799Sbrian {"lqrperiod", "echoperiod", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 2423138799Sbrian "LQR period", "set lqr/echo period value", (const void *)VAR_LQRPERIOD}, 242436285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 242536285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 242636285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 242736285Sbrian "set mrru value", (const void *)VAR_MRRU}, 242896038Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 242978410Sbrian "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 243078410Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 243178410Sbrian "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 243236285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 243336285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 243436285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 243536285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 243644305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 243744305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 243846686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 243946686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 244036285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 244136285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 244240679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 2443134789Sbrian "Process title", "set proctitle [value]", NULL}, 244443313Sbrian#ifndef NORADIUS 244543313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 244643313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 2447132273Sbrian {"rad_alive", NULL, SetVariable, LOCAL_AUTH, 2448132273Sbrian "Raduis alive interval", "set rad_alive value", 2449169986Snovel (const void *)VAR_RAD_ALIVE}, 2450169986Snovel {"rad_port_id", NULL, SetVariable, LOCAL_AUTH, 2451169986Snovel "NAS-Port-Id", "set rad_port_id [default|pid|ifnum|tunnum]", (const void *)VAR_PORT_ID}, 245243313Sbrian#endif 245336285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 2454134789Sbrian "Reconnect timeout", "set reconnect value ntries", NULL}, 245540665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 245640665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 245736285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 2458134789Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]", NULL}, 245940665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 246040665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 246171657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 2462134789Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]", 2463134789Sbrian NULL}, 246436285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 2465134789Sbrian "physical speed", "set speed value|sync", NULL}, 246636285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 2467134789Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]", NULL}, 246836285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 246936285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 247051048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 247151048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 247236285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 2473134789Sbrian "vj values", "set vj slots|slotcomp [value]", NULL}, 247428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 247531343Sbrian "Display this message", "set help|? [command]", SetCommands}, 2476132818Sglebius {"pppoe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2477132818Sglebius "Connect using standard/3Com mode", "set pppoe [standard|3Com]", 2478132818Sglebius (const char *)VAR_PPPOE}, 2479134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 24806059Samurai}; 24816059Samurai 24826059Samuraistatic int 248331343SbrianSetCommand(struct cmdargs const *arg) 24846059Samurai{ 248536285Sbrian if (arg->argc > arg->argn) 248636285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 248736285Sbrian arg->prompt, arg->cx); 248836285Sbrian else if (arg->prompt) 248936285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 249058044Sbrian " syntax help.\n"); 24916059Samurai else 249236285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 249326516Sbrian 249426516Sbrian return 0; 24956059Samurai} 24966059Samurai 24976059Samuraistatic int 249831343SbrianAddCommand(struct cmdargs const *arg) 24996059Samurai{ 250081634Sbrian struct ncpaddr gw; 250181634Sbrian struct ncprange dest; 250281634Sbrian struct in_addr host; 2503112673Sume#ifndef NOINET6 2504112673Sume struct in6_addr host6; 2505112673Sume#endif 250681634Sbrian int dest_default, gw_arg, addrs; 25076059Samurai 250836285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 250931598Sbrian return -1; 251031598Sbrian 251136285Sbrian addrs = 0; 251281634Sbrian dest_default = 0; 251381634Sbrian if (arg->argc == arg->argn + 2) { 251436285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 251581634Sbrian dest_default = 1; 251631598Sbrian else { 251781634Sbrian if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn])) 251836285Sbrian return -1; 251936285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 252036285Sbrian addrs = ROUTE_DSTMYADDR; 252181634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7)) 252281634Sbrian addrs = ROUTE_DSTMYADDR6; 252336285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 252436285Sbrian addrs = ROUTE_DSTHISADDR; 252581634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8)) 252681634Sbrian addrs = ROUTE_DSTHISADDR6; 252758044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 252858044Sbrian addrs = ROUTE_DSTDNS0; 252958044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 253058044Sbrian addrs = ROUTE_DSTDNS1; 253131598Sbrian } 253281634Sbrian gw_arg = 1; 253334536Sbrian } else { 253436285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 253536285Sbrian addrs = ROUTE_DSTMYADDR; 253681634Sbrian host = arg->bundle->ncp.ipcp.my_ip; 253736285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 253836285Sbrian addrs = ROUTE_DSTHISADDR; 253981634Sbrian host = arg->bundle->ncp.ipcp.peer_ip; 254058044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 254158044Sbrian addrs = ROUTE_DSTDNS0; 254281634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[0]; 254358044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 254458044Sbrian addrs = ROUTE_DSTDNS1; 254581634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[1]; 254665263Sbrian } else { 254781634Sbrian host = GetIpAddr(arg->argv[arg->argn]); 254881634Sbrian if (host.s_addr == INADDR_NONE) { 254965263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 255065263Sbrian arg->argv[arg->argn]); 255165263Sbrian return -1; 255265263Sbrian } 255365263Sbrian } 255481634Sbrian ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1])); 255581634Sbrian gw_arg = 2; 25566059Samurai } 255736285Sbrian 255881634Sbrian if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) { 255981634Sbrian ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip); 256036285Sbrian addrs |= ROUTE_GWHISADDR; 256181634Sbrian#ifndef NOINET6 256281897Sbrian } else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) { 2563112673Sume if (!ncpaddr_getip6(&arg->bundle->ncp.ipv6cp.hisaddr, &host6)) 2564112673Sume memset(&host6, '\0', sizeof host6); 2565112673Sume ncpaddr_setip6(&gw, &host6); 256681634Sbrian addrs |= ROUTE_GWHISADDR6; 256781634Sbrian#endif 256865263Sbrian } else { 256981634Sbrian if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) { 257065263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 257181634Sbrian arg->argv[arg->argn + gw_arg]); 257265263Sbrian return -1; 257365263Sbrian } 257465263Sbrian } 257536285Sbrian 257681634Sbrian if (dest_default) 257781634Sbrian ncprange_setdefault(&dest, ncpaddr_family(&gw)); 257881634Sbrian 257981634Sbrian if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0, 258081634Sbrian ((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0) 258143313Sbrian && addrs != ROUTE_STATIC) 258281634Sbrian route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw); 258336285Sbrian 258431598Sbrian return 0; 25856059Samurai} 25866059Samurai 25876059Samuraistatic int 258831343SbrianDeleteCommand(struct cmdargs const *arg) 25896059Samurai{ 259081634Sbrian struct ncprange dest; 259136285Sbrian int addrs; 25926059Samurai 259336285Sbrian if (arg->argc == arg->argn+1) { 259436285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 259536285Sbrian route_IfDelete(arg->bundle, 0); 259681634Sbrian route_DeleteAll(&arg->bundle->ncp.route); 259736285Sbrian } else { 259836285Sbrian addrs = 0; 259936285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 260081634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip); 260136285Sbrian addrs = ROUTE_DSTMYADDR; 260281634Sbrian#ifndef NOINET6 260381897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) { 260481634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr); 260581634Sbrian addrs = ROUTE_DSTMYADDR6; 260681634Sbrian#endif 260736285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 260881634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip); 260936285Sbrian addrs = ROUTE_DSTHISADDR; 261081634Sbrian#ifndef NOINET6 261181897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) { 261281634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr); 261381634Sbrian addrs = ROUTE_DSTHISADDR6; 261481634Sbrian#endif 261558044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 261681634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]); 261758044Sbrian addrs = ROUTE_DSTDNS0; 261858044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 261981634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]); 262058044Sbrian addrs = ROUTE_DSTDNS1; 262136285Sbrian } else { 262281634Sbrian ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]); 262336285Sbrian addrs = ROUTE_STATIC; 262436285Sbrian } 262581634Sbrian rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0); 262681634Sbrian route_Delete(&arg->bundle->ncp.route, addrs, &dest); 262731598Sbrian } 262834536Sbrian } else 262926516Sbrian return -1; 263026516Sbrian 263126516Sbrian return 0; 26326059Samurai} 26336059Samurai 263450059Sbrian#ifndef NONAT 263526031Sbrianstatic int 263658867SbrianNatEnable(struct cmdargs const *arg) 263726031Sbrian{ 263836285Sbrian if (arg->argc == arg->argn+1) { 263936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 264050059Sbrian if (!arg->bundle->NatEnabled) { 264146686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 2642177100Spiso LibAliasSetAddress(la, arg->bundle->ncp.ipcp.my_ip); 264350059Sbrian arg->bundle->NatEnabled = 1; 264446686Sbrian } 264537191Sbrian return 0; 264636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 264750059Sbrian arg->bundle->NatEnabled = 0; 2648138198Sbrian opt_disable(arg->bundle, OPT_IFACEALIAS); 264940561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 265026516Sbrian return 0; 265126142Sbrian } 265235449Sbrian } 265336285Sbrian 265426516Sbrian return -1; 265526031Sbrian} 265626031Sbrian 265726031Sbrian 265826031Sbrianstatic int 265958867SbrianNatOption(struct cmdargs const *arg) 266026031Sbrian{ 266138559Sbrian long param = (long)arg->cmd->args; 266238559Sbrian 266336285Sbrian if (arg->argc == arg->argn+1) { 266436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 266550059Sbrian if (arg->bundle->NatEnabled) { 2666177100Spiso LibAliasSetMode(la, param, param); 266728679Sbrian return 0; 266828679Sbrian } 266950059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 267036285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 267150059Sbrian if (arg->bundle->NatEnabled) { 2672177100Spiso LibAliasSetMode(la, 0, param); 267328679Sbrian return 0; 267428679Sbrian } 267550059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 267628679Sbrian } 267735449Sbrian } 267828679Sbrian return -1; 267926031Sbrian} 268050059Sbrian#endif /* #ifndef NONAT */ 268131121Sbrian 268231121Sbrianstatic int 268336285SbrianLinkCommand(struct cmdargs const *arg) 268436285Sbrian{ 268536285Sbrian if (arg->argc > arg->argn+1) { 268636285Sbrian char namelist[LINE_LEN]; 268736285Sbrian struct datalink *cx; 268836285Sbrian char *name; 268936285Sbrian int result = 0; 269036285Sbrian 269136285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 269236285Sbrian struct datalink *dl; 269336285Sbrian 269436285Sbrian cx = arg->bundle->links; 269536285Sbrian while (cx) { 269636285Sbrian /* Watch it, the command could be a ``remove'' */ 269736285Sbrian dl = cx->next; 269836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 269936285Sbrian arg->prompt, cx); 270036285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 270136285Sbrian if (cx == dl) 270236285Sbrian break; /* Pointer's still valid ! */ 270336285Sbrian } 270436285Sbrian } else { 270536285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 270636285Sbrian namelist[sizeof namelist - 1] = '\0'; 270736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 270836285Sbrian if (!bundle2datalink(arg->bundle, name)) { 270936285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 271036285Sbrian return 1; 271136285Sbrian } 271236285Sbrian 271336285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 271436285Sbrian namelist[sizeof namelist - 1] = '\0'; 271536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 271636285Sbrian cx = bundle2datalink(arg->bundle, name); 271736285Sbrian if (cx) 271836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 271936285Sbrian arg->prompt, cx); 272036285Sbrian else { 272136285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 272236285Sbrian result++; 272336285Sbrian } 272436285Sbrian } 272536285Sbrian } 272636285Sbrian return result; 272736285Sbrian } 272836285Sbrian 272995258Sdes log_Printf(LogWARN, "usage: %s\n", arg->cmd->syntax); 273036285Sbrian return 2; 273136285Sbrian} 273236285Sbrian 273336285Sbrianstruct link * 273436285Sbriancommand_ChooseLink(struct cmdargs const *arg) 273536285Sbrian{ 273636285Sbrian if (arg->cx) 273736285Sbrian return &arg->cx->physical->link; 273837210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 273936285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 274037210Sbrian if (dl) 274137210Sbrian return &dl->physical->link; 274236285Sbrian } 274337210Sbrian return &arg->bundle->ncp.mp.link; 274436285Sbrian} 274536285Sbrian 274636285Sbrianstatic const char * 274736285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 274836285Sbrian{ 274936285Sbrian const char *result; 275036285Sbrian 275136285Sbrian switch (*cmd) { 275236285Sbrian case 'A': 275336285Sbrian case 'a': 275436285Sbrian result = "accept"; 275536285Sbrian *keep = NEG_MYMASK; 275636285Sbrian *add = NEG_ACCEPTED; 275736285Sbrian break; 275836285Sbrian case 'D': 275936285Sbrian case 'd': 276036285Sbrian switch (cmd[1]) { 276136285Sbrian case 'E': 276236285Sbrian case 'e': 276336285Sbrian result = "deny"; 276436285Sbrian *keep = NEG_MYMASK; 276536285Sbrian *add = 0; 276636285Sbrian break; 276736285Sbrian case 'I': 276836285Sbrian case 'i': 276936285Sbrian result = "disable"; 277036285Sbrian *keep = NEG_HISMASK; 277136285Sbrian *add = 0; 277236285Sbrian break; 277336285Sbrian default: 277436285Sbrian return NULL; 277536285Sbrian } 277636285Sbrian break; 277736285Sbrian case 'E': 277836285Sbrian case 'e': 277936285Sbrian result = "enable"; 278036285Sbrian *keep = NEG_HISMASK; 278136285Sbrian *add = NEG_ENABLED; 278236285Sbrian break; 278336285Sbrian default: 278436285Sbrian return NULL; 278536285Sbrian } 278636285Sbrian 278736285Sbrian return result; 278836285Sbrian} 278936285Sbrian 279036285Sbrianstatic int 279136285SbrianOptSet(struct cmdargs const *arg) 279236285Sbrian{ 2793138198Sbrian int opt = (int)(long)arg->cmd->args; 2794138198Sbrian unsigned keep; /* Keep this opt */ 2795138198Sbrian unsigned add; /* Add this opt */ 279636285Sbrian 279781697Sbrian if (ident_cmd(arg->argv[arg->argn - 2], &keep, &add) == NULL) 279836285Sbrian return 1; 279936285Sbrian 280081885Sbrian#ifndef NOINET6 2801138198Sbrian if (add == NEG_ENABLED && opt == OPT_IPV6CP && !probe.ipv6_available) { 280281697Sbrian log_Printf(LogWARN, "IPv6 is not available on this machine\n"); 280381697Sbrian return 1; 280481697Sbrian } 280581885Sbrian#endif 2806138198Sbrian if (!add && ((opt == OPT_NAS_IP_ADDRESS && 2807138198Sbrian !Enabled(arg->bundle, OPT_NAS_IDENTIFIER)) || 2808138198Sbrian (opt == OPT_NAS_IDENTIFIER && 2809138198Sbrian !Enabled(arg->bundle, OPT_NAS_IP_ADDRESS)))) { 2810138198Sbrian log_Printf(LogWARN, 2811138198Sbrian "Cannot disable both NAS-IP-Address and NAS-Identifier\n"); 2812138198Sbrian return 1; 2813138198Sbrian } 281481697Sbrian 281536285Sbrian if (add) 2816138198Sbrian opt_enable(arg->bundle, opt); 281736285Sbrian else 2818138198Sbrian opt_disable(arg->bundle, opt); 281981697Sbrian 282036285Sbrian return 0; 282136285Sbrian} 282236285Sbrian 282336285Sbrianstatic int 282440561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 282540561Sbrian{ 2826138198Sbrian unsigned long long save = arg->bundle->cfg.optmask; 282740561Sbrian int result = OptSet(arg); 282840561Sbrian 282940561Sbrian if (result == 0) 283050059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 2831138198Sbrian arg->bundle->cfg.optmask = save; 283250059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 283340561Sbrian result = 2; 283440561Sbrian } 283540561Sbrian 283640561Sbrian return result; 283740561Sbrian} 283840561Sbrian 283940561Sbrianstatic int 284036285SbrianNegotiateSet(struct cmdargs const *arg) 284136285Sbrian{ 284237210Sbrian long param = (long)arg->cmd->args; 284336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 284436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 284536285Sbrian const char *cmd; 284636285Sbrian unsigned keep; /* Keep these bits */ 284736285Sbrian unsigned add; /* Add these bits */ 284836285Sbrian 284936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 285036285Sbrian return 1; 285136285Sbrian 285236285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 285336285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 285436285Sbrian cmd, arg->cmd->name); 285536285Sbrian return 2; 285636285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 285736285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 285836285Sbrian cmd, arg->cmd->name, cx->name); 285936285Sbrian cx = NULL; 286036285Sbrian } 286136285Sbrian 286236285Sbrian switch (param) { 286336285Sbrian case NEG_ACFCOMP: 286436285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 286536285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 286636285Sbrian break; 286744106Sbrian case NEG_CHAP05: 286844106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 286944106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 287036285Sbrian break; 287193418Sbrian#ifndef NODES 287244106Sbrian case NEG_CHAP80: 287344106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 287444106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 287544106Sbrian break; 287644106Sbrian case NEG_CHAP80LM: 287744106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 287844106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 287944106Sbrian break; 288067910Sbrian case NEG_CHAP81: 288167910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 288267910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 288367910Sbrian break; 288467910Sbrian case NEG_MPPE: 288567910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 288667910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 288767910Sbrian break; 288844106Sbrian#endif 288936285Sbrian case NEG_DEFLATE: 289036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 289136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 289236285Sbrian break; 289336285Sbrian case NEG_DNS: 289436285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 289536285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 289636285Sbrian break; 2897138799Sbrian case NEG_ECHO: /* probably misplaced in this function ! */ 2898138799Sbrian if (cx->physical->link.lcp.cfg.echo && !add) { 2899138799Sbrian cx->physical->link.lcp.cfg.echo = 0; 2900138799Sbrian cx->physical->hdlc.lqm.method &= ~LQM_ECHO; 2901138799Sbrian if (cx->physical->hdlc.lqm.method & LQM_ECHO && 2902138799Sbrian !cx->physical->link.lcp.want_lqrperiod && 2903138799Sbrian cx->physical->hdlc.lqm.timer.load) { 2904138799Sbrian cx->physical->hdlc.lqm.timer.load = 0; 2905138799Sbrian lqr_StopTimer(cx->physical); 2906138799Sbrian } 2907138799Sbrian } else if (!cx->physical->link.lcp.cfg.echo && add) { 2908138799Sbrian cx->physical->link.lcp.cfg.echo = 1; 2909138799Sbrian cx->physical->hdlc.lqm.method |= LQM_ECHO; 2910138799Sbrian cx->physical->hdlc.lqm.timer.load = 2911138799Sbrian cx->physical->link.lcp.cfg.lqrperiod * SECTICKS; 2912138799Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 2913138799Sbrian (*cx->physical->hdlc.lqm.timer.func)(&cx->physical->link.lcp); 2914138799Sbrian } 2915138799Sbrian break; 291647858Sbrian case NEG_ENDDISC: 291747858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 291847858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 291947858Sbrian break; 292036285Sbrian case NEG_LQR: 292136285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 292236285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 292336285Sbrian break; 292436285Sbrian case NEG_PAP: 292536285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 292636285Sbrian cx->physical->link.lcp.cfg.pap |= add; 292736285Sbrian break; 292836285Sbrian case NEG_PPPDDEFLATE: 292936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 293036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 293136285Sbrian break; 293236285Sbrian case NEG_PRED1: 293336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 293436285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 293536285Sbrian break; 293636285Sbrian case NEG_PROTOCOMP: 293736285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 293836285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 293936285Sbrian break; 294036285Sbrian case NEG_SHORTSEQ: 294140622Sbrian switch (bundle_Phase(arg->bundle)) { 294240622Sbrian case PHASE_DEAD: 294340622Sbrian break; 294440622Sbrian case PHASE_ESTABLISH: 294540622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 294640622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 2947228990Suqs log_Printf(LogWARN, "shortseq: Only changeable before" 294840622Sbrian " LCP negotiations\n"); 294940622Sbrian return 1; 295040622Sbrian } 295140622Sbrian break; 295240622Sbrian default: 2953228990Suqs log_Printf(LogWARN, "shortseq: Only changeable at phase" 295440622Sbrian " DEAD/ESTABLISH\n"); 295540622Sbrian return 1; 295636285Sbrian } 295740622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 295840622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 295936285Sbrian break; 296036285Sbrian case NEG_VJCOMP: 296136285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 296236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 296336285Sbrian break; 296436285Sbrian } 296536285Sbrian 296636285Sbrian return 0; 296736285Sbrian} 296836285Sbrian 296936285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 2970138799Sbrian {"echo", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, "Send echo requests", 2971138799Sbrian "disable|enable", (const void *)NEG_ECHO}, 297262778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 297362778Sbrian "filter on PPPoUDP payloads", "disable|enable", 297462778Sbrian (const void *)OPT_FILTERDECAP}, 2975112659Sbrian {"force-scripts", NULL, OptSet, LOCAL_AUTH, 2976112659Sbrian "Force execution of the configured chat scripts", "disable|enable", 2977112659Sbrian (const void *)OPT_FORCE_SCRIPTS}, 297836285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 297936285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 298040666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 298162778Sbrian "retain interface addresses", "disable|enable", 298262778Sbrian (const void *)OPT_IFACEALIAS}, 298381634Sbrian#ifndef NOINET6 298481634Sbrian {"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol", 298581634Sbrian "disable|enable", (const void *)OPT_IPCP}, 298681634Sbrian {"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol", 298781634Sbrian "disable|enable", (const void *)OPT_IPV6CP}, 298881634Sbrian#endif 298947689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 299047689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 299136285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 299236285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 2993138198Sbrian {"nas-ip-address", NULL, OptSet, LOCAL_AUTH, "Send NAS-IP-Address to RADIUS", 2994138198Sbrian "disable|enable", (const void *)OPT_NAS_IP_ADDRESS}, 2995138198Sbrian {"nas-identifier", NULL, OptSet, LOCAL_AUTH, "Send NAS-Identifier to RADIUS", 2996138198Sbrian "disable|enable", (const void *)OPT_NAS_IDENTIFIER}, 299736285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 299836285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 299940665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 300036285Sbrian "disable|enable", (const void *)OPT_PROXY}, 300140665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 300240665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 300336285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 300436285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 300569303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 300669303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 300736285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 300836285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 300936285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 301036285Sbrian "disable|enable", (const void *)OPT_UTMP}, 301136285Sbrian 301281634Sbrian#ifndef NOINET6 3013138799Sbrian#define NEG_OPT_MAX 17 /* accept/deny allowed below and not above */ 301481634Sbrian#else 3015138799Sbrian#define NEG_OPT_MAX 15 301681634Sbrian#endif 301736285Sbrian 301836285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 301936285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 302036285Sbrian (const void *)NEG_ACFCOMP}, 302144106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 302236285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 302344106Sbrian (const void *)NEG_CHAP05}, 302493418Sbrian#ifndef NODES 302544106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 302644106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 302744106Sbrian (const void *)NEG_CHAP80}, 302844106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 302944106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 303044106Sbrian (const void *)NEG_CHAP80LM}, 303167910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 303267910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 303367910Sbrian (const void *)NEG_CHAP81}, 303467910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 303567910Sbrian "MPPE encryption", "accept|deny|disable|enable", 303667910Sbrian (const void *)NEG_MPPE}, 303744106Sbrian#endif 303836285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 303936285Sbrian "Deflate compression", "accept|deny|disable|enable", 304036285Sbrian (const void *)NEG_DEFLATE}, 304136285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 304236285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 304336285Sbrian (const void *)NEG_PPPDDEFLATE}, 304436285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 304536285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 304647858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 304747858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 304836285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 304936285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 305036285Sbrian (const void *)NEG_LQR}, 305136285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 305236285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 305336285Sbrian (const void *)NEG_PAP}, 305436285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 305536285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 305636285Sbrian (const void *)NEG_PRED1}, 305736285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 305836285Sbrian "Protocol field compression", "accept|deny|disable|enable", 305936285Sbrian (const void *)NEG_PROTOCOMP}, 306036285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 306136285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 306236285Sbrian (const void *)NEG_SHORTSEQ}, 306336285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 306436285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 306536285Sbrian (const void *)NEG_VJCOMP}, 306636285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 306736285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 306836285Sbrian NegotiateCommands}, 3069134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 307036285Sbrian}; 307136285Sbrian 307236285Sbrianstatic int 307336285SbrianNegotiateCommand(struct cmdargs const *arg) 307436285Sbrian{ 307536285Sbrian if (arg->argc > arg->argn) { 307636285Sbrian char const *argv[3]; 307736285Sbrian unsigned keep, add; 307836285Sbrian int n; 307936285Sbrian 308036285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 308136285Sbrian return -1; 308236285Sbrian argv[2] = NULL; 308336285Sbrian 308436285Sbrian for (n = arg->argn; n < arg->argc; n++) { 308536285Sbrian argv[1] = arg->argv[n]; 308636285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 3087138198Sbrian 0 : NEG_OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 308836285Sbrian } 308936285Sbrian } else if (arg->prompt) 309036285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 309136285Sbrian arg->argv[arg->argn-1]); 309236285Sbrian else 309336285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 309436285Sbrian arg->argv[arg->argn] ); 309536285Sbrian 309636285Sbrian return 0; 309736285Sbrian} 309836285Sbrian 309936285Sbrianconst char * 310036285Sbriancommand_ShowNegval(unsigned val) 310136285Sbrian{ 310236285Sbrian switch (val&3) { 310336285Sbrian case 1: return "disabled & accepted"; 310436285Sbrian case 2: return "enabled & denied"; 310536285Sbrian case 3: return "enabled & accepted"; 310636285Sbrian } 310736285Sbrian return "disabled & denied"; 310836285Sbrian} 310936934Sbrian 311036934Sbrianstatic int 311136934SbrianClearCommand(struct cmdargs const *arg) 311236934Sbrian{ 311336934Sbrian struct pppThroughput *t; 311436934Sbrian struct datalink *cx; 311536934Sbrian int i, clear_type; 311636934Sbrian 311736934Sbrian if (arg->argc < arg->argn + 1) 311836934Sbrian return -1; 311936934Sbrian 312046686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 312136934Sbrian cx = arg->cx; 312236934Sbrian if (!cx) 312336934Sbrian cx = bundle2datalink(arg->bundle, NULL); 312436934Sbrian if (!cx) { 312546686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 312636934Sbrian return 1; 312736934Sbrian } 312864652Sbrian t = &cx->physical->link.stats.total; 312936934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 313036934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 313181634Sbrian#ifndef NOINET6 313281897Sbrian else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0) 313381634Sbrian t = &arg->bundle->ncp.ipv6cp.throughput; 313481634Sbrian#endif 313536934Sbrian else 313636934Sbrian return -1; 313736934Sbrian 313836934Sbrian if (arg->argc > arg->argn + 1) { 313936934Sbrian clear_type = 0; 314036934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 314136934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 314236934Sbrian clear_type |= THROUGHPUT_OVERALL; 314336934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 314436934Sbrian clear_type |= THROUGHPUT_CURRENT; 314536934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 314636934Sbrian clear_type |= THROUGHPUT_PEAK; 314736934Sbrian else 314836934Sbrian return -1; 314998243Sbrian } else 315036934Sbrian clear_type = THROUGHPUT_ALL; 315136934Sbrian 315236934Sbrian throughput_clear(t, clear_type, arg->prompt); 315336934Sbrian return 0; 315436934Sbrian} 315540561Sbrian 315640561Sbrianstatic int 315740561SbrianRunListCommand(struct cmdargs const *arg) 315840561Sbrian{ 315940561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 316040561Sbrian 316164801Sbrian#ifndef NONAT 316264801Sbrian if (arg->cmd->args == NatCommands && 316364801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 316464801Sbrian if (arg->prompt) 316565550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 316664801Sbrian else 316765550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 316864801Sbrian } 316964801Sbrian#endif 317064801Sbrian 317140561Sbrian if (arg->argc > arg->argn) 317240561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 317340561Sbrian arg->prompt, arg->cx); 317440561Sbrian else if (arg->prompt) 317540561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 317640561Sbrian " <option>' for syntax help.\n", cmd, cmd); 317740561Sbrian else 317840561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 317940561Sbrian 318040561Sbrian return 0; 318140561Sbrian} 318240561Sbrian 318340561Sbrianstatic int 3184218397SbrianIfaceNameCommand(struct cmdargs const *arg) 3185218397Sbrian{ 3186218397Sbrian int n = arg->argn; 3187218397Sbrian 3188218397Sbrian if (arg->argc != n + 1) 3189218397Sbrian return -1; 3190218397Sbrian 3191218397Sbrian if (!iface_Name(arg->bundle->iface, arg->argv[n])) 3192218397Sbrian return 1; 3193218397Sbrian 3194218397Sbrian log_SetTun(arg->bundle->unit, arg->bundle->iface->name); 3195218397Sbrian return 0; 3196218397Sbrian} 3197218397Sbrian 3198218397Sbrianstatic int 319940561SbrianIfaceAddCommand(struct cmdargs const *arg) 320040561Sbrian{ 320181634Sbrian struct ncpaddr peer, addr; 320281634Sbrian struct ncprange ifa; 320381634Sbrian struct in_addr mask; 320481634Sbrian int n, how; 320540561Sbrian 320640664Sbrian if (arg->argc == arg->argn + 1) { 320781634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 320840561Sbrian return -1; 320981634Sbrian ncpaddr_init(&peer); 321040664Sbrian } else { 321140664Sbrian if (arg->argc == arg->argn + 2) { 321281634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 321340664Sbrian return -1; 321440664Sbrian n = 1; 321540664Sbrian } else if (arg->argc == arg->argn + 3) { 321681634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn])) 321740664Sbrian return -1; 321881634Sbrian if (ncpaddr_family(&addr) != AF_INET) 321940664Sbrian return -1; 322081634Sbrian ncprange_sethost(&ifa, &addr); 322181634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1])) 322281634Sbrian return -1; 322381634Sbrian if (!ncpaddr_getip4(&addr, &mask)) 322481634Sbrian return -1; 322581634Sbrian if (!ncprange_setip4mask(&ifa, mask)) 322681634Sbrian return -1; 322740664Sbrian n = 2; 322840664Sbrian } else 322940561Sbrian return -1; 323040561Sbrian 323181634Sbrian if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n])) 323240664Sbrian return -1; 323381634Sbrian 323481634Sbrian if (ncprange_family(&ifa) != ncpaddr_family(&peer)) { 323581634Sbrian log_Printf(LogWARN, "IfaceAddCommand: src and dst address families" 323681634Sbrian " differ\n"); 323781634Sbrian return -1; 323881634Sbrian } 323940664Sbrian } 324040561Sbrian 324140561Sbrian how = IFACE_ADD_LAST; 324240561Sbrian if (arg->cmd->args) 324340561Sbrian how |= IFACE_FORCE_ADD; 324440561Sbrian 324581634Sbrian return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how); 324640561Sbrian} 324740561Sbrian 324840561Sbrianstatic int 324940561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 325040561Sbrian{ 325181634Sbrian struct ncpaddr ifa; 325281634Sbrian struct in_addr ifa4; 325340561Sbrian int ok; 325440561Sbrian 325540561Sbrian if (arg->argc != arg->argn + 1) 325640561Sbrian return -1; 325740561Sbrian 325881634Sbrian if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn])) 325940561Sbrian return -1; 326040561Sbrian 326140561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 326281634Sbrian ncpaddr_getip4(&ifa, &ifa4) && 326381634Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) { 326440561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 326581634Sbrian ncpaddr_ntoa(&ifa)); 326640561Sbrian return 1; 326740561Sbrian } 326840561Sbrian 326981634Sbrian ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa); 327040561Sbrian if (!ok) { 327140561Sbrian if (arg->cmd->args) 327240561Sbrian ok = 1; 327340561Sbrian else if (arg->prompt) 327481634Sbrian prompt_Printf(arg->prompt, "%s: No such interface address\n", 327581634Sbrian ncpaddr_ntoa(&ifa)); 327640561Sbrian else 327781634Sbrian log_Printf(LogWARN, "%s: No such interface address\n", 327881634Sbrian ncpaddr_ntoa(&ifa)); 327940561Sbrian } 328040561Sbrian 328140561Sbrian return !ok; 328240561Sbrian} 328340561Sbrian 328440561Sbrianstatic int 328540561SbrianIfaceClearCommand(struct cmdargs const *arg) 328640561Sbrian{ 328781634Sbrian int family, how; 328840561Sbrian 328981634Sbrian family = 0; 329081634Sbrian if (arg->argc == arg->argn + 1) { 329181634Sbrian if (strcasecmp(arg->argv[arg->argn], "inet") == 0) 329281634Sbrian family = AF_INET; 329381634Sbrian#ifndef NOINET6 329481897Sbrian else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0) 329581634Sbrian family = AF_INET6; 329681634Sbrian#endif 329781634Sbrian else 329881634Sbrian return -1; 329981634Sbrian } else if (arg->argc != arg->argn) 330040561Sbrian return -1; 330140561Sbrian 330240941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 330340941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 330440561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 330581634Sbrian iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how); 330640561Sbrian 330740561Sbrian return 0; 330840561Sbrian} 330940679Sbrian 331040679Sbrianstatic int 331140679SbrianSetProcTitle(struct cmdargs const *arg) 331240679Sbrian{ 331340679Sbrian static char title[LINE_LEN]; 331486028Sbrian char *argv[MAXARGS]; 331586028Sbrian int argc = arg->argc - arg->argn; 331640679Sbrian 3317134789Sbrian if (arg->argc <= arg->argn) { 331864698Sbrian SetTitle(NULL); 331940679Sbrian return 0; 332040679Sbrian } 332140679Sbrian 3322134789Sbrian if ((unsigned)argc >= sizeof argv / sizeof argv[0]) { 332340679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 332440679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 332540679Sbrian } 332647849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 332785991Sbrian Concatinate(title, sizeof title, argc, (const char *const *)argv); 332864698Sbrian SetTitle(title); 332985991Sbrian command_Free(argc, argv); 333040679Sbrian 333140679Sbrian return 0; 333240679Sbrian} 3333