command.c revision 81697
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 81697 2001-08-15 13:53:38Z brian $ 296059Samurai */ 3078189Sbrian 3143313Sbrian#include <sys/param.h> 3230715Sbrian#include <netinet/in_systm.h> 3326031Sbrian#include <netinet/in.h> 3430715Sbrian#include <netinet/ip.h> 3526031Sbrian#include <arpa/inet.h> 3630715Sbrian#include <sys/socket.h> 3726031Sbrian#include <net/route.h> 3830715Sbrian#include <netdb.h> 3936285Sbrian#include <sys/un.h> 4030715Sbrian 4138628Sbrian#include <ctype.h> 4230715Sbrian#include <errno.h> 4326516Sbrian#include <fcntl.h> 4430715Sbrian#include <paths.h> 4530715Sbrian#include <stdio.h> 4630715Sbrian#include <stdlib.h> 4730715Sbrian#include <string.h> 4830715Sbrian#include <sys/wait.h> 4930715Sbrian#include <termios.h> 5030715Sbrian#include <unistd.h> 5130715Sbrian 5250059Sbrian#ifndef NONAT 5358037Sbrian#ifdef LOCALNAT 5458037Sbrian#include "alias.h" 5558037Sbrian#else 5646086Sbrian#include <alias.h> 5739395Sbrian#endif 5839395Sbrian#endif 5958037Sbrian 6046686Sbrian#include "layer.h" 6137009Sbrian#include "defs.h" 6231343Sbrian#include "command.h" 6330715Sbrian#include "mbuf.h" 6430715Sbrian#include "log.h" 6530715Sbrian#include "timer.h" 666059Samurai#include "fsm.h" 6731690Sbrian#include "iplist.h" 6836285Sbrian#include "throughput.h" 6936285Sbrian#include "slcompress.h" 7038557Sbrian#include "lqr.h" 7138557Sbrian#include "hdlc.h" 7263484Sbrian#include "lcp.h" 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 16781634Sbrianconst char Version[] = "3.0.0"; 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{ 25863484Sbrian int f, pos; 25963484Sbrian 26063484Sbrian *arg->cx->physical->link.lcp.cfg.ident = '\0'; 26163484Sbrian 26263484Sbrian for (pos = 0, f = arg->argn; f < arg->argc; f++) 26363484Sbrian pos += snprintf(arg->cx->physical->link.lcp.cfg.ident + pos, 26463484Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident - pos, "%s%s", 26563484Sbrian f == arg->argn ? "" : " ", arg->argv[f]); 26663484Sbrian 26763484Sbrian return 0; 26863484Sbrian} 26963484Sbrian 27063484Sbrianstatic int 27163484SbrianSendIdentification(struct cmdargs const *arg) 27263484Sbrian{ 27363484Sbrian if (arg->cx->state < DATALINK_LCP) { 27463484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 27563484Sbrian return 2; 27663484Sbrian } 27763484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 27863484Sbrian} 27963484Sbrian 28063484Sbrianstatic int 28136285SbrianCloneCommand(struct cmdargs const *arg) 2826059Samurai{ 28336285Sbrian char namelist[LINE_LEN]; 28436285Sbrian char *name; 28536285Sbrian int f; 2866059Samurai 28736285Sbrian if (arg->argc == arg->argn) 28836285Sbrian return -1; 28936285Sbrian 29036285Sbrian namelist[sizeof namelist - 1] = '\0'; 29136285Sbrian for (f = arg->argn; f < arg->argc; f++) { 29236285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 29336285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 29436285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2956059Samurai } 29636285Sbrian 29736285Sbrian return 0; 2986059Samurai} 2996059Samurai 3006059Samuraistatic int 30136285SbrianRemoveCommand(struct cmdargs const *arg) 3026059Samurai{ 30336285Sbrian if (arg->argc != arg->argn) 30436285Sbrian return -1; 30511336Samurai 30636285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 30736285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 30836285Sbrian return 2; 3096059Samurai } 31026516Sbrian 31136285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 31236285Sbrian return 0; 31336285Sbrian} 31432711Sbrian 31536285Sbrianstatic int 31636285SbrianRenameCommand(struct cmdargs const *arg) 31736285Sbrian{ 31836285Sbrian if (arg->argc != arg->argn + 1) 31936285Sbrian return -1; 32031121Sbrian 32136285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 32236285Sbrian return 0; 32336285Sbrian 32436285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 32536285Sbrian arg->cx->name, arg->argv[arg->argn]); 32636285Sbrian return 1; 32736285Sbrian} 32836285Sbrian 32936285Sbrianint 33036285SbrianLoadCommand(struct cmdargs const *arg) 33136285Sbrian{ 33240797Sbrian const char *err; 33340797Sbrian int n, mode; 33436285Sbrian 33540797Sbrian mode = arg->bundle->phys_type.all; 33636285Sbrian 33740797Sbrian if (arg->argn < arg->argc) { 33840797Sbrian for (n = arg->argn; n < arg->argc; n++) 33940797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 34040797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 34140797Sbrian return 1; 34240797Sbrian } 34340797Sbrian 34440797Sbrian for (n = arg->argn; n < arg->argc; n++) { 34540797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34640797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 34740797Sbrian } 34840797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34940797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 35040797Sbrian log_Printf(LogWARN, "default: %s\n", err); 35136285Sbrian return 1; 35236285Sbrian } else { 35340797Sbrian bundle_SetLabel(arg->bundle, "default"); 35440797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 35540797Sbrian bundle_SetLabel(arg->bundle, "default"); 35636285Sbrian } 35740797Sbrian 35826516Sbrian return 0; 3596059Samurai} 3606059Samurai 36136285Sbrianint 36236285SbrianSaveCommand(struct cmdargs const *arg) 36336285Sbrian{ 36436285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 36536285Sbrian return 1; 36636285Sbrian} 36736285Sbrian 36810528Samuraistatic int 36936285SbrianDialCommand(struct cmdargs const *arg) 37028536Sbrian{ 37136285Sbrian int res; 37236285Sbrian 37336465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 37436465Sbrian || (!arg->cx && 37536928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 37636285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 37736285Sbrian " interactive links\n"); 37836285Sbrian return 1; 37934536Sbrian } 38036285Sbrian 38136285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 38236285Sbrian return res; 38336285Sbrian 38437993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 38536285Sbrian 38636285Sbrian return 0; 38728536Sbrian} 38828536Sbrian 38938628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 39038628Sbrian 39138628Sbrianstatic char * 39238628Sbrianstrstrword(char *big, const char *little) 39338628Sbrian{ 39438628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 39538628Sbrian char *pos; 39638628Sbrian int len; 39738628Sbrian 39838628Sbrian pos = big; 39938628Sbrian len = strlen(little); 40038628Sbrian 40138628Sbrian while ((pos = strstr(pos, little)) != NULL) 40247865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 40347865Sbrian pos++; 40447865Sbrian else if (pos != big && pos[-1] == '\\') 40547865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 40647865Sbrian else 40738628Sbrian break; 40838628Sbrian 40938628Sbrian return pos; 41038628Sbrian} 41138628Sbrian 41238628Sbrianstatic char * 41338628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 41438628Sbrian{ 41538628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 41638628Sbrian char *word, *ntgt; 41738628Sbrian int ltgt, loldstr, lnewstr, pos; 41838628Sbrian 41938628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 42038628Sbrian return tgt; 42138628Sbrian 42238628Sbrian ltgt = strlen(tgt) + 1; 42338628Sbrian loldstr = strlen(oldstr); 42438628Sbrian lnewstr = strlen(newstr); 42538628Sbrian do { 42638628Sbrian pos = word - tgt; 42738628Sbrian if (loldstr > lnewstr) 42838628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 42938628Sbrian if (loldstr != lnewstr) { 43038628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 43138628Sbrian if (ntgt == NULL) 43238628Sbrian break; /* Oh wonderful ! */ 43338628Sbrian word = ntgt + pos; 43438628Sbrian tgt = ntgt; 43538628Sbrian } 43638628Sbrian if (lnewstr > loldstr) 43738628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 43838628Sbrian bcopy(newstr, word, lnewstr); 43938628Sbrian } while ((word = strstrword(word, oldstr))); 44038628Sbrian 44138628Sbrian return tgt; 44238628Sbrian} 44338628Sbrian 44443888Sbrianvoid 44543888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 44647849Sbrian struct bundle *bundle, int inc0, pid_t pid) 44738628Sbrian{ 44838628Sbrian int arg; 44947849Sbrian char pidstr[12]; 45038628Sbrian 45141755Sbrian if (inc0) 45241755Sbrian arg = 0; /* Start at arg 0 */ 45341755Sbrian else { 45441755Sbrian nargv[0] = strdup(oargv[0]); 45541755Sbrian arg = 1; 45641755Sbrian } 45747849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 45841755Sbrian for (; arg < argc; arg++) { 45938629Sbrian nargv[arg] = strdup(oargv[arg]); 46038629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 46138628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 46281634Sbrian#ifndef NOINET6 46381634Sbrian nargv[arg] = subst(nargv[arg], "HISADDR6", 46481634Sbrian ncpaddr_ntoa(&bundle->ncp.ipv6cp.hisaddr)); 46581634Sbrian#endif 46638629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 46740561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 46838628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 46981634Sbrian#ifndef NOINET6 47081634Sbrian nargv[arg] = subst(nargv[arg], "MYADDR6", 47181634Sbrian ncpaddr_ntoa(&bundle->ncp.ipv6cp.myaddr)); 47281634Sbrian#endif 47338629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 47438629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 47538629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 47638629Sbrian bundle->ncp.mp.peer.enddisc.address, 47738629Sbrian bundle->ncp.mp.peer.enddisc.len)); 47838629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 47938629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 48038629Sbrian bundle->ncp.mp.cfg.enddisc.address, 48138629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 48247849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 48338629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 48458044Sbrian nargv[arg] = subst(nargv[arg], "DNS0", 48558044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); 48658044Sbrian nargv[arg] = subst(nargv[arg], "DNS1", 48758044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); 48863484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 48963484Sbrian nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 49038628Sbrian } 49138628Sbrian nargv[arg] = NULL; 49238628Sbrian} 49338628Sbrian 49428536Sbrianstatic int 49531343SbrianShellCommand(struct cmdargs const *arg, int bg) 49610528Samurai{ 49710528Samurai const char *shell; 49847849Sbrian pid_t shpid, pid; 49920813Sjkh 50018856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 50126911Sbrian /* we're only allowed to shell when we run ppp interactively */ 50236285Sbrian if (arg->prompt && arg->prompt->owner) { 50336285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 50426516Sbrian return 1; 50510528Samurai } 50626911Sbrian#endif 50728679Sbrian 50836285Sbrian if (arg->argc == arg->argn) { 50936285Sbrian if (!arg->prompt) { 51036285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 51136285Sbrian " a config file\n"); 51228381Sbrian return 1; 51336285Sbrian } else if (arg->prompt->owner) { 51436285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 51536285Sbrian " a socket connection\n"); 51636285Sbrian return 1; 51728381Sbrian } else if (bg) { 51836285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 51928679Sbrian " the foreground mode\n"); 52028381Sbrian return 1; 52128381Sbrian } 52234536Sbrian } 52334536Sbrian 52447849Sbrian pid = getpid(); 52528679Sbrian if ((shpid = fork()) == 0) { 52636285Sbrian int i, fd; 52718531Sbde 52836285Sbrian if ((shell = getenv("SHELL")) == 0) 52936285Sbrian shell = _PATH_BSHELL; 53032017Sbrian 53136285Sbrian timer_TermService(); 53236285Sbrian 53336285Sbrian if (arg->prompt) 53436285Sbrian fd = arg->prompt->fd_out; 53536285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 53636285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 53736285Sbrian _PATH_DEVNULL, strerror(errno)); 53828679Sbrian exit(1); 53928679Sbrian } 54049976Sbrian dup2(fd, STDIN_FILENO); 54149976Sbrian dup2(fd, STDOUT_FILENO); 54249976Sbrian dup2(fd, STDERR_FILENO); 54349976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 54449976Sbrian fcntl(i, F_SETFD, 1); 54526516Sbrian 54664802Sbrian#ifndef NOSUID 54755252Sbrian setuid(ID0realuid()); 54864802Sbrian#endif 54936285Sbrian if (arg->argc > arg->argn) { 55028679Sbrian /* substitute pseudo args */ 55138628Sbrian char *argv[MAXARGS]; 55238628Sbrian int argc = arg->argc - arg->argn; 55338628Sbrian 55438628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 55538628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 55638628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 55731343Sbrian } 55847849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 55928679Sbrian if (bg) { 56028679Sbrian pid_t p; 56110528Samurai 56228679Sbrian p = getpid(); 56328679Sbrian if (daemon(1, 1) == -1) { 56436832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 56528679Sbrian exit(1); 56628679Sbrian } 56736285Sbrian } else if (arg->prompt) 56836285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 56931343Sbrian execvp(argv[0], argv); 57030316Sbrian } else { 57136285Sbrian if (arg->prompt) 57232017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 57336285Sbrian prompt_TtyOldMode(arg->prompt); 57479450Sbrian execl(shell, shell, (char *)NULL); 57530316Sbrian } 57620813Sjkh 57740665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 57840665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 57940665Sbrian strerror(errno)); 58049976Sbrian _exit(255); 58110528Samurai } 58236285Sbrian 58336285Sbrian if (shpid == (pid_t) - 1) 58436285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 58536285Sbrian else { 58610528Samurai int status; 58731343Sbrian waitpid(shpid, &status, 0); 58810528Samurai } 58920813Sjkh 59036285Sbrian if (arg->prompt && !arg->prompt->owner) 59136285Sbrian prompt_TtyCommandMode(arg->prompt); 59220813Sjkh 59336285Sbrian return 0; 59410528Samurai} 59510528Samurai 59631343Sbrianstatic int 59731343SbrianBgShellCommand(struct cmdargs const *arg) 59831343Sbrian{ 59936285Sbrian if (arg->argc == arg->argn) 60031343Sbrian return -1; 60131343Sbrian return ShellCommand(arg, 1); 60231343Sbrian} 60331343Sbrian 60431343Sbrianstatic int 60531343SbrianFgShellCommand(struct cmdargs const *arg) 60631343Sbrian{ 60731343Sbrian return ShellCommand(arg, 0); 60831343Sbrian} 60931343Sbrian 61058044Sbrianstatic int 61158044SbrianResolvCommand(struct cmdargs const *arg) 61258044Sbrian{ 61358044Sbrian if (arg->argc == arg->argn + 1) { 61458044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 61558044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 61658044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 61758044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 61858044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 61958044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 62058044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 62158044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 62258044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 62358044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 62458044Sbrian else 62558044Sbrian return -1; 62658044Sbrian 62758044Sbrian return 0; 62858044Sbrian } 62958044Sbrian 63058044Sbrian return -1; 63158044Sbrian} 63258044Sbrian 63350059Sbrian#ifndef NONAT 63458867Sbrianstatic struct cmdtab const NatCommands[] = 63540561Sbrian{ 63650059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 63750059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 63858867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 63950059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 64040561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 64158867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 64250059Sbrian "enable NAT", "nat enable yes|no"}, 64358867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 64450059Sbrian "log NAT link creation", "nat log yes|no", 64540561Sbrian (const void *) PKT_ALIAS_LOG}, 64650059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 64750059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 64879433Sbrian {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 64979433Sbrian "nat proto proto localIP [publicIP [remoteIP]]"}, 65050059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 65150059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 65281033Sbrian#ifndef NO_FW_PUNCH 65381033Sbrian {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 65481033Sbrian "firewall control", "nat punch_fw [base count]"}, 65581033Sbrian#endif 65658867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 65750059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 65840561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 65958867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 66058867Sbrian "Default address for incoming connections", "nat target addr" }, 66158867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 66250059Sbrian "translate unregistered (private) IP address space only", 66350059Sbrian "nat unregistered_only yes|no", 66440561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 66558867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 66650059Sbrian "allocate host sockets", "nat use_sockets yes|no", 66740561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 66840561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 66958867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 67040561Sbrian {NULL, NULL, NULL}, 67140561Sbrian}; 67240561Sbrian#endif 67340561Sbrian 67440561Sbrianstatic struct cmdtab const AllowCommands[] = { 67540561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 67640561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 67740561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 67840561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 67940561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 68040561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 68140561Sbrian {NULL, NULL, NULL}, 68240561Sbrian}; 68340561Sbrian 68440561Sbrianstatic struct cmdtab const IfaceCommands[] = 68540561Sbrian{ 68640561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 68740561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 68840561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 68940561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 69040561Sbrian (void *)1}, 69140561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 69281634Sbrian "Clear iface address(es)", "iface clear [INET | INET6]"}, 69340561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 69440561Sbrian "Delete iface address", "iface delete addr", NULL}, 69540561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 69640561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 69740561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 69840561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 69940561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 70040561Sbrian "Show iface address(es)", "iface show"}, 70140561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 70250059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 70340561Sbrian {NULL, NULL, NULL}, 70440561Sbrian}; 70540561Sbrian 70630715Sbrianstatic struct cmdtab const Commands[] = { 70736285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70828679Sbrian "accept option request", "accept option .."}, 70928679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 71032109Sbrian "add route", "add dest mask gateway", NULL}, 71136285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 71232109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 71340561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 71440561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 71528679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 71631372Sbrian "Run a background command", "[!]bg command"}, 71736934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71846686Sbrian "Clear throughput statistics", 71981634Sbrian "clear ipcp|ipv6cp|physical [current|overall|peak]..."}, 72036285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 72136285Sbrian "Clone a link", "clone newname..."}, 72236285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 72336285Sbrian "Close an FSM", "close [lcp|ccp]"}, 72428679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 72532109Sbrian "delete route", "delete dest", NULL}, 72636285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 72732109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 72836285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 72928679Sbrian "Deny option request", "deny option .."}, 73036285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 73140797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 73236285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 73328679Sbrian "Disable option", "disable option .."}, 73436285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 73546686Sbrian "Generate a down event", "down [ccp|lcp]"}, 73636285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 73728679Sbrian "Enable option", "enable option .."}, 73863484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 73963484Sbrian "Set the link identity", "ident text..."}, 74040561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 74140561Sbrian "interface control", "iface option ...", IfaceCommands}, 74236285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 74336285Sbrian "Link specific commands", "link name command ..."}, 74437008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 74540797Sbrian "Load settings", "load [system ...]"}, 74650059Sbrian#ifndef NONAT 74750059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 74858867Sbrian "NAT control", "nat option yes|no", NatCommands}, 74950059Sbrian#endif 75036285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 75137955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 75236285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 75336285Sbrian "Password for manipulation", "passwd LocalPassword"}, 75436285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 75536285Sbrian "Quit PPP program", "quit|bye [all]"}, 75636285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 75736285Sbrian "Remove a link", "remove"}, 75836285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 75936285Sbrian "Rename a link", "rename name"}, 76058044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 76158044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 76228679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 76328679Sbrian "Save settings", "save"}, 76463484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 76563484Sbrian "Transmit the link identity", "sendident"}, 76636285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 76728679Sbrian "Set parameters", "set[up] var value"}, 76828679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 76928679Sbrian "Run a subshell", "shell|! [sh command]"}, 77036285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 77131372Sbrian "Show status and stats", "show var"}, 77236285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 77331372Sbrian "Enter terminal mode", "term"}, 77428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 77531343Sbrian "Display this message", "help|? [command]", Commands}, 77628679Sbrian {NULL, NULL, NULL}, 7776059Samurai}; 7786059Samurai 77928536Sbrianstatic int 78031343SbrianShowEscape(struct cmdargs const *arg) 7816059Samurai{ 78236285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 78336285Sbrian int code, bit; 78436285Sbrian const char *sep = ""; 7856059Samurai 78626516Sbrian for (code = 0; code < 32; code++) 78736285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 78828679Sbrian for (bit = 0; bit < 8; bit++) 78936285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 79036285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 79136285Sbrian sep = ", "; 79236285Sbrian } 79336285Sbrian prompt_Printf(arg->prompt, "\n"); 7946059Samurai } 79531077Sbrian return 0; 7966059Samurai} 7976059Samurai 79828679Sbrianstatic int 79936285SbrianShowTimerList(struct cmdargs const *arg) 8006059Samurai{ 80136285Sbrian timer_Show(0, arg->prompt); 80231077Sbrian return 0; 8036059Samurai} 8046059Samurai 80528679Sbrianstatic int 80631343SbrianShowStopped(struct cmdargs const *arg) 80728327Sbrian{ 80836285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 80936285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 81036285Sbrian prompt_Printf(arg->prompt, "Disabled"); 81128327Sbrian else 81236285Sbrian prompt_Printf(arg->prompt, "%ld secs", 81336285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 81428461Sbrian 81536285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 81636285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 81736285Sbrian prompt_Printf(arg->prompt, "Disabled"); 81828461Sbrian else 81936285Sbrian prompt_Printf(arg->prompt, "%ld secs", 82036285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 82128461Sbrian 82236285Sbrian prompt_Printf(arg->prompt, "\n"); 82328461Sbrian 82431077Sbrian return 0; 82528327Sbrian} 82628327Sbrian 82728679Sbrianstatic int 82831343SbrianShowVersion(struct cmdargs const *arg) 8296059Samurai{ 83051026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 83131077Sbrian return 0; 8326059Samurai} 8336059Samurai 83428679Sbrianstatic int 83536285SbrianShowProtocolStats(struct cmdargs const *arg) 83626326Sbrian{ 83736285Sbrian struct link *l = command_ChooseLink(arg); 83826326Sbrian 83936285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 84036285Sbrian link_ReportProtocolStatus(l, arg->prompt); 84131077Sbrian return 0; 84226326Sbrian} 84326326Sbrian 84430715Sbrianstatic struct cmdtab const ShowCommands[] = { 84536285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 84636285Sbrian "bundle details", "show bundle"}, 84736285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 84836285Sbrian "CCP status", "show cpp"}, 84936285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 85036285Sbrian "VJ compression stats", "show compress"}, 85136285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 85236285Sbrian "escape characters", "show escape"}, 85336285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 85436285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 85536285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 85636285Sbrian "HDLC errors", "show hdlc"}, 85740561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 85840561Sbrian "Interface status", "show iface"}, 85936285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 86036285Sbrian "IPCP status", "show ipcp"}, 86181634Sbrian#ifndef NOINET6 86281634Sbrian {"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH, 86381634Sbrian "IPV6CP status", "show ipv6cp"}, 86481634Sbrian#endif 86547211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 86647211Sbrian "Protocol layers", "show layers"}, 86736285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 86836285Sbrian "LCP status", "show lcp"}, 86936285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 87036285Sbrian "(high-level) link info", "show link"}, 87136285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 87236285Sbrian "available link names", "show links"}, 87336285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 87436285Sbrian "log levels", "show log"}, 87536285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 87636285Sbrian "mbuf allocations", "show mem"}, 87781634Sbrian {"ncp", NULL, ncp_Show, LOCAL_AUTH, 87881634Sbrian "NCP status", "show ncp"}, 87946686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 88046686Sbrian "(low-level) link info", "show physical"}, 88136285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 88236285Sbrian "multilink setup", "show mp"}, 88336285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 88436285Sbrian "protocol summary", "show proto"}, 88536285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 88636285Sbrian "routing table", "show route"}, 88736285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 88836285Sbrian "STOPPED timeout", "show stopped"}, 88936285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 89036285Sbrian "alarm timers", "show timers"}, 89128679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 89236285Sbrian "version string", "show version"}, 89336285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 89436285Sbrian "client list", "show who"}, 89528679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 89631343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 89728679Sbrian {NULL, NULL, NULL}, 8986059Samurai}; 8996059Samurai 90030715Sbrianstatic struct cmdtab const * 90131343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 9026059Samurai{ 90326516Sbrian int nmatch; 90426516Sbrian int len; 90528679Sbrian struct cmdtab const *found; 9066059Samurai 90726516Sbrian found = NULL; 90826516Sbrian len = strlen(str); 90926516Sbrian nmatch = 0; 9106059Samurai while (cmds->func) { 91125566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 91226516Sbrian if (cmds->name[len] == '\0') { 91328679Sbrian *pmatch = 1; 91428679Sbrian return cmds; 91526516Sbrian } 9166059Samurai nmatch++; 9176059Samurai found = cmds; 91828679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 91926516Sbrian if (cmds->alias[len] == '\0') { 92028679Sbrian *pmatch = 1; 92128679Sbrian return cmds; 92226516Sbrian } 9236059Samurai nmatch++; 9246059Samurai found = cmds; 9256059Samurai } 9266059Samurai cmds++; 9276059Samurai } 9286059Samurai *pmatch = nmatch; 92926516Sbrian return found; 9306059Samurai} 9316059Samurai 93236285Sbrianstatic const char * 93336285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 93436285Sbrian{ 93536285Sbrian int f, tlen, len; 93636285Sbrian 93736285Sbrian tlen = 0; 93836285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 93936285Sbrian if (f) 94036285Sbrian tgt[tlen++] = ' '; 94136285Sbrian len = strlen(argv[f]); 94236285Sbrian if (len > sz - tlen - 1) 94336285Sbrian len = sz - tlen - 1; 94436285Sbrian strncpy(tgt+tlen, argv[f], len); 94536285Sbrian tlen += len; 94636285Sbrian } 94736285Sbrian tgt[tlen] = '\0'; 94836285Sbrian return tgt; 94936285Sbrian} 95036285Sbrian 95130715Sbrianstatic int 95236285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 95336285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 9546059Samurai{ 95528679Sbrian struct cmdtab const *cmd; 9566059Samurai int val = 1; 9576059Samurai int nmatch; 95831343Sbrian struct cmdargs arg; 95936285Sbrian char prefix[100]; 9606059Samurai 96136285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 9626059Samurai if (nmatch > 1) 96336285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 96436285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 96536285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 96636285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 96736285Sbrian /* We've got no context, but we require it */ 96836285Sbrian cx = bundle2datalink(bundle, NULL); 96936285Sbrian 97036285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 97136285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 97236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 97336285Sbrian else { 97436285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 97536285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 97636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 97736285Sbrian cx = NULL; 97836285Sbrian } 97936285Sbrian arg.cmdtab = cmds; 98036285Sbrian arg.cmd = cmd; 98136285Sbrian arg.argc = argc; 98236285Sbrian arg.argn = argn+1; 98336285Sbrian arg.argv = argv; 98436285Sbrian arg.bundle = bundle; 98536285Sbrian arg.cx = cx; 98636285Sbrian arg.prompt = prompt; 98736285Sbrian val = (*cmd->func) (&arg); 98836285Sbrian } 98931343Sbrian } else 99036285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 99136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 99226516Sbrian 99326516Sbrian if (val == -1) 99436285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 99528679Sbrian else if (val) 99636285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 99736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 99826516Sbrian 99926516Sbrian return val; 10006059Samurai} 10016059Samurai 100237009Sbrianint 100358045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 100458045Sbrian{ 100558045Sbrian char buff2[LINE_LEN-offset]; 100658045Sbrian 100758045Sbrian InterpretArg(buff, buff2); 100858045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 100958045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 101058045Sbrian 101158045Sbrian return command_Interpret(buff, nb, argv); 101258045Sbrian} 101358045Sbrian 101458045Sbrianint 101537009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 10166059Samurai{ 10176059Samurai char *cp; 10186059Samurai 10196059Samurai if (nb > 0) { 10206059Samurai cp = buff + strcspn(buff, "\r\n"); 10216059Samurai if (cp) 10226059Samurai *cp = '\0'; 102355145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 102437009Sbrian } 102537009Sbrian return 0; 102631121Sbrian} 10276059Samurai 102831822Sbrianstatic int 102931822Sbrianarghidden(int argc, char const *const *argv, int n) 103031822Sbrian{ 103131822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 103231828Sbrian 103331828Sbrian /* set authkey xxxxx */ 103431828Sbrian /* set key xxxxx */ 103531822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 103631822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 103731822Sbrian return 1; 103831822Sbrian 103931828Sbrian /* passwd xxxxx */ 104031828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 104131828Sbrian return 1; 104231828Sbrian 104336285Sbrian /* set server port xxxxx .... */ 104436285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 104536285Sbrian !strncasecmp(argv[1], "se", 2)) 104636285Sbrian return 1; 104736285Sbrian 104831822Sbrian return 0; 104931822Sbrian} 105031822Sbrian 105131121Sbrianvoid 105236285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 105337008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 105431121Sbrian{ 105531156Sbrian if (argc > 0) { 105636285Sbrian if (log_IsKept(LogCOMMAND)) { 105747844Sbrian char buf[LINE_LEN]; 105831156Sbrian int f, n; 105931156Sbrian 106031156Sbrian if (label) { 106131962Sbrian strncpy(buf, label, sizeof buf - 3); 106231962Sbrian buf[sizeof buf - 3] = '\0'; 106331156Sbrian strcat(buf, ": "); 106447844Sbrian n = strlen(buf); 106547844Sbrian } else { 106647844Sbrian *buf = '\0'; 106747844Sbrian n = 0; 106831156Sbrian } 106947844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 107047844Sbrian 107131156Sbrian for (f = 0; f < argc; f++) { 107231962Sbrian if (n < sizeof buf - 1 && f) 107331156Sbrian buf[n++] = ' '; 107431822Sbrian if (arghidden(argc, argv, f)) 107536285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 107631822Sbrian else 107731962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 107831156Sbrian n += strlen(buf+n); 107931156Sbrian } 108036285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 108131156Sbrian } 108237008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 108331156Sbrian } 10846059Samurai} 10856059Samurai 108654914Sbrianint 108736285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 108836285Sbrian const char *label) 108931121Sbrian{ 109031121Sbrian int argc; 109137009Sbrian char *argv[MAXARGS]; 109231121Sbrian 109358045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 109454914Sbrian return 0; 109554914Sbrian 109637008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 109754914Sbrian return 1; 109831121Sbrian} 109931121Sbrian 11006059Samuraistatic int 110131343SbrianShowCommand(struct cmdargs const *arg) 11026059Samurai{ 110336285Sbrian if (!arg->prompt) 110436285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 110536285Sbrian else if (arg->argc > arg->argn) 110636285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 110736285Sbrian arg->prompt, arg->cx); 11086059Samurai else 110936285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 111026516Sbrian 111126516Sbrian return 0; 11126059Samurai} 11136059Samurai 11146059Samuraistatic int 111531343SbrianTerminalCommand(struct cmdargs const *arg) 11166059Samurai{ 111736285Sbrian if (!arg->prompt) { 111836285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 111926516Sbrian return 1; 11206059Samurai } 112136285Sbrian 112236285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 112336285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 112436285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 112536285Sbrian return 1; 11266059Samurai } 112736285Sbrian 112836285Sbrian datalink_Up(arg->cx, 0, 0); 112936285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 113036285Sbrian return 0; 11316059Samurai} 11326059Samurai 11336059Samuraistatic int 113431343SbrianQuitCommand(struct cmdargs const *arg) 11356059Samurai{ 113636285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 113736285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 113836285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 113936285Sbrian Cleanup(EX_NORMAL); 114036285Sbrian if (arg->prompt) 114136285Sbrian prompt_Destroy(arg->prompt, 1); 114226516Sbrian 114326516Sbrian return 0; 11446059Samurai} 11456059Samurai 11466059Samuraistatic int 114736285SbrianOpenCommand(struct cmdargs const *arg) 11486059Samurai{ 114937160Sbrian if (arg->argc == arg->argn) 115037993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 115137160Sbrian else if (arg->argc == arg->argn + 1) { 115237160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 115337385Sbrian struct datalink *cx = arg->cx ? 115437385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 115537385Sbrian if (cx) { 115637385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 115737385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 115837160Sbrian else 115937993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 116037160Sbrian } else 116137160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 116237160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 116337160Sbrian struct fsm *fp; 11646059Samurai 116537210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 116637160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 116737160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 116837160Sbrian else if (fp->state == ST_OPENED) 116937160Sbrian fsm_Reopen(fp); 117037160Sbrian else { 117137160Sbrian fp->open_mode = 0; /* Not passive any more */ 117237160Sbrian if (fp->state == ST_STOPPED) { 117337160Sbrian fsm_Down(fp); 117437160Sbrian fsm_Up(fp); 117537160Sbrian } else { 117637160Sbrian fsm_Up(fp); 117737160Sbrian fsm_Open(fp); 117837160Sbrian } 117936285Sbrian } 118037160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 118137160Sbrian if (arg->cx) 118237160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 118337160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 118437160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 118537160Sbrian else 118637993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 118737160Sbrian } else 118837160Sbrian return -1; 118936285Sbrian } else 119036285Sbrian return -1; 119136285Sbrian 119226516Sbrian return 0; 11936059Samurai} 11946059Samurai 119525067Sbrianstatic int 119636285SbrianCloseCommand(struct cmdargs const *arg) 11976059Samurai{ 119837007Sbrian if (arg->argc == arg->argn) 119937007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 120037007Sbrian else if (arg->argc == arg->argn + 1) { 120137007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 120237007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 120337007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 120437007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 120537007Sbrian struct fsm *fp; 12066059Samurai 120737210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 120837007Sbrian if (fp->state == ST_OPENED) { 120937007Sbrian fsm_Close(fp); 121037007Sbrian if (arg->argv[arg->argn][3] == '!') 121137007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 121237007Sbrian else 121337007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 121437007Sbrian } 121537007Sbrian } else 121636285Sbrian return -1; 121736285Sbrian } else 121836285Sbrian return -1; 121936285Sbrian 122036285Sbrian return 0; 12216059Samurai} 12226059Samurai 122325067Sbrianstatic int 122436285SbrianDownCommand(struct cmdargs const *arg) 122511336Samurai{ 122637018Sbrian if (arg->argc == arg->argn) { 122737018Sbrian if (arg->cx) 122837018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 122937018Sbrian else 123037018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 123137018Sbrian } else if (arg->argc == arg->argn + 1) { 123237018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 123337018Sbrian if (arg->cx) 123437018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 123537018Sbrian else 123637018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 123737018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 123837018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 123937018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 124037060Sbrian fsm2initial(fp); 124137018Sbrian } else 124237018Sbrian return -1; 124336285Sbrian } else 124436285Sbrian return -1; 124536285Sbrian 124636285Sbrian return 0; 124725067Sbrian} 124825067Sbrian 124925067Sbrianstatic int 125036285SbrianSetModemSpeed(struct cmdargs const *arg) 125125067Sbrian{ 125236285Sbrian long speed; 125336285Sbrian char *end; 125411336Samurai 125536285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 125636285Sbrian if (arg->argc > arg->argn+1) { 125754917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 125836285Sbrian return -1; 125911336Samurai } 126036285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 126136285Sbrian physical_SetSync(arg->cx->physical); 126236285Sbrian return 0; 126336285Sbrian } 126436285Sbrian end = NULL; 126536285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 126636285Sbrian if (*end) { 126736285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 126836285Sbrian arg->argv[arg->argn]); 126936285Sbrian return -1; 127036285Sbrian } 127136285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 127236285Sbrian return 0; 127336285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 127436285Sbrian } else 127536285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 127624939Sbrian 127726516Sbrian return -1; 127811336Samurai} 127911336Samurai 128025067Sbrianstatic int 128131343SbrianSetStoppedTimeout(struct cmdargs const *arg) 128228327Sbrian{ 128336285Sbrian struct link *l = &arg->cx->physical->link; 128436285Sbrian 128536285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 128636285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 128736285Sbrian if (arg->argc <= arg->argn+2) { 128836285Sbrian if (arg->argc > arg->argn) { 128936285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 129036285Sbrian if (arg->argc > arg->argn+1) 129136285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 129228461Sbrian } 129328327Sbrian return 0; 129428327Sbrian } 129528327Sbrian return -1; 129628327Sbrian} 129728327Sbrian 129828327Sbrianstatic int 129931343SbrianSetServer(struct cmdargs const *arg) 130026940Sbrian{ 130126940Sbrian int res = -1; 130226940Sbrian 130336285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 130431081Sbrian const char *port, *passwd, *mask; 130553125Sbrian int mlen; 130631081Sbrian 130731081Sbrian /* What's what ? */ 130836285Sbrian port = arg->argv[arg->argn]; 130936285Sbrian if (arg->argc == arg->argn + 2) { 131036285Sbrian passwd = arg->argv[arg->argn+1]; 131136285Sbrian mask = NULL; 131236285Sbrian } else if (arg->argc == arg->argn + 3) { 131336285Sbrian passwd = arg->argv[arg->argn+1]; 131436285Sbrian mask = arg->argv[arg->argn+2]; 131553125Sbrian mlen = strlen(mask); 131653125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 131753125Sbrian (mlen == 4 && *mask != '0')) { 131853125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 131953125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 132031081Sbrian return -1; 132153125Sbrian } 132271764Sbrian } else if (arg->argc != arg->argn + 1) 132371764Sbrian return -1; 132471764Sbrian else if (strcasecmp(port, "none") == 0) { 132571657Sbrian if (server_Clear(arg->bundle)) 132671657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 132771657Sbrian return 0; 132871657Sbrian } else if (strcasecmp(port, "open") == 0) { 132971657Sbrian switch (server_Reopen(arg->bundle)) { 133071657Sbrian case SERVER_OK: 133171657Sbrian return 0; 133271657Sbrian case SERVER_FAILED: 133371764Sbrian log_Printf(LogWARN, "Failed to reopen server port\n"); 133471657Sbrian return 1; 133571657Sbrian case SERVER_UNSET: 133671764Sbrian log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 133771657Sbrian return 1; 133871657Sbrian default: 133971657Sbrian break; 134071657Sbrian } 134171657Sbrian return -1; 134271657Sbrian } else if (strcasecmp(port, "closed") == 0) { 134336285Sbrian if (server_Close(arg->bundle)) 134471657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 134571657Sbrian else 134671657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 134771657Sbrian 134836285Sbrian return 0; 134931081Sbrian } else 135036285Sbrian return -1; 135131081Sbrian 135271657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 135371657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 135431081Sbrian 135536285Sbrian if (*port == '/') { 135631081Sbrian mode_t imask; 135736285Sbrian char *ptr, name[LINE_LEN + 12]; 135828679Sbrian 135953125Sbrian if (mask == NULL) 136031081Sbrian imask = (mode_t)-1; 136153125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 136253125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 136336285Sbrian 136436285Sbrian ptr = strstr(port, "%d"); 136536285Sbrian if (ptr) { 136636285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 136737210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 136836285Sbrian port = name; 136936285Sbrian } 137036285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 137127346Sbrian } else { 137236285Sbrian int iport, add = 0; 137328679Sbrian 137431081Sbrian if (mask != NULL) 137531081Sbrian return -1; 137628679Sbrian 137736285Sbrian if (*port == '+') { 137836285Sbrian port++; 137936285Sbrian add = 1; 138036285Sbrian } 138131081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 138231081Sbrian struct servent *s; 138331081Sbrian 138431081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 138531081Sbrian iport = 0; 138636285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 138728679Sbrian } else 138831081Sbrian iport = ntohs(s->s_port); 138927346Sbrian } else 139031081Sbrian iport = atoi(port); 139136285Sbrian 139236285Sbrian if (iport) { 139336285Sbrian if (add) 139436285Sbrian iport += arg->bundle->unit; 139536285Sbrian res = server_TcpOpen(arg->bundle, iport); 139636285Sbrian } else 139736285Sbrian res = -1; 139827346Sbrian } 139931081Sbrian } 140026940Sbrian 140126940Sbrian return res; 140226940Sbrian} 140326940Sbrian 140426940Sbrianstatic int 140531343SbrianSetEscape(struct cmdargs const *arg) 14066059Samurai{ 14076059Samurai int code; 140836285Sbrian int argc = arg->argc - arg->argn; 140936285Sbrian char const *const *argv = arg->argv + arg->argn; 14106059Samurai 14116059Samurai for (code = 0; code < 33; code++) 141236285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 141331343Sbrian 14146059Samurai while (argc-- > 0) { 14156059Samurai sscanf(*argv++, "%x", &code); 14166059Samurai code &= 0xff; 141736285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 141836285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 14196059Samurai } 142026516Sbrian return 0; 14216059Samurai} 14226059Samurai 14236059Samuraistatic int 142431343SbrianSetInterfaceAddr(struct cmdargs const *arg) 14256059Samurai{ 142681634Sbrian struct ncp *ncp = &arg->bundle->ncp; 142781634Sbrian struct ncpaddr ncpaddr; 142832267Sbrian const char *hisaddr; 142932267Sbrian 143040561Sbrian if (arg->argc > arg->argn + 4) 143140561Sbrian return -1; 143240561Sbrian 143332267Sbrian hisaddr = NULL; 143481634Sbrian memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range); 143581634Sbrian memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range); 143681634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 0; 143781634Sbrian ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY; 143881634Sbrian iplist_reset(&ncp->ipcp.cfg.peer_list); 143928394Sbrian 144036285Sbrian if (arg->argc > arg->argn) { 144181634Sbrian if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn])) 144228679Sbrian return 1; 144336285Sbrian if (arg->argc > arg->argn+1) { 144436285Sbrian hisaddr = arg->argv[arg->argn+1]; 144536285Sbrian if (arg->argc > arg->argn+2) { 144681634Sbrian ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask = 144781634Sbrian GetIpAddr(arg->argv[arg->argn+2]); 144836285Sbrian if (arg->argc > arg->argn+3) { 144981634Sbrian ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 145081634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 1; 14519440Samurai } 14526059Samurai } 14536059Samurai } 14546059Samurai } 145528394Sbrian 145640561Sbrian /* 0.0.0.0 means any address (0 bits) */ 145781634Sbrian ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip); 145881634Sbrian ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr); 145981634Sbrian if (ncp->ipcp.my_ip.s_addr == INADDR_ANY) 146081634Sbrian ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0); 146181634Sbrian bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL); 146236285Sbrian 146336285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 146436928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 146532267Sbrian return 4; 146631121Sbrian 146726516Sbrian return 0; 14686059Samurai} 14696059Samurai 147018752Sjkhstatic int 147144305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 147244305Sbrian u_int *maxtrm, int def) 147344305Sbrian{ 147444305Sbrian if (argc == 0) { 147544305Sbrian *timeout = DEF_FSMRETRY; 147644305Sbrian *maxreq = def; 147744305Sbrian if (maxtrm != NULL) 147844305Sbrian *maxtrm = def; 147944305Sbrian } else { 148044305Sbrian long l = atol(argv[0]); 148144305Sbrian 148244305Sbrian if (l < MIN_FSMRETRY) { 148344305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 148444305Sbrian l, MIN_FSMRETRY); 148544305Sbrian return 1; 148644305Sbrian } else 148744305Sbrian *timeout = l; 148844305Sbrian 148944305Sbrian if (argc > 1) { 149044305Sbrian l = atol(argv[1]); 149144305Sbrian if (l < 1) { 149244305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 149344305Sbrian l = 1; 149444305Sbrian } 149544305Sbrian *maxreq = l; 149644305Sbrian 149744305Sbrian if (argc > 2 && maxtrm != NULL) { 149844305Sbrian l = atol(argv[2]); 149944305Sbrian if (l < 1) { 150044305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 150144305Sbrian l = 1; 150244305Sbrian } 150344305Sbrian *maxtrm = l; 150444305Sbrian } 150544305Sbrian } 150644305Sbrian } 150744305Sbrian 150844305Sbrian return 0; 150944305Sbrian} 151044305Sbrian 151144305Sbrianstatic int 151231343SbrianSetVariable(struct cmdargs const *arg) 15136059Samurai{ 151437210Sbrian long long_val, param = (long)arg->cmd->args; 151579119Sbrian int mode, dummyint, f, first, res; 151678410Sbrian u_short *change; 151731343Sbrian const char *argp; 151836285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 151936285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 152081634Sbrian struct in_addr *ipaddr; 152181634Sbrian struct ncpaddr ncpaddr[2]; 15226059Samurai 152336285Sbrian if (arg->argc > arg->argn) 152436285Sbrian argp = arg->argv[arg->argn]; 152526551Sbrian else 152631343Sbrian argp = ""; 152726551Sbrian 152879119Sbrian res = 0; 152979119Sbrian 153036285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 153136285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 153236285Sbrian arg->cmd->name); 153336285Sbrian return 1; 153436285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 153536285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 153636285Sbrian arg->cmd->name, cx->name); 153736285Sbrian cx = NULL; 153836285Sbrian } 153936285Sbrian 154026551Sbrian switch (param) { 154128679Sbrian case VAR_AUTHKEY: 154250139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 154350139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 154450139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 154528679Sbrian break; 154637210Sbrian 154728679Sbrian case VAR_AUTHNAME: 154840622Sbrian switch (bundle_Phase(arg->bundle)) { 154958880Sbrian default: 155058880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 155158880Sbrian bundle_PhaseName(arg->bundle)); 155258880Sbrian /* drop through */ 155340622Sbrian case PHASE_DEAD: 155440622Sbrian case PHASE_ESTABLISH: 155540622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 155640622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 155740622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 155840622Sbrian break; 155936285Sbrian } 156028679Sbrian break; 156137210Sbrian 156236285Sbrian case VAR_AUTOLOAD: 156349434Sbrian if (arg->argc == arg->argn + 3) { 156449434Sbrian int v1, v2, v3; 156549434Sbrian char *end; 156649434Sbrian 156749434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 156849434Sbrian if (v1 < 0 || *end) { 156949434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 157049434Sbrian arg->argv[arg->argn]); 157179119Sbrian res = 1; 157279119Sbrian break; 157336285Sbrian } 157449434Sbrian 157549434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 157649434Sbrian if (v2 < 0 || *end) { 157749434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 157849434Sbrian arg->argv[arg->argn + 1]); 157979119Sbrian res = 1; 158079119Sbrian break; 158149434Sbrian } 158249434Sbrian if (v2 < v1) { 158349434Sbrian v3 = v1; 158449434Sbrian v1 = v2; 158549434Sbrian v2 = v3; 158649434Sbrian } 158749434Sbrian 158849434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 158949434Sbrian if (v3 <= 0 || *end) { 159049434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 159149434Sbrian arg->argv[arg->argn + 2]); 159279119Sbrian res = 1; 159379119Sbrian break; 159449434Sbrian } 159549434Sbrian 159649434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 159749434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 159849434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 159949434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 160036285Sbrian } else { 160179119Sbrian log_Printf(LogWARN, "Set autoload requires three arguments\n"); 160279119Sbrian res = 1; 160336285Sbrian } 160436285Sbrian break; 160537210Sbrian 160628679Sbrian case VAR_DIAL: 160736285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 160836285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 160928679Sbrian break; 161037210Sbrian 161128679Sbrian case VAR_LOGIN: 161236285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 161336285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 161428679Sbrian break; 161537210Sbrian 161636285Sbrian case VAR_WINSIZE: 161736285Sbrian if (arg->argc > arg->argn) { 161836285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 161936285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 162036285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 162136285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 162236285Sbrian l->ccp.cfg.deflate.out.winsize); 162336285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 162436285Sbrian } 162536285Sbrian if (arg->argc > arg->argn+1) { 162636285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 162736285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 162836285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 162936285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 163036285Sbrian l->ccp.cfg.deflate.in.winsize); 163136285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 163236285Sbrian } 163336285Sbrian } else 163436285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 163536285Sbrian } else { 163679119Sbrian log_Printf(LogWARN, "No window size specified\n"); 163779119Sbrian res = 1; 163836285Sbrian } 163936285Sbrian break; 164037210Sbrian 164167910Sbrian#ifdef HAVE_DES 164278411Sbrian case VAR_MPPE: 164379119Sbrian if (arg->argc > arg->argn + 2) { 164479119Sbrian res = -1; 164579119Sbrian break; 164679119Sbrian } 164778411Sbrian 164878411Sbrian if (arg->argc == arg->argn) { 164978411Sbrian l->ccp.cfg.mppe.keybits = 0; 165078411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 165178411Sbrian l->ccp.cfg.mppe.required = 0; 165278411Sbrian break; 165378411Sbrian } 165478411Sbrian 165578411Sbrian if (!strcmp(argp, "*")) 165678411Sbrian long_val = 0; 165778411Sbrian else { 165878411Sbrian long_val = atol(argp); 165978411Sbrian if (long_val != 40 && long_val != 56 && long_val != 128) { 166078411Sbrian log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 166179119Sbrian res = -1; 166279119Sbrian break; 166367910Sbrian } 166467910Sbrian } 166578411Sbrian 166678411Sbrian if (arg->argc == arg->argn + 2) { 166778411Sbrian if (!strcmp(arg->argv[arg->argn + 1], "*")) 166878411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 166978411Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 167078411Sbrian l->ccp.cfg.mppe.state = MPPE_STATELESS; 167179370Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 167278411Sbrian l->ccp.cfg.mppe.state = MPPE_STATEFUL; 167378411Sbrian else { 167478411Sbrian log_Printf(LogWARN, "%s: Invalid state value\n", 167578411Sbrian arg->argv[arg->argn + 1]); 167679119Sbrian res = -1; 167779119Sbrian break; 167878411Sbrian } 167978411Sbrian } else 168078411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 168178411Sbrian l->ccp.cfg.mppe.keybits = long_val; 168278411Sbrian l->ccp.cfg.mppe.required = 1; 168367910Sbrian break; 168467910Sbrian#endif 168567910Sbrian 168628679Sbrian case VAR_DEVICE: 168736285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 168836285Sbrian arg->argv + arg->argn); 168936285Sbrian break; 169037210Sbrian 169136285Sbrian case VAR_ACCMAP: 169236285Sbrian if (arg->argc > arg->argn) { 169337210Sbrian u_long ulong_val; 169436285Sbrian sscanf(argp, "%lx", &ulong_val); 169537210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 169636285Sbrian } else { 169779119Sbrian log_Printf(LogWARN, "No accmap specified\n"); 169879119Sbrian res = 1; 169936285Sbrian } 170036285Sbrian break; 170137210Sbrian 170236285Sbrian case VAR_MODE: 170336285Sbrian mode = Nam2mode(argp); 170436285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 170536285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 170679119Sbrian res = -1; 170779119Sbrian break; 170836285Sbrian } 170936285Sbrian bundle_SetMode(arg->bundle, cx, mode); 171036285Sbrian break; 171137210Sbrian 171236285Sbrian case VAR_MRRU: 171340622Sbrian switch (bundle_Phase(arg->bundle)) { 171440622Sbrian case PHASE_DEAD: 171540622Sbrian break; 171640622Sbrian case PHASE_ESTABLISH: 171740622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 171840622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 171940622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 172079119Sbrian res = 1; 172179119Sbrian break; 172240622Sbrian } 172340622Sbrian break; 172440622Sbrian default: 172540622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 172679119Sbrian res = 1; 172779119Sbrian break; 172829696Sbrian } 172979119Sbrian if (res != 0) 173079119Sbrian break; 173137210Sbrian long_val = atol(argp); 173237210Sbrian if (long_val && long_val < MIN_MRU) { 173337210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 173479119Sbrian res = 1; 173579119Sbrian break; 173637210Sbrian } else if (long_val > MAX_MRU) { 173737210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 173879119Sbrian res = 1; 173979119Sbrian break; 174037210Sbrian } else 174137210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 174228679Sbrian break; 174337210Sbrian 174436285Sbrian case VAR_MRU: 174579163Sbrian long_val = 0; /* silence gcc */ 174679163Sbrian change = NULL; /* silence gcc */ 174778410Sbrian switch(arg->argc - arg->argn) { 174878410Sbrian case 1: 174979119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 175079119Sbrian res = -1; 175179119Sbrian break; 175279119Sbrian } 175379119Sbrian /*FALLTHRU*/ 175478410Sbrian case 0: 175578410Sbrian long_val = atol(argp); 175678410Sbrian change = &l->lcp.cfg.mru; 175778410Sbrian if (long_val > l->lcp.cfg.max_mru) { 175878410Sbrian log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 175978410Sbrian l->lcp.cfg.max_mru); 176079119Sbrian res = 1; 176179119Sbrian break; 176278410Sbrian } 176378410Sbrian break; 176478410Sbrian case 2: 176579119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 176679119Sbrian res = -1; 176779119Sbrian break; 176879119Sbrian } 176978410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 177078410Sbrian change = &l->lcp.cfg.max_mru; 177178410Sbrian if (long_val > MAX_MRU) { 177278410Sbrian log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 177378410Sbrian MAX_MRU); 177479119Sbrian res = 1; 177579119Sbrian break; 177678410Sbrian } 177778410Sbrian break; 177878410Sbrian default: 177979119Sbrian res = -1; 178079119Sbrian break; 178178410Sbrian } 178279119Sbrian if (res != 0) 178379119Sbrian break; 178478410Sbrian 178537210Sbrian if (long_val == 0) 178680385Sbrian *change = 0; 178737210Sbrian else if (long_val < MIN_MRU) { 178837210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 178979119Sbrian res = 1; 179079119Sbrian break; 179137210Sbrian } else if (long_val > MAX_MRU) { 179237210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 179379119Sbrian res = 1; 179479119Sbrian break; 179537210Sbrian } else 179678410Sbrian *change = long_val; 179778410Sbrian if (l->lcp.cfg.mru > *change) 179878410Sbrian l->lcp.cfg.mru = *change; 179928679Sbrian break; 180037210Sbrian 180136285Sbrian case VAR_MTU: 180279163Sbrian long_val = 0; /* silence gcc */ 180379163Sbrian change = NULL; /* silence gcc */ 180478410Sbrian switch(arg->argc - arg->argn) { 180578410Sbrian case 1: 180679119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 180779119Sbrian res = -1; 180879119Sbrian break; 180979119Sbrian } 181079119Sbrian /*FALLTHRU*/ 181178410Sbrian case 0: 181278410Sbrian long_val = atol(argp); 181378410Sbrian change = &l->lcp.cfg.mtu; 181478410Sbrian if (long_val > l->lcp.cfg.max_mtu) { 181578410Sbrian log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 181678410Sbrian l->lcp.cfg.max_mtu); 181779119Sbrian res = 1; 181879119Sbrian break; 181978410Sbrian } 182078410Sbrian break; 182178410Sbrian case 2: 182279119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 182379119Sbrian res = -1; 182479119Sbrian break; 182579119Sbrian } 182678410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 182778410Sbrian change = &l->lcp.cfg.max_mtu; 182878410Sbrian if (long_val > MAX_MTU) { 182978410Sbrian log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 183078410Sbrian MAX_MTU); 183179119Sbrian res = 1; 183279119Sbrian break; 183378410Sbrian } 183478410Sbrian break; 183578410Sbrian default: 183679119Sbrian res = -1; 183779119Sbrian break; 183878410Sbrian } 183978410Sbrian 184079119Sbrian if (res != 0) 184179119Sbrian break; 184279119Sbrian 184337210Sbrian if (long_val && long_val < MIN_MTU) { 184437210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 184579119Sbrian res = 1; 184679119Sbrian break; 184737210Sbrian } else if (long_val > MAX_MTU) { 184837210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 184979119Sbrian res = 1; 185079119Sbrian break; 185137210Sbrian } else 185278410Sbrian *change = long_val; 185378410Sbrian if (l->lcp.cfg.mtu > *change) 185478410Sbrian l->lcp.cfg.mtu = *change; 185536285Sbrian break; 185637210Sbrian 185736285Sbrian case VAR_OPENMODE: 185836285Sbrian if (strcasecmp(argp, "active") == 0) 185936285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 186036285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 186136285Sbrian else if (strcasecmp(argp, "passive") == 0) 186236285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 186336285Sbrian else { 186479119Sbrian log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 186579119Sbrian res = 1; 186636285Sbrian } 186736285Sbrian break; 186837210Sbrian 186928679Sbrian case VAR_PHONE: 187036285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 187136285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 187238174Sbrian cx->phone.alt = cx->phone.next = NULL; 187328679Sbrian break; 187437210Sbrian 187528679Sbrian case VAR_HANGUP: 187636285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 187736285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 187828679Sbrian break; 187937210Sbrian 188061534Sbrian case VAR_IFQUEUE: 188161534Sbrian long_val = atol(argp); 188261534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 188361534Sbrian break; 188461534Sbrian 188552488Sbrian case VAR_LOGOUT: 188652488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 188752488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 188852488Sbrian break; 188952488Sbrian 189036285Sbrian case VAR_IDLETIMEOUT: 189179119Sbrian if (arg->argc > arg->argn+2) { 189279119Sbrian log_Printf(LogWARN, "Too many idle timeout values\n"); 189379119Sbrian res = 1; 189479119Sbrian } else if (arg->argc == arg->argn) { 189579119Sbrian log_Printf(LogWARN, "Too few idle timeout values\n"); 189679119Sbrian res = 1; 189779119Sbrian } else { 189849978Sbrian int timeout, min; 189949978Sbrian 190049978Sbrian timeout = atoi(argp); 190149978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 190249978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 190349978Sbrian } 190429549Sbrian break; 190537210Sbrian 190636285Sbrian case VAR_LQRPERIOD: 190737210Sbrian long_val = atol(argp); 190837210Sbrian if (long_val < MIN_LQRPERIOD) { 190937210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 191037210Sbrian long_val, MIN_LQRPERIOD); 191179119Sbrian res = 1; 191236285Sbrian } else 191337210Sbrian l->lcp.cfg.lqrperiod = long_val; 191436285Sbrian break; 191537210Sbrian 191636285Sbrian case VAR_LCPRETRY: 191779119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 191879119Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 191979119Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 192079119Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 192136285Sbrian break; 192237210Sbrian 192336285Sbrian case VAR_CHAPRETRY: 192479119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 192579119Sbrian &cx->chap.auth.cfg.fsm.timeout, 192679119Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 192736285Sbrian break; 192837210Sbrian 192936285Sbrian case VAR_PAPRETRY: 193079119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 193179119Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 193279119Sbrian NULL, DEF_FSMAUTHTRIES); 193336285Sbrian break; 193437210Sbrian 193536285Sbrian case VAR_CCPRETRY: 193679119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 193779119Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 193879119Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 193936285Sbrian break; 194037210Sbrian 194136285Sbrian case VAR_IPCPRETRY: 194279119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 194379119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 194479119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 194579119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 194636285Sbrian break; 194737210Sbrian 194836285Sbrian case VAR_NBNS: 194936285Sbrian case VAR_DNS: 195058044Sbrian if (param == VAR_DNS) { 195181634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns; 195281634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE; 195358044Sbrian } else { 195481634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 195581634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY; 195658044Sbrian } 195736285Sbrian 195836285Sbrian if (arg->argc > arg->argn) { 195981634Sbrian ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]); 196081634Sbrian if (!ncpaddr_getip4(ncpaddr, ipaddr)) 196181634Sbrian return -1; 196281634Sbrian if (arg->argc > arg->argn+1) { 196381634Sbrian ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]); 196481634Sbrian if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1)) 196581634Sbrian return -1; 196681634Sbrian } 196736285Sbrian 196881634Sbrian if (ipaddr[0].s_addr == INADDR_ANY) { 196981634Sbrian ipaddr[0] = ipaddr[1]; 197081634Sbrian ipaddr[1].s_addr = INADDR_ANY; 197158044Sbrian } 197281634Sbrian if (ipaddr[0].s_addr == INADDR_NONE) { 197381634Sbrian ipaddr[0] = ipaddr[1]; 197481634Sbrian ipaddr[1].s_addr = INADDR_NONE; 197558044Sbrian } 197636285Sbrian } 197736285Sbrian break; 197838174Sbrian 197938174Sbrian case VAR_CALLBACK: 198038174Sbrian cx->cfg.callback.opmask = 0; 198138174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 198238174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 198338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 198438174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 198538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 198638174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 198738174Sbrian if (dummyint == arg->argc - 1) 198838174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 198938174Sbrian else { 199038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 199138174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 199238174Sbrian sizeof cx->cfg.callback.msg - 1); 199338174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 199438174Sbrian } 199538174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 199638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 199779119Sbrian else { 199879119Sbrian res = -1; 199979119Sbrian break; 200079119Sbrian } 200138174Sbrian } 200238174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 200338174Sbrian cx->cfg.callback.opmask = 0; 200438174Sbrian break; 200538174Sbrian 200638174Sbrian case VAR_CBCP: 200738174Sbrian cx->cfg.cbcp.delay = 0; 200838174Sbrian *cx->cfg.cbcp.phone = '\0'; 200938174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 201038174Sbrian if (arg->argc > arg->argn) { 201138174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 201238174Sbrian sizeof cx->cfg.cbcp.phone - 1); 201338174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 201438174Sbrian if (arg->argc > arg->argn + 1) { 201538174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 201638174Sbrian if (arg->argc > arg->argn + 2) { 201738174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 201838174Sbrian if (long_val < MIN_FSMRETRY) 201938174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 202038174Sbrian long_val, MIN_FSMRETRY); 202138174Sbrian else 202238174Sbrian cx->cfg.cbcp.fsmretry = long_val; 202338174Sbrian } 202438174Sbrian } 202538174Sbrian } 202638174Sbrian break; 202738544Sbrian 202838544Sbrian case VAR_CHOKED: 202938544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 203038544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 203138544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 203238544Sbrian break; 203340665Sbrian 203440665Sbrian case VAR_SENDPIPE: 203540665Sbrian long_val = atol(argp); 203681634Sbrian arg->bundle->ncp.cfg.sendpipe = long_val; 203740665Sbrian break; 203840665Sbrian 203940665Sbrian case VAR_RECVPIPE: 204040665Sbrian long_val = atol(argp); 204181634Sbrian arg->bundle->ncp.cfg.recvpipe = long_val; 204240665Sbrian break; 204343313Sbrian 204443313Sbrian#ifndef NORADIUS 204543313Sbrian case VAR_RADIUS: 204643313Sbrian if (!*argp) 204743313Sbrian *arg->bundle->radius.cfg.file = '\0'; 204843313Sbrian else if (access(argp, R_OK)) { 204943313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 205079119Sbrian res = 1; 205179119Sbrian break; 205243313Sbrian } else { 205343313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 205443313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 205543313Sbrian arg->bundle->radius.cfg.file 205643313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 205743313Sbrian } 205843313Sbrian break; 205943313Sbrian#endif 206044073Sbrian 206144073Sbrian case VAR_CD: 206244073Sbrian if (*argp) { 206351699Sbrian if (strcasecmp(argp, "off")) { 206451699Sbrian long_val = atol(argp); 206551699Sbrian if (long_val < 0) 206651699Sbrian long_val = 0; 206751699Sbrian cx->physical->cfg.cd.delay = long_val; 206851699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 206951699Sbrian CD_REQUIRED : CD_VARIABLE; 207051699Sbrian } else 207151699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 207244073Sbrian } else { 207353733Sbrian cx->physical->cfg.cd.delay = 0; 207453733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 207544073Sbrian } 207644073Sbrian break; 207736285Sbrian 207846686Sbrian case VAR_PARITY: 207946686Sbrian if (arg->argc == arg->argn + 1) 208079119Sbrian res = physical_SetParity(arg->cx->physical, argp); 208146686Sbrian else { 208279119Sbrian log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 208379119Sbrian res = 1; 208446686Sbrian } 208546686Sbrian break; 20866059Samurai 208746686Sbrian case VAR_CRTSCTS: 208846686Sbrian if (strcasecmp(argp, "on") == 0) 208936285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 209046686Sbrian else if (strcasecmp(argp, "off") == 0) 209136285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 209246686Sbrian else { 209379119Sbrian log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 209479119Sbrian res = 1; 209546686Sbrian } 209646686Sbrian break; 209750867Sbrian 209850867Sbrian case VAR_URGENTPORTS: 209951048Sbrian if (arg->argn == arg->argc) { 210081634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 210181634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 210281634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 210351048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 210481634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 210551048Sbrian if (arg->argn == arg->argc - 1) 210681634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 210751048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 210851048Sbrian if (*arg->argv[f] == '+') 210981634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 211051048Sbrian else if (*arg->argv[f] == '-') 211181634Sbrian ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 211251048Sbrian else { 211351048Sbrian if (f == arg->argn) 211481634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 211581634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 211651048Sbrian } 211761430Sbrian } else if (arg->argn == arg->argc - 1 && 211861430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 211981634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 212081634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 212181634Sbrian ncp_ClearUrgentTOS(&arg->bundle->ncp); 212251048Sbrian } else { 212381634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 212451048Sbrian first = arg->argn; 212551048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 212681634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 212751048Sbrian 212851048Sbrian for (f = first; f < arg->argc; f++) 212951048Sbrian if (*arg->argv[f] == '+') 213081634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 213151048Sbrian else if (*arg->argv[f] == '-') 213281634Sbrian ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 213351048Sbrian else { 213451048Sbrian if (f == first) 213581634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 213681634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 213751048Sbrian } 213851048Sbrian } 213950867Sbrian break; 214020812Sjkh } 214146686Sbrian 214279119Sbrian return res; 214320812Sjkh} 214420812Sjkh 214530715Sbrianstatic struct cmdtab const SetCommands[] = { 214636285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 214736285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 214828679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 214936285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 215028679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 215136285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 215236285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 215336285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 215436285Sbrian (const void *)VAR_AUTOLOAD}, 215550867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 215650867Sbrian "datalink bandwidth", "set bandwidth value"}, 215738174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 215838174Sbrian "callback control", "set callback [none|auth|cbcp|" 215938174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 216038174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 216138174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 216238174Sbrian (const void *)VAR_CBCP}, 216344305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 216444305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 216544073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 216644073Sbrian "set cd value[!]", (const void *)VAR_CD}, 216744305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 216844305Sbrian "CHAP retries", "set chapretry value [attempts]", 216944305Sbrian (const void *)VAR_CHAPRETRY}, 217038544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 217138544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 217246686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 217346686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 217446686Sbrian (const char *)VAR_CRTSCTS}, 217536285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 217636285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 217736285Sbrian (const void *) VAR_WINSIZE}, 217867910Sbrian#ifdef HAVE_DES 217967910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 218079370Sbrian "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 218178411Sbrian (const void *) VAR_MPPE}, 218267910Sbrian#endif 218336285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 218446686Sbrian "physical device name", "set device|line device-name[,device-name]", 218536285Sbrian (const void *) VAR_DEVICE}, 218636285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 218736285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 218836285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 218936285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 219036285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 219136285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 219236285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 219336285Sbrian "escape characters", "set escape hex-digit ..."}, 219436285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 219536285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 219681634Sbrian "[src_addr[/width]] [dst_addr[/width]] [proto " 219748142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 219836285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 219936285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 220036285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 220131343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 220261534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 220361534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 220444305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 220544305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 220644305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 220744305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 220836712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 220967916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 221058033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 221136285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 221236285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 221352488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 221452488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 221536285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 221636285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 221736285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 221836285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 221936285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 222036285Sbrian "set mrru value", (const void *)VAR_MRRU}, 222136285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 222278410Sbrian "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 222378410Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 222478410Sbrian "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 222536285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 222636285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 222736285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 222836285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 222944305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 223044305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 223146686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 223246686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 223336285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 223436285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 223540679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 223640679Sbrian "Process title", "set proctitle [value]"}, 223743313Sbrian#ifndef NORADIUS 223843313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 223943313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 224043313Sbrian#endif 224136285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 224236285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 224340665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 224440665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 224536285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 224644468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 224740665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 224840665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 224971657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 225071657Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 225136285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 225246686Sbrian "physical speed", "set speed value|sync"}, 225336285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 225436285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 225536285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 225636285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 225751048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 225851048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 225936285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 226036285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 226128679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 226231343Sbrian "Display this message", "set help|? [command]", SetCommands}, 226328679Sbrian {NULL, NULL, NULL}, 22646059Samurai}; 22656059Samurai 22666059Samuraistatic int 226731343SbrianSetCommand(struct cmdargs const *arg) 22686059Samurai{ 226936285Sbrian if (arg->argc > arg->argn) 227036285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 227136285Sbrian arg->prompt, arg->cx); 227236285Sbrian else if (arg->prompt) 227336285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 227458044Sbrian " syntax help.\n"); 22756059Samurai else 227636285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 227726516Sbrian 227826516Sbrian return 0; 22796059Samurai} 22806059Samurai 22816059Samuraistatic int 228231343SbrianAddCommand(struct cmdargs const *arg) 22836059Samurai{ 228481634Sbrian struct ncpaddr gw; 228581634Sbrian struct ncprange dest; 228681634Sbrian struct in_addr host; 228781634Sbrian int dest_default, gw_arg, addrs; 22886059Samurai 228936285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 229031598Sbrian return -1; 229131598Sbrian 229236285Sbrian addrs = 0; 229381634Sbrian dest_default = 0; 229481634Sbrian if (arg->argc == arg->argn + 2) { 229536285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 229681634Sbrian dest_default = 1; 229731598Sbrian else { 229881634Sbrian if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn])) 229936285Sbrian return -1; 230036285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 230136285Sbrian addrs = ROUTE_DSTMYADDR; 230281634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7)) 230381634Sbrian addrs = ROUTE_DSTMYADDR6; 230436285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 230536285Sbrian addrs = ROUTE_DSTHISADDR; 230681634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8)) 230781634Sbrian addrs = ROUTE_DSTHISADDR6; 230858044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 230958044Sbrian addrs = ROUTE_DSTDNS0; 231058044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 231158044Sbrian addrs = ROUTE_DSTDNS1; 231231598Sbrian } 231381634Sbrian gw_arg = 1; 231434536Sbrian } else { 231536285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 231636285Sbrian addrs = ROUTE_DSTMYADDR; 231781634Sbrian host = arg->bundle->ncp.ipcp.my_ip; 231836285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 231936285Sbrian addrs = ROUTE_DSTHISADDR; 232081634Sbrian host = arg->bundle->ncp.ipcp.peer_ip; 232158044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 232258044Sbrian addrs = ROUTE_DSTDNS0; 232381634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[0]; 232458044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 232558044Sbrian addrs = ROUTE_DSTDNS1; 232681634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[1]; 232765263Sbrian } else { 232881634Sbrian host = GetIpAddr(arg->argv[arg->argn]); 232981634Sbrian if (host.s_addr == INADDR_NONE) { 233065263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 233165263Sbrian arg->argv[arg->argn]); 233265263Sbrian return -1; 233365263Sbrian } 233465263Sbrian } 233581634Sbrian ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1])); 233681634Sbrian gw_arg = 2; 23376059Samurai } 233836285Sbrian 233981634Sbrian if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) { 234081634Sbrian ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip); 234136285Sbrian addrs |= ROUTE_GWHISADDR; 234281634Sbrian#ifndef NOINET6 234381634Sbrian } else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) { 234481634Sbrian ncpaddr_copy(&gw, &arg->bundle->ncp.ipv6cp.hisaddr); 234581634Sbrian addrs |= ROUTE_GWHISADDR6; 234681634Sbrian#endif 234765263Sbrian } else { 234881634Sbrian if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) { 234965263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 235081634Sbrian arg->argv[arg->argn + gw_arg]); 235165263Sbrian return -1; 235265263Sbrian } 235365263Sbrian } 235436285Sbrian 235581634Sbrian if (dest_default) 235681634Sbrian ncprange_setdefault(&dest, ncpaddr_family(&gw)); 235781634Sbrian 235881634Sbrian if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0, 235981634Sbrian ((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0) 236043313Sbrian && addrs != ROUTE_STATIC) 236181634Sbrian route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw); 236236285Sbrian 236331598Sbrian return 0; 23646059Samurai} 23656059Samurai 23666059Samuraistatic int 236731343SbrianDeleteCommand(struct cmdargs const *arg) 23686059Samurai{ 236981634Sbrian struct ncprange dest; 237036285Sbrian int addrs; 23716059Samurai 237236285Sbrian if (arg->argc == arg->argn+1) { 237336285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 237436285Sbrian route_IfDelete(arg->bundle, 0); 237581634Sbrian route_DeleteAll(&arg->bundle->ncp.route); 237636285Sbrian } else { 237736285Sbrian addrs = 0; 237836285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 237981634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip); 238036285Sbrian addrs = ROUTE_DSTMYADDR; 238181634Sbrian#ifndef NOINET6 238281634Sbrian } else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) { 238381634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr); 238481634Sbrian addrs = ROUTE_DSTMYADDR6; 238581634Sbrian#endif 238636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 238781634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip); 238836285Sbrian addrs = ROUTE_DSTHISADDR; 238981634Sbrian#ifndef NOINET6 239081634Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) { 239181634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr); 239281634Sbrian addrs = ROUTE_DSTHISADDR6; 239381634Sbrian#endif 239458044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 239581634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]); 239658044Sbrian addrs = ROUTE_DSTDNS0; 239758044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 239881634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]); 239958044Sbrian addrs = ROUTE_DSTDNS1; 240036285Sbrian } else { 240181634Sbrian ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]); 240236285Sbrian addrs = ROUTE_STATIC; 240336285Sbrian } 240481634Sbrian rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0); 240581634Sbrian route_Delete(&arg->bundle->ncp.route, addrs, &dest); 240631598Sbrian } 240734536Sbrian } else 240826516Sbrian return -1; 240926516Sbrian 241026516Sbrian return 0; 24116059Samurai} 24126059Samurai 241350059Sbrian#ifndef NONAT 241426031Sbrianstatic int 241558867SbrianNatEnable(struct cmdargs const *arg) 241626031Sbrian{ 241736285Sbrian if (arg->argc == arg->argn+1) { 241836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 241950059Sbrian if (!arg->bundle->NatEnabled) { 242046686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 242146686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 242250059Sbrian arg->bundle->NatEnabled = 1; 242346686Sbrian } 242437191Sbrian return 0; 242536285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 242650059Sbrian arg->bundle->NatEnabled = 0; 242740561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 242840561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 242926516Sbrian return 0; 243026142Sbrian } 243135449Sbrian } 243236285Sbrian 243326516Sbrian return -1; 243426031Sbrian} 243526031Sbrian 243626031Sbrian 243726031Sbrianstatic int 243858867SbrianNatOption(struct cmdargs const *arg) 243926031Sbrian{ 244038559Sbrian long param = (long)arg->cmd->args; 244138559Sbrian 244236285Sbrian if (arg->argc == arg->argn+1) { 244336285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 244450059Sbrian if (arg->bundle->NatEnabled) { 244537191Sbrian PacketAliasSetMode(param, param); 244628679Sbrian return 0; 244728679Sbrian } 244850059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 244936285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 245050059Sbrian if (arg->bundle->NatEnabled) { 245137191Sbrian PacketAliasSetMode(0, param); 245228679Sbrian return 0; 245328679Sbrian } 245450059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 245528679Sbrian } 245635449Sbrian } 245728679Sbrian return -1; 245826031Sbrian} 245950059Sbrian#endif /* #ifndef NONAT */ 246031121Sbrian 246131121Sbrianstatic int 246236285SbrianLinkCommand(struct cmdargs const *arg) 246336285Sbrian{ 246436285Sbrian if (arg->argc > arg->argn+1) { 246536285Sbrian char namelist[LINE_LEN]; 246636285Sbrian struct datalink *cx; 246736285Sbrian char *name; 246836285Sbrian int result = 0; 246936285Sbrian 247036285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 247136285Sbrian struct datalink *dl; 247236285Sbrian 247336285Sbrian cx = arg->bundle->links; 247436285Sbrian while (cx) { 247536285Sbrian /* Watch it, the command could be a ``remove'' */ 247636285Sbrian dl = cx->next; 247736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 247836285Sbrian arg->prompt, cx); 247936285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 248036285Sbrian if (cx == dl) 248136285Sbrian break; /* Pointer's still valid ! */ 248236285Sbrian } 248336285Sbrian } else { 248436285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 248536285Sbrian namelist[sizeof namelist - 1] = '\0'; 248636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 248736285Sbrian if (!bundle2datalink(arg->bundle, name)) { 248836285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 248936285Sbrian return 1; 249036285Sbrian } 249136285Sbrian 249236285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 249336285Sbrian namelist[sizeof namelist - 1] = '\0'; 249436285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 249536285Sbrian cx = bundle2datalink(arg->bundle, name); 249636285Sbrian if (cx) 249736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 249836285Sbrian arg->prompt, cx); 249936285Sbrian else { 250036285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 250136285Sbrian result++; 250236285Sbrian } 250336285Sbrian } 250436285Sbrian } 250536285Sbrian return result; 250636285Sbrian } 250736285Sbrian 250836285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 250936285Sbrian return 2; 251036285Sbrian} 251136285Sbrian 251236285Sbrianstruct link * 251336285Sbriancommand_ChooseLink(struct cmdargs const *arg) 251436285Sbrian{ 251536285Sbrian if (arg->cx) 251636285Sbrian return &arg->cx->physical->link; 251737210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 251836285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 251937210Sbrian if (dl) 252037210Sbrian return &dl->physical->link; 252136285Sbrian } 252237210Sbrian return &arg->bundle->ncp.mp.link; 252336285Sbrian} 252436285Sbrian 252536285Sbrianstatic const char * 252636285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 252736285Sbrian{ 252836285Sbrian const char *result; 252936285Sbrian 253036285Sbrian switch (*cmd) { 253136285Sbrian case 'A': 253236285Sbrian case 'a': 253336285Sbrian result = "accept"; 253436285Sbrian *keep = NEG_MYMASK; 253536285Sbrian *add = NEG_ACCEPTED; 253636285Sbrian break; 253736285Sbrian case 'D': 253836285Sbrian case 'd': 253936285Sbrian switch (cmd[1]) { 254036285Sbrian case 'E': 254136285Sbrian case 'e': 254236285Sbrian result = "deny"; 254336285Sbrian *keep = NEG_MYMASK; 254436285Sbrian *add = 0; 254536285Sbrian break; 254636285Sbrian case 'I': 254736285Sbrian case 'i': 254836285Sbrian result = "disable"; 254936285Sbrian *keep = NEG_HISMASK; 255036285Sbrian *add = 0; 255136285Sbrian break; 255236285Sbrian default: 255336285Sbrian return NULL; 255436285Sbrian } 255536285Sbrian break; 255636285Sbrian case 'E': 255736285Sbrian case 'e': 255836285Sbrian result = "enable"; 255936285Sbrian *keep = NEG_HISMASK; 256036285Sbrian *add = NEG_ENABLED; 256136285Sbrian break; 256236285Sbrian default: 256336285Sbrian return NULL; 256436285Sbrian } 256536285Sbrian 256636285Sbrian return result; 256736285Sbrian} 256836285Sbrian 256936285Sbrianstatic int 257036285SbrianOptSet(struct cmdargs const *arg) 257136285Sbrian{ 257237574Sbrian int bit = (int)(long)arg->cmd->args; 257336285Sbrian const char *cmd; 257436285Sbrian unsigned keep; /* Keep these bits */ 257536285Sbrian unsigned add; /* Add these bits */ 257636285Sbrian 257781697Sbrian if (ident_cmd(arg->argv[arg->argn - 2], &keep, &add) == NULL) 257836285Sbrian return 1; 257936285Sbrian 258081697Sbrian if (add == NEG_ENABLED && bit == OPT_IPV6CP && !probe.ipv6_available) { 258181697Sbrian log_Printf(LogWARN, "IPv6 is not available on this machine\n"); 258281697Sbrian return 1; 258381697Sbrian } 258481697Sbrian 258536285Sbrian if (add) 258636285Sbrian arg->bundle->cfg.opt |= bit; 258736285Sbrian else 258836285Sbrian arg->bundle->cfg.opt &= ~bit; 258981697Sbrian 259036285Sbrian return 0; 259136285Sbrian} 259236285Sbrian 259336285Sbrianstatic int 259440561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 259540561Sbrian{ 259640561Sbrian unsigned save = arg->bundle->cfg.opt; 259740561Sbrian int result = OptSet(arg); 259840561Sbrian 259940561Sbrian if (result == 0) 260050059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 260140561Sbrian arg->bundle->cfg.opt = save; 260250059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 260340561Sbrian result = 2; 260440561Sbrian } 260540561Sbrian 260640561Sbrian return result; 260740561Sbrian} 260840561Sbrian 260940561Sbrianstatic int 261036285SbrianNegotiateSet(struct cmdargs const *arg) 261136285Sbrian{ 261237210Sbrian long param = (long)arg->cmd->args; 261336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 261436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 261536285Sbrian const char *cmd; 261636285Sbrian unsigned keep; /* Keep these bits */ 261736285Sbrian unsigned add; /* Add these bits */ 261836285Sbrian 261936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 262036285Sbrian return 1; 262136285Sbrian 262236285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 262336285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 262436285Sbrian cmd, arg->cmd->name); 262536285Sbrian return 2; 262636285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 262736285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 262836285Sbrian cmd, arg->cmd->name, cx->name); 262936285Sbrian cx = NULL; 263036285Sbrian } 263136285Sbrian 263236285Sbrian switch (param) { 263336285Sbrian case NEG_ACFCOMP: 263436285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 263536285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 263636285Sbrian break; 263744106Sbrian case NEG_CHAP05: 263844106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 263944106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 264036285Sbrian break; 264144106Sbrian#ifdef HAVE_DES 264244106Sbrian case NEG_CHAP80: 264344106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 264444106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 264544106Sbrian break; 264644106Sbrian case NEG_CHAP80LM: 264744106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 264844106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 264944106Sbrian break; 265067910Sbrian case NEG_CHAP81: 265167910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 265267910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 265367910Sbrian break; 265467910Sbrian case NEG_MPPE: 265567910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 265667910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 265767910Sbrian break; 265844106Sbrian#endif 265936285Sbrian case NEG_DEFLATE: 266036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 266136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 266236285Sbrian break; 266336285Sbrian case NEG_DNS: 266436285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 266536285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 266636285Sbrian break; 266747858Sbrian case NEG_ENDDISC: 266847858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 266947858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 267047858Sbrian break; 267136285Sbrian case NEG_LQR: 267236285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 267336285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 267436285Sbrian break; 267536285Sbrian case NEG_PAP: 267636285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 267736285Sbrian cx->physical->link.lcp.cfg.pap |= add; 267836285Sbrian break; 267936285Sbrian case NEG_PPPDDEFLATE: 268036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 268136285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 268236285Sbrian break; 268336285Sbrian case NEG_PRED1: 268436285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 268536285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 268636285Sbrian break; 268736285Sbrian case NEG_PROTOCOMP: 268836285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 268936285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 269036285Sbrian break; 269136285Sbrian case NEG_SHORTSEQ: 269240622Sbrian switch (bundle_Phase(arg->bundle)) { 269340622Sbrian case PHASE_DEAD: 269440622Sbrian break; 269540622Sbrian case PHASE_ESTABLISH: 269640622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 269740622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 269840622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 269940622Sbrian " LCP negotiations\n"); 270040622Sbrian return 1; 270140622Sbrian } 270240622Sbrian break; 270340622Sbrian default: 270440622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 270540622Sbrian " DEAD/ESTABLISH\n"); 270640622Sbrian return 1; 270736285Sbrian } 270840622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 270940622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 271036285Sbrian break; 271136285Sbrian case NEG_VJCOMP: 271236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 271336285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 271436285Sbrian break; 271536285Sbrian } 271636285Sbrian 271736285Sbrian return 0; 271836285Sbrian} 271936285Sbrian 272036285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 272162778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 272262778Sbrian "filter on PPPoUDP payloads", "disable|enable", 272362778Sbrian (const void *)OPT_FILTERDECAP}, 272436285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 272536285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 272640666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 272762778Sbrian "retain interface addresses", "disable|enable", 272862778Sbrian (const void *)OPT_IFACEALIAS}, 272981634Sbrian#ifndef NOINET6 273081634Sbrian {"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol", 273181634Sbrian "disable|enable", (const void *)OPT_IPCP}, 273281634Sbrian {"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol", 273381634Sbrian "disable|enable", (const void *)OPT_IPV6CP}, 273481634Sbrian#endif 273547689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 273647689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 273736285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 273836285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 273936285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 274036285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 274140665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 274236285Sbrian "disable|enable", (const void *)OPT_PROXY}, 274340665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 274440665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 274536285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 274636285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 274769303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 274869303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 274936285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 275036285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 275136285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 275236285Sbrian "disable|enable", (const void *)OPT_UTMP}, 275336285Sbrian 275481634Sbrian#ifndef NOINET6 275581634Sbrian#define OPT_MAX 13 /* accept/deny allowed below and not above */ 275681634Sbrian#else 275781634Sbrian#define OPT_MAX 11 275881634Sbrian#endif 275936285Sbrian 276036285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 276136285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 276236285Sbrian (const void *)NEG_ACFCOMP}, 276344106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 276436285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 276544106Sbrian (const void *)NEG_CHAP05}, 276644106Sbrian#ifdef HAVE_DES 276744106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 276844106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 276944106Sbrian (const void *)NEG_CHAP80}, 277044106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 277144106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 277244106Sbrian (const void *)NEG_CHAP80LM}, 277367910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 277467910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 277567910Sbrian (const void *)NEG_CHAP81}, 277667910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 277767910Sbrian "MPPE encryption", "accept|deny|disable|enable", 277867910Sbrian (const void *)NEG_MPPE}, 277944106Sbrian#endif 278036285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 278136285Sbrian "Deflate compression", "accept|deny|disable|enable", 278236285Sbrian (const void *)NEG_DEFLATE}, 278336285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 278436285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 278536285Sbrian (const void *)NEG_PPPDDEFLATE}, 278636285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 278736285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 278847858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 278947858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 279036285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 279136285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 279236285Sbrian (const void *)NEG_LQR}, 279336285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 279436285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 279536285Sbrian (const void *)NEG_PAP}, 279636285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 279736285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 279836285Sbrian (const void *)NEG_PRED1}, 279936285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 280036285Sbrian "Protocol field compression", "accept|deny|disable|enable", 280136285Sbrian (const void *)NEG_PROTOCOMP}, 280236285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 280336285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 280436285Sbrian (const void *)NEG_SHORTSEQ}, 280536285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 280636285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 280736285Sbrian (const void *)NEG_VJCOMP}, 280836285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 280936285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 281036285Sbrian NegotiateCommands}, 281136285Sbrian {NULL, NULL, NULL}, 281236285Sbrian}; 281336285Sbrian 281436285Sbrianstatic int 281536285SbrianNegotiateCommand(struct cmdargs const *arg) 281636285Sbrian{ 281736285Sbrian if (arg->argc > arg->argn) { 281836285Sbrian char const *argv[3]; 281936285Sbrian unsigned keep, add; 282036285Sbrian int n; 282136285Sbrian 282236285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 282336285Sbrian return -1; 282436285Sbrian argv[2] = NULL; 282536285Sbrian 282636285Sbrian for (n = arg->argn; n < arg->argc; n++) { 282736285Sbrian argv[1] = arg->argv[n]; 282836285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 282936285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 283036285Sbrian } 283136285Sbrian } else if (arg->prompt) 283236285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 283336285Sbrian arg->argv[arg->argn-1]); 283436285Sbrian else 283536285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 283636285Sbrian arg->argv[arg->argn] ); 283736285Sbrian 283836285Sbrian return 0; 283936285Sbrian} 284036285Sbrian 284136285Sbrianconst char * 284236285Sbriancommand_ShowNegval(unsigned val) 284336285Sbrian{ 284436285Sbrian switch (val&3) { 284536285Sbrian case 1: return "disabled & accepted"; 284636285Sbrian case 2: return "enabled & denied"; 284736285Sbrian case 3: return "enabled & accepted"; 284836285Sbrian } 284936285Sbrian return "disabled & denied"; 285036285Sbrian} 285136934Sbrian 285236934Sbrianstatic int 285336934SbrianClearCommand(struct cmdargs const *arg) 285436934Sbrian{ 285536934Sbrian struct pppThroughput *t; 285636934Sbrian struct datalink *cx; 285736934Sbrian int i, clear_type; 285836934Sbrian 285936934Sbrian if (arg->argc < arg->argn + 1) 286036934Sbrian return -1; 286136934Sbrian 286246686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 286336934Sbrian cx = arg->cx; 286436934Sbrian if (!cx) 286536934Sbrian cx = bundle2datalink(arg->bundle, NULL); 286636934Sbrian if (!cx) { 286746686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 286836934Sbrian return 1; 286936934Sbrian } 287064652Sbrian t = &cx->physical->link.stats.total; 287136934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 287236934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 287381634Sbrian#ifndef NOINET6 287481634Sbrian else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0) 287581634Sbrian t = &arg->bundle->ncp.ipv6cp.throughput; 287681634Sbrian#endif 287736934Sbrian else 287836934Sbrian return -1; 287936934Sbrian 288036934Sbrian if (arg->argc > arg->argn + 1) { 288136934Sbrian clear_type = 0; 288236934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 288336934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 288436934Sbrian clear_type |= THROUGHPUT_OVERALL; 288536934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 288636934Sbrian clear_type |= THROUGHPUT_CURRENT; 288736934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 288836934Sbrian clear_type |= THROUGHPUT_PEAK; 288936934Sbrian else 289036934Sbrian return -1; 289136934Sbrian } else 289236934Sbrian clear_type = THROUGHPUT_ALL; 289336934Sbrian 289436934Sbrian throughput_clear(t, clear_type, arg->prompt); 289536934Sbrian return 0; 289636934Sbrian} 289740561Sbrian 289840561Sbrianstatic int 289940561SbrianRunListCommand(struct cmdargs const *arg) 290040561Sbrian{ 290140561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 290240561Sbrian 290364801Sbrian#ifndef NONAT 290464801Sbrian if (arg->cmd->args == NatCommands && 290564801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 290664801Sbrian if (arg->prompt) 290765550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 290864801Sbrian else 290965550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 291064801Sbrian } 291164801Sbrian#endif 291264801Sbrian 291340561Sbrian if (arg->argc > arg->argn) 291440561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 291540561Sbrian arg->prompt, arg->cx); 291640561Sbrian else if (arg->prompt) 291740561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 291840561Sbrian " <option>' for syntax help.\n", cmd, cmd); 291940561Sbrian else 292040561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 292140561Sbrian 292240561Sbrian return 0; 292340561Sbrian} 292440561Sbrian 292540561Sbrianstatic int 292640561SbrianIfaceAddCommand(struct cmdargs const *arg) 292740561Sbrian{ 292881634Sbrian struct ncpaddr peer, addr; 292981634Sbrian struct ncprange ifa; 293081634Sbrian struct in_addr mask; 293181634Sbrian int n, how; 293240561Sbrian 293340664Sbrian if (arg->argc == arg->argn + 1) { 293481634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 293540561Sbrian return -1; 293681634Sbrian ncpaddr_init(&peer); 293740664Sbrian } else { 293840664Sbrian if (arg->argc == arg->argn + 2) { 293981634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 294040664Sbrian return -1; 294140664Sbrian n = 1; 294240664Sbrian } else if (arg->argc == arg->argn + 3) { 294381634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn])) 294440664Sbrian return -1; 294581634Sbrian if (ncpaddr_family(&addr) != AF_INET) 294640664Sbrian return -1; 294781634Sbrian ncprange_sethost(&ifa, &addr); 294881634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1])) 294981634Sbrian return -1; 295081634Sbrian if (!ncpaddr_getip4(&addr, &mask)) 295181634Sbrian return -1; 295281634Sbrian if (!ncprange_setip4mask(&ifa, mask)) 295381634Sbrian return -1; 295440664Sbrian n = 2; 295540664Sbrian } else 295640561Sbrian return -1; 295740561Sbrian 295881634Sbrian if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n])) 295940664Sbrian return -1; 296081634Sbrian 296181634Sbrian if (ncprange_family(&ifa) != ncpaddr_family(&peer)) { 296281634Sbrian log_Printf(LogWARN, "IfaceAddCommand: src and dst address families" 296381634Sbrian " differ\n"); 296481634Sbrian return -1; 296581634Sbrian } 296640664Sbrian } 296740561Sbrian 296840561Sbrian how = IFACE_ADD_LAST; 296940561Sbrian if (arg->cmd->args) 297040561Sbrian how |= IFACE_FORCE_ADD; 297140561Sbrian 297281634Sbrian return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how); 297340561Sbrian} 297440561Sbrian 297540561Sbrianstatic int 297640561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 297740561Sbrian{ 297881634Sbrian struct ncpaddr ifa; 297981634Sbrian struct in_addr ifa4; 298040561Sbrian int ok; 298140561Sbrian 298240561Sbrian if (arg->argc != arg->argn + 1) 298340561Sbrian return -1; 298440561Sbrian 298581634Sbrian if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn])) 298640561Sbrian return -1; 298740561Sbrian 298840561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 298981634Sbrian ncpaddr_getip4(&ifa, &ifa4) && 299081634Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) { 299140561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 299281634Sbrian ncpaddr_ntoa(&ifa)); 299340561Sbrian return 1; 299440561Sbrian } 299540561Sbrian 299681634Sbrian ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa); 299740561Sbrian if (!ok) { 299840561Sbrian if (arg->cmd->args) 299940561Sbrian ok = 1; 300040561Sbrian else if (arg->prompt) 300181634Sbrian prompt_Printf(arg->prompt, "%s: No such interface address\n", 300281634Sbrian ncpaddr_ntoa(&ifa)); 300340561Sbrian else 300481634Sbrian log_Printf(LogWARN, "%s: No such interface address\n", 300581634Sbrian ncpaddr_ntoa(&ifa)); 300640561Sbrian } 300740561Sbrian 300840561Sbrian return !ok; 300940561Sbrian} 301040561Sbrian 301140561Sbrianstatic int 301240561SbrianIfaceClearCommand(struct cmdargs const *arg) 301340561Sbrian{ 301481634Sbrian int family, how; 301540561Sbrian 301681634Sbrian family = 0; 301781634Sbrian if (arg->argc == arg->argn + 1) { 301881634Sbrian if (strcasecmp(arg->argv[arg->argn], "inet") == 0) 301981634Sbrian family = AF_INET; 302081634Sbrian#ifndef NOINET6 302181634Sbrian else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0) 302281634Sbrian family = AF_INET6; 302381634Sbrian#endif 302481634Sbrian else 302581634Sbrian return -1; 302681634Sbrian } else if (arg->argc != arg->argn) 302740561Sbrian return -1; 302840561Sbrian 302940941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 303040941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 303140561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 303281634Sbrian iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how); 303340561Sbrian 303440561Sbrian return 0; 303540561Sbrian} 303640679Sbrian 303740679Sbrianstatic int 303840679SbrianSetProcTitle(struct cmdargs const *arg) 303940679Sbrian{ 304040679Sbrian static char title[LINE_LEN]; 304140679Sbrian char *argv[MAXARGS], *ptr; 304240679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 304340679Sbrian 304440679Sbrian if (arg->argc == arg->argn) { 304564698Sbrian SetTitle(NULL); 304640679Sbrian return 0; 304740679Sbrian } 304840679Sbrian 304940679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 305040679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 305140679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 305240679Sbrian } 305347849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 305440679Sbrian 305540679Sbrian ptr = title; 305640679Sbrian remaining = sizeof title - 1; 305740679Sbrian for (f = 0; f < argc && remaining; f++) { 305840679Sbrian if (f) { 305940679Sbrian *ptr++ = ' '; 306040679Sbrian remaining--; 306140679Sbrian } 306240679Sbrian len = strlen(argv[f]); 306340679Sbrian if (len > remaining) 306440679Sbrian len = remaining; 306540679Sbrian memcpy(ptr, argv[f], len); 306640679Sbrian remaining -= len; 306740679Sbrian ptr += len; 306840679Sbrian } 306940679Sbrian *ptr = '\0'; 307040679Sbrian 307164698Sbrian SetTitle(title); 307240679Sbrian 307340679Sbrian return 0; 307440679Sbrian} 3075