command.c revision 95258
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 95258 2002-04-22 13:44:47Z des $ 296059Samurai */ 3078189Sbrian 3143313Sbrian#include <sys/param.h> 3230715Sbrian#include <netinet/in_systm.h> 3326031Sbrian#include <netinet/in.h> 3430715Sbrian#include <netinet/ip.h> 3526031Sbrian#include <arpa/inet.h> 3630715Sbrian#include <sys/socket.h> 3726031Sbrian#include <net/route.h> 3830715Sbrian#include <netdb.h> 3936285Sbrian#include <sys/un.h> 4030715Sbrian 4138628Sbrian#include <ctype.h> 4230715Sbrian#include <errno.h> 4326516Sbrian#include <fcntl.h> 4430715Sbrian#include <paths.h> 4530715Sbrian#include <stdio.h> 4630715Sbrian#include <stdlib.h> 4730715Sbrian#include <string.h> 4830715Sbrian#include <sys/wait.h> 4930715Sbrian#include <termios.h> 5030715Sbrian#include <unistd.h> 5130715Sbrian 5250059Sbrian#ifndef NONAT 5358037Sbrian#ifdef LOCALNAT 5458037Sbrian#include "alias.h" 5558037Sbrian#else 5646086Sbrian#include <alias.h> 5739395Sbrian#endif 5839395Sbrian#endif 5958037Sbrian 6046686Sbrian#include "layer.h" 6137009Sbrian#include "defs.h" 6231343Sbrian#include "command.h" 6330715Sbrian#include "mbuf.h" 6430715Sbrian#include "log.h" 6530715Sbrian#include "timer.h" 666059Samurai#include "fsm.h" 6731690Sbrian#include "iplist.h" 6836285Sbrian#include "throughput.h" 6936285Sbrian#include "slcompress.h" 7038557Sbrian#include "lqr.h" 7138557Sbrian#include "hdlc.h" 7263484Sbrian#include "lcp.h" 7381634Sbrian#include "ncpaddr.h" 7481634Sbrian#include "ip.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 1446059Samurai 14536285Sbrian/* ``accept|deny|disable|enable'' masks */ 14636285Sbrian#define NEG_HISMASK (1) 14736285Sbrian#define NEG_MYMASK (2) 14836285Sbrian 14936285Sbrian/* ``accept|deny|disable|enable'' values */ 15036285Sbrian#define NEG_ACFCOMP 40 15144106Sbrian#define NEG_CHAP05 41 15244106Sbrian#define NEG_CHAP80 42 15344106Sbrian#define NEG_CHAP80LM 43 15444106Sbrian#define NEG_DEFLATE 44 15547858Sbrian#define NEG_DNS 45 15647858Sbrian#define NEG_ENDDISC 46 15747858Sbrian#define NEG_LQR 47 15847858Sbrian#define NEG_PAP 48 15947858Sbrian#define NEG_PPPDDEFLATE 49 16047858Sbrian#define NEG_PRED1 50 16147858Sbrian#define NEG_PROTOCOMP 51 16247858Sbrian#define NEG_SHORTSEQ 52 16347858Sbrian#define NEG_VJCOMP 53 16467910Sbrian#define NEG_MPPE 54 16567910Sbrian#define NEG_CHAP81 55 16636285Sbrian 16794894Sbrianconst char Version[] = "3.0.2"; 16836285Sbrian 16936285Sbrianstatic int ShowCommand(struct cmdargs const *); 17036285Sbrianstatic int TerminalCommand(struct cmdargs const *); 17136285Sbrianstatic int QuitCommand(struct cmdargs const *); 17236285Sbrianstatic int OpenCommand(struct cmdargs const *); 17336285Sbrianstatic int CloseCommand(struct cmdargs const *); 17436285Sbrianstatic int DownCommand(struct cmdargs const *); 17536285Sbrianstatic int SetCommand(struct cmdargs const *); 17636285Sbrianstatic int LinkCommand(struct cmdargs const *); 17736285Sbrianstatic int AddCommand(struct cmdargs const *); 17836285Sbrianstatic int DeleteCommand(struct cmdargs const *); 17936285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 18036934Sbrianstatic int ClearCommand(struct cmdargs const *); 18140561Sbrianstatic int RunListCommand(struct cmdargs const *); 18240561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 18340561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 18440561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 18540679Sbrianstatic int SetProcTitle(struct cmdargs const *); 18650059Sbrian#ifndef NONAT 18758867Sbrianstatic int NatEnable(struct cmdargs const *); 18858867Sbrianstatic int NatOption(struct cmdargs const *); 18931343Sbrian#endif 1906059Samurai 19136285Sbrianstatic const char * 19236285Sbrianshowcx(struct cmdtab const *cmd) 19336285Sbrian{ 19436285Sbrian if (cmd->lauth & LOCAL_CX) 19536285Sbrian return "(c)"; 19636285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 19736285Sbrian return "(o)"; 19836285Sbrian 19936285Sbrian return ""; 20036285Sbrian} 20136285Sbrian 2026059Samuraistatic int 20331343SbrianHelpCommand(struct cmdargs const *arg) 2046059Samurai{ 20528679Sbrian struct cmdtab const *cmd; 20636285Sbrian int n, cmax, dmax, cols, cxlen; 20736285Sbrian const char *cx; 2086059Samurai 20936285Sbrian if (!arg->prompt) { 21036285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 21126516Sbrian return 0; 21236285Sbrian } 21326516Sbrian 21436285Sbrian if (arg->argc > arg->argn) { 21536285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 21636285Sbrian if ((cmd->lauth & arg->prompt->auth) && 21736285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 21836285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 21936285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 22028679Sbrian return 0; 2216059Samurai } 22226516Sbrian return -1; 2236059Samurai } 22436285Sbrian 22531372Sbrian cmax = dmax = 0; 22636285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22736285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22836285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 22931372Sbrian cmax = n; 23031372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 23131372Sbrian dmax = n; 23231372Sbrian } 23331372Sbrian 23431372Sbrian cols = 80 / (dmax + cmax + 3); 2356059Samurai n = 0; 23636285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 23736285Sbrian " (c) = Context required\n"); 23836285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 23936285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 24036285Sbrian cx = showcx(cmd); 24136285Sbrian cxlen = cmax - strlen(cmd->name); 24240482Sbrian if (n % cols != 0) 24340482Sbrian prompt_Printf(arg->prompt, " "); 24440482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 24536285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 24631372Sbrian if (++n % cols == 0) 24736285Sbrian prompt_Printf(arg->prompt, "\n"); 2486059Samurai } 24931372Sbrian if (n % cols != 0) 25036285Sbrian prompt_Printf(arg->prompt, "\n"); 25126516Sbrian 25226516Sbrian return 0; 2536059Samurai} 2546059Samurai 25536285Sbrianstatic int 25663484SbrianIdentCommand(struct cmdargs const *arg) 25763484Sbrian{ 25885991Sbrian Concatinate(arg->cx->physical->link.lcp.cfg.ident, 25985991Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident, 26085991Sbrian arg->argc - arg->argn, arg->argv + arg->argn); 26163484Sbrian return 0; 26263484Sbrian} 26363484Sbrian 26463484Sbrianstatic int 26563484SbrianSendIdentification(struct cmdargs const *arg) 26663484Sbrian{ 26763484Sbrian if (arg->cx->state < DATALINK_LCP) { 26863484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 26963484Sbrian return 2; 27063484Sbrian } 27163484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 27263484Sbrian} 27363484Sbrian 27463484Sbrianstatic int 27536285SbrianCloneCommand(struct cmdargs const *arg) 2766059Samurai{ 27736285Sbrian char namelist[LINE_LEN]; 27836285Sbrian char *name; 27936285Sbrian int f; 2806059Samurai 28136285Sbrian if (arg->argc == arg->argn) 28236285Sbrian return -1; 28336285Sbrian 28436285Sbrian namelist[sizeof namelist - 1] = '\0'; 28536285Sbrian for (f = arg->argn; f < arg->argc; f++) { 28636285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 28736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 28836285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2896059Samurai } 29036285Sbrian 29136285Sbrian return 0; 2926059Samurai} 2936059Samurai 2946059Samuraistatic int 29536285SbrianRemoveCommand(struct cmdargs const *arg) 2966059Samurai{ 29736285Sbrian if (arg->argc != arg->argn) 29836285Sbrian return -1; 29911336Samurai 30036285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 30136285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 30236285Sbrian return 2; 3036059Samurai } 30426516Sbrian 30536285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 30636285Sbrian return 0; 30736285Sbrian} 30832711Sbrian 30936285Sbrianstatic int 31036285SbrianRenameCommand(struct cmdargs const *arg) 31136285Sbrian{ 31236285Sbrian if (arg->argc != arg->argn + 1) 31336285Sbrian return -1; 31431121Sbrian 31536285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 31636285Sbrian return 0; 31736285Sbrian 31836285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 31936285Sbrian arg->cx->name, arg->argv[arg->argn]); 32036285Sbrian return 1; 32136285Sbrian} 32236285Sbrian 32385991Sbrianstatic int 32436285SbrianLoadCommand(struct cmdargs const *arg) 32536285Sbrian{ 32640797Sbrian const char *err; 32740797Sbrian int n, mode; 32836285Sbrian 32940797Sbrian mode = arg->bundle->phys_type.all; 33036285Sbrian 33140797Sbrian if (arg->argn < arg->argc) { 33240797Sbrian for (n = arg->argn; n < arg->argc; n++) 33340797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 33440797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 33540797Sbrian return 1; 33640797Sbrian } 33740797Sbrian 33840797Sbrian for (n = arg->argn; n < arg->argc; n++) { 33940797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34040797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 34140797Sbrian } 34240797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34340797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 34440797Sbrian log_Printf(LogWARN, "default: %s\n", err); 34536285Sbrian return 1; 34636285Sbrian } else { 34740797Sbrian bundle_SetLabel(arg->bundle, "default"); 34840797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 34940797Sbrian bundle_SetLabel(arg->bundle, "default"); 35036285Sbrian } 35140797Sbrian 35226516Sbrian return 0; 3536059Samurai} 3546059Samurai 35585991Sbrianstatic int 35685991SbrianLogCommand(struct cmdargs const *arg) 35785991Sbrian{ 35885991Sbrian char buf[LINE_LEN]; 35985991Sbrian 36085991Sbrian if (arg->argn < arg->argc) { 36185991Sbrian char *argv[MAXARGS]; 36285991Sbrian int argc = arg->argc - arg->argn; 36385991Sbrian 36485991Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 36585991Sbrian argc = sizeof argv / sizeof argv[0] - 1; 36685991Sbrian log_Printf(LogWARN, "Truncating log command to %d args\n", argc); 36785991Sbrian } 36886760Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 36985991Sbrian Concatinate(buf, sizeof buf, argc, (const char *const *)argv); 37085991Sbrian log_Printf(LogLOG, "%s\n", buf); 37185991Sbrian command_Free(argc, argv); 37285991Sbrian return 0; 37385991Sbrian } 37485991Sbrian 37585991Sbrian return -1; 37685991Sbrian} 37785991Sbrian 37885991Sbrianstatic int 37936285SbrianSaveCommand(struct cmdargs const *arg) 38036285Sbrian{ 38185991Sbrian log_Printf(LogWARN, "save command is not yet implemented.\n"); 38236285Sbrian return 1; 38336285Sbrian} 38436285Sbrian 38510528Samuraistatic int 38636285SbrianDialCommand(struct cmdargs const *arg) 38728536Sbrian{ 38836285Sbrian int res; 38936285Sbrian 39036465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 39136465Sbrian || (!arg->cx && 39236928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 39336285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 39436285Sbrian " interactive links\n"); 39536285Sbrian return 1; 39634536Sbrian } 39736285Sbrian 39836285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 39936285Sbrian return res; 40036285Sbrian 40137993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 40236285Sbrian 40336285Sbrian return 0; 40428536Sbrian} 40528536Sbrian 40638628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 40738628Sbrian 40838628Sbrianstatic char * 40938628Sbrianstrstrword(char *big, const char *little) 41038628Sbrian{ 41138628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 41238628Sbrian char *pos; 41338628Sbrian int len; 41438628Sbrian 41538628Sbrian pos = big; 41638628Sbrian len = strlen(little); 41738628Sbrian 41838628Sbrian while ((pos = strstr(pos, little)) != NULL) 41947865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 42047865Sbrian pos++; 42147865Sbrian else if (pos != big && pos[-1] == '\\') 42247865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 42347865Sbrian else 42438628Sbrian break; 42538628Sbrian 42638628Sbrian return pos; 42738628Sbrian} 42838628Sbrian 42938628Sbrianstatic char * 43038628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 43138628Sbrian{ 43238628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 43338628Sbrian char *word, *ntgt; 43438628Sbrian int ltgt, loldstr, lnewstr, pos; 43538628Sbrian 43638628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 43738628Sbrian return tgt; 43838628Sbrian 43938628Sbrian ltgt = strlen(tgt) + 1; 44038628Sbrian loldstr = strlen(oldstr); 44138628Sbrian lnewstr = strlen(newstr); 44238628Sbrian do { 44338628Sbrian pos = word - tgt; 44438628Sbrian if (loldstr > lnewstr) 44538628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 44638628Sbrian if (loldstr != lnewstr) { 44738628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 44838628Sbrian if (ntgt == NULL) 44938628Sbrian break; /* Oh wonderful ! */ 45038628Sbrian word = ntgt + pos; 45138628Sbrian tgt = ntgt; 45238628Sbrian } 45338628Sbrian if (lnewstr > loldstr) 45438628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 45538628Sbrian bcopy(newstr, word, lnewstr); 45638628Sbrian } while ((word = strstrword(word, oldstr))); 45738628Sbrian 45838628Sbrian return tgt; 45938628Sbrian} 46038628Sbrian 46194934Sbrianstatic char * 46294934Sbriansubstip(char *tgt, const char *oldstr, struct in_addr ip) 46394934Sbrian{ 46494934Sbrian return subst(tgt, oldstr, inet_ntoa(ip)); 46594934Sbrian} 46694934Sbrian 46794934Sbrianstatic char * 46894934Sbriansubstint(char *tgt, const char *oldstr, int i) 46994934Sbrian{ 47094934Sbrian char buf[12]; 47194934Sbrian 47294934Sbrian snprintf(buf, sizeof buf, "%d", i); 47394934Sbrian 47494934Sbrian return subst(tgt, oldstr, buf); 47594934Sbrian} 47694934Sbrian 47794934Sbrianstatic char * 47894934Sbriansubstull(char *tgt, const char *oldstr, unsigned long long ull) 47994934Sbrian{ 48094934Sbrian char buf[21]; 48194934Sbrian 48294934Sbrian snprintf(buf, sizeof buf, "%llu", ull); 48394934Sbrian 48494934Sbrian return subst(tgt, oldstr, buf); 48594934Sbrian} 48694934Sbrian 48794934Sbrian 48894934Sbrian#ifndef NOINET6 48994934Sbrianstatic char * 49094934Sbriansubstipv6(char *tgt, const char *oldstr, const struct ncpaddr *ip) 49194934Sbrian{ 49294934Sbrian return subst(tgt, oldstr, ncpaddr_ntoa(ip)); 49394934Sbrian} 49494934Sbrian#endif 49594934Sbrian 49643888Sbrianvoid 49743888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 49847849Sbrian struct bundle *bundle, int inc0, pid_t pid) 49938628Sbrian{ 50085991Sbrian int arg, secs; 50194934Sbrian char uptime[20]; 50294934Sbrian unsigned long long oin, oout, pin, pout; 50338628Sbrian 50441755Sbrian if (inc0) 50541755Sbrian arg = 0; /* Start at arg 0 */ 50641755Sbrian else { 50741755Sbrian nargv[0] = strdup(oargv[0]); 50841755Sbrian arg = 1; 50941755Sbrian } 51094934Sbrian 51194934Sbrian secs = bundle_Uptime(bundle); 51294934Sbrian snprintf(uptime, sizeof uptime, "%d:%02d:%02d", 51394934Sbrian secs / 3600, (secs / 60) % 60, secs % 60); 51494934Sbrian oin = bundle->ncp.ipcp.throughput.OctetsIn; 51594934Sbrian oout = bundle->ncp.ipcp.throughput.OctetsOut; 51694934Sbrian pin = bundle->ncp.ipcp.throughput.PacketsIn; 51794934Sbrian pout = bundle->ncp.ipcp.throughput.PacketsOut; 51894934Sbrian#ifndef NOINET6 51994934Sbrian oin += bundle->ncp.ipv6cp.throughput.OctetsIn; 52094934Sbrian oout += bundle->ncp.ipv6cp.throughput.OctetsOut; 52194934Sbrian pin += bundle->ncp.ipv6cp.throughput.PacketsIn; 52294934Sbrian pout += bundle->ncp.ipv6cp.throughput.PacketsOut; 52394934Sbrian#endif 52494934Sbrian 52541755Sbrian for (; arg < argc; arg++) { 52638629Sbrian nargv[arg] = strdup(oargv[arg]); 52794934Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 52894934Sbrian nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 52994934Sbrian nargv[arg] = substip(nargv[arg], "DNS0", bundle->ncp.ipcp.ns.dns[0]); 53094934Sbrian nargv[arg] = substip(nargv[arg], "DNS1", bundle->ncp.ipcp.ns.dns[1]); 53194934Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 53294934Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 53394934Sbrian bundle->ncp.mp.cfg.enddisc.address, 53494934Sbrian bundle->ncp.mp.cfg.enddisc.len)); 53594934Sbrian nargv[arg] = substip(nargv[arg], "HISADDR", bundle->ncp.ipcp.peer_ip); 53681634Sbrian#ifndef NOINET6 53794934Sbrian nargv[arg] = substipv6(nargv[arg], "HISADDR6", &bundle->ncp.ipv6cp.hisaddr); 53881634Sbrian#endif 53940561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 54094934Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSIN", 54194934Sbrian bundle->ncp.ipcp.throughput.OctetsIn); 54294934Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSOUT", 54394934Sbrian bundle->ncp.ipcp.throughput.OctetsOut); 54494934Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSIN", 54594934Sbrian bundle->ncp.ipcp.throughput.PacketsIn); 54694934Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSOUT", 54794934Sbrian bundle->ncp.ipcp.throughput.PacketsOut); 54881634Sbrian#ifndef NOINET6 54994934Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSIN", 55094934Sbrian bundle->ncp.ipv6cp.throughput.OctetsIn); 55194934Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSOUT", 55294934Sbrian bundle->ncp.ipv6cp.throughput.OctetsOut); 55394934Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSIN", 55494934Sbrian bundle->ncp.ipv6cp.throughput.PacketsIn); 55594934Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSOUT", 55694934Sbrian bundle->ncp.ipv6cp.throughput.PacketsOut); 55781634Sbrian#endif 55894934Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 55994934Sbrian nargv[arg] = substip(nargv[arg], "MYADDR", bundle->ncp.ipcp.my_ip); 56094934Sbrian#ifndef NOINET6 56194934Sbrian nargv[arg] = substipv6(nargv[arg], "MYADDR6", &bundle->ncp.ipv6cp.myaddr); 56294934Sbrian#endif 56394934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSIN", oin); 56494934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSOUT", oout); 56594934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSIN", pin); 56694934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSOUT", pout); 56738629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 56838629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 56938629Sbrian bundle->ncp.mp.peer.enddisc.address, 57038629Sbrian bundle->ncp.mp.peer.enddisc.len)); 57194934Sbrian nargv[arg] = substint(nargv[arg], "PROCESSID", pid); 57294934Sbrian if (server.cfg.port) 57394934Sbrian nargv[arg] = substint(nargv[arg], "SOCKNAME", server.cfg.port); 57494934Sbrian else 57594934Sbrian nargv[arg] = subst(nargv[arg], "SOCKNAME", server.cfg.sockname); 57694934Sbrian nargv[arg] = subst(nargv[arg], "UPTIME", uptime); 57794934Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 57863484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 57938628Sbrian } 58038628Sbrian nargv[arg] = NULL; 58138628Sbrian} 58238628Sbrian 58385991Sbrianvoid 58485991Sbriancommand_Free(int argc, char **argv) 58585991Sbrian{ 58685991Sbrian while (argc) { 58785991Sbrian free(*argv); 58885991Sbrian argc--; 58985991Sbrian argv++; 59085991Sbrian } 59185991Sbrian} 59285991Sbrian 59328536Sbrianstatic int 59431343SbrianShellCommand(struct cmdargs const *arg, int bg) 59510528Samurai{ 59610528Samurai const char *shell; 59747849Sbrian pid_t shpid, pid; 59820813Sjkh 59918856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 60026911Sbrian /* we're only allowed to shell when we run ppp interactively */ 60136285Sbrian if (arg->prompt && arg->prompt->owner) { 60236285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 60326516Sbrian return 1; 60410528Samurai } 60526911Sbrian#endif 60628679Sbrian 60736285Sbrian if (arg->argc == arg->argn) { 60836285Sbrian if (!arg->prompt) { 60936285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 61036285Sbrian " a config file\n"); 61128381Sbrian return 1; 61236285Sbrian } else if (arg->prompt->owner) { 61336285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 61436285Sbrian " a socket connection\n"); 61536285Sbrian return 1; 61628381Sbrian } else if (bg) { 61736285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 61828679Sbrian " the foreground mode\n"); 61928381Sbrian return 1; 62028381Sbrian } 62134536Sbrian } 62234536Sbrian 62347849Sbrian pid = getpid(); 62428679Sbrian if ((shpid = fork()) == 0) { 62536285Sbrian int i, fd; 62618531Sbde 62736285Sbrian if ((shell = getenv("SHELL")) == 0) 62836285Sbrian shell = _PATH_BSHELL; 62932017Sbrian 63036285Sbrian timer_TermService(); 63136285Sbrian 63236285Sbrian if (arg->prompt) 63336285Sbrian fd = arg->prompt->fd_out; 63436285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 63536285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 63636285Sbrian _PATH_DEVNULL, strerror(errno)); 63728679Sbrian exit(1); 63828679Sbrian } 63949976Sbrian dup2(fd, STDIN_FILENO); 64049976Sbrian dup2(fd, STDOUT_FILENO); 64149976Sbrian dup2(fd, STDERR_FILENO); 64249976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 64349976Sbrian fcntl(i, F_SETFD, 1); 64426516Sbrian 64564802Sbrian#ifndef NOSUID 64655252Sbrian setuid(ID0realuid()); 64764802Sbrian#endif 64836285Sbrian if (arg->argc > arg->argn) { 64928679Sbrian /* substitute pseudo args */ 65038628Sbrian char *argv[MAXARGS]; 65138628Sbrian int argc = arg->argc - arg->argn; 65238628Sbrian 65338628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 65438628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 65538628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 65631343Sbrian } 65747849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 65828679Sbrian if (bg) { 65928679Sbrian pid_t p; 66010528Samurai 66128679Sbrian p = getpid(); 66228679Sbrian if (daemon(1, 1) == -1) { 66336832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 66428679Sbrian exit(1); 66528679Sbrian } 66636285Sbrian } else if (arg->prompt) 66736285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 66831343Sbrian execvp(argv[0], argv); 66930316Sbrian } else { 67036285Sbrian if (arg->prompt) 67132017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 67236285Sbrian prompt_TtyOldMode(arg->prompt); 67379450Sbrian execl(shell, shell, (char *)NULL); 67430316Sbrian } 67520813Sjkh 67640665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 67740665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 67840665Sbrian strerror(errno)); 67949976Sbrian _exit(255); 68010528Samurai } 68136285Sbrian 68236285Sbrian if (shpid == (pid_t) - 1) 68336285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 68436285Sbrian else { 68510528Samurai int status; 68631343Sbrian waitpid(shpid, &status, 0); 68710528Samurai } 68820813Sjkh 68936285Sbrian if (arg->prompt && !arg->prompt->owner) 69036285Sbrian prompt_TtyCommandMode(arg->prompt); 69120813Sjkh 69236285Sbrian return 0; 69310528Samurai} 69410528Samurai 69531343Sbrianstatic int 69631343SbrianBgShellCommand(struct cmdargs const *arg) 69731343Sbrian{ 69836285Sbrian if (arg->argc == arg->argn) 69931343Sbrian return -1; 70031343Sbrian return ShellCommand(arg, 1); 70131343Sbrian} 70231343Sbrian 70331343Sbrianstatic int 70431343SbrianFgShellCommand(struct cmdargs const *arg) 70531343Sbrian{ 70631343Sbrian return ShellCommand(arg, 0); 70731343Sbrian} 70831343Sbrian 70958044Sbrianstatic int 71058044SbrianResolvCommand(struct cmdargs const *arg) 71158044Sbrian{ 71258044Sbrian if (arg->argc == arg->argn + 1) { 71358044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 71458044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 71558044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 71658044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 71758044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 71858044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 71958044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 72058044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 72158044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 72258044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 72358044Sbrian else 72458044Sbrian return -1; 72558044Sbrian 72658044Sbrian return 0; 72758044Sbrian } 72858044Sbrian 72958044Sbrian return -1; 73058044Sbrian} 73158044Sbrian 73250059Sbrian#ifndef NONAT 73358867Sbrianstatic struct cmdtab const NatCommands[] = 73440561Sbrian{ 73550059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 73650059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 73758867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 73850059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 73940561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 74058867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 74150059Sbrian "enable NAT", "nat enable yes|no"}, 74258867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 74350059Sbrian "log NAT link creation", "nat log yes|no", 74440561Sbrian (const void *) PKT_ALIAS_LOG}, 74550059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 74650059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 74779433Sbrian {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 74879433Sbrian "nat proto proto localIP [publicIP [remoteIP]]"}, 74950059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 75050059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 75181033Sbrian#ifndef NO_FW_PUNCH 75281033Sbrian {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 75381033Sbrian "firewall control", "nat punch_fw [base count]"}, 75481033Sbrian#endif 75558867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 75650059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 75740561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 75858867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 75958867Sbrian "Default address for incoming connections", "nat target addr" }, 76058867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 76150059Sbrian "translate unregistered (private) IP address space only", 76250059Sbrian "nat unregistered_only yes|no", 76340561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 76458867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 76550059Sbrian "allocate host sockets", "nat use_sockets yes|no", 76640561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 76740561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 76858867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 76940561Sbrian {NULL, NULL, NULL}, 77040561Sbrian}; 77140561Sbrian#endif 77240561Sbrian 77340561Sbrianstatic struct cmdtab const AllowCommands[] = { 77440561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 77540561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 77640561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 77740561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 77840561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 77940561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 78040561Sbrian {NULL, NULL, NULL}, 78140561Sbrian}; 78240561Sbrian 78340561Sbrianstatic struct cmdtab const IfaceCommands[] = 78440561Sbrian{ 78540561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 78640561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 78740561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 78840561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 78940561Sbrian (void *)1}, 79040561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 79181634Sbrian "Clear iface address(es)", "iface clear [INET | INET6]"}, 79240561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 79340561Sbrian "Delete iface address", "iface delete addr", NULL}, 79440561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 79540561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 79640561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 79740561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 79840561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 79940561Sbrian "Show iface address(es)", "iface show"}, 80040561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 80150059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 80240561Sbrian {NULL, NULL, NULL}, 80340561Sbrian}; 80440561Sbrian 80530715Sbrianstatic struct cmdtab const Commands[] = { 80636285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 80728679Sbrian "accept option request", "accept option .."}, 80828679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 80932109Sbrian "add route", "add dest mask gateway", NULL}, 81036285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 81132109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 81240561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 81340561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 81428679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 81531372Sbrian "Run a background command", "[!]bg command"}, 81636934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 81746686Sbrian "Clear throughput statistics", 81881634Sbrian "clear ipcp|ipv6cp|physical [current|overall|peak]..."}, 81936285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 82036285Sbrian "Clone a link", "clone newname..."}, 82136285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 82236285Sbrian "Close an FSM", "close [lcp|ccp]"}, 82328679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 82432109Sbrian "delete route", "delete dest", NULL}, 82536285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 82632109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 82736285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 82828679Sbrian "Deny option request", "deny option .."}, 82936285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 83040797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 83136285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 83228679Sbrian "Disable option", "disable option .."}, 83336285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 83446686Sbrian "Generate a down event", "down [ccp|lcp]"}, 83536285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 83628679Sbrian "Enable option", "enable option .."}, 83763484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 83863484Sbrian "Set the link identity", "ident text..."}, 83940561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 84040561Sbrian "interface control", "iface option ...", IfaceCommands}, 84136285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 84236285Sbrian "Link specific commands", "link name command ..."}, 84337008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 84440797Sbrian "Load settings", "load [system ...]"}, 84585991Sbrian {"log", NULL, LogCommand, LOCAL_AUTH | LOCAL_CX_OPT, 84685991Sbrian "log information", "log word ..."}, 84750059Sbrian#ifndef NONAT 84850059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 84958867Sbrian "NAT control", "nat option yes|no", NatCommands}, 85050059Sbrian#endif 85136285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85237955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 85336285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 85436285Sbrian "Password for manipulation", "passwd LocalPassword"}, 85536285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 85636285Sbrian "Quit PPP program", "quit|bye [all]"}, 85736285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 85836285Sbrian "Remove a link", "remove"}, 85936285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 86036285Sbrian "Rename a link", "rename name"}, 86158044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 86258044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 86328679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 86428679Sbrian "Save settings", "save"}, 86563484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 86663484Sbrian "Transmit the link identity", "sendident"}, 86736285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 86828679Sbrian "Set parameters", "set[up] var value"}, 86928679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 87028679Sbrian "Run a subshell", "shell|! [sh command]"}, 87136285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 87231372Sbrian "Show status and stats", "show var"}, 87336285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 87431372Sbrian "Enter terminal mode", "term"}, 87528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 87631343Sbrian "Display this message", "help|? [command]", Commands}, 87728679Sbrian {NULL, NULL, NULL}, 8786059Samurai}; 8796059Samurai 88028536Sbrianstatic int 88131343SbrianShowEscape(struct cmdargs const *arg) 8826059Samurai{ 88336285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 88436285Sbrian int code, bit; 88536285Sbrian const char *sep = ""; 8866059Samurai 88726516Sbrian for (code = 0; code < 32; code++) 88836285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 88928679Sbrian for (bit = 0; bit < 8; bit++) 89036285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 89136285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 89236285Sbrian sep = ", "; 89336285Sbrian } 89436285Sbrian prompt_Printf(arg->prompt, "\n"); 8956059Samurai } 89631077Sbrian return 0; 8976059Samurai} 8986059Samurai 89928679Sbrianstatic int 90036285SbrianShowTimerList(struct cmdargs const *arg) 9016059Samurai{ 90236285Sbrian timer_Show(0, arg->prompt); 90331077Sbrian return 0; 9046059Samurai} 9056059Samurai 90628679Sbrianstatic int 90731343SbrianShowStopped(struct cmdargs const *arg) 90828327Sbrian{ 90936285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 91036285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 91136285Sbrian prompt_Printf(arg->prompt, "Disabled"); 91228327Sbrian else 91336285Sbrian prompt_Printf(arg->prompt, "%ld secs", 91436285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 91528461Sbrian 91636285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 91736285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 91836285Sbrian prompt_Printf(arg->prompt, "Disabled"); 91928461Sbrian else 92036285Sbrian prompt_Printf(arg->prompt, "%ld secs", 92136285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 92228461Sbrian 92336285Sbrian prompt_Printf(arg->prompt, "\n"); 92428461Sbrian 92531077Sbrian return 0; 92628327Sbrian} 92728327Sbrian 92828679Sbrianstatic int 92931343SbrianShowVersion(struct cmdargs const *arg) 9306059Samurai{ 93151026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 93231077Sbrian return 0; 9336059Samurai} 9346059Samurai 93528679Sbrianstatic int 93636285SbrianShowProtocolStats(struct cmdargs const *arg) 93726326Sbrian{ 93836285Sbrian struct link *l = command_ChooseLink(arg); 93926326Sbrian 94036285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 94136285Sbrian link_ReportProtocolStatus(l, arg->prompt); 94231077Sbrian return 0; 94326326Sbrian} 94426326Sbrian 94530715Sbrianstatic struct cmdtab const ShowCommands[] = { 94636285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 94736285Sbrian "bundle details", "show bundle"}, 94836285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 94936285Sbrian "CCP status", "show cpp"}, 95036285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 95136285Sbrian "VJ compression stats", "show compress"}, 95236285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 95336285Sbrian "escape characters", "show escape"}, 95436285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 95536285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 95636285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 95736285Sbrian "HDLC errors", "show hdlc"}, 95840561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 95940561Sbrian "Interface status", "show iface"}, 96036285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 96136285Sbrian "IPCP status", "show ipcp"}, 96281634Sbrian#ifndef NOINET6 96381634Sbrian {"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH, 96481634Sbrian "IPV6CP status", "show ipv6cp"}, 96581634Sbrian#endif 96647211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 96747211Sbrian "Protocol layers", "show layers"}, 96836285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 96936285Sbrian "LCP status", "show lcp"}, 97036285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 97136285Sbrian "(high-level) link info", "show link"}, 97236285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 97336285Sbrian "available link names", "show links"}, 97436285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 97536285Sbrian "log levels", "show log"}, 97636285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 97736285Sbrian "mbuf allocations", "show mem"}, 97881634Sbrian {"ncp", NULL, ncp_Show, LOCAL_AUTH, 97981634Sbrian "NCP status", "show ncp"}, 98046686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 98146686Sbrian "(low-level) link info", "show physical"}, 98236285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 98336285Sbrian "multilink setup", "show mp"}, 98436285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 98536285Sbrian "protocol summary", "show proto"}, 98636285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 98736285Sbrian "routing table", "show route"}, 98836285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 98936285Sbrian "STOPPED timeout", "show stopped"}, 99036285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 99136285Sbrian "alarm timers", "show timers"}, 99228679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 99336285Sbrian "version string", "show version"}, 99436285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 99536285Sbrian "client list", "show who"}, 99628679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 99731343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 99828679Sbrian {NULL, NULL, NULL}, 9996059Samurai}; 10006059Samurai 100130715Sbrianstatic struct cmdtab const * 100231343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 10036059Samurai{ 100426516Sbrian int nmatch; 100526516Sbrian int len; 100628679Sbrian struct cmdtab const *found; 10076059Samurai 100826516Sbrian found = NULL; 100926516Sbrian len = strlen(str); 101026516Sbrian nmatch = 0; 10116059Samurai while (cmds->func) { 101225566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 101326516Sbrian if (cmds->name[len] == '\0') { 101428679Sbrian *pmatch = 1; 101528679Sbrian return cmds; 101626516Sbrian } 10176059Samurai nmatch++; 10186059Samurai found = cmds; 101928679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 102026516Sbrian if (cmds->alias[len] == '\0') { 102128679Sbrian *pmatch = 1; 102228679Sbrian return cmds; 102326516Sbrian } 10246059Samurai nmatch++; 10256059Samurai found = cmds; 10266059Samurai } 10276059Samurai cmds++; 10286059Samurai } 10296059Samurai *pmatch = nmatch; 103026516Sbrian return found; 10316059Samurai} 10326059Samurai 103336285Sbrianstatic const char * 103436285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 103536285Sbrian{ 103636285Sbrian int f, tlen, len; 103736285Sbrian 103836285Sbrian tlen = 0; 103936285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 104036285Sbrian if (f) 104136285Sbrian tgt[tlen++] = ' '; 104236285Sbrian len = strlen(argv[f]); 104336285Sbrian if (len > sz - tlen - 1) 104436285Sbrian len = sz - tlen - 1; 104536285Sbrian strncpy(tgt+tlen, argv[f], len); 104636285Sbrian tlen += len; 104736285Sbrian } 104836285Sbrian tgt[tlen] = '\0'; 104936285Sbrian return tgt; 105036285Sbrian} 105136285Sbrian 105230715Sbrianstatic int 105336285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 105436285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 10556059Samurai{ 105628679Sbrian struct cmdtab const *cmd; 10576059Samurai int val = 1; 10586059Samurai int nmatch; 105931343Sbrian struct cmdargs arg; 106036285Sbrian char prefix[100]; 10616059Samurai 106236285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 10636059Samurai if (nmatch > 1) 106436285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 106536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 106636285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 106736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 106836285Sbrian /* We've got no context, but we require it */ 106936285Sbrian cx = bundle2datalink(bundle, NULL); 107036285Sbrian 107136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 107236285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 107336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 107436285Sbrian else { 107536285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 107636285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 107736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 107836285Sbrian cx = NULL; 107936285Sbrian } 108036285Sbrian arg.cmdtab = cmds; 108136285Sbrian arg.cmd = cmd; 108236285Sbrian arg.argc = argc; 108336285Sbrian arg.argn = argn+1; 108436285Sbrian arg.argv = argv; 108536285Sbrian arg.bundle = bundle; 108636285Sbrian arg.cx = cx; 108736285Sbrian arg.prompt = prompt; 108836285Sbrian val = (*cmd->func) (&arg); 108936285Sbrian } 109031343Sbrian } else 109136285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 109236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 109326516Sbrian 109426516Sbrian if (val == -1) 109595258Sdes log_Printf(LogWARN, "usage: %s\n", cmd->syntax); 109628679Sbrian else if (val) 109736285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 109836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 109926516Sbrian 110026516Sbrian return val; 11016059Samurai} 11026059Samurai 110337009Sbrianint 110458045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 110558045Sbrian{ 110658045Sbrian char buff2[LINE_LEN-offset]; 110758045Sbrian 110858045Sbrian InterpretArg(buff, buff2); 110958045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 111058045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 111158045Sbrian 111258045Sbrian return command_Interpret(buff, nb, argv); 111358045Sbrian} 111458045Sbrian 111558045Sbrianint 111637009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 11176059Samurai{ 11186059Samurai char *cp; 11196059Samurai 11206059Samurai if (nb > 0) { 11216059Samurai cp = buff + strcspn(buff, "\r\n"); 11226059Samurai if (cp) 11236059Samurai *cp = '\0'; 112455145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 112537009Sbrian } 112637009Sbrian return 0; 112731121Sbrian} 11286059Samurai 112931822Sbrianstatic int 113031822Sbrianarghidden(int argc, char const *const *argv, int n) 113131822Sbrian{ 113231822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 113331828Sbrian 113431828Sbrian /* set authkey xxxxx */ 113531828Sbrian /* set key xxxxx */ 113631822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 113731822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 113831822Sbrian return 1; 113931822Sbrian 114031828Sbrian /* passwd xxxxx */ 114131828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 114231828Sbrian return 1; 114331828Sbrian 114436285Sbrian /* set server port xxxxx .... */ 114536285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 114636285Sbrian !strncasecmp(argv[1], "se", 2)) 114736285Sbrian return 1; 114836285Sbrian 114931822Sbrian return 0; 115031822Sbrian} 115131822Sbrian 115231121Sbrianvoid 115336285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 115437008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 115531121Sbrian{ 115631156Sbrian if (argc > 0) { 115736285Sbrian if (log_IsKept(LogCOMMAND)) { 115847844Sbrian char buf[LINE_LEN]; 115931156Sbrian int f, n; 116031156Sbrian 116131156Sbrian if (label) { 116231962Sbrian strncpy(buf, label, sizeof buf - 3); 116331962Sbrian buf[sizeof buf - 3] = '\0'; 116431156Sbrian strcat(buf, ": "); 116547844Sbrian n = strlen(buf); 116647844Sbrian } else { 116747844Sbrian *buf = '\0'; 116847844Sbrian n = 0; 116931156Sbrian } 117047844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 117147844Sbrian 117231156Sbrian for (f = 0; f < argc; f++) { 117331962Sbrian if (n < sizeof buf - 1 && f) 117431156Sbrian buf[n++] = ' '; 117531822Sbrian if (arghidden(argc, argv, f)) 117636285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 117731822Sbrian else 117831962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 117931156Sbrian n += strlen(buf+n); 118031156Sbrian } 118136285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 118231156Sbrian } 118337008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 118431156Sbrian } 11856059Samurai} 11866059Samurai 118754914Sbrianint 118836285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 118936285Sbrian const char *label) 119031121Sbrian{ 119131121Sbrian int argc; 119237009Sbrian char *argv[MAXARGS]; 119331121Sbrian 119458045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 119554914Sbrian return 0; 119654914Sbrian 119737008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 119854914Sbrian return 1; 119931121Sbrian} 120031121Sbrian 12016059Samuraistatic int 120231343SbrianShowCommand(struct cmdargs const *arg) 12036059Samurai{ 120436285Sbrian if (!arg->prompt) 120536285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 120636285Sbrian else if (arg->argc > arg->argn) 120736285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 120836285Sbrian arg->prompt, arg->cx); 12096059Samurai else 121036285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 121126516Sbrian 121226516Sbrian return 0; 12136059Samurai} 12146059Samurai 12156059Samuraistatic int 121631343SbrianTerminalCommand(struct cmdargs const *arg) 12176059Samurai{ 121836285Sbrian if (!arg->prompt) { 121936285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 122026516Sbrian return 1; 12216059Samurai } 122236285Sbrian 122336285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 122436285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 122536285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 122636285Sbrian return 1; 12276059Samurai } 122836285Sbrian 122936285Sbrian datalink_Up(arg->cx, 0, 0); 123036285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 123136285Sbrian return 0; 12326059Samurai} 12336059Samurai 12346059Samuraistatic int 123531343SbrianQuitCommand(struct cmdargs const *arg) 12366059Samurai{ 123736285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 123836285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 123936285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 124036285Sbrian Cleanup(EX_NORMAL); 124136285Sbrian if (arg->prompt) 124236285Sbrian prompt_Destroy(arg->prompt, 1); 124326516Sbrian 124426516Sbrian return 0; 12456059Samurai} 12466059Samurai 12476059Samuraistatic int 124836285SbrianOpenCommand(struct cmdargs const *arg) 12496059Samurai{ 125037160Sbrian if (arg->argc == arg->argn) 125137993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 125237160Sbrian else if (arg->argc == arg->argn + 1) { 125337160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 125437385Sbrian struct datalink *cx = arg->cx ? 125537385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 125637385Sbrian if (cx) { 125737385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 125837385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 125937160Sbrian else 126037993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 126137160Sbrian } else 126237160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 126337160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 126437160Sbrian struct fsm *fp; 12656059Samurai 126637210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 126737160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 126837160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 126937160Sbrian else if (fp->state == ST_OPENED) 127037160Sbrian fsm_Reopen(fp); 127137160Sbrian else { 127237160Sbrian fp->open_mode = 0; /* Not passive any more */ 127337160Sbrian if (fp->state == ST_STOPPED) { 127437160Sbrian fsm_Down(fp); 127537160Sbrian fsm_Up(fp); 127637160Sbrian } else { 127737160Sbrian fsm_Up(fp); 127837160Sbrian fsm_Open(fp); 127937160Sbrian } 128036285Sbrian } 128137160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 128237160Sbrian if (arg->cx) 128337160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 128437160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 128537160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 128637160Sbrian else 128737993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 128837160Sbrian } else 128937160Sbrian return -1; 129036285Sbrian } else 129136285Sbrian return -1; 129236285Sbrian 129326516Sbrian return 0; 12946059Samurai} 12956059Samurai 129625067Sbrianstatic int 129736285SbrianCloseCommand(struct cmdargs const *arg) 12986059Samurai{ 129937007Sbrian if (arg->argc == arg->argn) 130037007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 130137007Sbrian else if (arg->argc == arg->argn + 1) { 130237007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 130337007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 130437007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 130537007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 130637007Sbrian struct fsm *fp; 13076059Samurai 130837210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 130937007Sbrian if (fp->state == ST_OPENED) { 131037007Sbrian fsm_Close(fp); 131137007Sbrian if (arg->argv[arg->argn][3] == '!') 131237007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 131337007Sbrian else 131437007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 131537007Sbrian } 131637007Sbrian } else 131736285Sbrian return -1; 131836285Sbrian } else 131936285Sbrian return -1; 132036285Sbrian 132136285Sbrian return 0; 13226059Samurai} 13236059Samurai 132425067Sbrianstatic int 132536285SbrianDownCommand(struct cmdargs const *arg) 132611336Samurai{ 132737018Sbrian if (arg->argc == arg->argn) { 132837018Sbrian if (arg->cx) 132937018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 133037018Sbrian else 133137018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 133237018Sbrian } else if (arg->argc == arg->argn + 1) { 133337018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 133437018Sbrian if (arg->cx) 133537018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 133637018Sbrian else 133737018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 133837018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 133937018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 134037018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 134137060Sbrian fsm2initial(fp); 134237018Sbrian } else 134337018Sbrian return -1; 134436285Sbrian } else 134536285Sbrian return -1; 134636285Sbrian 134736285Sbrian return 0; 134825067Sbrian} 134925067Sbrian 135025067Sbrianstatic int 135136285SbrianSetModemSpeed(struct cmdargs const *arg) 135225067Sbrian{ 135336285Sbrian long speed; 135436285Sbrian char *end; 135511336Samurai 135636285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 135736285Sbrian if (arg->argc > arg->argn+1) { 135854917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 135936285Sbrian return -1; 136011336Samurai } 136136285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 136236285Sbrian physical_SetSync(arg->cx->physical); 136336285Sbrian return 0; 136436285Sbrian } 136536285Sbrian end = NULL; 136636285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 136736285Sbrian if (*end) { 136836285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 136936285Sbrian arg->argv[arg->argn]); 137036285Sbrian return -1; 137136285Sbrian } 137236285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 137336285Sbrian return 0; 137436285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 137536285Sbrian } else 137636285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 137724939Sbrian 137826516Sbrian return -1; 137911336Samurai} 138011336Samurai 138125067Sbrianstatic int 138231343SbrianSetStoppedTimeout(struct cmdargs const *arg) 138328327Sbrian{ 138436285Sbrian struct link *l = &arg->cx->physical->link; 138536285Sbrian 138636285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 138736285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 138836285Sbrian if (arg->argc <= arg->argn+2) { 138936285Sbrian if (arg->argc > arg->argn) { 139036285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 139136285Sbrian if (arg->argc > arg->argn+1) 139236285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 139328461Sbrian } 139428327Sbrian return 0; 139528327Sbrian } 139628327Sbrian return -1; 139728327Sbrian} 139828327Sbrian 139928327Sbrianstatic int 140031343SbrianSetServer(struct cmdargs const *arg) 140126940Sbrian{ 140226940Sbrian int res = -1; 140326940Sbrian 140436285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 140531081Sbrian const char *port, *passwd, *mask; 140653125Sbrian int mlen; 140731081Sbrian 140831081Sbrian /* What's what ? */ 140936285Sbrian port = arg->argv[arg->argn]; 141036285Sbrian if (arg->argc == arg->argn + 2) { 141136285Sbrian passwd = arg->argv[arg->argn+1]; 141236285Sbrian mask = NULL; 141336285Sbrian } else if (arg->argc == arg->argn + 3) { 141436285Sbrian passwd = arg->argv[arg->argn+1]; 141536285Sbrian mask = arg->argv[arg->argn+2]; 141653125Sbrian mlen = strlen(mask); 141753125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 141853125Sbrian (mlen == 4 && *mask != '0')) { 141953125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 142053125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 142131081Sbrian return -1; 142253125Sbrian } 142371764Sbrian } else if (arg->argc != arg->argn + 1) 142471764Sbrian return -1; 142571764Sbrian else if (strcasecmp(port, "none") == 0) { 142671657Sbrian if (server_Clear(arg->bundle)) 142771657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 142871657Sbrian return 0; 142971657Sbrian } else if (strcasecmp(port, "open") == 0) { 143071657Sbrian switch (server_Reopen(arg->bundle)) { 143171657Sbrian case SERVER_OK: 143271657Sbrian return 0; 143371657Sbrian case SERVER_FAILED: 143471764Sbrian log_Printf(LogWARN, "Failed to reopen server port\n"); 143571657Sbrian return 1; 143671657Sbrian case SERVER_UNSET: 143771764Sbrian log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 143871657Sbrian return 1; 143971657Sbrian default: 144071657Sbrian break; 144171657Sbrian } 144271657Sbrian return -1; 144371657Sbrian } else if (strcasecmp(port, "closed") == 0) { 144436285Sbrian if (server_Close(arg->bundle)) 144571657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 144671657Sbrian else 144771657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 144871657Sbrian 144936285Sbrian return 0; 145031081Sbrian } else 145136285Sbrian return -1; 145231081Sbrian 145371657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 145471657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 145531081Sbrian 145636285Sbrian if (*port == '/') { 145731081Sbrian mode_t imask; 145836285Sbrian char *ptr, name[LINE_LEN + 12]; 145928679Sbrian 146053125Sbrian if (mask == NULL) 146131081Sbrian imask = (mode_t)-1; 146253125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 146353125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 146436285Sbrian 146536285Sbrian ptr = strstr(port, "%d"); 146636285Sbrian if (ptr) { 146736285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 146837210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 146936285Sbrian port = name; 147036285Sbrian } 147136285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 147227346Sbrian } else { 147336285Sbrian int iport, add = 0; 147428679Sbrian 147531081Sbrian if (mask != NULL) 147631081Sbrian return -1; 147728679Sbrian 147836285Sbrian if (*port == '+') { 147936285Sbrian port++; 148036285Sbrian add = 1; 148136285Sbrian } 148231081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 148331081Sbrian struct servent *s; 148431081Sbrian 148531081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 148631081Sbrian iport = 0; 148736285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 148828679Sbrian } else 148931081Sbrian iport = ntohs(s->s_port); 149027346Sbrian } else 149131081Sbrian iport = atoi(port); 149236285Sbrian 149336285Sbrian if (iport) { 149436285Sbrian if (add) 149536285Sbrian iport += arg->bundle->unit; 149636285Sbrian res = server_TcpOpen(arg->bundle, iport); 149736285Sbrian } else 149836285Sbrian res = -1; 149927346Sbrian } 150031081Sbrian } 150126940Sbrian 150226940Sbrian return res; 150326940Sbrian} 150426940Sbrian 150526940Sbrianstatic int 150631343SbrianSetEscape(struct cmdargs const *arg) 15076059Samurai{ 15086059Samurai int code; 150936285Sbrian int argc = arg->argc - arg->argn; 151036285Sbrian char const *const *argv = arg->argv + arg->argn; 15116059Samurai 15126059Samurai for (code = 0; code < 33; code++) 151336285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 151431343Sbrian 15156059Samurai while (argc-- > 0) { 15166059Samurai sscanf(*argv++, "%x", &code); 15176059Samurai code &= 0xff; 151836285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 151936285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 15206059Samurai } 152126516Sbrian return 0; 15226059Samurai} 15236059Samurai 15246059Samuraistatic int 152531343SbrianSetInterfaceAddr(struct cmdargs const *arg) 15266059Samurai{ 152781634Sbrian struct ncp *ncp = &arg->bundle->ncp; 152881634Sbrian struct ncpaddr ncpaddr; 152932267Sbrian const char *hisaddr; 153032267Sbrian 153140561Sbrian if (arg->argc > arg->argn + 4) 153240561Sbrian return -1; 153340561Sbrian 153432267Sbrian hisaddr = NULL; 153581634Sbrian memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range); 153681634Sbrian memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range); 153781634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 0; 153881634Sbrian ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY; 153981634Sbrian iplist_reset(&ncp->ipcp.cfg.peer_list); 154028394Sbrian 154136285Sbrian if (arg->argc > arg->argn) { 154281634Sbrian if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn])) 154328679Sbrian return 1; 154436285Sbrian if (arg->argc > arg->argn+1) { 154536285Sbrian hisaddr = arg->argv[arg->argn+1]; 154636285Sbrian if (arg->argc > arg->argn+2) { 154781634Sbrian ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask = 154881634Sbrian GetIpAddr(arg->argv[arg->argn+2]); 154936285Sbrian if (arg->argc > arg->argn+3) { 155081634Sbrian ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 155181634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 1; 15529440Samurai } 15536059Samurai } 15546059Samurai } 15556059Samurai } 155628394Sbrian 155740561Sbrian /* 0.0.0.0 means any address (0 bits) */ 155881634Sbrian ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip); 155981634Sbrian ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr); 156081634Sbrian if (ncp->ipcp.my_ip.s_addr == INADDR_ANY) 156181634Sbrian ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0); 156281634Sbrian bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL); 156336285Sbrian 156436285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 156536928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 156632267Sbrian return 4; 156731121Sbrian 156826516Sbrian return 0; 15696059Samurai} 15706059Samurai 157118752Sjkhstatic int 157244305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 157344305Sbrian u_int *maxtrm, int def) 157444305Sbrian{ 157544305Sbrian if (argc == 0) { 157644305Sbrian *timeout = DEF_FSMRETRY; 157744305Sbrian *maxreq = def; 157844305Sbrian if (maxtrm != NULL) 157944305Sbrian *maxtrm = def; 158044305Sbrian } else { 158144305Sbrian long l = atol(argv[0]); 158244305Sbrian 158344305Sbrian if (l < MIN_FSMRETRY) { 158444305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 158544305Sbrian l, MIN_FSMRETRY); 158644305Sbrian return 1; 158744305Sbrian } else 158844305Sbrian *timeout = l; 158944305Sbrian 159044305Sbrian if (argc > 1) { 159144305Sbrian l = atol(argv[1]); 159244305Sbrian if (l < 1) { 159344305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 159444305Sbrian l = 1; 159544305Sbrian } 159644305Sbrian *maxreq = l; 159744305Sbrian 159844305Sbrian if (argc > 2 && maxtrm != NULL) { 159944305Sbrian l = atol(argv[2]); 160044305Sbrian if (l < 1) { 160144305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 160244305Sbrian l = 1; 160344305Sbrian } 160444305Sbrian *maxtrm = l; 160544305Sbrian } 160644305Sbrian } 160744305Sbrian } 160844305Sbrian 160944305Sbrian return 0; 161044305Sbrian} 161144305Sbrian 161244305Sbrianstatic int 161331343SbrianSetVariable(struct cmdargs const *arg) 16146059Samurai{ 161537210Sbrian long long_val, param = (long)arg->cmd->args; 161679119Sbrian int mode, dummyint, f, first, res; 161778410Sbrian u_short *change; 161831343Sbrian const char *argp; 161936285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 162036285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 162181634Sbrian struct in_addr *ipaddr; 162281634Sbrian struct ncpaddr ncpaddr[2]; 16236059Samurai 162436285Sbrian if (arg->argc > arg->argn) 162536285Sbrian argp = arg->argv[arg->argn]; 162626551Sbrian else 162731343Sbrian argp = ""; 162826551Sbrian 162979119Sbrian res = 0; 163079119Sbrian 163136285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 163236285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 163336285Sbrian arg->cmd->name); 163436285Sbrian return 1; 163536285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 163636285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 163736285Sbrian arg->cmd->name, cx->name); 163836285Sbrian cx = NULL; 163936285Sbrian } 164036285Sbrian 164126551Sbrian switch (param) { 164228679Sbrian case VAR_AUTHKEY: 164350139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 164450139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 164550139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 164628679Sbrian break; 164737210Sbrian 164828679Sbrian case VAR_AUTHNAME: 164940622Sbrian switch (bundle_Phase(arg->bundle)) { 165058880Sbrian default: 165158880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 165258880Sbrian bundle_PhaseName(arg->bundle)); 165358880Sbrian /* drop through */ 165440622Sbrian case PHASE_DEAD: 165540622Sbrian case PHASE_ESTABLISH: 165640622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 165740622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 165840622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 165940622Sbrian break; 166036285Sbrian } 166128679Sbrian break; 166237210Sbrian 166336285Sbrian case VAR_AUTOLOAD: 166449434Sbrian if (arg->argc == arg->argn + 3) { 166549434Sbrian int v1, v2, v3; 166649434Sbrian char *end; 166749434Sbrian 166849434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 166949434Sbrian if (v1 < 0 || *end) { 167049434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 167149434Sbrian arg->argv[arg->argn]); 167279119Sbrian res = 1; 167379119Sbrian break; 167436285Sbrian } 167549434Sbrian 167649434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 167749434Sbrian if (v2 < 0 || *end) { 167849434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 167949434Sbrian arg->argv[arg->argn + 1]); 168079119Sbrian res = 1; 168179119Sbrian break; 168249434Sbrian } 168349434Sbrian if (v2 < v1) { 168449434Sbrian v3 = v1; 168549434Sbrian v1 = v2; 168649434Sbrian v2 = v3; 168749434Sbrian } 168849434Sbrian 168949434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 169049434Sbrian if (v3 <= 0 || *end) { 169149434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 169249434Sbrian arg->argv[arg->argn + 2]); 169379119Sbrian res = 1; 169479119Sbrian break; 169549434Sbrian } 169649434Sbrian 169749434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 169849434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 169949434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 170049434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 170136285Sbrian } else { 170279119Sbrian log_Printf(LogWARN, "Set autoload requires three arguments\n"); 170379119Sbrian res = 1; 170436285Sbrian } 170536285Sbrian break; 170637210Sbrian 170728679Sbrian case VAR_DIAL: 170836285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 170936285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 171028679Sbrian break; 171137210Sbrian 171228679Sbrian case VAR_LOGIN: 171336285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 171436285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 171528679Sbrian break; 171637210Sbrian 171736285Sbrian case VAR_WINSIZE: 171836285Sbrian if (arg->argc > arg->argn) { 171936285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 172036285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 172136285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 172236285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 172336285Sbrian l->ccp.cfg.deflate.out.winsize); 172436285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 172536285Sbrian } 172636285Sbrian if (arg->argc > arg->argn+1) { 172736285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 172836285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 172936285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 173036285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 173136285Sbrian l->ccp.cfg.deflate.in.winsize); 173236285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 173336285Sbrian } 173436285Sbrian } else 173536285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 173636285Sbrian } else { 173779119Sbrian log_Printf(LogWARN, "No window size specified\n"); 173879119Sbrian res = 1; 173936285Sbrian } 174036285Sbrian break; 174137210Sbrian 174293418Sbrian#ifndef NODES 174378411Sbrian case VAR_MPPE: 174479119Sbrian if (arg->argc > arg->argn + 2) { 174579119Sbrian res = -1; 174679119Sbrian break; 174779119Sbrian } 174878411Sbrian 174978411Sbrian if (arg->argc == arg->argn) { 175078411Sbrian l->ccp.cfg.mppe.keybits = 0; 175178411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 175278411Sbrian l->ccp.cfg.mppe.required = 0; 175378411Sbrian break; 175478411Sbrian } 175578411Sbrian 175678411Sbrian if (!strcmp(argp, "*")) 175778411Sbrian long_val = 0; 175878411Sbrian else { 175978411Sbrian long_val = atol(argp); 176078411Sbrian if (long_val != 40 && long_val != 56 && long_val != 128) { 176178411Sbrian log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 176279119Sbrian res = -1; 176379119Sbrian break; 176467910Sbrian } 176567910Sbrian } 176678411Sbrian 176778411Sbrian if (arg->argc == arg->argn + 2) { 176878411Sbrian if (!strcmp(arg->argv[arg->argn + 1], "*")) 176978411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 177078411Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 177178411Sbrian l->ccp.cfg.mppe.state = MPPE_STATELESS; 177279370Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 177378411Sbrian l->ccp.cfg.mppe.state = MPPE_STATEFUL; 177478411Sbrian else { 177578411Sbrian log_Printf(LogWARN, "%s: Invalid state value\n", 177678411Sbrian arg->argv[arg->argn + 1]); 177779119Sbrian res = -1; 177879119Sbrian break; 177978411Sbrian } 178078411Sbrian } else 178178411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 178278411Sbrian l->ccp.cfg.mppe.keybits = long_val; 178378411Sbrian l->ccp.cfg.mppe.required = 1; 178467910Sbrian break; 178567910Sbrian#endif 178667910Sbrian 178728679Sbrian case VAR_DEVICE: 178836285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 178936285Sbrian arg->argv + arg->argn); 179036285Sbrian break; 179137210Sbrian 179236285Sbrian case VAR_ACCMAP: 179336285Sbrian if (arg->argc > arg->argn) { 179437210Sbrian u_long ulong_val; 179536285Sbrian sscanf(argp, "%lx", &ulong_val); 179637210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 179736285Sbrian } else { 179879119Sbrian log_Printf(LogWARN, "No accmap specified\n"); 179979119Sbrian res = 1; 180036285Sbrian } 180136285Sbrian break; 180237210Sbrian 180336285Sbrian case VAR_MODE: 180436285Sbrian mode = Nam2mode(argp); 180536285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 180636285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 180779119Sbrian res = -1; 180879119Sbrian break; 180936285Sbrian } 181036285Sbrian bundle_SetMode(arg->bundle, cx, mode); 181136285Sbrian break; 181237210Sbrian 181336285Sbrian case VAR_MRRU: 181440622Sbrian switch (bundle_Phase(arg->bundle)) { 181540622Sbrian case PHASE_DEAD: 181640622Sbrian break; 181740622Sbrian case PHASE_ESTABLISH: 181840622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 181940622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 182040622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 182179119Sbrian res = 1; 182279119Sbrian break; 182340622Sbrian } 182440622Sbrian break; 182540622Sbrian default: 182640622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 182779119Sbrian res = 1; 182879119Sbrian break; 182929696Sbrian } 183079119Sbrian if (res != 0) 183179119Sbrian break; 183237210Sbrian long_val = atol(argp); 183337210Sbrian if (long_val && long_val < MIN_MRU) { 183437210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 183579119Sbrian res = 1; 183679119Sbrian break; 183737210Sbrian } else if (long_val > MAX_MRU) { 183837210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 183979119Sbrian res = 1; 184079119Sbrian break; 184137210Sbrian } else 184237210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 184328679Sbrian break; 184437210Sbrian 184536285Sbrian case VAR_MRU: 184679163Sbrian long_val = 0; /* silence gcc */ 184779163Sbrian change = NULL; /* silence gcc */ 184878410Sbrian switch(arg->argc - arg->argn) { 184978410Sbrian case 1: 185079119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 185179119Sbrian res = -1; 185279119Sbrian break; 185379119Sbrian } 185479119Sbrian /*FALLTHRU*/ 185578410Sbrian case 0: 185678410Sbrian long_val = atol(argp); 185778410Sbrian change = &l->lcp.cfg.mru; 185878410Sbrian if (long_val > l->lcp.cfg.max_mru) { 185978410Sbrian log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 186078410Sbrian l->lcp.cfg.max_mru); 186179119Sbrian res = 1; 186279119Sbrian break; 186378410Sbrian } 186478410Sbrian break; 186578410Sbrian case 2: 186679119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 186779119Sbrian res = -1; 186879119Sbrian break; 186979119Sbrian } 187078410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 187178410Sbrian change = &l->lcp.cfg.max_mru; 187278410Sbrian if (long_val > MAX_MRU) { 187378410Sbrian log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 187478410Sbrian MAX_MRU); 187579119Sbrian res = 1; 187679119Sbrian break; 187778410Sbrian } 187878410Sbrian break; 187978410Sbrian default: 188079119Sbrian res = -1; 188179119Sbrian break; 188278410Sbrian } 188379119Sbrian if (res != 0) 188479119Sbrian break; 188578410Sbrian 188637210Sbrian if (long_val == 0) 188780385Sbrian *change = 0; 188837210Sbrian else if (long_val < MIN_MRU) { 188937210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 189079119Sbrian res = 1; 189179119Sbrian break; 189237210Sbrian } else if (long_val > MAX_MRU) { 189337210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 189479119Sbrian res = 1; 189579119Sbrian break; 189637210Sbrian } else 189778410Sbrian *change = long_val; 189878410Sbrian if (l->lcp.cfg.mru > *change) 189978410Sbrian l->lcp.cfg.mru = *change; 190028679Sbrian break; 190137210Sbrian 190236285Sbrian case VAR_MTU: 190379163Sbrian long_val = 0; /* silence gcc */ 190479163Sbrian change = NULL; /* silence gcc */ 190578410Sbrian switch(arg->argc - arg->argn) { 190678410Sbrian case 1: 190779119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 190879119Sbrian res = -1; 190979119Sbrian break; 191079119Sbrian } 191179119Sbrian /*FALLTHRU*/ 191278410Sbrian case 0: 191378410Sbrian long_val = atol(argp); 191478410Sbrian change = &l->lcp.cfg.mtu; 191578410Sbrian if (long_val > l->lcp.cfg.max_mtu) { 191678410Sbrian log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 191778410Sbrian l->lcp.cfg.max_mtu); 191879119Sbrian res = 1; 191979119Sbrian break; 192078410Sbrian } 192178410Sbrian break; 192278410Sbrian case 2: 192379119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 192479119Sbrian res = -1; 192579119Sbrian break; 192679119Sbrian } 192778410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 192878410Sbrian change = &l->lcp.cfg.max_mtu; 192978410Sbrian if (long_val > MAX_MTU) { 193078410Sbrian log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 193178410Sbrian MAX_MTU); 193279119Sbrian res = 1; 193379119Sbrian break; 193478410Sbrian } 193578410Sbrian break; 193678410Sbrian default: 193779119Sbrian res = -1; 193879119Sbrian break; 193978410Sbrian } 194078410Sbrian 194179119Sbrian if (res != 0) 194279119Sbrian break; 194379119Sbrian 194437210Sbrian if (long_val && long_val < MIN_MTU) { 194537210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 194679119Sbrian res = 1; 194779119Sbrian break; 194837210Sbrian } else if (long_val > MAX_MTU) { 194937210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 195079119Sbrian res = 1; 195179119Sbrian break; 195237210Sbrian } else 195378410Sbrian *change = long_val; 195478410Sbrian if (l->lcp.cfg.mtu > *change) 195578410Sbrian l->lcp.cfg.mtu = *change; 195636285Sbrian break; 195737210Sbrian 195836285Sbrian case VAR_OPENMODE: 195936285Sbrian if (strcasecmp(argp, "active") == 0) 196036285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 196136285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 196236285Sbrian else if (strcasecmp(argp, "passive") == 0) 196336285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 196436285Sbrian else { 196579119Sbrian log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 196679119Sbrian res = 1; 196736285Sbrian } 196836285Sbrian break; 196937210Sbrian 197028679Sbrian case VAR_PHONE: 197136285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 197236285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 197338174Sbrian cx->phone.alt = cx->phone.next = NULL; 197428679Sbrian break; 197537210Sbrian 197628679Sbrian case VAR_HANGUP: 197736285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 197836285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 197928679Sbrian break; 198037210Sbrian 198161534Sbrian case VAR_IFQUEUE: 198261534Sbrian long_val = atol(argp); 198361534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 198461534Sbrian break; 198561534Sbrian 198652488Sbrian case VAR_LOGOUT: 198752488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 198852488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 198952488Sbrian break; 199052488Sbrian 199136285Sbrian case VAR_IDLETIMEOUT: 199279119Sbrian if (arg->argc > arg->argn+2) { 199379119Sbrian log_Printf(LogWARN, "Too many idle timeout values\n"); 199479119Sbrian res = 1; 199579119Sbrian } else if (arg->argc == arg->argn) { 199679119Sbrian log_Printf(LogWARN, "Too few idle timeout values\n"); 199779119Sbrian res = 1; 199879119Sbrian } else { 199949978Sbrian int timeout, min; 200049978Sbrian 200149978Sbrian timeout = atoi(argp); 200249978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 200349978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 200449978Sbrian } 200529549Sbrian break; 200637210Sbrian 200736285Sbrian case VAR_LQRPERIOD: 200837210Sbrian long_val = atol(argp); 200937210Sbrian if (long_val < MIN_LQRPERIOD) { 201037210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 201137210Sbrian long_val, MIN_LQRPERIOD); 201279119Sbrian res = 1; 201336285Sbrian } else 201437210Sbrian l->lcp.cfg.lqrperiod = long_val; 201536285Sbrian break; 201637210Sbrian 201736285Sbrian case VAR_LCPRETRY: 201879119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 201979119Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 202079119Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 202179119Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 202236285Sbrian break; 202337210Sbrian 202436285Sbrian case VAR_CHAPRETRY: 202579119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 202679119Sbrian &cx->chap.auth.cfg.fsm.timeout, 202779119Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 202836285Sbrian break; 202937210Sbrian 203036285Sbrian case VAR_PAPRETRY: 203179119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 203279119Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 203379119Sbrian NULL, DEF_FSMAUTHTRIES); 203436285Sbrian break; 203537210Sbrian 203636285Sbrian case VAR_CCPRETRY: 203779119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 203879119Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 203979119Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 204036285Sbrian break; 204137210Sbrian 204236285Sbrian case VAR_IPCPRETRY: 204379119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 204479119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 204579119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 204679119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 204736285Sbrian break; 204837210Sbrian 204936285Sbrian case VAR_NBNS: 205036285Sbrian case VAR_DNS: 205158044Sbrian if (param == VAR_DNS) { 205281634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns; 205381634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE; 205458044Sbrian } else { 205581634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 205681634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY; 205758044Sbrian } 205836285Sbrian 205936285Sbrian if (arg->argc > arg->argn) { 206081634Sbrian ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]); 206181634Sbrian if (!ncpaddr_getip4(ncpaddr, ipaddr)) 206281634Sbrian return -1; 206381634Sbrian if (arg->argc > arg->argn+1) { 206481634Sbrian ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]); 206581634Sbrian if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1)) 206681634Sbrian return -1; 206781634Sbrian } 206836285Sbrian 206981634Sbrian if (ipaddr[0].s_addr == INADDR_ANY) { 207081634Sbrian ipaddr[0] = ipaddr[1]; 207181634Sbrian ipaddr[1].s_addr = INADDR_ANY; 207258044Sbrian } 207381634Sbrian if (ipaddr[0].s_addr == INADDR_NONE) { 207481634Sbrian ipaddr[0] = ipaddr[1]; 207581634Sbrian ipaddr[1].s_addr = INADDR_NONE; 207658044Sbrian } 207736285Sbrian } 207836285Sbrian break; 207938174Sbrian 208038174Sbrian case VAR_CALLBACK: 208138174Sbrian cx->cfg.callback.opmask = 0; 208238174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 208338174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 208438174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 208538174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 208638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 208738174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 208838174Sbrian if (dummyint == arg->argc - 1) 208938174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 209038174Sbrian else { 209138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 209238174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 209338174Sbrian sizeof cx->cfg.callback.msg - 1); 209438174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 209538174Sbrian } 209638174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 209738174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 209879119Sbrian else { 209979119Sbrian res = -1; 210079119Sbrian break; 210179119Sbrian } 210238174Sbrian } 210338174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 210438174Sbrian cx->cfg.callback.opmask = 0; 210538174Sbrian break; 210638174Sbrian 210738174Sbrian case VAR_CBCP: 210838174Sbrian cx->cfg.cbcp.delay = 0; 210938174Sbrian *cx->cfg.cbcp.phone = '\0'; 211038174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 211138174Sbrian if (arg->argc > arg->argn) { 211238174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 211338174Sbrian sizeof cx->cfg.cbcp.phone - 1); 211438174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 211538174Sbrian if (arg->argc > arg->argn + 1) { 211638174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 211738174Sbrian if (arg->argc > arg->argn + 2) { 211838174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 211938174Sbrian if (long_val < MIN_FSMRETRY) 212038174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 212138174Sbrian long_val, MIN_FSMRETRY); 212238174Sbrian else 212338174Sbrian cx->cfg.cbcp.fsmretry = long_val; 212438174Sbrian } 212538174Sbrian } 212638174Sbrian } 212738174Sbrian break; 212838544Sbrian 212938544Sbrian case VAR_CHOKED: 213038544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 213138544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 213238544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 213338544Sbrian break; 213440665Sbrian 213540665Sbrian case VAR_SENDPIPE: 213640665Sbrian long_val = atol(argp); 213781634Sbrian arg->bundle->ncp.cfg.sendpipe = long_val; 213840665Sbrian break; 213940665Sbrian 214040665Sbrian case VAR_RECVPIPE: 214140665Sbrian long_val = atol(argp); 214281634Sbrian arg->bundle->ncp.cfg.recvpipe = long_val; 214340665Sbrian break; 214443313Sbrian 214543313Sbrian#ifndef NORADIUS 214643313Sbrian case VAR_RADIUS: 214743313Sbrian if (!*argp) 214843313Sbrian *arg->bundle->radius.cfg.file = '\0'; 214943313Sbrian else if (access(argp, R_OK)) { 215043313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 215179119Sbrian res = 1; 215279119Sbrian break; 215343313Sbrian } else { 215443313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 215543313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 215643313Sbrian arg->bundle->radius.cfg.file 215743313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 215843313Sbrian } 215943313Sbrian break; 216043313Sbrian#endif 216144073Sbrian 216244073Sbrian case VAR_CD: 216344073Sbrian if (*argp) { 216451699Sbrian if (strcasecmp(argp, "off")) { 216551699Sbrian long_val = atol(argp); 216651699Sbrian if (long_val < 0) 216751699Sbrian long_val = 0; 216851699Sbrian cx->physical->cfg.cd.delay = long_val; 216951699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 217051699Sbrian CD_REQUIRED : CD_VARIABLE; 217151699Sbrian } else 217251699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 217344073Sbrian } else { 217453733Sbrian cx->physical->cfg.cd.delay = 0; 217553733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 217644073Sbrian } 217744073Sbrian break; 217836285Sbrian 217946686Sbrian case VAR_PARITY: 218046686Sbrian if (arg->argc == arg->argn + 1) 218179119Sbrian res = physical_SetParity(arg->cx->physical, argp); 218246686Sbrian else { 218379119Sbrian log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 218479119Sbrian res = 1; 218546686Sbrian } 218646686Sbrian break; 21876059Samurai 218846686Sbrian case VAR_CRTSCTS: 218946686Sbrian if (strcasecmp(argp, "on") == 0) 219036285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 219146686Sbrian else if (strcasecmp(argp, "off") == 0) 219236285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 219346686Sbrian else { 219479119Sbrian log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 219579119Sbrian res = 1; 219646686Sbrian } 219746686Sbrian break; 219850867Sbrian 219950867Sbrian case VAR_URGENTPORTS: 220051048Sbrian if (arg->argn == arg->argc) { 220181634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 220281634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 220381634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 220451048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 220581634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 220651048Sbrian if (arg->argn == arg->argc - 1) 220781634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 220851048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 220951048Sbrian if (*arg->argv[f] == '+') 221081634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 221151048Sbrian else if (*arg->argv[f] == '-') 221281634Sbrian ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 221351048Sbrian else { 221451048Sbrian if (f == arg->argn) 221581634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 221681634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 221751048Sbrian } 221861430Sbrian } else if (arg->argn == arg->argc - 1 && 221961430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 222081634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 222181634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 222281634Sbrian ncp_ClearUrgentTOS(&arg->bundle->ncp); 222351048Sbrian } else { 222481634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 222551048Sbrian first = arg->argn; 222651048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 222781634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 222851048Sbrian 222951048Sbrian for (f = first; f < arg->argc; f++) 223051048Sbrian if (*arg->argv[f] == '+') 223181634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 223251048Sbrian else if (*arg->argv[f] == '-') 223381634Sbrian ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 223451048Sbrian else { 223551048Sbrian if (f == first) 223681634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 223781634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 223851048Sbrian } 223951048Sbrian } 224050867Sbrian break; 224120812Sjkh } 224246686Sbrian 224379119Sbrian return res; 224420812Sjkh} 224520812Sjkh 224630715Sbrianstatic struct cmdtab const SetCommands[] = { 224736285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 224836285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 224928679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 225036285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 225128679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 225236285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 225336285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 225436285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 225536285Sbrian (const void *)VAR_AUTOLOAD}, 225650867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 225750867Sbrian "datalink bandwidth", "set bandwidth value"}, 225838174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 225938174Sbrian "callback control", "set callback [none|auth|cbcp|" 226038174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 226138174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 226238174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 226338174Sbrian (const void *)VAR_CBCP}, 226444305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 226544305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 226644073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 226744073Sbrian "set cd value[!]", (const void *)VAR_CD}, 226844305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 226944305Sbrian "CHAP retries", "set chapretry value [attempts]", 227044305Sbrian (const void *)VAR_CHAPRETRY}, 227138544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 227238544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 227346686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 227446686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 227546686Sbrian (const char *)VAR_CRTSCTS}, 227636285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 227736285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 227836285Sbrian (const void *) VAR_WINSIZE}, 227993418Sbrian#ifndef NODES 228067910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 228179370Sbrian "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 228278411Sbrian (const void *) VAR_MPPE}, 228367910Sbrian#endif 228436285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 228546686Sbrian "physical device name", "set device|line device-name[,device-name]", 228636285Sbrian (const void *) VAR_DEVICE}, 228736285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 228836285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 228936285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 229036285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 229136285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 229236285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 229336285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 229436285Sbrian "escape characters", "set escape hex-digit ..."}, 229536285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 229636285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 229781634Sbrian "[src_addr[/width]] [dst_addr[/width]] [proto " 229848142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 229936285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 230036285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 230136285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 230231343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 230361534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 230461534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 230544305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 230644305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 230744305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 230844305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 230936712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 231067916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 231158033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 231236285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 231336285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 231452488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 231552488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 231636285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 231736285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 231836285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 231936285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 232036285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 232136285Sbrian "set mrru value", (const void *)VAR_MRRU}, 232236285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 232378410Sbrian "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 232478410Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 232578410Sbrian "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 232636285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 232736285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 232836285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 232936285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 233044305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 233144305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 233246686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 233346686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 233436285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 233536285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 233640679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 233740679Sbrian "Process title", "set proctitle [value]"}, 233843313Sbrian#ifndef NORADIUS 233943313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 234043313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 234143313Sbrian#endif 234236285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 234336285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 234440665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 234540665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 234636285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 234744468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 234840665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 234940665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 235071657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 235171657Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 235236285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 235346686Sbrian "physical speed", "set speed value|sync"}, 235436285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 235536285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 235636285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 235736285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 235851048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 235951048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 236036285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 236136285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 236228679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 236331343Sbrian "Display this message", "set help|? [command]", SetCommands}, 236428679Sbrian {NULL, NULL, NULL}, 23656059Samurai}; 23666059Samurai 23676059Samuraistatic int 236831343SbrianSetCommand(struct cmdargs const *arg) 23696059Samurai{ 237036285Sbrian if (arg->argc > arg->argn) 237136285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 237236285Sbrian arg->prompt, arg->cx); 237336285Sbrian else if (arg->prompt) 237436285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 237558044Sbrian " syntax help.\n"); 23766059Samurai else 237736285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 237826516Sbrian 237926516Sbrian return 0; 23806059Samurai} 23816059Samurai 23826059Samuraistatic int 238331343SbrianAddCommand(struct cmdargs const *arg) 23846059Samurai{ 238581634Sbrian struct ncpaddr gw; 238681634Sbrian struct ncprange dest; 238781634Sbrian struct in_addr host; 238881634Sbrian int dest_default, gw_arg, addrs; 23896059Samurai 239036285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 239131598Sbrian return -1; 239231598Sbrian 239336285Sbrian addrs = 0; 239481634Sbrian dest_default = 0; 239581634Sbrian if (arg->argc == arg->argn + 2) { 239636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 239781634Sbrian dest_default = 1; 239831598Sbrian else { 239981634Sbrian if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn])) 240036285Sbrian return -1; 240136285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 240236285Sbrian addrs = ROUTE_DSTMYADDR; 240381634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7)) 240481634Sbrian addrs = ROUTE_DSTMYADDR6; 240536285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 240636285Sbrian addrs = ROUTE_DSTHISADDR; 240781634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8)) 240881634Sbrian addrs = ROUTE_DSTHISADDR6; 240958044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 241058044Sbrian addrs = ROUTE_DSTDNS0; 241158044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 241258044Sbrian addrs = ROUTE_DSTDNS1; 241331598Sbrian } 241481634Sbrian gw_arg = 1; 241534536Sbrian } else { 241636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 241736285Sbrian addrs = ROUTE_DSTMYADDR; 241881634Sbrian host = arg->bundle->ncp.ipcp.my_ip; 241936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 242036285Sbrian addrs = ROUTE_DSTHISADDR; 242181634Sbrian host = arg->bundle->ncp.ipcp.peer_ip; 242258044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 242358044Sbrian addrs = ROUTE_DSTDNS0; 242481634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[0]; 242558044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 242658044Sbrian addrs = ROUTE_DSTDNS1; 242781634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[1]; 242865263Sbrian } else { 242981634Sbrian host = GetIpAddr(arg->argv[arg->argn]); 243081634Sbrian if (host.s_addr == INADDR_NONE) { 243165263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 243265263Sbrian arg->argv[arg->argn]); 243365263Sbrian return -1; 243465263Sbrian } 243565263Sbrian } 243681634Sbrian ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1])); 243781634Sbrian gw_arg = 2; 24386059Samurai } 243936285Sbrian 244081634Sbrian if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) { 244181634Sbrian ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip); 244236285Sbrian addrs |= ROUTE_GWHISADDR; 244381634Sbrian#ifndef NOINET6 244481897Sbrian } else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) { 244581634Sbrian ncpaddr_copy(&gw, &arg->bundle->ncp.ipv6cp.hisaddr); 244681634Sbrian addrs |= ROUTE_GWHISADDR6; 244781634Sbrian#endif 244865263Sbrian } else { 244981634Sbrian if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) { 245065263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 245181634Sbrian arg->argv[arg->argn + gw_arg]); 245265263Sbrian return -1; 245365263Sbrian } 245465263Sbrian } 245536285Sbrian 245681634Sbrian if (dest_default) 245781634Sbrian ncprange_setdefault(&dest, ncpaddr_family(&gw)); 245881634Sbrian 245981634Sbrian if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0, 246081634Sbrian ((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0) 246143313Sbrian && addrs != ROUTE_STATIC) 246281634Sbrian route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw); 246336285Sbrian 246431598Sbrian return 0; 24656059Samurai} 24666059Samurai 24676059Samuraistatic int 246831343SbrianDeleteCommand(struct cmdargs const *arg) 24696059Samurai{ 247081634Sbrian struct ncprange dest; 247136285Sbrian int addrs; 24726059Samurai 247336285Sbrian if (arg->argc == arg->argn+1) { 247436285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 247536285Sbrian route_IfDelete(arg->bundle, 0); 247681634Sbrian route_DeleteAll(&arg->bundle->ncp.route); 247736285Sbrian } else { 247836285Sbrian addrs = 0; 247936285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 248081634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip); 248136285Sbrian addrs = ROUTE_DSTMYADDR; 248281634Sbrian#ifndef NOINET6 248381897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) { 248481634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr); 248581634Sbrian addrs = ROUTE_DSTMYADDR6; 248681634Sbrian#endif 248736285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 248881634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip); 248936285Sbrian addrs = ROUTE_DSTHISADDR; 249081634Sbrian#ifndef NOINET6 249181897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) { 249281634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr); 249381634Sbrian addrs = ROUTE_DSTHISADDR6; 249481634Sbrian#endif 249558044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 249681634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]); 249758044Sbrian addrs = ROUTE_DSTDNS0; 249858044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 249981634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]); 250058044Sbrian addrs = ROUTE_DSTDNS1; 250136285Sbrian } else { 250281634Sbrian ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]); 250336285Sbrian addrs = ROUTE_STATIC; 250436285Sbrian } 250581634Sbrian rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0); 250681634Sbrian route_Delete(&arg->bundle->ncp.route, addrs, &dest); 250731598Sbrian } 250834536Sbrian } else 250926516Sbrian return -1; 251026516Sbrian 251126516Sbrian return 0; 25126059Samurai} 25136059Samurai 251450059Sbrian#ifndef NONAT 251526031Sbrianstatic int 251658867SbrianNatEnable(struct cmdargs const *arg) 251726031Sbrian{ 251836285Sbrian if (arg->argc == arg->argn+1) { 251936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 252050059Sbrian if (!arg->bundle->NatEnabled) { 252146686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 252246686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 252350059Sbrian arg->bundle->NatEnabled = 1; 252446686Sbrian } 252537191Sbrian return 0; 252636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 252750059Sbrian arg->bundle->NatEnabled = 0; 252840561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 252940561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 253026516Sbrian return 0; 253126142Sbrian } 253235449Sbrian } 253336285Sbrian 253426516Sbrian return -1; 253526031Sbrian} 253626031Sbrian 253726031Sbrian 253826031Sbrianstatic int 253958867SbrianNatOption(struct cmdargs const *arg) 254026031Sbrian{ 254138559Sbrian long param = (long)arg->cmd->args; 254238559Sbrian 254336285Sbrian if (arg->argc == arg->argn+1) { 254436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 254550059Sbrian if (arg->bundle->NatEnabled) { 254637191Sbrian PacketAliasSetMode(param, param); 254728679Sbrian return 0; 254828679Sbrian } 254950059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 255036285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 255150059Sbrian if (arg->bundle->NatEnabled) { 255237191Sbrian PacketAliasSetMode(0, param); 255328679Sbrian return 0; 255428679Sbrian } 255550059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 255628679Sbrian } 255735449Sbrian } 255828679Sbrian return -1; 255926031Sbrian} 256050059Sbrian#endif /* #ifndef NONAT */ 256131121Sbrian 256231121Sbrianstatic int 256336285SbrianLinkCommand(struct cmdargs const *arg) 256436285Sbrian{ 256536285Sbrian if (arg->argc > arg->argn+1) { 256636285Sbrian char namelist[LINE_LEN]; 256736285Sbrian struct datalink *cx; 256836285Sbrian char *name; 256936285Sbrian int result = 0; 257036285Sbrian 257136285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 257236285Sbrian struct datalink *dl; 257336285Sbrian 257436285Sbrian cx = arg->bundle->links; 257536285Sbrian while (cx) { 257636285Sbrian /* Watch it, the command could be a ``remove'' */ 257736285Sbrian dl = cx->next; 257836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 257936285Sbrian arg->prompt, cx); 258036285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 258136285Sbrian if (cx == dl) 258236285Sbrian break; /* Pointer's still valid ! */ 258336285Sbrian } 258436285Sbrian } else { 258536285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 258636285Sbrian namelist[sizeof namelist - 1] = '\0'; 258736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 258836285Sbrian if (!bundle2datalink(arg->bundle, name)) { 258936285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 259036285Sbrian return 1; 259136285Sbrian } 259236285Sbrian 259336285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 259436285Sbrian namelist[sizeof namelist - 1] = '\0'; 259536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 259636285Sbrian cx = bundle2datalink(arg->bundle, name); 259736285Sbrian if (cx) 259836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 259936285Sbrian arg->prompt, cx); 260036285Sbrian else { 260136285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 260236285Sbrian result++; 260336285Sbrian } 260436285Sbrian } 260536285Sbrian } 260636285Sbrian return result; 260736285Sbrian } 260836285Sbrian 260995258Sdes log_Printf(LogWARN, "usage: %s\n", arg->cmd->syntax); 261036285Sbrian return 2; 261136285Sbrian} 261236285Sbrian 261336285Sbrianstruct link * 261436285Sbriancommand_ChooseLink(struct cmdargs const *arg) 261536285Sbrian{ 261636285Sbrian if (arg->cx) 261736285Sbrian return &arg->cx->physical->link; 261837210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 261936285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 262037210Sbrian if (dl) 262137210Sbrian return &dl->physical->link; 262236285Sbrian } 262337210Sbrian return &arg->bundle->ncp.mp.link; 262436285Sbrian} 262536285Sbrian 262636285Sbrianstatic const char * 262736285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 262836285Sbrian{ 262936285Sbrian const char *result; 263036285Sbrian 263136285Sbrian switch (*cmd) { 263236285Sbrian case 'A': 263336285Sbrian case 'a': 263436285Sbrian result = "accept"; 263536285Sbrian *keep = NEG_MYMASK; 263636285Sbrian *add = NEG_ACCEPTED; 263736285Sbrian break; 263836285Sbrian case 'D': 263936285Sbrian case 'd': 264036285Sbrian switch (cmd[1]) { 264136285Sbrian case 'E': 264236285Sbrian case 'e': 264336285Sbrian result = "deny"; 264436285Sbrian *keep = NEG_MYMASK; 264536285Sbrian *add = 0; 264636285Sbrian break; 264736285Sbrian case 'I': 264836285Sbrian case 'i': 264936285Sbrian result = "disable"; 265036285Sbrian *keep = NEG_HISMASK; 265136285Sbrian *add = 0; 265236285Sbrian break; 265336285Sbrian default: 265436285Sbrian return NULL; 265536285Sbrian } 265636285Sbrian break; 265736285Sbrian case 'E': 265836285Sbrian case 'e': 265936285Sbrian result = "enable"; 266036285Sbrian *keep = NEG_HISMASK; 266136285Sbrian *add = NEG_ENABLED; 266236285Sbrian break; 266336285Sbrian default: 266436285Sbrian return NULL; 266536285Sbrian } 266636285Sbrian 266736285Sbrian return result; 266836285Sbrian} 266936285Sbrian 267036285Sbrianstatic int 267136285SbrianOptSet(struct cmdargs const *arg) 267236285Sbrian{ 267337574Sbrian int bit = (int)(long)arg->cmd->args; 267436285Sbrian unsigned keep; /* Keep these bits */ 267536285Sbrian unsigned add; /* Add these bits */ 267636285Sbrian 267781697Sbrian if (ident_cmd(arg->argv[arg->argn - 2], &keep, &add) == NULL) 267836285Sbrian return 1; 267936285Sbrian 268081885Sbrian#ifndef NOINET6 268181697Sbrian if (add == NEG_ENABLED && bit == OPT_IPV6CP && !probe.ipv6_available) { 268281697Sbrian log_Printf(LogWARN, "IPv6 is not available on this machine\n"); 268381697Sbrian return 1; 268481697Sbrian } 268581885Sbrian#endif 268681697Sbrian 268736285Sbrian if (add) 268836285Sbrian arg->bundle->cfg.opt |= bit; 268936285Sbrian else 269036285Sbrian arg->bundle->cfg.opt &= ~bit; 269181697Sbrian 269236285Sbrian return 0; 269336285Sbrian} 269436285Sbrian 269536285Sbrianstatic int 269640561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 269740561Sbrian{ 269840561Sbrian unsigned save = arg->bundle->cfg.opt; 269940561Sbrian int result = OptSet(arg); 270040561Sbrian 270140561Sbrian if (result == 0) 270250059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 270340561Sbrian arg->bundle->cfg.opt = save; 270450059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 270540561Sbrian result = 2; 270640561Sbrian } 270740561Sbrian 270840561Sbrian return result; 270940561Sbrian} 271040561Sbrian 271140561Sbrianstatic int 271236285SbrianNegotiateSet(struct cmdargs const *arg) 271336285Sbrian{ 271437210Sbrian long param = (long)arg->cmd->args; 271536285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 271636285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 271736285Sbrian const char *cmd; 271836285Sbrian unsigned keep; /* Keep these bits */ 271936285Sbrian unsigned add; /* Add these bits */ 272036285Sbrian 272136285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 272236285Sbrian return 1; 272336285Sbrian 272436285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 272536285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 272636285Sbrian cmd, arg->cmd->name); 272736285Sbrian return 2; 272836285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 272936285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 273036285Sbrian cmd, arg->cmd->name, cx->name); 273136285Sbrian cx = NULL; 273236285Sbrian } 273336285Sbrian 273436285Sbrian switch (param) { 273536285Sbrian case NEG_ACFCOMP: 273636285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 273736285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 273836285Sbrian break; 273944106Sbrian case NEG_CHAP05: 274044106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 274144106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 274236285Sbrian break; 274393418Sbrian#ifndef NODES 274444106Sbrian case NEG_CHAP80: 274544106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 274644106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 274744106Sbrian break; 274844106Sbrian case NEG_CHAP80LM: 274944106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 275044106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 275144106Sbrian break; 275267910Sbrian case NEG_CHAP81: 275367910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 275467910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 275567910Sbrian break; 275667910Sbrian case NEG_MPPE: 275767910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 275867910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 275967910Sbrian break; 276044106Sbrian#endif 276136285Sbrian case NEG_DEFLATE: 276236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 276336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 276436285Sbrian break; 276536285Sbrian case NEG_DNS: 276636285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 276736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 276836285Sbrian break; 276947858Sbrian case NEG_ENDDISC: 277047858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 277147858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 277247858Sbrian break; 277336285Sbrian case NEG_LQR: 277436285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 277536285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 277636285Sbrian break; 277736285Sbrian case NEG_PAP: 277836285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 277936285Sbrian cx->physical->link.lcp.cfg.pap |= add; 278036285Sbrian break; 278136285Sbrian case NEG_PPPDDEFLATE: 278236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 278336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 278436285Sbrian break; 278536285Sbrian case NEG_PRED1: 278636285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 278736285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 278836285Sbrian break; 278936285Sbrian case NEG_PROTOCOMP: 279036285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 279136285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 279236285Sbrian break; 279336285Sbrian case NEG_SHORTSEQ: 279440622Sbrian switch (bundle_Phase(arg->bundle)) { 279540622Sbrian case PHASE_DEAD: 279640622Sbrian break; 279740622Sbrian case PHASE_ESTABLISH: 279840622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 279940622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 280040622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 280140622Sbrian " LCP negotiations\n"); 280240622Sbrian return 1; 280340622Sbrian } 280440622Sbrian break; 280540622Sbrian default: 280640622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 280740622Sbrian " DEAD/ESTABLISH\n"); 280840622Sbrian return 1; 280936285Sbrian } 281040622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 281140622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 281236285Sbrian break; 281336285Sbrian case NEG_VJCOMP: 281436285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 281536285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 281636285Sbrian break; 281736285Sbrian } 281836285Sbrian 281936285Sbrian return 0; 282036285Sbrian} 282136285Sbrian 282236285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 282362778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 282462778Sbrian "filter on PPPoUDP payloads", "disable|enable", 282562778Sbrian (const void *)OPT_FILTERDECAP}, 282636285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 282736285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 282840666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 282962778Sbrian "retain interface addresses", "disable|enable", 283062778Sbrian (const void *)OPT_IFACEALIAS}, 283181634Sbrian#ifndef NOINET6 283281634Sbrian {"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol", 283381634Sbrian "disable|enable", (const void *)OPT_IPCP}, 283481634Sbrian {"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol", 283581634Sbrian "disable|enable", (const void *)OPT_IPV6CP}, 283681634Sbrian#endif 283747689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 283847689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 283936285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 284036285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 284136285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 284236285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 284340665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 284436285Sbrian "disable|enable", (const void *)OPT_PROXY}, 284540665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 284640665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 284736285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 284836285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 284969303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 285069303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 285136285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 285236285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 285336285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 285436285Sbrian "disable|enable", (const void *)OPT_UTMP}, 285536285Sbrian 285681634Sbrian#ifndef NOINET6 285781634Sbrian#define OPT_MAX 13 /* accept/deny allowed below and not above */ 285881634Sbrian#else 285981634Sbrian#define OPT_MAX 11 286081634Sbrian#endif 286136285Sbrian 286236285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 286336285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 286436285Sbrian (const void *)NEG_ACFCOMP}, 286544106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 286636285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 286744106Sbrian (const void *)NEG_CHAP05}, 286893418Sbrian#ifndef NODES 286944106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 287044106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 287144106Sbrian (const void *)NEG_CHAP80}, 287244106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 287344106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 287444106Sbrian (const void *)NEG_CHAP80LM}, 287567910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 287667910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 287767910Sbrian (const void *)NEG_CHAP81}, 287867910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 287967910Sbrian "MPPE encryption", "accept|deny|disable|enable", 288067910Sbrian (const void *)NEG_MPPE}, 288144106Sbrian#endif 288236285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 288336285Sbrian "Deflate compression", "accept|deny|disable|enable", 288436285Sbrian (const void *)NEG_DEFLATE}, 288536285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 288636285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 288736285Sbrian (const void *)NEG_PPPDDEFLATE}, 288836285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 288936285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 289047858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 289147858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 289236285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 289336285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 289436285Sbrian (const void *)NEG_LQR}, 289536285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 289636285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 289736285Sbrian (const void *)NEG_PAP}, 289836285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 289936285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 290036285Sbrian (const void *)NEG_PRED1}, 290136285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 290236285Sbrian "Protocol field compression", "accept|deny|disable|enable", 290336285Sbrian (const void *)NEG_PROTOCOMP}, 290436285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 290536285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 290636285Sbrian (const void *)NEG_SHORTSEQ}, 290736285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 290836285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 290936285Sbrian (const void *)NEG_VJCOMP}, 291036285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 291136285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 291236285Sbrian NegotiateCommands}, 291336285Sbrian {NULL, NULL, NULL}, 291436285Sbrian}; 291536285Sbrian 291636285Sbrianstatic int 291736285SbrianNegotiateCommand(struct cmdargs const *arg) 291836285Sbrian{ 291936285Sbrian if (arg->argc > arg->argn) { 292036285Sbrian char const *argv[3]; 292136285Sbrian unsigned keep, add; 292236285Sbrian int n; 292336285Sbrian 292436285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 292536285Sbrian return -1; 292636285Sbrian argv[2] = NULL; 292736285Sbrian 292836285Sbrian for (n = arg->argn; n < arg->argc; n++) { 292936285Sbrian argv[1] = arg->argv[n]; 293036285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 293136285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 293236285Sbrian } 293336285Sbrian } else if (arg->prompt) 293436285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 293536285Sbrian arg->argv[arg->argn-1]); 293636285Sbrian else 293736285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 293836285Sbrian arg->argv[arg->argn] ); 293936285Sbrian 294036285Sbrian return 0; 294136285Sbrian} 294236285Sbrian 294336285Sbrianconst char * 294436285Sbriancommand_ShowNegval(unsigned val) 294536285Sbrian{ 294636285Sbrian switch (val&3) { 294736285Sbrian case 1: return "disabled & accepted"; 294836285Sbrian case 2: return "enabled & denied"; 294936285Sbrian case 3: return "enabled & accepted"; 295036285Sbrian } 295136285Sbrian return "disabled & denied"; 295236285Sbrian} 295336934Sbrian 295436934Sbrianstatic int 295536934SbrianClearCommand(struct cmdargs const *arg) 295636934Sbrian{ 295736934Sbrian struct pppThroughput *t; 295836934Sbrian struct datalink *cx; 295936934Sbrian int i, clear_type; 296036934Sbrian 296136934Sbrian if (arg->argc < arg->argn + 1) 296236934Sbrian return -1; 296336934Sbrian 296446686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 296536934Sbrian cx = arg->cx; 296636934Sbrian if (!cx) 296736934Sbrian cx = bundle2datalink(arg->bundle, NULL); 296836934Sbrian if (!cx) { 296946686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 297036934Sbrian return 1; 297136934Sbrian } 297264652Sbrian t = &cx->physical->link.stats.total; 297336934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 297436934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 297581634Sbrian#ifndef NOINET6 297681897Sbrian else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0) 297781634Sbrian t = &arg->bundle->ncp.ipv6cp.throughput; 297881634Sbrian#endif 297936934Sbrian else 298036934Sbrian return -1; 298136934Sbrian 298236934Sbrian if (arg->argc > arg->argn + 1) { 298336934Sbrian clear_type = 0; 298436934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 298536934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 298636934Sbrian clear_type |= THROUGHPUT_OVERALL; 298736934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 298836934Sbrian clear_type |= THROUGHPUT_CURRENT; 298936934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 299036934Sbrian clear_type |= THROUGHPUT_PEAK; 299136934Sbrian else 299236934Sbrian return -1; 299336934Sbrian } else 299436934Sbrian clear_type = THROUGHPUT_ALL; 299536934Sbrian 299636934Sbrian throughput_clear(t, clear_type, arg->prompt); 299736934Sbrian return 0; 299836934Sbrian} 299940561Sbrian 300040561Sbrianstatic int 300140561SbrianRunListCommand(struct cmdargs const *arg) 300240561Sbrian{ 300340561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 300440561Sbrian 300564801Sbrian#ifndef NONAT 300664801Sbrian if (arg->cmd->args == NatCommands && 300764801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 300864801Sbrian if (arg->prompt) 300965550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 301064801Sbrian else 301165550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 301264801Sbrian } 301364801Sbrian#endif 301464801Sbrian 301540561Sbrian if (arg->argc > arg->argn) 301640561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 301740561Sbrian arg->prompt, arg->cx); 301840561Sbrian else if (arg->prompt) 301940561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 302040561Sbrian " <option>' for syntax help.\n", cmd, cmd); 302140561Sbrian else 302240561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 302340561Sbrian 302440561Sbrian return 0; 302540561Sbrian} 302640561Sbrian 302740561Sbrianstatic int 302840561SbrianIfaceAddCommand(struct cmdargs const *arg) 302940561Sbrian{ 303081634Sbrian struct ncpaddr peer, addr; 303181634Sbrian struct ncprange ifa; 303281634Sbrian struct in_addr mask; 303381634Sbrian int n, how; 303440561Sbrian 303540664Sbrian if (arg->argc == arg->argn + 1) { 303681634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 303740561Sbrian return -1; 303881634Sbrian ncpaddr_init(&peer); 303940664Sbrian } else { 304040664Sbrian if (arg->argc == arg->argn + 2) { 304181634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 304240664Sbrian return -1; 304340664Sbrian n = 1; 304440664Sbrian } else if (arg->argc == arg->argn + 3) { 304581634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn])) 304640664Sbrian return -1; 304781634Sbrian if (ncpaddr_family(&addr) != AF_INET) 304840664Sbrian return -1; 304981634Sbrian ncprange_sethost(&ifa, &addr); 305081634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1])) 305181634Sbrian return -1; 305281634Sbrian if (!ncpaddr_getip4(&addr, &mask)) 305381634Sbrian return -1; 305481634Sbrian if (!ncprange_setip4mask(&ifa, mask)) 305581634Sbrian return -1; 305640664Sbrian n = 2; 305740664Sbrian } else 305840561Sbrian return -1; 305940561Sbrian 306081634Sbrian if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n])) 306140664Sbrian return -1; 306281634Sbrian 306381634Sbrian if (ncprange_family(&ifa) != ncpaddr_family(&peer)) { 306481634Sbrian log_Printf(LogWARN, "IfaceAddCommand: src and dst address families" 306581634Sbrian " differ\n"); 306681634Sbrian return -1; 306781634Sbrian } 306840664Sbrian } 306940561Sbrian 307040561Sbrian how = IFACE_ADD_LAST; 307140561Sbrian if (arg->cmd->args) 307240561Sbrian how |= IFACE_FORCE_ADD; 307340561Sbrian 307481634Sbrian return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how); 307540561Sbrian} 307640561Sbrian 307740561Sbrianstatic int 307840561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 307940561Sbrian{ 308081634Sbrian struct ncpaddr ifa; 308181634Sbrian struct in_addr ifa4; 308240561Sbrian int ok; 308340561Sbrian 308440561Sbrian if (arg->argc != arg->argn + 1) 308540561Sbrian return -1; 308640561Sbrian 308781634Sbrian if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn])) 308840561Sbrian return -1; 308940561Sbrian 309040561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 309181634Sbrian ncpaddr_getip4(&ifa, &ifa4) && 309281634Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) { 309340561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 309481634Sbrian ncpaddr_ntoa(&ifa)); 309540561Sbrian return 1; 309640561Sbrian } 309740561Sbrian 309881634Sbrian ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa); 309940561Sbrian if (!ok) { 310040561Sbrian if (arg->cmd->args) 310140561Sbrian ok = 1; 310240561Sbrian else if (arg->prompt) 310381634Sbrian prompt_Printf(arg->prompt, "%s: No such interface address\n", 310481634Sbrian ncpaddr_ntoa(&ifa)); 310540561Sbrian else 310681634Sbrian log_Printf(LogWARN, "%s: No such interface address\n", 310781634Sbrian ncpaddr_ntoa(&ifa)); 310840561Sbrian } 310940561Sbrian 311040561Sbrian return !ok; 311140561Sbrian} 311240561Sbrian 311340561Sbrianstatic int 311440561SbrianIfaceClearCommand(struct cmdargs const *arg) 311540561Sbrian{ 311681634Sbrian int family, how; 311740561Sbrian 311881634Sbrian family = 0; 311981634Sbrian if (arg->argc == arg->argn + 1) { 312081634Sbrian if (strcasecmp(arg->argv[arg->argn], "inet") == 0) 312181634Sbrian family = AF_INET; 312281634Sbrian#ifndef NOINET6 312381897Sbrian else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0) 312481634Sbrian family = AF_INET6; 312581634Sbrian#endif 312681634Sbrian else 312781634Sbrian return -1; 312881634Sbrian } else if (arg->argc != arg->argn) 312940561Sbrian return -1; 313040561Sbrian 313140941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 313240941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 313340561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 313481634Sbrian iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how); 313540561Sbrian 313640561Sbrian return 0; 313740561Sbrian} 313840679Sbrian 313940679Sbrianstatic int 314040679SbrianSetProcTitle(struct cmdargs const *arg) 314140679Sbrian{ 314240679Sbrian static char title[LINE_LEN]; 314386028Sbrian char *argv[MAXARGS]; 314486028Sbrian int argc = arg->argc - arg->argn; 314540679Sbrian 314640679Sbrian if (arg->argc == arg->argn) { 314764698Sbrian SetTitle(NULL); 314840679Sbrian return 0; 314940679Sbrian } 315040679Sbrian 315140679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 315240679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 315340679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 315440679Sbrian } 315547849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 315685991Sbrian Concatinate(title, sizeof title, argc, (const char *const *)argv); 315764698Sbrian SetTitle(title); 315885991Sbrian command_Free(argc, argv); 315940679Sbrian 316040679Sbrian return 0; 316140679Sbrian} 3162