command.c revision 86028
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 86028 2001-11-04 16:19:05Z 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 16785362Sbrianconst char Version[] = "3.0.1"; 16836285Sbrian 16936285Sbrianstatic int ShowCommand(struct cmdargs const *); 17036285Sbrianstatic int TerminalCommand(struct cmdargs const *); 17136285Sbrianstatic int QuitCommand(struct cmdargs const *); 17236285Sbrianstatic int OpenCommand(struct cmdargs const *); 17336285Sbrianstatic int CloseCommand(struct cmdargs const *); 17436285Sbrianstatic int DownCommand(struct cmdargs const *); 17536285Sbrianstatic int SetCommand(struct cmdargs const *); 17636285Sbrianstatic int LinkCommand(struct cmdargs const *); 17736285Sbrianstatic int AddCommand(struct cmdargs const *); 17836285Sbrianstatic int DeleteCommand(struct cmdargs const *); 17936285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 18036934Sbrianstatic int ClearCommand(struct cmdargs const *); 18140561Sbrianstatic int RunListCommand(struct cmdargs const *); 18240561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 18340561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 18440561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 18540679Sbrianstatic int SetProcTitle(struct cmdargs const *); 18650059Sbrian#ifndef NONAT 18758867Sbrianstatic int NatEnable(struct cmdargs const *); 18858867Sbrianstatic int NatOption(struct cmdargs const *); 18931343Sbrian#endif 1906059Samurai 19136285Sbrianstatic const char * 19236285Sbrianshowcx(struct cmdtab const *cmd) 19336285Sbrian{ 19436285Sbrian if (cmd->lauth & LOCAL_CX) 19536285Sbrian return "(c)"; 19636285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 19736285Sbrian return "(o)"; 19836285Sbrian 19936285Sbrian return ""; 20036285Sbrian} 20136285Sbrian 2026059Samuraistatic int 20331343SbrianHelpCommand(struct cmdargs const *arg) 2046059Samurai{ 20528679Sbrian struct cmdtab const *cmd; 20636285Sbrian int n, cmax, dmax, cols, cxlen; 20736285Sbrian const char *cx; 2086059Samurai 20936285Sbrian if (!arg->prompt) { 21036285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 21126516Sbrian return 0; 21236285Sbrian } 21326516Sbrian 21436285Sbrian if (arg->argc > arg->argn) { 21536285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 21636285Sbrian if ((cmd->lauth & arg->prompt->auth) && 21736285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 21836285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 21936285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 22028679Sbrian return 0; 2216059Samurai } 22226516Sbrian return -1; 2236059Samurai } 22436285Sbrian 22531372Sbrian cmax = dmax = 0; 22636285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22736285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22836285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 22931372Sbrian cmax = n; 23031372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 23131372Sbrian dmax = n; 23231372Sbrian } 23331372Sbrian 23431372Sbrian cols = 80 / (dmax + cmax + 3); 2356059Samurai n = 0; 23636285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 23736285Sbrian " (c) = Context required\n"); 23836285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 23936285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 24036285Sbrian cx = showcx(cmd); 24136285Sbrian cxlen = cmax - strlen(cmd->name); 24240482Sbrian if (n % cols != 0) 24340482Sbrian prompt_Printf(arg->prompt, " "); 24440482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 24536285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 24631372Sbrian if (++n % cols == 0) 24736285Sbrian prompt_Printf(arg->prompt, "\n"); 2486059Samurai } 24931372Sbrian if (n % cols != 0) 25036285Sbrian prompt_Printf(arg->prompt, "\n"); 25126516Sbrian 25226516Sbrian return 0; 2536059Samurai} 2546059Samurai 25536285Sbrianstatic int 25663484SbrianIdentCommand(struct cmdargs const *arg) 25763484Sbrian{ 25885991Sbrian Concatinate(arg->cx->physical->link.lcp.cfg.ident, 25985991Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident, 26085991Sbrian arg->argc - arg->argn, arg->argv + arg->argn); 26163484Sbrian return 0; 26263484Sbrian} 26363484Sbrian 26463484Sbrianstatic int 26563484SbrianSendIdentification(struct cmdargs const *arg) 26663484Sbrian{ 26763484Sbrian if (arg->cx->state < DATALINK_LCP) { 26863484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 26963484Sbrian return 2; 27063484Sbrian } 27163484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 27263484Sbrian} 27363484Sbrian 27463484Sbrianstatic int 27536285SbrianCloneCommand(struct cmdargs const *arg) 2766059Samurai{ 27736285Sbrian char namelist[LINE_LEN]; 27836285Sbrian char *name; 27936285Sbrian int f; 2806059Samurai 28136285Sbrian if (arg->argc == arg->argn) 28236285Sbrian return -1; 28336285Sbrian 28436285Sbrian namelist[sizeof namelist - 1] = '\0'; 28536285Sbrian for (f = arg->argn; f < arg->argc; f++) { 28636285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 28736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 28836285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2896059Samurai } 29036285Sbrian 29136285Sbrian return 0; 2926059Samurai} 2936059Samurai 2946059Samuraistatic int 29536285SbrianRemoveCommand(struct cmdargs const *arg) 2966059Samurai{ 29736285Sbrian if (arg->argc != arg->argn) 29836285Sbrian return -1; 29911336Samurai 30036285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 30136285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 30236285Sbrian return 2; 3036059Samurai } 30426516Sbrian 30536285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 30636285Sbrian return 0; 30736285Sbrian} 30832711Sbrian 30936285Sbrianstatic int 31036285SbrianRenameCommand(struct cmdargs const *arg) 31136285Sbrian{ 31236285Sbrian if (arg->argc != arg->argn + 1) 31336285Sbrian return -1; 31431121Sbrian 31536285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 31636285Sbrian return 0; 31736285Sbrian 31836285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 31936285Sbrian arg->cx->name, arg->argv[arg->argn]); 32036285Sbrian return 1; 32136285Sbrian} 32236285Sbrian 32385991Sbrianstatic int 32436285SbrianLoadCommand(struct cmdargs const *arg) 32536285Sbrian{ 32640797Sbrian const char *err; 32740797Sbrian int n, mode; 32836285Sbrian 32940797Sbrian mode = arg->bundle->phys_type.all; 33036285Sbrian 33140797Sbrian if (arg->argn < arg->argc) { 33240797Sbrian for (n = arg->argn; n < arg->argc; n++) 33340797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 33440797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 33540797Sbrian return 1; 33640797Sbrian } 33740797Sbrian 33840797Sbrian for (n = arg->argn; n < arg->argc; n++) { 33940797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34040797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 34140797Sbrian } 34240797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34340797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 34440797Sbrian log_Printf(LogWARN, "default: %s\n", err); 34536285Sbrian return 1; 34636285Sbrian } else { 34740797Sbrian bundle_SetLabel(arg->bundle, "default"); 34840797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 34940797Sbrian bundle_SetLabel(arg->bundle, "default"); 35036285Sbrian } 35140797Sbrian 35226516Sbrian return 0; 3536059Samurai} 3546059Samurai 35585991Sbrianstatic int 35685991SbrianLogCommand(struct cmdargs const *arg) 35785991Sbrian{ 35885991Sbrian char buf[LINE_LEN]; 35985991Sbrian 36085991Sbrian if (arg->argn < arg->argc) { 36185991Sbrian char *argv[MAXARGS]; 36285991Sbrian int argc = arg->argc - arg->argn; 36385991Sbrian 36485991Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 36585991Sbrian argc = sizeof argv / sizeof argv[0] - 1; 36685991Sbrian log_Printf(LogWARN, "Truncating log command to %d args\n", argc); 36785991Sbrian } 36885991Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, getpid()); 36985991Sbrian Concatinate(buf, sizeof buf, argc, (const char *const *)argv); 37085991Sbrian log_Printf(LogLOG, "%s\n", buf); 37185991Sbrian command_Free(argc, argv); 37285991Sbrian return 0; 37385991Sbrian } 37485991Sbrian 37585991Sbrian return -1; 37685991Sbrian} 37785991Sbrian 37885991Sbrianstatic int 37936285SbrianSaveCommand(struct cmdargs const *arg) 38036285Sbrian{ 38185991Sbrian log_Printf(LogWARN, "save command is not yet implemented.\n"); 38236285Sbrian return 1; 38336285Sbrian} 38436285Sbrian 38510528Samuraistatic int 38636285SbrianDialCommand(struct cmdargs const *arg) 38728536Sbrian{ 38836285Sbrian int res; 38936285Sbrian 39036465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 39136465Sbrian || (!arg->cx && 39236928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 39336285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 39436285Sbrian " interactive links\n"); 39536285Sbrian return 1; 39634536Sbrian } 39736285Sbrian 39836285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 39936285Sbrian return res; 40036285Sbrian 40137993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 40236285Sbrian 40336285Sbrian return 0; 40428536Sbrian} 40528536Sbrian 40638628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 40738628Sbrian 40838628Sbrianstatic char * 40938628Sbrianstrstrword(char *big, const char *little) 41038628Sbrian{ 41138628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 41238628Sbrian char *pos; 41338628Sbrian int len; 41438628Sbrian 41538628Sbrian pos = big; 41638628Sbrian len = strlen(little); 41738628Sbrian 41838628Sbrian while ((pos = strstr(pos, little)) != NULL) 41947865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 42047865Sbrian pos++; 42147865Sbrian else if (pos != big && pos[-1] == '\\') 42247865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 42347865Sbrian else 42438628Sbrian break; 42538628Sbrian 42638628Sbrian return pos; 42738628Sbrian} 42838628Sbrian 42938628Sbrianstatic char * 43038628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 43138628Sbrian{ 43238628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 43338628Sbrian char *word, *ntgt; 43438628Sbrian int ltgt, loldstr, lnewstr, pos; 43538628Sbrian 43638628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 43738628Sbrian return tgt; 43838628Sbrian 43938628Sbrian ltgt = strlen(tgt) + 1; 44038628Sbrian loldstr = strlen(oldstr); 44138628Sbrian lnewstr = strlen(newstr); 44238628Sbrian do { 44338628Sbrian pos = word - tgt; 44438628Sbrian if (loldstr > lnewstr) 44538628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 44638628Sbrian if (loldstr != lnewstr) { 44738628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 44838628Sbrian if (ntgt == NULL) 44938628Sbrian break; /* Oh wonderful ! */ 45038628Sbrian word = ntgt + pos; 45138628Sbrian tgt = ntgt; 45238628Sbrian } 45338628Sbrian if (lnewstr > loldstr) 45438628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 45538628Sbrian bcopy(newstr, word, lnewstr); 45638628Sbrian } while ((word = strstrword(word, oldstr))); 45738628Sbrian 45838628Sbrian return tgt; 45938628Sbrian} 46038628Sbrian 46143888Sbrianvoid 46243888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 46347849Sbrian struct bundle *bundle, int inc0, pid_t pid) 46438628Sbrian{ 46585991Sbrian int arg, secs; 46685991Sbrian char buf[20]; 46747849Sbrian char pidstr[12]; 46838628Sbrian 46941755Sbrian if (inc0) 47041755Sbrian arg = 0; /* Start at arg 0 */ 47141755Sbrian else { 47241755Sbrian nargv[0] = strdup(oargv[0]); 47341755Sbrian arg = 1; 47441755Sbrian } 47547849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 47641755Sbrian for (; arg < argc; arg++) { 47738629Sbrian nargv[arg] = strdup(oargv[arg]); 47838629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 47938628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 48081634Sbrian#ifndef NOINET6 48181897Sbrian nargv[arg] = subst(nargv[arg], "HISADDR6", 48281897Sbrian ncpaddr_ntoa(&bundle->ncp.ipv6cp.hisaddr)); 48381634Sbrian#endif 48438629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 48540561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 48638628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 48781634Sbrian#ifndef NOINET6 48881897Sbrian nargv[arg] = subst(nargv[arg], "MYADDR6", 48981897Sbrian ncpaddr_ntoa(&bundle->ncp.ipv6cp.myaddr)); 49081634Sbrian#endif 49138629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 49238629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 49338629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 49438629Sbrian bundle->ncp.mp.peer.enddisc.address, 49538629Sbrian bundle->ncp.mp.peer.enddisc.len)); 49638629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 49738629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 49838629Sbrian bundle->ncp.mp.cfg.enddisc.address, 49938629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 50047849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 50138629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 50258044Sbrian nargv[arg] = subst(nargv[arg], "DNS0", 50358044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); 50458044Sbrian nargv[arg] = subst(nargv[arg], "DNS1", 50558044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); 50663484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 50763484Sbrian nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 50885991Sbrian 50985991Sbrian secs = bundle_Uptime(bundle); 51085991Sbrian snprintf(buf, sizeof buf, "%d:%02d:%02d", secs / 3600, (secs / 60) % 60, 51185991Sbrian secs % 60); 51285991Sbrian nargv[arg] = subst(nargv[arg], "UPTIME", buf); 51338628Sbrian } 51438628Sbrian nargv[arg] = NULL; 51538628Sbrian} 51638628Sbrian 51785991Sbrianvoid 51885991Sbriancommand_Free(int argc, char **argv) 51985991Sbrian{ 52085991Sbrian while (argc) { 52185991Sbrian free(*argv); 52285991Sbrian argc--; 52385991Sbrian argv++; 52485991Sbrian } 52585991Sbrian} 52685991Sbrian 52728536Sbrianstatic int 52831343SbrianShellCommand(struct cmdargs const *arg, int bg) 52910528Samurai{ 53010528Samurai const char *shell; 53147849Sbrian pid_t shpid, pid; 53220813Sjkh 53318856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 53426911Sbrian /* we're only allowed to shell when we run ppp interactively */ 53536285Sbrian if (arg->prompt && arg->prompt->owner) { 53636285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 53726516Sbrian return 1; 53810528Samurai } 53926911Sbrian#endif 54028679Sbrian 54136285Sbrian if (arg->argc == arg->argn) { 54236285Sbrian if (!arg->prompt) { 54336285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 54436285Sbrian " a config file\n"); 54528381Sbrian return 1; 54636285Sbrian } else if (arg->prompt->owner) { 54736285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 54836285Sbrian " a socket connection\n"); 54936285Sbrian return 1; 55028381Sbrian } else if (bg) { 55136285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 55228679Sbrian " the foreground mode\n"); 55328381Sbrian return 1; 55428381Sbrian } 55534536Sbrian } 55634536Sbrian 55747849Sbrian pid = getpid(); 55828679Sbrian if ((shpid = fork()) == 0) { 55936285Sbrian int i, fd; 56018531Sbde 56136285Sbrian if ((shell = getenv("SHELL")) == 0) 56236285Sbrian shell = _PATH_BSHELL; 56332017Sbrian 56436285Sbrian timer_TermService(); 56536285Sbrian 56636285Sbrian if (arg->prompt) 56736285Sbrian fd = arg->prompt->fd_out; 56836285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 56936285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 57036285Sbrian _PATH_DEVNULL, strerror(errno)); 57128679Sbrian exit(1); 57228679Sbrian } 57349976Sbrian dup2(fd, STDIN_FILENO); 57449976Sbrian dup2(fd, STDOUT_FILENO); 57549976Sbrian dup2(fd, STDERR_FILENO); 57649976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 57749976Sbrian fcntl(i, F_SETFD, 1); 57826516Sbrian 57964802Sbrian#ifndef NOSUID 58055252Sbrian setuid(ID0realuid()); 58164802Sbrian#endif 58236285Sbrian if (arg->argc > arg->argn) { 58328679Sbrian /* substitute pseudo args */ 58438628Sbrian char *argv[MAXARGS]; 58538628Sbrian int argc = arg->argc - arg->argn; 58638628Sbrian 58738628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 58838628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 58938628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 59031343Sbrian } 59147849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 59228679Sbrian if (bg) { 59328679Sbrian pid_t p; 59410528Samurai 59528679Sbrian p = getpid(); 59628679Sbrian if (daemon(1, 1) == -1) { 59736832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 59828679Sbrian exit(1); 59928679Sbrian } 60036285Sbrian } else if (arg->prompt) 60136285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 60231343Sbrian execvp(argv[0], argv); 60330316Sbrian } else { 60436285Sbrian if (arg->prompt) 60532017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 60636285Sbrian prompt_TtyOldMode(arg->prompt); 60779450Sbrian execl(shell, shell, (char *)NULL); 60830316Sbrian } 60920813Sjkh 61040665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 61140665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 61240665Sbrian strerror(errno)); 61349976Sbrian _exit(255); 61410528Samurai } 61536285Sbrian 61636285Sbrian if (shpid == (pid_t) - 1) 61736285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 61836285Sbrian else { 61910528Samurai int status; 62031343Sbrian waitpid(shpid, &status, 0); 62110528Samurai } 62220813Sjkh 62336285Sbrian if (arg->prompt && !arg->prompt->owner) 62436285Sbrian prompt_TtyCommandMode(arg->prompt); 62520813Sjkh 62636285Sbrian return 0; 62710528Samurai} 62810528Samurai 62931343Sbrianstatic int 63031343SbrianBgShellCommand(struct cmdargs const *arg) 63131343Sbrian{ 63236285Sbrian if (arg->argc == arg->argn) 63331343Sbrian return -1; 63431343Sbrian return ShellCommand(arg, 1); 63531343Sbrian} 63631343Sbrian 63731343Sbrianstatic int 63831343SbrianFgShellCommand(struct cmdargs const *arg) 63931343Sbrian{ 64031343Sbrian return ShellCommand(arg, 0); 64131343Sbrian} 64231343Sbrian 64358044Sbrianstatic int 64458044SbrianResolvCommand(struct cmdargs const *arg) 64558044Sbrian{ 64658044Sbrian if (arg->argc == arg->argn + 1) { 64758044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 64858044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 64958044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 65058044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 65158044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 65258044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 65358044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 65458044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 65558044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 65658044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 65758044Sbrian else 65858044Sbrian return -1; 65958044Sbrian 66058044Sbrian return 0; 66158044Sbrian } 66258044Sbrian 66358044Sbrian return -1; 66458044Sbrian} 66558044Sbrian 66650059Sbrian#ifndef NONAT 66758867Sbrianstatic struct cmdtab const NatCommands[] = 66840561Sbrian{ 66950059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 67050059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 67158867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 67250059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 67340561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 67458867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 67550059Sbrian "enable NAT", "nat enable yes|no"}, 67658867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 67750059Sbrian "log NAT link creation", "nat log yes|no", 67840561Sbrian (const void *) PKT_ALIAS_LOG}, 67950059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 68050059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 68179433Sbrian {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 68279433Sbrian "nat proto proto localIP [publicIP [remoteIP]]"}, 68350059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 68450059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 68581033Sbrian#ifndef NO_FW_PUNCH 68681033Sbrian {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 68781033Sbrian "firewall control", "nat punch_fw [base count]"}, 68881033Sbrian#endif 68958867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 69050059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 69140561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 69258867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 69358867Sbrian "Default address for incoming connections", "nat target addr" }, 69458867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 69550059Sbrian "translate unregistered (private) IP address space only", 69650059Sbrian "nat unregistered_only yes|no", 69740561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 69858867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 69950059Sbrian "allocate host sockets", "nat use_sockets yes|no", 70040561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 70140561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 70258867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 70340561Sbrian {NULL, NULL, NULL}, 70440561Sbrian}; 70540561Sbrian#endif 70640561Sbrian 70740561Sbrianstatic struct cmdtab const AllowCommands[] = { 70840561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 70940561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 71040561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 71140561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 71240561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 71340561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 71440561Sbrian {NULL, NULL, NULL}, 71540561Sbrian}; 71640561Sbrian 71740561Sbrianstatic struct cmdtab const IfaceCommands[] = 71840561Sbrian{ 71940561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 72040561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 72140561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 72240561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 72340561Sbrian (void *)1}, 72440561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 72581634Sbrian "Clear iface address(es)", "iface clear [INET | INET6]"}, 72640561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 72740561Sbrian "Delete iface address", "iface delete addr", NULL}, 72840561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 72940561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 73040561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 73140561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 73240561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 73340561Sbrian "Show iface address(es)", "iface show"}, 73440561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 73550059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 73640561Sbrian {NULL, NULL, NULL}, 73740561Sbrian}; 73840561Sbrian 73930715Sbrianstatic struct cmdtab const Commands[] = { 74036285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 74128679Sbrian "accept option request", "accept option .."}, 74228679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 74332109Sbrian "add route", "add dest mask gateway", NULL}, 74436285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 74532109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 74640561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 74740561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 74828679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 74931372Sbrian "Run a background command", "[!]bg command"}, 75036934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 75146686Sbrian "Clear throughput statistics", 75281634Sbrian "clear ipcp|ipv6cp|physical [current|overall|peak]..."}, 75336285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 75436285Sbrian "Clone a link", "clone newname..."}, 75536285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 75636285Sbrian "Close an FSM", "close [lcp|ccp]"}, 75728679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 75832109Sbrian "delete route", "delete dest", NULL}, 75936285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 76032109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 76136285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 76228679Sbrian "Deny option request", "deny option .."}, 76336285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 76440797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 76536285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 76628679Sbrian "Disable option", "disable option .."}, 76736285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 76846686Sbrian "Generate a down event", "down [ccp|lcp]"}, 76936285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 77028679Sbrian "Enable option", "enable option .."}, 77163484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 77263484Sbrian "Set the link identity", "ident text..."}, 77340561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 77440561Sbrian "interface control", "iface option ...", IfaceCommands}, 77536285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 77636285Sbrian "Link specific commands", "link name command ..."}, 77737008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 77840797Sbrian "Load settings", "load [system ...]"}, 77985991Sbrian {"log", NULL, LogCommand, LOCAL_AUTH | LOCAL_CX_OPT, 78085991Sbrian "log information", "log word ..."}, 78150059Sbrian#ifndef NONAT 78250059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 78358867Sbrian "NAT control", "nat option yes|no", NatCommands}, 78450059Sbrian#endif 78536285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 78637955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 78736285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 78836285Sbrian "Password for manipulation", "passwd LocalPassword"}, 78936285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 79036285Sbrian "Quit PPP program", "quit|bye [all]"}, 79136285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 79236285Sbrian "Remove a link", "remove"}, 79336285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 79436285Sbrian "Rename a link", "rename name"}, 79558044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 79658044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 79728679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 79828679Sbrian "Save settings", "save"}, 79963484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 80063484Sbrian "Transmit the link identity", "sendident"}, 80136285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 80228679Sbrian "Set parameters", "set[up] var value"}, 80328679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 80428679Sbrian "Run a subshell", "shell|! [sh command]"}, 80536285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 80631372Sbrian "Show status and stats", "show var"}, 80736285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 80831372Sbrian "Enter terminal mode", "term"}, 80928679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 81031343Sbrian "Display this message", "help|? [command]", Commands}, 81128679Sbrian {NULL, NULL, NULL}, 8126059Samurai}; 8136059Samurai 81428536Sbrianstatic int 81531343SbrianShowEscape(struct cmdargs const *arg) 8166059Samurai{ 81736285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 81836285Sbrian int code, bit; 81936285Sbrian const char *sep = ""; 8206059Samurai 82126516Sbrian for (code = 0; code < 32; code++) 82236285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 82328679Sbrian for (bit = 0; bit < 8; bit++) 82436285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 82536285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 82636285Sbrian sep = ", "; 82736285Sbrian } 82836285Sbrian prompt_Printf(arg->prompt, "\n"); 8296059Samurai } 83031077Sbrian return 0; 8316059Samurai} 8326059Samurai 83328679Sbrianstatic int 83436285SbrianShowTimerList(struct cmdargs const *arg) 8356059Samurai{ 83636285Sbrian timer_Show(0, arg->prompt); 83731077Sbrian return 0; 8386059Samurai} 8396059Samurai 84028679Sbrianstatic int 84131343SbrianShowStopped(struct cmdargs const *arg) 84228327Sbrian{ 84336285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 84436285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 84536285Sbrian prompt_Printf(arg->prompt, "Disabled"); 84628327Sbrian else 84736285Sbrian prompt_Printf(arg->prompt, "%ld secs", 84836285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 84928461Sbrian 85036285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 85136285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 85236285Sbrian prompt_Printf(arg->prompt, "Disabled"); 85328461Sbrian else 85436285Sbrian prompt_Printf(arg->prompt, "%ld secs", 85536285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 85628461Sbrian 85736285Sbrian prompt_Printf(arg->prompt, "\n"); 85828461Sbrian 85931077Sbrian return 0; 86028327Sbrian} 86128327Sbrian 86228679Sbrianstatic int 86331343SbrianShowVersion(struct cmdargs const *arg) 8646059Samurai{ 86551026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 86631077Sbrian return 0; 8676059Samurai} 8686059Samurai 86928679Sbrianstatic int 87036285SbrianShowProtocolStats(struct cmdargs const *arg) 87126326Sbrian{ 87236285Sbrian struct link *l = command_ChooseLink(arg); 87326326Sbrian 87436285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 87536285Sbrian link_ReportProtocolStatus(l, arg->prompt); 87631077Sbrian return 0; 87726326Sbrian} 87826326Sbrian 87930715Sbrianstatic struct cmdtab const ShowCommands[] = { 88036285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 88136285Sbrian "bundle details", "show bundle"}, 88236285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 88336285Sbrian "CCP status", "show cpp"}, 88436285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 88536285Sbrian "VJ compression stats", "show compress"}, 88636285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 88736285Sbrian "escape characters", "show escape"}, 88836285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 88936285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 89036285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 89136285Sbrian "HDLC errors", "show hdlc"}, 89240561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 89340561Sbrian "Interface status", "show iface"}, 89436285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 89536285Sbrian "IPCP status", "show ipcp"}, 89681634Sbrian#ifndef NOINET6 89781634Sbrian {"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH, 89881634Sbrian "IPV6CP status", "show ipv6cp"}, 89981634Sbrian#endif 90047211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 90147211Sbrian "Protocol layers", "show layers"}, 90236285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 90336285Sbrian "LCP status", "show lcp"}, 90436285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 90536285Sbrian "(high-level) link info", "show link"}, 90636285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 90736285Sbrian "available link names", "show links"}, 90836285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 90936285Sbrian "log levels", "show log"}, 91036285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 91136285Sbrian "mbuf allocations", "show mem"}, 91281634Sbrian {"ncp", NULL, ncp_Show, LOCAL_AUTH, 91381634Sbrian "NCP status", "show ncp"}, 91446686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 91546686Sbrian "(low-level) link info", "show physical"}, 91636285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 91736285Sbrian "multilink setup", "show mp"}, 91836285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 91936285Sbrian "protocol summary", "show proto"}, 92036285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 92136285Sbrian "routing table", "show route"}, 92236285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 92336285Sbrian "STOPPED timeout", "show stopped"}, 92436285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 92536285Sbrian "alarm timers", "show timers"}, 92628679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 92736285Sbrian "version string", "show version"}, 92836285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 92936285Sbrian "client list", "show who"}, 93028679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 93131343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 93228679Sbrian {NULL, NULL, NULL}, 9336059Samurai}; 9346059Samurai 93530715Sbrianstatic struct cmdtab const * 93631343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 9376059Samurai{ 93826516Sbrian int nmatch; 93926516Sbrian int len; 94028679Sbrian struct cmdtab const *found; 9416059Samurai 94226516Sbrian found = NULL; 94326516Sbrian len = strlen(str); 94426516Sbrian nmatch = 0; 9456059Samurai while (cmds->func) { 94625566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 94726516Sbrian if (cmds->name[len] == '\0') { 94828679Sbrian *pmatch = 1; 94928679Sbrian return cmds; 95026516Sbrian } 9516059Samurai nmatch++; 9526059Samurai found = cmds; 95328679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 95426516Sbrian if (cmds->alias[len] == '\0') { 95528679Sbrian *pmatch = 1; 95628679Sbrian return cmds; 95726516Sbrian } 9586059Samurai nmatch++; 9596059Samurai found = cmds; 9606059Samurai } 9616059Samurai cmds++; 9626059Samurai } 9636059Samurai *pmatch = nmatch; 96426516Sbrian return found; 9656059Samurai} 9666059Samurai 96736285Sbrianstatic const char * 96836285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 96936285Sbrian{ 97036285Sbrian int f, tlen, len; 97136285Sbrian 97236285Sbrian tlen = 0; 97336285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 97436285Sbrian if (f) 97536285Sbrian tgt[tlen++] = ' '; 97636285Sbrian len = strlen(argv[f]); 97736285Sbrian if (len > sz - tlen - 1) 97836285Sbrian len = sz - tlen - 1; 97936285Sbrian strncpy(tgt+tlen, argv[f], len); 98036285Sbrian tlen += len; 98136285Sbrian } 98236285Sbrian tgt[tlen] = '\0'; 98336285Sbrian return tgt; 98436285Sbrian} 98536285Sbrian 98630715Sbrianstatic int 98736285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 98836285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 9896059Samurai{ 99028679Sbrian struct cmdtab const *cmd; 9916059Samurai int val = 1; 9926059Samurai int nmatch; 99331343Sbrian struct cmdargs arg; 99436285Sbrian char prefix[100]; 9956059Samurai 99636285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 9976059Samurai if (nmatch > 1) 99836285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 99936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 100036285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 100136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 100236285Sbrian /* We've got no context, but we require it */ 100336285Sbrian cx = bundle2datalink(bundle, NULL); 100436285Sbrian 100536285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 100636285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 100736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 100836285Sbrian else { 100936285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 101036285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 101136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 101236285Sbrian cx = NULL; 101336285Sbrian } 101436285Sbrian arg.cmdtab = cmds; 101536285Sbrian arg.cmd = cmd; 101636285Sbrian arg.argc = argc; 101736285Sbrian arg.argn = argn+1; 101836285Sbrian arg.argv = argv; 101936285Sbrian arg.bundle = bundle; 102036285Sbrian arg.cx = cx; 102136285Sbrian arg.prompt = prompt; 102236285Sbrian val = (*cmd->func) (&arg); 102336285Sbrian } 102431343Sbrian } else 102536285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 102636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 102726516Sbrian 102826516Sbrian if (val == -1) 102936285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 103028679Sbrian else if (val) 103136285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 103236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 103326516Sbrian 103426516Sbrian return val; 10356059Samurai} 10366059Samurai 103737009Sbrianint 103858045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 103958045Sbrian{ 104058045Sbrian char buff2[LINE_LEN-offset]; 104158045Sbrian 104258045Sbrian InterpretArg(buff, buff2); 104358045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 104458045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 104558045Sbrian 104658045Sbrian return command_Interpret(buff, nb, argv); 104758045Sbrian} 104858045Sbrian 104958045Sbrianint 105037009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 10516059Samurai{ 10526059Samurai char *cp; 10536059Samurai 10546059Samurai if (nb > 0) { 10556059Samurai cp = buff + strcspn(buff, "\r\n"); 10566059Samurai if (cp) 10576059Samurai *cp = '\0'; 105855145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 105937009Sbrian } 106037009Sbrian return 0; 106131121Sbrian} 10626059Samurai 106331822Sbrianstatic int 106431822Sbrianarghidden(int argc, char const *const *argv, int n) 106531822Sbrian{ 106631822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 106731828Sbrian 106831828Sbrian /* set authkey xxxxx */ 106931828Sbrian /* set key xxxxx */ 107031822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 107131822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 107231822Sbrian return 1; 107331822Sbrian 107431828Sbrian /* passwd xxxxx */ 107531828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 107631828Sbrian return 1; 107731828Sbrian 107836285Sbrian /* set server port xxxxx .... */ 107936285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 108036285Sbrian !strncasecmp(argv[1], "se", 2)) 108136285Sbrian return 1; 108236285Sbrian 108331822Sbrian return 0; 108431822Sbrian} 108531822Sbrian 108631121Sbrianvoid 108736285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 108837008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 108931121Sbrian{ 109031156Sbrian if (argc > 0) { 109136285Sbrian if (log_IsKept(LogCOMMAND)) { 109247844Sbrian char buf[LINE_LEN]; 109331156Sbrian int f, n; 109431156Sbrian 109531156Sbrian if (label) { 109631962Sbrian strncpy(buf, label, sizeof buf - 3); 109731962Sbrian buf[sizeof buf - 3] = '\0'; 109831156Sbrian strcat(buf, ": "); 109947844Sbrian n = strlen(buf); 110047844Sbrian } else { 110147844Sbrian *buf = '\0'; 110247844Sbrian n = 0; 110331156Sbrian } 110447844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 110547844Sbrian 110631156Sbrian for (f = 0; f < argc; f++) { 110731962Sbrian if (n < sizeof buf - 1 && f) 110831156Sbrian buf[n++] = ' '; 110931822Sbrian if (arghidden(argc, argv, f)) 111036285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 111131822Sbrian else 111231962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 111331156Sbrian n += strlen(buf+n); 111431156Sbrian } 111536285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 111631156Sbrian } 111737008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 111831156Sbrian } 11196059Samurai} 11206059Samurai 112154914Sbrianint 112236285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 112336285Sbrian const char *label) 112431121Sbrian{ 112531121Sbrian int argc; 112637009Sbrian char *argv[MAXARGS]; 112731121Sbrian 112858045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 112954914Sbrian return 0; 113054914Sbrian 113137008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 113254914Sbrian return 1; 113331121Sbrian} 113431121Sbrian 11356059Samuraistatic int 113631343SbrianShowCommand(struct cmdargs const *arg) 11376059Samurai{ 113836285Sbrian if (!arg->prompt) 113936285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 114036285Sbrian else if (arg->argc > arg->argn) 114136285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 114236285Sbrian arg->prompt, arg->cx); 11436059Samurai else 114436285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 114526516Sbrian 114626516Sbrian return 0; 11476059Samurai} 11486059Samurai 11496059Samuraistatic int 115031343SbrianTerminalCommand(struct cmdargs const *arg) 11516059Samurai{ 115236285Sbrian if (!arg->prompt) { 115336285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 115426516Sbrian return 1; 11556059Samurai } 115636285Sbrian 115736285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 115836285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 115936285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 116036285Sbrian return 1; 11616059Samurai } 116236285Sbrian 116336285Sbrian datalink_Up(arg->cx, 0, 0); 116436285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 116536285Sbrian return 0; 11666059Samurai} 11676059Samurai 11686059Samuraistatic int 116931343SbrianQuitCommand(struct cmdargs const *arg) 11706059Samurai{ 117136285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 117236285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 117336285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 117436285Sbrian Cleanup(EX_NORMAL); 117536285Sbrian if (arg->prompt) 117636285Sbrian prompt_Destroy(arg->prompt, 1); 117726516Sbrian 117826516Sbrian return 0; 11796059Samurai} 11806059Samurai 11816059Samuraistatic int 118236285SbrianOpenCommand(struct cmdargs const *arg) 11836059Samurai{ 118437160Sbrian if (arg->argc == arg->argn) 118537993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 118637160Sbrian else if (arg->argc == arg->argn + 1) { 118737160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 118837385Sbrian struct datalink *cx = arg->cx ? 118937385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 119037385Sbrian if (cx) { 119137385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 119237385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 119337160Sbrian else 119437993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 119537160Sbrian } else 119637160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 119737160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 119837160Sbrian struct fsm *fp; 11996059Samurai 120037210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 120137160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 120237160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 120337160Sbrian else if (fp->state == ST_OPENED) 120437160Sbrian fsm_Reopen(fp); 120537160Sbrian else { 120637160Sbrian fp->open_mode = 0; /* Not passive any more */ 120737160Sbrian if (fp->state == ST_STOPPED) { 120837160Sbrian fsm_Down(fp); 120937160Sbrian fsm_Up(fp); 121037160Sbrian } else { 121137160Sbrian fsm_Up(fp); 121237160Sbrian fsm_Open(fp); 121337160Sbrian } 121436285Sbrian } 121537160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 121637160Sbrian if (arg->cx) 121737160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 121837160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 121937160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 122037160Sbrian else 122137993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 122237160Sbrian } else 122337160Sbrian return -1; 122436285Sbrian } else 122536285Sbrian return -1; 122636285Sbrian 122726516Sbrian return 0; 12286059Samurai} 12296059Samurai 123025067Sbrianstatic int 123136285SbrianCloseCommand(struct cmdargs const *arg) 12326059Samurai{ 123337007Sbrian if (arg->argc == arg->argn) 123437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 123537007Sbrian else if (arg->argc == arg->argn + 1) { 123637007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 123737007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 123837007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 123937007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 124037007Sbrian struct fsm *fp; 12416059Samurai 124237210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 124337007Sbrian if (fp->state == ST_OPENED) { 124437007Sbrian fsm_Close(fp); 124537007Sbrian if (arg->argv[arg->argn][3] == '!') 124637007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 124737007Sbrian else 124837007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 124937007Sbrian } 125037007Sbrian } else 125136285Sbrian return -1; 125236285Sbrian } else 125336285Sbrian return -1; 125436285Sbrian 125536285Sbrian return 0; 12566059Samurai} 12576059Samurai 125825067Sbrianstatic int 125936285SbrianDownCommand(struct cmdargs const *arg) 126011336Samurai{ 126137018Sbrian if (arg->argc == arg->argn) { 126237018Sbrian if (arg->cx) 126337018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 126437018Sbrian else 126537018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 126637018Sbrian } else if (arg->argc == arg->argn + 1) { 126737018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 126837018Sbrian if (arg->cx) 126937018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 127037018Sbrian else 127137018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 127237018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 127337018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 127437018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 127537060Sbrian fsm2initial(fp); 127637018Sbrian } else 127737018Sbrian return -1; 127836285Sbrian } else 127936285Sbrian return -1; 128036285Sbrian 128136285Sbrian return 0; 128225067Sbrian} 128325067Sbrian 128425067Sbrianstatic int 128536285SbrianSetModemSpeed(struct cmdargs const *arg) 128625067Sbrian{ 128736285Sbrian long speed; 128836285Sbrian char *end; 128911336Samurai 129036285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 129136285Sbrian if (arg->argc > arg->argn+1) { 129254917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 129336285Sbrian return -1; 129411336Samurai } 129536285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 129636285Sbrian physical_SetSync(arg->cx->physical); 129736285Sbrian return 0; 129836285Sbrian } 129936285Sbrian end = NULL; 130036285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 130136285Sbrian if (*end) { 130236285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 130336285Sbrian arg->argv[arg->argn]); 130436285Sbrian return -1; 130536285Sbrian } 130636285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 130736285Sbrian return 0; 130836285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 130936285Sbrian } else 131036285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 131124939Sbrian 131226516Sbrian return -1; 131311336Samurai} 131411336Samurai 131525067Sbrianstatic int 131631343SbrianSetStoppedTimeout(struct cmdargs const *arg) 131728327Sbrian{ 131836285Sbrian struct link *l = &arg->cx->physical->link; 131936285Sbrian 132036285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 132136285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 132236285Sbrian if (arg->argc <= arg->argn+2) { 132336285Sbrian if (arg->argc > arg->argn) { 132436285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 132536285Sbrian if (arg->argc > arg->argn+1) 132636285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 132728461Sbrian } 132828327Sbrian return 0; 132928327Sbrian } 133028327Sbrian return -1; 133128327Sbrian} 133228327Sbrian 133328327Sbrianstatic int 133431343SbrianSetServer(struct cmdargs const *arg) 133526940Sbrian{ 133626940Sbrian int res = -1; 133726940Sbrian 133836285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 133931081Sbrian const char *port, *passwd, *mask; 134053125Sbrian int mlen; 134131081Sbrian 134231081Sbrian /* What's what ? */ 134336285Sbrian port = arg->argv[arg->argn]; 134436285Sbrian if (arg->argc == arg->argn + 2) { 134536285Sbrian passwd = arg->argv[arg->argn+1]; 134636285Sbrian mask = NULL; 134736285Sbrian } else if (arg->argc == arg->argn + 3) { 134836285Sbrian passwd = arg->argv[arg->argn+1]; 134936285Sbrian mask = arg->argv[arg->argn+2]; 135053125Sbrian mlen = strlen(mask); 135153125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 135253125Sbrian (mlen == 4 && *mask != '0')) { 135353125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 135453125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 135531081Sbrian return -1; 135653125Sbrian } 135771764Sbrian } else if (arg->argc != arg->argn + 1) 135871764Sbrian return -1; 135971764Sbrian else if (strcasecmp(port, "none") == 0) { 136071657Sbrian if (server_Clear(arg->bundle)) 136171657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 136271657Sbrian return 0; 136371657Sbrian } else if (strcasecmp(port, "open") == 0) { 136471657Sbrian switch (server_Reopen(arg->bundle)) { 136571657Sbrian case SERVER_OK: 136671657Sbrian return 0; 136771657Sbrian case SERVER_FAILED: 136871764Sbrian log_Printf(LogWARN, "Failed to reopen server port\n"); 136971657Sbrian return 1; 137071657Sbrian case SERVER_UNSET: 137171764Sbrian log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 137271657Sbrian return 1; 137371657Sbrian default: 137471657Sbrian break; 137571657Sbrian } 137671657Sbrian return -1; 137771657Sbrian } else if (strcasecmp(port, "closed") == 0) { 137836285Sbrian if (server_Close(arg->bundle)) 137971657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 138071657Sbrian else 138171657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 138271657Sbrian 138336285Sbrian return 0; 138431081Sbrian } else 138536285Sbrian return -1; 138631081Sbrian 138771657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 138871657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 138931081Sbrian 139036285Sbrian if (*port == '/') { 139131081Sbrian mode_t imask; 139236285Sbrian char *ptr, name[LINE_LEN + 12]; 139328679Sbrian 139453125Sbrian if (mask == NULL) 139531081Sbrian imask = (mode_t)-1; 139653125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 139753125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 139836285Sbrian 139936285Sbrian ptr = strstr(port, "%d"); 140036285Sbrian if (ptr) { 140136285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 140237210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 140336285Sbrian port = name; 140436285Sbrian } 140536285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 140627346Sbrian } else { 140736285Sbrian int iport, add = 0; 140828679Sbrian 140931081Sbrian if (mask != NULL) 141031081Sbrian return -1; 141128679Sbrian 141236285Sbrian if (*port == '+') { 141336285Sbrian port++; 141436285Sbrian add = 1; 141536285Sbrian } 141631081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 141731081Sbrian struct servent *s; 141831081Sbrian 141931081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 142031081Sbrian iport = 0; 142136285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 142228679Sbrian } else 142331081Sbrian iport = ntohs(s->s_port); 142427346Sbrian } else 142531081Sbrian iport = atoi(port); 142636285Sbrian 142736285Sbrian if (iport) { 142836285Sbrian if (add) 142936285Sbrian iport += arg->bundle->unit; 143036285Sbrian res = server_TcpOpen(arg->bundle, iport); 143136285Sbrian } else 143236285Sbrian res = -1; 143327346Sbrian } 143431081Sbrian } 143526940Sbrian 143626940Sbrian return res; 143726940Sbrian} 143826940Sbrian 143926940Sbrianstatic int 144031343SbrianSetEscape(struct cmdargs const *arg) 14416059Samurai{ 14426059Samurai int code; 144336285Sbrian int argc = arg->argc - arg->argn; 144436285Sbrian char const *const *argv = arg->argv + arg->argn; 14456059Samurai 14466059Samurai for (code = 0; code < 33; code++) 144736285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 144831343Sbrian 14496059Samurai while (argc-- > 0) { 14506059Samurai sscanf(*argv++, "%x", &code); 14516059Samurai code &= 0xff; 145236285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 145336285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 14546059Samurai } 145526516Sbrian return 0; 14566059Samurai} 14576059Samurai 14586059Samuraistatic int 145931343SbrianSetInterfaceAddr(struct cmdargs const *arg) 14606059Samurai{ 146181634Sbrian struct ncp *ncp = &arg->bundle->ncp; 146281634Sbrian struct ncpaddr ncpaddr; 146332267Sbrian const char *hisaddr; 146432267Sbrian 146540561Sbrian if (arg->argc > arg->argn + 4) 146640561Sbrian return -1; 146740561Sbrian 146832267Sbrian hisaddr = NULL; 146981634Sbrian memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range); 147081634Sbrian memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range); 147181634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 0; 147281634Sbrian ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY; 147381634Sbrian iplist_reset(&ncp->ipcp.cfg.peer_list); 147428394Sbrian 147536285Sbrian if (arg->argc > arg->argn) { 147681634Sbrian if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn])) 147728679Sbrian return 1; 147836285Sbrian if (arg->argc > arg->argn+1) { 147936285Sbrian hisaddr = arg->argv[arg->argn+1]; 148036285Sbrian if (arg->argc > arg->argn+2) { 148181634Sbrian ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask = 148281634Sbrian GetIpAddr(arg->argv[arg->argn+2]); 148336285Sbrian if (arg->argc > arg->argn+3) { 148481634Sbrian ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 148581634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 1; 14869440Samurai } 14876059Samurai } 14886059Samurai } 14896059Samurai } 149028394Sbrian 149140561Sbrian /* 0.0.0.0 means any address (0 bits) */ 149281634Sbrian ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip); 149381634Sbrian ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr); 149481634Sbrian if (ncp->ipcp.my_ip.s_addr == INADDR_ANY) 149581634Sbrian ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0); 149681634Sbrian bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL); 149736285Sbrian 149836285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 149936928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 150032267Sbrian return 4; 150131121Sbrian 150226516Sbrian return 0; 15036059Samurai} 15046059Samurai 150518752Sjkhstatic int 150644305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 150744305Sbrian u_int *maxtrm, int def) 150844305Sbrian{ 150944305Sbrian if (argc == 0) { 151044305Sbrian *timeout = DEF_FSMRETRY; 151144305Sbrian *maxreq = def; 151244305Sbrian if (maxtrm != NULL) 151344305Sbrian *maxtrm = def; 151444305Sbrian } else { 151544305Sbrian long l = atol(argv[0]); 151644305Sbrian 151744305Sbrian if (l < MIN_FSMRETRY) { 151844305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 151944305Sbrian l, MIN_FSMRETRY); 152044305Sbrian return 1; 152144305Sbrian } else 152244305Sbrian *timeout = l; 152344305Sbrian 152444305Sbrian if (argc > 1) { 152544305Sbrian l = atol(argv[1]); 152644305Sbrian if (l < 1) { 152744305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 152844305Sbrian l = 1; 152944305Sbrian } 153044305Sbrian *maxreq = l; 153144305Sbrian 153244305Sbrian if (argc > 2 && maxtrm != NULL) { 153344305Sbrian l = atol(argv[2]); 153444305Sbrian if (l < 1) { 153544305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 153644305Sbrian l = 1; 153744305Sbrian } 153844305Sbrian *maxtrm = l; 153944305Sbrian } 154044305Sbrian } 154144305Sbrian } 154244305Sbrian 154344305Sbrian return 0; 154444305Sbrian} 154544305Sbrian 154644305Sbrianstatic int 154731343SbrianSetVariable(struct cmdargs const *arg) 15486059Samurai{ 154937210Sbrian long long_val, param = (long)arg->cmd->args; 155079119Sbrian int mode, dummyint, f, first, res; 155178410Sbrian u_short *change; 155231343Sbrian const char *argp; 155336285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 155436285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 155581634Sbrian struct in_addr *ipaddr; 155681634Sbrian struct ncpaddr ncpaddr[2]; 15576059Samurai 155836285Sbrian if (arg->argc > arg->argn) 155936285Sbrian argp = arg->argv[arg->argn]; 156026551Sbrian else 156131343Sbrian argp = ""; 156226551Sbrian 156379119Sbrian res = 0; 156479119Sbrian 156536285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 156636285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 156736285Sbrian arg->cmd->name); 156836285Sbrian return 1; 156936285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 157036285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 157136285Sbrian arg->cmd->name, cx->name); 157236285Sbrian cx = NULL; 157336285Sbrian } 157436285Sbrian 157526551Sbrian switch (param) { 157628679Sbrian case VAR_AUTHKEY: 157750139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 157850139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 157950139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 158028679Sbrian break; 158137210Sbrian 158228679Sbrian case VAR_AUTHNAME: 158340622Sbrian switch (bundle_Phase(arg->bundle)) { 158458880Sbrian default: 158558880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 158658880Sbrian bundle_PhaseName(arg->bundle)); 158758880Sbrian /* drop through */ 158840622Sbrian case PHASE_DEAD: 158940622Sbrian case PHASE_ESTABLISH: 159040622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 159140622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 159240622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 159340622Sbrian break; 159436285Sbrian } 159528679Sbrian break; 159637210Sbrian 159736285Sbrian case VAR_AUTOLOAD: 159849434Sbrian if (arg->argc == arg->argn + 3) { 159949434Sbrian int v1, v2, v3; 160049434Sbrian char *end; 160149434Sbrian 160249434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 160349434Sbrian if (v1 < 0 || *end) { 160449434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 160549434Sbrian arg->argv[arg->argn]); 160679119Sbrian res = 1; 160779119Sbrian break; 160836285Sbrian } 160949434Sbrian 161049434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 161149434Sbrian if (v2 < 0 || *end) { 161249434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 161349434Sbrian arg->argv[arg->argn + 1]); 161479119Sbrian res = 1; 161579119Sbrian break; 161649434Sbrian } 161749434Sbrian if (v2 < v1) { 161849434Sbrian v3 = v1; 161949434Sbrian v1 = v2; 162049434Sbrian v2 = v3; 162149434Sbrian } 162249434Sbrian 162349434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 162449434Sbrian if (v3 <= 0 || *end) { 162549434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 162649434Sbrian arg->argv[arg->argn + 2]); 162779119Sbrian res = 1; 162879119Sbrian break; 162949434Sbrian } 163049434Sbrian 163149434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 163249434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 163349434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 163449434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 163536285Sbrian } else { 163679119Sbrian log_Printf(LogWARN, "Set autoload requires three arguments\n"); 163779119Sbrian res = 1; 163836285Sbrian } 163936285Sbrian break; 164037210Sbrian 164128679Sbrian case VAR_DIAL: 164236285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 164336285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 164428679Sbrian break; 164537210Sbrian 164628679Sbrian case VAR_LOGIN: 164736285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 164836285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 164928679Sbrian break; 165037210Sbrian 165136285Sbrian case VAR_WINSIZE: 165236285Sbrian if (arg->argc > arg->argn) { 165336285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 165436285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 165536285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 165636285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 165736285Sbrian l->ccp.cfg.deflate.out.winsize); 165836285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 165936285Sbrian } 166036285Sbrian if (arg->argc > arg->argn+1) { 166136285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 166236285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 166336285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 166436285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 166536285Sbrian l->ccp.cfg.deflate.in.winsize); 166636285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 166736285Sbrian } 166836285Sbrian } else 166936285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 167036285Sbrian } else { 167179119Sbrian log_Printf(LogWARN, "No window size specified\n"); 167279119Sbrian res = 1; 167336285Sbrian } 167436285Sbrian break; 167537210Sbrian 167667910Sbrian#ifdef HAVE_DES 167778411Sbrian case VAR_MPPE: 167879119Sbrian if (arg->argc > arg->argn + 2) { 167979119Sbrian res = -1; 168079119Sbrian break; 168179119Sbrian } 168278411Sbrian 168378411Sbrian if (arg->argc == arg->argn) { 168478411Sbrian l->ccp.cfg.mppe.keybits = 0; 168578411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 168678411Sbrian l->ccp.cfg.mppe.required = 0; 168778411Sbrian break; 168878411Sbrian } 168978411Sbrian 169078411Sbrian if (!strcmp(argp, "*")) 169178411Sbrian long_val = 0; 169278411Sbrian else { 169378411Sbrian long_val = atol(argp); 169478411Sbrian if (long_val != 40 && long_val != 56 && long_val != 128) { 169578411Sbrian log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 169679119Sbrian res = -1; 169779119Sbrian break; 169867910Sbrian } 169967910Sbrian } 170078411Sbrian 170178411Sbrian if (arg->argc == arg->argn + 2) { 170278411Sbrian if (!strcmp(arg->argv[arg->argn + 1], "*")) 170378411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 170478411Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 170578411Sbrian l->ccp.cfg.mppe.state = MPPE_STATELESS; 170679370Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 170778411Sbrian l->ccp.cfg.mppe.state = MPPE_STATEFUL; 170878411Sbrian else { 170978411Sbrian log_Printf(LogWARN, "%s: Invalid state value\n", 171078411Sbrian arg->argv[arg->argn + 1]); 171179119Sbrian res = -1; 171279119Sbrian break; 171378411Sbrian } 171478411Sbrian } else 171578411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 171678411Sbrian l->ccp.cfg.mppe.keybits = long_val; 171778411Sbrian l->ccp.cfg.mppe.required = 1; 171867910Sbrian break; 171967910Sbrian#endif 172067910Sbrian 172128679Sbrian case VAR_DEVICE: 172236285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 172336285Sbrian arg->argv + arg->argn); 172436285Sbrian break; 172537210Sbrian 172636285Sbrian case VAR_ACCMAP: 172736285Sbrian if (arg->argc > arg->argn) { 172837210Sbrian u_long ulong_val; 172936285Sbrian sscanf(argp, "%lx", &ulong_val); 173037210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 173136285Sbrian } else { 173279119Sbrian log_Printf(LogWARN, "No accmap specified\n"); 173379119Sbrian res = 1; 173436285Sbrian } 173536285Sbrian break; 173637210Sbrian 173736285Sbrian case VAR_MODE: 173836285Sbrian mode = Nam2mode(argp); 173936285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 174036285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 174179119Sbrian res = -1; 174279119Sbrian break; 174336285Sbrian } 174436285Sbrian bundle_SetMode(arg->bundle, cx, mode); 174536285Sbrian break; 174637210Sbrian 174736285Sbrian case VAR_MRRU: 174840622Sbrian switch (bundle_Phase(arg->bundle)) { 174940622Sbrian case PHASE_DEAD: 175040622Sbrian break; 175140622Sbrian case PHASE_ESTABLISH: 175240622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 175340622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 175440622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 175579119Sbrian res = 1; 175679119Sbrian break; 175740622Sbrian } 175840622Sbrian break; 175940622Sbrian default: 176040622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 176179119Sbrian res = 1; 176279119Sbrian break; 176329696Sbrian } 176479119Sbrian if (res != 0) 176579119Sbrian break; 176637210Sbrian long_val = atol(argp); 176737210Sbrian if (long_val && long_val < MIN_MRU) { 176837210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 176979119Sbrian res = 1; 177079119Sbrian break; 177137210Sbrian } else if (long_val > MAX_MRU) { 177237210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 177379119Sbrian res = 1; 177479119Sbrian break; 177537210Sbrian } else 177637210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 177728679Sbrian break; 177837210Sbrian 177936285Sbrian case VAR_MRU: 178079163Sbrian long_val = 0; /* silence gcc */ 178179163Sbrian change = NULL; /* silence gcc */ 178278410Sbrian switch(arg->argc - arg->argn) { 178378410Sbrian case 1: 178479119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 178579119Sbrian res = -1; 178679119Sbrian break; 178779119Sbrian } 178879119Sbrian /*FALLTHRU*/ 178978410Sbrian case 0: 179078410Sbrian long_val = atol(argp); 179178410Sbrian change = &l->lcp.cfg.mru; 179278410Sbrian if (long_val > l->lcp.cfg.max_mru) { 179378410Sbrian log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 179478410Sbrian l->lcp.cfg.max_mru); 179579119Sbrian res = 1; 179679119Sbrian break; 179778410Sbrian } 179878410Sbrian break; 179978410Sbrian case 2: 180079119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 180179119Sbrian res = -1; 180279119Sbrian break; 180379119Sbrian } 180478410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 180578410Sbrian change = &l->lcp.cfg.max_mru; 180678410Sbrian if (long_val > MAX_MRU) { 180778410Sbrian log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 180878410Sbrian MAX_MRU); 180979119Sbrian res = 1; 181079119Sbrian break; 181178410Sbrian } 181278410Sbrian break; 181378410Sbrian default: 181479119Sbrian res = -1; 181579119Sbrian break; 181678410Sbrian } 181779119Sbrian if (res != 0) 181879119Sbrian break; 181978410Sbrian 182037210Sbrian if (long_val == 0) 182180385Sbrian *change = 0; 182237210Sbrian else if (long_val < MIN_MRU) { 182337210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 182479119Sbrian res = 1; 182579119Sbrian break; 182637210Sbrian } else if (long_val > MAX_MRU) { 182737210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 182879119Sbrian res = 1; 182979119Sbrian break; 183037210Sbrian } else 183178410Sbrian *change = long_val; 183278410Sbrian if (l->lcp.cfg.mru > *change) 183378410Sbrian l->lcp.cfg.mru = *change; 183428679Sbrian break; 183537210Sbrian 183636285Sbrian case VAR_MTU: 183779163Sbrian long_val = 0; /* silence gcc */ 183879163Sbrian change = NULL; /* silence gcc */ 183978410Sbrian switch(arg->argc - arg->argn) { 184078410Sbrian case 1: 184179119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 184279119Sbrian res = -1; 184379119Sbrian break; 184479119Sbrian } 184579119Sbrian /*FALLTHRU*/ 184678410Sbrian case 0: 184778410Sbrian long_val = atol(argp); 184878410Sbrian change = &l->lcp.cfg.mtu; 184978410Sbrian if (long_val > l->lcp.cfg.max_mtu) { 185078410Sbrian log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 185178410Sbrian l->lcp.cfg.max_mtu); 185279119Sbrian res = 1; 185379119Sbrian break; 185478410Sbrian } 185578410Sbrian break; 185678410Sbrian case 2: 185779119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 185879119Sbrian res = -1; 185979119Sbrian break; 186079119Sbrian } 186178410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 186278410Sbrian change = &l->lcp.cfg.max_mtu; 186378410Sbrian if (long_val > MAX_MTU) { 186478410Sbrian log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 186578410Sbrian MAX_MTU); 186679119Sbrian res = 1; 186779119Sbrian break; 186878410Sbrian } 186978410Sbrian break; 187078410Sbrian default: 187179119Sbrian res = -1; 187279119Sbrian break; 187378410Sbrian } 187478410Sbrian 187579119Sbrian if (res != 0) 187679119Sbrian break; 187779119Sbrian 187837210Sbrian if (long_val && long_val < MIN_MTU) { 187937210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 188079119Sbrian res = 1; 188179119Sbrian break; 188237210Sbrian } else if (long_val > MAX_MTU) { 188337210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 188479119Sbrian res = 1; 188579119Sbrian break; 188637210Sbrian } else 188778410Sbrian *change = long_val; 188878410Sbrian if (l->lcp.cfg.mtu > *change) 188978410Sbrian l->lcp.cfg.mtu = *change; 189036285Sbrian break; 189137210Sbrian 189236285Sbrian case VAR_OPENMODE: 189336285Sbrian if (strcasecmp(argp, "active") == 0) 189436285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 189536285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 189636285Sbrian else if (strcasecmp(argp, "passive") == 0) 189736285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 189836285Sbrian else { 189979119Sbrian log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 190079119Sbrian res = 1; 190136285Sbrian } 190236285Sbrian break; 190337210Sbrian 190428679Sbrian case VAR_PHONE: 190536285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 190636285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 190738174Sbrian cx->phone.alt = cx->phone.next = NULL; 190828679Sbrian break; 190937210Sbrian 191028679Sbrian case VAR_HANGUP: 191136285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 191236285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 191328679Sbrian break; 191437210Sbrian 191561534Sbrian case VAR_IFQUEUE: 191661534Sbrian long_val = atol(argp); 191761534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 191861534Sbrian break; 191961534Sbrian 192052488Sbrian case VAR_LOGOUT: 192152488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 192252488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 192352488Sbrian break; 192452488Sbrian 192536285Sbrian case VAR_IDLETIMEOUT: 192679119Sbrian if (arg->argc > arg->argn+2) { 192779119Sbrian log_Printf(LogWARN, "Too many idle timeout values\n"); 192879119Sbrian res = 1; 192979119Sbrian } else if (arg->argc == arg->argn) { 193079119Sbrian log_Printf(LogWARN, "Too few idle timeout values\n"); 193179119Sbrian res = 1; 193279119Sbrian } else { 193349978Sbrian int timeout, min; 193449978Sbrian 193549978Sbrian timeout = atoi(argp); 193649978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 193749978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 193849978Sbrian } 193929549Sbrian break; 194037210Sbrian 194136285Sbrian case VAR_LQRPERIOD: 194237210Sbrian long_val = atol(argp); 194337210Sbrian if (long_val < MIN_LQRPERIOD) { 194437210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 194537210Sbrian long_val, MIN_LQRPERIOD); 194679119Sbrian res = 1; 194736285Sbrian } else 194837210Sbrian l->lcp.cfg.lqrperiod = long_val; 194936285Sbrian break; 195037210Sbrian 195136285Sbrian case VAR_LCPRETRY: 195279119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 195379119Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 195479119Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 195579119Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 195636285Sbrian break; 195737210Sbrian 195836285Sbrian case VAR_CHAPRETRY: 195979119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 196079119Sbrian &cx->chap.auth.cfg.fsm.timeout, 196179119Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 196236285Sbrian break; 196337210Sbrian 196436285Sbrian case VAR_PAPRETRY: 196579119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 196679119Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 196779119Sbrian NULL, DEF_FSMAUTHTRIES); 196836285Sbrian break; 196937210Sbrian 197036285Sbrian case VAR_CCPRETRY: 197179119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 197279119Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 197379119Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 197436285Sbrian break; 197537210Sbrian 197636285Sbrian case VAR_IPCPRETRY: 197779119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 197879119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 197979119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 198079119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 198136285Sbrian break; 198237210Sbrian 198336285Sbrian case VAR_NBNS: 198436285Sbrian case VAR_DNS: 198558044Sbrian if (param == VAR_DNS) { 198681634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns; 198781634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE; 198858044Sbrian } else { 198981634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 199081634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY; 199158044Sbrian } 199236285Sbrian 199336285Sbrian if (arg->argc > arg->argn) { 199481634Sbrian ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]); 199581634Sbrian if (!ncpaddr_getip4(ncpaddr, ipaddr)) 199681634Sbrian return -1; 199781634Sbrian if (arg->argc > arg->argn+1) { 199881634Sbrian ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]); 199981634Sbrian if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1)) 200081634Sbrian return -1; 200181634Sbrian } 200236285Sbrian 200381634Sbrian if (ipaddr[0].s_addr == INADDR_ANY) { 200481634Sbrian ipaddr[0] = ipaddr[1]; 200581634Sbrian ipaddr[1].s_addr = INADDR_ANY; 200658044Sbrian } 200781634Sbrian if (ipaddr[0].s_addr == INADDR_NONE) { 200881634Sbrian ipaddr[0] = ipaddr[1]; 200981634Sbrian ipaddr[1].s_addr = INADDR_NONE; 201058044Sbrian } 201136285Sbrian } 201236285Sbrian break; 201338174Sbrian 201438174Sbrian case VAR_CALLBACK: 201538174Sbrian cx->cfg.callback.opmask = 0; 201638174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 201738174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 201838174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 201938174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 202038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 202138174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 202238174Sbrian if (dummyint == arg->argc - 1) 202338174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 202438174Sbrian else { 202538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 202638174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 202738174Sbrian sizeof cx->cfg.callback.msg - 1); 202838174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 202938174Sbrian } 203038174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 203138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 203279119Sbrian else { 203379119Sbrian res = -1; 203479119Sbrian break; 203579119Sbrian } 203638174Sbrian } 203738174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 203838174Sbrian cx->cfg.callback.opmask = 0; 203938174Sbrian break; 204038174Sbrian 204138174Sbrian case VAR_CBCP: 204238174Sbrian cx->cfg.cbcp.delay = 0; 204338174Sbrian *cx->cfg.cbcp.phone = '\0'; 204438174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 204538174Sbrian if (arg->argc > arg->argn) { 204638174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 204738174Sbrian sizeof cx->cfg.cbcp.phone - 1); 204838174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 204938174Sbrian if (arg->argc > arg->argn + 1) { 205038174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 205138174Sbrian if (arg->argc > arg->argn + 2) { 205238174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 205338174Sbrian if (long_val < MIN_FSMRETRY) 205438174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 205538174Sbrian long_val, MIN_FSMRETRY); 205638174Sbrian else 205738174Sbrian cx->cfg.cbcp.fsmretry = long_val; 205838174Sbrian } 205938174Sbrian } 206038174Sbrian } 206138174Sbrian break; 206238544Sbrian 206338544Sbrian case VAR_CHOKED: 206438544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 206538544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 206638544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 206738544Sbrian break; 206840665Sbrian 206940665Sbrian case VAR_SENDPIPE: 207040665Sbrian long_val = atol(argp); 207181634Sbrian arg->bundle->ncp.cfg.sendpipe = long_val; 207240665Sbrian break; 207340665Sbrian 207440665Sbrian case VAR_RECVPIPE: 207540665Sbrian long_val = atol(argp); 207681634Sbrian arg->bundle->ncp.cfg.recvpipe = long_val; 207740665Sbrian break; 207843313Sbrian 207943313Sbrian#ifndef NORADIUS 208043313Sbrian case VAR_RADIUS: 208143313Sbrian if (!*argp) 208243313Sbrian *arg->bundle->radius.cfg.file = '\0'; 208343313Sbrian else if (access(argp, R_OK)) { 208443313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 208579119Sbrian res = 1; 208679119Sbrian break; 208743313Sbrian } else { 208843313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 208943313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 209043313Sbrian arg->bundle->radius.cfg.file 209143313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 209243313Sbrian } 209343313Sbrian break; 209443313Sbrian#endif 209544073Sbrian 209644073Sbrian case VAR_CD: 209744073Sbrian if (*argp) { 209851699Sbrian if (strcasecmp(argp, "off")) { 209951699Sbrian long_val = atol(argp); 210051699Sbrian if (long_val < 0) 210151699Sbrian long_val = 0; 210251699Sbrian cx->physical->cfg.cd.delay = long_val; 210351699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 210451699Sbrian CD_REQUIRED : CD_VARIABLE; 210551699Sbrian } else 210651699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 210744073Sbrian } else { 210853733Sbrian cx->physical->cfg.cd.delay = 0; 210953733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 211044073Sbrian } 211144073Sbrian break; 211236285Sbrian 211346686Sbrian case VAR_PARITY: 211446686Sbrian if (arg->argc == arg->argn + 1) 211579119Sbrian res = physical_SetParity(arg->cx->physical, argp); 211646686Sbrian else { 211779119Sbrian log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 211879119Sbrian res = 1; 211946686Sbrian } 212046686Sbrian break; 21216059Samurai 212246686Sbrian case VAR_CRTSCTS: 212346686Sbrian if (strcasecmp(argp, "on") == 0) 212436285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 212546686Sbrian else if (strcasecmp(argp, "off") == 0) 212636285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 212746686Sbrian else { 212879119Sbrian log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 212979119Sbrian res = 1; 213046686Sbrian } 213146686Sbrian break; 213250867Sbrian 213350867Sbrian case VAR_URGENTPORTS: 213451048Sbrian if (arg->argn == arg->argc) { 213581634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 213681634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 213781634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 213851048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 213981634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 214051048Sbrian if (arg->argn == arg->argc - 1) 214181634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 214251048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 214351048Sbrian if (*arg->argv[f] == '+') 214481634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 214551048Sbrian else if (*arg->argv[f] == '-') 214681634Sbrian ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 214751048Sbrian else { 214851048Sbrian if (f == arg->argn) 214981634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 215081634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 215151048Sbrian } 215261430Sbrian } else if (arg->argn == arg->argc - 1 && 215361430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 215481634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 215581634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 215681634Sbrian ncp_ClearUrgentTOS(&arg->bundle->ncp); 215751048Sbrian } else { 215881634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 215951048Sbrian first = arg->argn; 216051048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 216181634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 216251048Sbrian 216351048Sbrian for (f = first; f < arg->argc; f++) 216451048Sbrian if (*arg->argv[f] == '+') 216581634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 216651048Sbrian else if (*arg->argv[f] == '-') 216781634Sbrian ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 216851048Sbrian else { 216951048Sbrian if (f == first) 217081634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 217181634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 217251048Sbrian } 217351048Sbrian } 217450867Sbrian break; 217520812Sjkh } 217646686Sbrian 217779119Sbrian return res; 217820812Sjkh} 217920812Sjkh 218030715Sbrianstatic struct cmdtab const SetCommands[] = { 218136285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 218236285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 218328679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 218436285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 218528679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 218636285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 218736285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 218836285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 218936285Sbrian (const void *)VAR_AUTOLOAD}, 219050867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 219150867Sbrian "datalink bandwidth", "set bandwidth value"}, 219238174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 219338174Sbrian "callback control", "set callback [none|auth|cbcp|" 219438174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 219538174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 219638174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 219738174Sbrian (const void *)VAR_CBCP}, 219844305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 219944305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 220044073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 220144073Sbrian "set cd value[!]", (const void *)VAR_CD}, 220244305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 220344305Sbrian "CHAP retries", "set chapretry value [attempts]", 220444305Sbrian (const void *)VAR_CHAPRETRY}, 220538544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 220638544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 220746686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 220846686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 220946686Sbrian (const char *)VAR_CRTSCTS}, 221036285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 221136285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 221236285Sbrian (const void *) VAR_WINSIZE}, 221367910Sbrian#ifdef HAVE_DES 221467910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 221579370Sbrian "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 221678411Sbrian (const void *) VAR_MPPE}, 221767910Sbrian#endif 221836285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 221946686Sbrian "physical device name", "set device|line device-name[,device-name]", 222036285Sbrian (const void *) VAR_DEVICE}, 222136285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 222236285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 222336285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 222436285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 222536285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 222636285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 222736285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 222836285Sbrian "escape characters", "set escape hex-digit ..."}, 222936285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 223036285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 223181634Sbrian "[src_addr[/width]] [dst_addr[/width]] [proto " 223248142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 223336285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 223436285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 223536285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 223631343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 223761534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 223861534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 223944305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 224044305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 224144305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 224244305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 224336712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 224467916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 224558033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 224636285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 224736285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 224852488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 224952488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 225036285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 225136285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 225236285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 225336285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 225436285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 225536285Sbrian "set mrru value", (const void *)VAR_MRRU}, 225636285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 225778410Sbrian "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 225878410Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 225978410Sbrian "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 226036285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 226136285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 226236285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 226336285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 226444305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 226544305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 226646686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 226746686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 226836285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 226936285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 227040679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 227140679Sbrian "Process title", "set proctitle [value]"}, 227243313Sbrian#ifndef NORADIUS 227343313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 227443313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 227543313Sbrian#endif 227636285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 227736285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 227840665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 227940665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 228036285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 228144468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 228240665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 228340665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 228471657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 228571657Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 228636285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 228746686Sbrian "physical speed", "set speed value|sync"}, 228836285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 228936285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 229036285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 229136285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 229251048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 229351048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 229436285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 229536285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 229628679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 229731343Sbrian "Display this message", "set help|? [command]", SetCommands}, 229828679Sbrian {NULL, NULL, NULL}, 22996059Samurai}; 23006059Samurai 23016059Samuraistatic int 230231343SbrianSetCommand(struct cmdargs const *arg) 23036059Samurai{ 230436285Sbrian if (arg->argc > arg->argn) 230536285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 230636285Sbrian arg->prompt, arg->cx); 230736285Sbrian else if (arg->prompt) 230836285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 230958044Sbrian " syntax help.\n"); 23106059Samurai else 231136285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 231226516Sbrian 231326516Sbrian return 0; 23146059Samurai} 23156059Samurai 23166059Samuraistatic int 231731343SbrianAddCommand(struct cmdargs const *arg) 23186059Samurai{ 231981634Sbrian struct ncpaddr gw; 232081634Sbrian struct ncprange dest; 232181634Sbrian struct in_addr host; 232281634Sbrian int dest_default, gw_arg, addrs; 23236059Samurai 232436285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 232531598Sbrian return -1; 232631598Sbrian 232736285Sbrian addrs = 0; 232881634Sbrian dest_default = 0; 232981634Sbrian if (arg->argc == arg->argn + 2) { 233036285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 233181634Sbrian dest_default = 1; 233231598Sbrian else { 233381634Sbrian if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn])) 233436285Sbrian return -1; 233536285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 233636285Sbrian addrs = ROUTE_DSTMYADDR; 233781634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7)) 233881634Sbrian addrs = ROUTE_DSTMYADDR6; 233936285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 234036285Sbrian addrs = ROUTE_DSTHISADDR; 234181634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8)) 234281634Sbrian addrs = ROUTE_DSTHISADDR6; 234358044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 234458044Sbrian addrs = ROUTE_DSTDNS0; 234558044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 234658044Sbrian addrs = ROUTE_DSTDNS1; 234731598Sbrian } 234881634Sbrian gw_arg = 1; 234934536Sbrian } else { 235036285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 235136285Sbrian addrs = ROUTE_DSTMYADDR; 235281634Sbrian host = arg->bundle->ncp.ipcp.my_ip; 235336285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 235436285Sbrian addrs = ROUTE_DSTHISADDR; 235581634Sbrian host = arg->bundle->ncp.ipcp.peer_ip; 235658044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 235758044Sbrian addrs = ROUTE_DSTDNS0; 235881634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[0]; 235958044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 236058044Sbrian addrs = ROUTE_DSTDNS1; 236181634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[1]; 236265263Sbrian } else { 236381634Sbrian host = GetIpAddr(arg->argv[arg->argn]); 236481634Sbrian if (host.s_addr == INADDR_NONE) { 236565263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 236665263Sbrian arg->argv[arg->argn]); 236765263Sbrian return -1; 236865263Sbrian } 236965263Sbrian } 237081634Sbrian ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1])); 237181634Sbrian gw_arg = 2; 23726059Samurai } 237336285Sbrian 237481634Sbrian if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) { 237581634Sbrian ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip); 237636285Sbrian addrs |= ROUTE_GWHISADDR; 237781634Sbrian#ifndef NOINET6 237881897Sbrian } else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) { 237981634Sbrian ncpaddr_copy(&gw, &arg->bundle->ncp.ipv6cp.hisaddr); 238081634Sbrian addrs |= ROUTE_GWHISADDR6; 238181634Sbrian#endif 238265263Sbrian } else { 238381634Sbrian if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) { 238465263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 238581634Sbrian arg->argv[arg->argn + gw_arg]); 238665263Sbrian return -1; 238765263Sbrian } 238865263Sbrian } 238936285Sbrian 239081634Sbrian if (dest_default) 239181634Sbrian ncprange_setdefault(&dest, ncpaddr_family(&gw)); 239281634Sbrian 239381634Sbrian if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0, 239481634Sbrian ((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0) 239543313Sbrian && addrs != ROUTE_STATIC) 239681634Sbrian route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw); 239736285Sbrian 239831598Sbrian return 0; 23996059Samurai} 24006059Samurai 24016059Samuraistatic int 240231343SbrianDeleteCommand(struct cmdargs const *arg) 24036059Samurai{ 240481634Sbrian struct ncprange dest; 240536285Sbrian int addrs; 24066059Samurai 240736285Sbrian if (arg->argc == arg->argn+1) { 240836285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 240936285Sbrian route_IfDelete(arg->bundle, 0); 241081634Sbrian route_DeleteAll(&arg->bundle->ncp.route); 241136285Sbrian } else { 241236285Sbrian addrs = 0; 241336285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 241481634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip); 241536285Sbrian addrs = ROUTE_DSTMYADDR; 241681634Sbrian#ifndef NOINET6 241781897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) { 241881634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr); 241981634Sbrian addrs = ROUTE_DSTMYADDR6; 242081634Sbrian#endif 242136285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 242281634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip); 242336285Sbrian addrs = ROUTE_DSTHISADDR; 242481634Sbrian#ifndef NOINET6 242581897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) { 242681634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr); 242781634Sbrian addrs = ROUTE_DSTHISADDR6; 242881634Sbrian#endif 242958044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 243081634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]); 243158044Sbrian addrs = ROUTE_DSTDNS0; 243258044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 243381634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]); 243458044Sbrian addrs = ROUTE_DSTDNS1; 243536285Sbrian } else { 243681634Sbrian ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]); 243736285Sbrian addrs = ROUTE_STATIC; 243836285Sbrian } 243981634Sbrian rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0); 244081634Sbrian route_Delete(&arg->bundle->ncp.route, addrs, &dest); 244131598Sbrian } 244234536Sbrian } else 244326516Sbrian return -1; 244426516Sbrian 244526516Sbrian return 0; 24466059Samurai} 24476059Samurai 244850059Sbrian#ifndef NONAT 244926031Sbrianstatic int 245058867SbrianNatEnable(struct cmdargs const *arg) 245126031Sbrian{ 245236285Sbrian if (arg->argc == arg->argn+1) { 245336285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 245450059Sbrian if (!arg->bundle->NatEnabled) { 245546686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 245646686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 245750059Sbrian arg->bundle->NatEnabled = 1; 245846686Sbrian } 245937191Sbrian return 0; 246036285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 246150059Sbrian arg->bundle->NatEnabled = 0; 246240561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 246340561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 246426516Sbrian return 0; 246526142Sbrian } 246635449Sbrian } 246736285Sbrian 246826516Sbrian return -1; 246926031Sbrian} 247026031Sbrian 247126031Sbrian 247226031Sbrianstatic int 247358867SbrianNatOption(struct cmdargs const *arg) 247426031Sbrian{ 247538559Sbrian long param = (long)arg->cmd->args; 247638559Sbrian 247736285Sbrian if (arg->argc == arg->argn+1) { 247836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 247950059Sbrian if (arg->bundle->NatEnabled) { 248037191Sbrian PacketAliasSetMode(param, param); 248128679Sbrian return 0; 248228679Sbrian } 248350059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 248436285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 248550059Sbrian if (arg->bundle->NatEnabled) { 248637191Sbrian PacketAliasSetMode(0, param); 248728679Sbrian return 0; 248828679Sbrian } 248950059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 249028679Sbrian } 249135449Sbrian } 249228679Sbrian return -1; 249326031Sbrian} 249450059Sbrian#endif /* #ifndef NONAT */ 249531121Sbrian 249631121Sbrianstatic int 249736285SbrianLinkCommand(struct cmdargs const *arg) 249836285Sbrian{ 249936285Sbrian if (arg->argc > arg->argn+1) { 250036285Sbrian char namelist[LINE_LEN]; 250136285Sbrian struct datalink *cx; 250236285Sbrian char *name; 250336285Sbrian int result = 0; 250436285Sbrian 250536285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 250636285Sbrian struct datalink *dl; 250736285Sbrian 250836285Sbrian cx = arg->bundle->links; 250936285Sbrian while (cx) { 251036285Sbrian /* Watch it, the command could be a ``remove'' */ 251136285Sbrian dl = cx->next; 251236285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 251336285Sbrian arg->prompt, cx); 251436285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 251536285Sbrian if (cx == dl) 251636285Sbrian break; /* Pointer's still valid ! */ 251736285Sbrian } 251836285Sbrian } else { 251936285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 252036285Sbrian namelist[sizeof namelist - 1] = '\0'; 252136285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 252236285Sbrian if (!bundle2datalink(arg->bundle, name)) { 252336285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 252436285Sbrian return 1; 252536285Sbrian } 252636285Sbrian 252736285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 252836285Sbrian namelist[sizeof namelist - 1] = '\0'; 252936285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 253036285Sbrian cx = bundle2datalink(arg->bundle, name); 253136285Sbrian if (cx) 253236285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 253336285Sbrian arg->prompt, cx); 253436285Sbrian else { 253536285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 253636285Sbrian result++; 253736285Sbrian } 253836285Sbrian } 253936285Sbrian } 254036285Sbrian return result; 254136285Sbrian } 254236285Sbrian 254336285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 254436285Sbrian return 2; 254536285Sbrian} 254636285Sbrian 254736285Sbrianstruct link * 254836285Sbriancommand_ChooseLink(struct cmdargs const *arg) 254936285Sbrian{ 255036285Sbrian if (arg->cx) 255136285Sbrian return &arg->cx->physical->link; 255237210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 255336285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 255437210Sbrian if (dl) 255537210Sbrian return &dl->physical->link; 255636285Sbrian } 255737210Sbrian return &arg->bundle->ncp.mp.link; 255836285Sbrian} 255936285Sbrian 256036285Sbrianstatic const char * 256136285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 256236285Sbrian{ 256336285Sbrian const char *result; 256436285Sbrian 256536285Sbrian switch (*cmd) { 256636285Sbrian case 'A': 256736285Sbrian case 'a': 256836285Sbrian result = "accept"; 256936285Sbrian *keep = NEG_MYMASK; 257036285Sbrian *add = NEG_ACCEPTED; 257136285Sbrian break; 257236285Sbrian case 'D': 257336285Sbrian case 'd': 257436285Sbrian switch (cmd[1]) { 257536285Sbrian case 'E': 257636285Sbrian case 'e': 257736285Sbrian result = "deny"; 257836285Sbrian *keep = NEG_MYMASK; 257936285Sbrian *add = 0; 258036285Sbrian break; 258136285Sbrian case 'I': 258236285Sbrian case 'i': 258336285Sbrian result = "disable"; 258436285Sbrian *keep = NEG_HISMASK; 258536285Sbrian *add = 0; 258636285Sbrian break; 258736285Sbrian default: 258836285Sbrian return NULL; 258936285Sbrian } 259036285Sbrian break; 259136285Sbrian case 'E': 259236285Sbrian case 'e': 259336285Sbrian result = "enable"; 259436285Sbrian *keep = NEG_HISMASK; 259536285Sbrian *add = NEG_ENABLED; 259636285Sbrian break; 259736285Sbrian default: 259836285Sbrian return NULL; 259936285Sbrian } 260036285Sbrian 260136285Sbrian return result; 260236285Sbrian} 260336285Sbrian 260436285Sbrianstatic int 260536285SbrianOptSet(struct cmdargs const *arg) 260636285Sbrian{ 260737574Sbrian int bit = (int)(long)arg->cmd->args; 260836285Sbrian unsigned keep; /* Keep these bits */ 260936285Sbrian unsigned add; /* Add these bits */ 261036285Sbrian 261181697Sbrian if (ident_cmd(arg->argv[arg->argn - 2], &keep, &add) == NULL) 261236285Sbrian return 1; 261336285Sbrian 261481885Sbrian#ifndef NOINET6 261581697Sbrian if (add == NEG_ENABLED && bit == OPT_IPV6CP && !probe.ipv6_available) { 261681697Sbrian log_Printf(LogWARN, "IPv6 is not available on this machine\n"); 261781697Sbrian return 1; 261881697Sbrian } 261981885Sbrian#endif 262081697Sbrian 262136285Sbrian if (add) 262236285Sbrian arg->bundle->cfg.opt |= bit; 262336285Sbrian else 262436285Sbrian arg->bundle->cfg.opt &= ~bit; 262581697Sbrian 262636285Sbrian return 0; 262736285Sbrian} 262836285Sbrian 262936285Sbrianstatic int 263040561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 263140561Sbrian{ 263240561Sbrian unsigned save = arg->bundle->cfg.opt; 263340561Sbrian int result = OptSet(arg); 263440561Sbrian 263540561Sbrian if (result == 0) 263650059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 263740561Sbrian arg->bundle->cfg.opt = save; 263850059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 263940561Sbrian result = 2; 264040561Sbrian } 264140561Sbrian 264240561Sbrian return result; 264340561Sbrian} 264440561Sbrian 264540561Sbrianstatic int 264636285SbrianNegotiateSet(struct cmdargs const *arg) 264736285Sbrian{ 264837210Sbrian long param = (long)arg->cmd->args; 264936285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 265036285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 265136285Sbrian const char *cmd; 265236285Sbrian unsigned keep; /* Keep these bits */ 265336285Sbrian unsigned add; /* Add these bits */ 265436285Sbrian 265536285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 265636285Sbrian return 1; 265736285Sbrian 265836285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 265936285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 266036285Sbrian cmd, arg->cmd->name); 266136285Sbrian return 2; 266236285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 266336285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 266436285Sbrian cmd, arg->cmd->name, cx->name); 266536285Sbrian cx = NULL; 266636285Sbrian } 266736285Sbrian 266836285Sbrian switch (param) { 266936285Sbrian case NEG_ACFCOMP: 267036285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 267136285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 267236285Sbrian break; 267344106Sbrian case NEG_CHAP05: 267444106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 267544106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 267636285Sbrian break; 267744106Sbrian#ifdef HAVE_DES 267844106Sbrian case NEG_CHAP80: 267944106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 268044106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 268144106Sbrian break; 268244106Sbrian case NEG_CHAP80LM: 268344106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 268444106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 268544106Sbrian break; 268667910Sbrian case NEG_CHAP81: 268767910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 268867910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 268967910Sbrian break; 269067910Sbrian case NEG_MPPE: 269167910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 269267910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 269367910Sbrian break; 269444106Sbrian#endif 269536285Sbrian case NEG_DEFLATE: 269636285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 269736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 269836285Sbrian break; 269936285Sbrian case NEG_DNS: 270036285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 270136285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 270236285Sbrian break; 270347858Sbrian case NEG_ENDDISC: 270447858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 270547858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 270647858Sbrian break; 270736285Sbrian case NEG_LQR: 270836285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 270936285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 271036285Sbrian break; 271136285Sbrian case NEG_PAP: 271236285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 271336285Sbrian cx->physical->link.lcp.cfg.pap |= add; 271436285Sbrian break; 271536285Sbrian case NEG_PPPDDEFLATE: 271636285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 271736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 271836285Sbrian break; 271936285Sbrian case NEG_PRED1: 272036285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 272136285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 272236285Sbrian break; 272336285Sbrian case NEG_PROTOCOMP: 272436285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 272536285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 272636285Sbrian break; 272736285Sbrian case NEG_SHORTSEQ: 272840622Sbrian switch (bundle_Phase(arg->bundle)) { 272940622Sbrian case PHASE_DEAD: 273040622Sbrian break; 273140622Sbrian case PHASE_ESTABLISH: 273240622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 273340622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 273440622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 273540622Sbrian " LCP negotiations\n"); 273640622Sbrian return 1; 273740622Sbrian } 273840622Sbrian break; 273940622Sbrian default: 274040622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 274140622Sbrian " DEAD/ESTABLISH\n"); 274240622Sbrian return 1; 274336285Sbrian } 274440622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 274540622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 274636285Sbrian break; 274736285Sbrian case NEG_VJCOMP: 274836285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 274936285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 275036285Sbrian break; 275136285Sbrian } 275236285Sbrian 275336285Sbrian return 0; 275436285Sbrian} 275536285Sbrian 275636285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 275762778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 275862778Sbrian "filter on PPPoUDP payloads", "disable|enable", 275962778Sbrian (const void *)OPT_FILTERDECAP}, 276036285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 276136285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 276240666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 276362778Sbrian "retain interface addresses", "disable|enable", 276462778Sbrian (const void *)OPT_IFACEALIAS}, 276581634Sbrian#ifndef NOINET6 276681634Sbrian {"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol", 276781634Sbrian "disable|enable", (const void *)OPT_IPCP}, 276881634Sbrian {"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol", 276981634Sbrian "disable|enable", (const void *)OPT_IPV6CP}, 277081634Sbrian#endif 277147689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 277247689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 277336285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 277436285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 277536285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 277636285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 277740665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 277836285Sbrian "disable|enable", (const void *)OPT_PROXY}, 277940665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 278040665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 278136285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 278236285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 278369303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 278469303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 278536285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 278636285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 278736285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 278836285Sbrian "disable|enable", (const void *)OPT_UTMP}, 278936285Sbrian 279081634Sbrian#ifndef NOINET6 279181634Sbrian#define OPT_MAX 13 /* accept/deny allowed below and not above */ 279281634Sbrian#else 279381634Sbrian#define OPT_MAX 11 279481634Sbrian#endif 279536285Sbrian 279636285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 279736285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 279836285Sbrian (const void *)NEG_ACFCOMP}, 279944106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 280036285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 280144106Sbrian (const void *)NEG_CHAP05}, 280244106Sbrian#ifdef HAVE_DES 280344106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 280444106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 280544106Sbrian (const void *)NEG_CHAP80}, 280644106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 280744106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 280844106Sbrian (const void *)NEG_CHAP80LM}, 280967910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 281067910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 281167910Sbrian (const void *)NEG_CHAP81}, 281267910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 281367910Sbrian "MPPE encryption", "accept|deny|disable|enable", 281467910Sbrian (const void *)NEG_MPPE}, 281544106Sbrian#endif 281636285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 281736285Sbrian "Deflate compression", "accept|deny|disable|enable", 281836285Sbrian (const void *)NEG_DEFLATE}, 281936285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 282036285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 282136285Sbrian (const void *)NEG_PPPDDEFLATE}, 282236285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 282336285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 282447858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 282547858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 282636285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 282736285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 282836285Sbrian (const void *)NEG_LQR}, 282936285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 283036285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 283136285Sbrian (const void *)NEG_PAP}, 283236285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 283336285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 283436285Sbrian (const void *)NEG_PRED1}, 283536285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 283636285Sbrian "Protocol field compression", "accept|deny|disable|enable", 283736285Sbrian (const void *)NEG_PROTOCOMP}, 283836285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 283936285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 284036285Sbrian (const void *)NEG_SHORTSEQ}, 284136285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 284236285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 284336285Sbrian (const void *)NEG_VJCOMP}, 284436285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 284536285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 284636285Sbrian NegotiateCommands}, 284736285Sbrian {NULL, NULL, NULL}, 284836285Sbrian}; 284936285Sbrian 285036285Sbrianstatic int 285136285SbrianNegotiateCommand(struct cmdargs const *arg) 285236285Sbrian{ 285336285Sbrian if (arg->argc > arg->argn) { 285436285Sbrian char const *argv[3]; 285536285Sbrian unsigned keep, add; 285636285Sbrian int n; 285736285Sbrian 285836285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 285936285Sbrian return -1; 286036285Sbrian argv[2] = NULL; 286136285Sbrian 286236285Sbrian for (n = arg->argn; n < arg->argc; n++) { 286336285Sbrian argv[1] = arg->argv[n]; 286436285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 286536285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 286636285Sbrian } 286736285Sbrian } else if (arg->prompt) 286836285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 286936285Sbrian arg->argv[arg->argn-1]); 287036285Sbrian else 287136285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 287236285Sbrian arg->argv[arg->argn] ); 287336285Sbrian 287436285Sbrian return 0; 287536285Sbrian} 287636285Sbrian 287736285Sbrianconst char * 287836285Sbriancommand_ShowNegval(unsigned val) 287936285Sbrian{ 288036285Sbrian switch (val&3) { 288136285Sbrian case 1: return "disabled & accepted"; 288236285Sbrian case 2: return "enabled & denied"; 288336285Sbrian case 3: return "enabled & accepted"; 288436285Sbrian } 288536285Sbrian return "disabled & denied"; 288636285Sbrian} 288736934Sbrian 288836934Sbrianstatic int 288936934SbrianClearCommand(struct cmdargs const *arg) 289036934Sbrian{ 289136934Sbrian struct pppThroughput *t; 289236934Sbrian struct datalink *cx; 289336934Sbrian int i, clear_type; 289436934Sbrian 289536934Sbrian if (arg->argc < arg->argn + 1) 289636934Sbrian return -1; 289736934Sbrian 289846686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 289936934Sbrian cx = arg->cx; 290036934Sbrian if (!cx) 290136934Sbrian cx = bundle2datalink(arg->bundle, NULL); 290236934Sbrian if (!cx) { 290346686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 290436934Sbrian return 1; 290536934Sbrian } 290664652Sbrian t = &cx->physical->link.stats.total; 290736934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 290836934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 290981634Sbrian#ifndef NOINET6 291081897Sbrian else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0) 291181634Sbrian t = &arg->bundle->ncp.ipv6cp.throughput; 291281634Sbrian#endif 291336934Sbrian else 291436934Sbrian return -1; 291536934Sbrian 291636934Sbrian if (arg->argc > arg->argn + 1) { 291736934Sbrian clear_type = 0; 291836934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 291936934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 292036934Sbrian clear_type |= THROUGHPUT_OVERALL; 292136934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 292236934Sbrian clear_type |= THROUGHPUT_CURRENT; 292336934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 292436934Sbrian clear_type |= THROUGHPUT_PEAK; 292536934Sbrian else 292636934Sbrian return -1; 292736934Sbrian } else 292836934Sbrian clear_type = THROUGHPUT_ALL; 292936934Sbrian 293036934Sbrian throughput_clear(t, clear_type, arg->prompt); 293136934Sbrian return 0; 293236934Sbrian} 293340561Sbrian 293440561Sbrianstatic int 293540561SbrianRunListCommand(struct cmdargs const *arg) 293640561Sbrian{ 293740561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 293840561Sbrian 293964801Sbrian#ifndef NONAT 294064801Sbrian if (arg->cmd->args == NatCommands && 294164801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 294264801Sbrian if (arg->prompt) 294365550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 294464801Sbrian else 294565550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 294664801Sbrian } 294764801Sbrian#endif 294864801Sbrian 294940561Sbrian if (arg->argc > arg->argn) 295040561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 295140561Sbrian arg->prompt, arg->cx); 295240561Sbrian else if (arg->prompt) 295340561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 295440561Sbrian " <option>' for syntax help.\n", cmd, cmd); 295540561Sbrian else 295640561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 295740561Sbrian 295840561Sbrian return 0; 295940561Sbrian} 296040561Sbrian 296140561Sbrianstatic int 296240561SbrianIfaceAddCommand(struct cmdargs const *arg) 296340561Sbrian{ 296481634Sbrian struct ncpaddr peer, addr; 296581634Sbrian struct ncprange ifa; 296681634Sbrian struct in_addr mask; 296781634Sbrian int n, how; 296840561Sbrian 296940664Sbrian if (arg->argc == arg->argn + 1) { 297081634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 297140561Sbrian return -1; 297281634Sbrian ncpaddr_init(&peer); 297340664Sbrian } else { 297440664Sbrian if (arg->argc == arg->argn + 2) { 297581634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 297640664Sbrian return -1; 297740664Sbrian n = 1; 297840664Sbrian } else if (arg->argc == arg->argn + 3) { 297981634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn])) 298040664Sbrian return -1; 298181634Sbrian if (ncpaddr_family(&addr) != AF_INET) 298240664Sbrian return -1; 298381634Sbrian ncprange_sethost(&ifa, &addr); 298481634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1])) 298581634Sbrian return -1; 298681634Sbrian if (!ncpaddr_getip4(&addr, &mask)) 298781634Sbrian return -1; 298881634Sbrian if (!ncprange_setip4mask(&ifa, mask)) 298981634Sbrian return -1; 299040664Sbrian n = 2; 299140664Sbrian } else 299240561Sbrian return -1; 299340561Sbrian 299481634Sbrian if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n])) 299540664Sbrian return -1; 299681634Sbrian 299781634Sbrian if (ncprange_family(&ifa) != ncpaddr_family(&peer)) { 299881634Sbrian log_Printf(LogWARN, "IfaceAddCommand: src and dst address families" 299981634Sbrian " differ\n"); 300081634Sbrian return -1; 300181634Sbrian } 300240664Sbrian } 300340561Sbrian 300440561Sbrian how = IFACE_ADD_LAST; 300540561Sbrian if (arg->cmd->args) 300640561Sbrian how |= IFACE_FORCE_ADD; 300740561Sbrian 300881634Sbrian return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how); 300940561Sbrian} 301040561Sbrian 301140561Sbrianstatic int 301240561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 301340561Sbrian{ 301481634Sbrian struct ncpaddr ifa; 301581634Sbrian struct in_addr ifa4; 301640561Sbrian int ok; 301740561Sbrian 301840561Sbrian if (arg->argc != arg->argn + 1) 301940561Sbrian return -1; 302040561Sbrian 302181634Sbrian if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn])) 302240561Sbrian return -1; 302340561Sbrian 302440561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 302581634Sbrian ncpaddr_getip4(&ifa, &ifa4) && 302681634Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) { 302740561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 302881634Sbrian ncpaddr_ntoa(&ifa)); 302940561Sbrian return 1; 303040561Sbrian } 303140561Sbrian 303281634Sbrian ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa); 303340561Sbrian if (!ok) { 303440561Sbrian if (arg->cmd->args) 303540561Sbrian ok = 1; 303640561Sbrian else if (arg->prompt) 303781634Sbrian prompt_Printf(arg->prompt, "%s: No such interface address\n", 303881634Sbrian ncpaddr_ntoa(&ifa)); 303940561Sbrian else 304081634Sbrian log_Printf(LogWARN, "%s: No such interface address\n", 304181634Sbrian ncpaddr_ntoa(&ifa)); 304240561Sbrian } 304340561Sbrian 304440561Sbrian return !ok; 304540561Sbrian} 304640561Sbrian 304740561Sbrianstatic int 304840561SbrianIfaceClearCommand(struct cmdargs const *arg) 304940561Sbrian{ 305081634Sbrian int family, how; 305140561Sbrian 305281634Sbrian family = 0; 305381634Sbrian if (arg->argc == arg->argn + 1) { 305481634Sbrian if (strcasecmp(arg->argv[arg->argn], "inet") == 0) 305581634Sbrian family = AF_INET; 305681634Sbrian#ifndef NOINET6 305781897Sbrian else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0) 305881634Sbrian family = AF_INET6; 305981634Sbrian#endif 306081634Sbrian else 306181634Sbrian return -1; 306281634Sbrian } else if (arg->argc != arg->argn) 306340561Sbrian return -1; 306440561Sbrian 306540941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 306640941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 306740561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 306881634Sbrian iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how); 306940561Sbrian 307040561Sbrian return 0; 307140561Sbrian} 307240679Sbrian 307340679Sbrianstatic int 307440679SbrianSetProcTitle(struct cmdargs const *arg) 307540679Sbrian{ 307640679Sbrian static char title[LINE_LEN]; 307786028Sbrian char *argv[MAXARGS]; 307886028Sbrian int argc = arg->argc - arg->argn; 307940679Sbrian 308040679Sbrian if (arg->argc == arg->argn) { 308164698Sbrian SetTitle(NULL); 308240679Sbrian return 0; 308340679Sbrian } 308440679Sbrian 308540679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 308640679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 308740679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 308840679Sbrian } 308947849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 309085991Sbrian Concatinate(title, sizeof title, argc, (const char *const *)argv); 309164698Sbrian SetTitle(title); 309285991Sbrian command_Free(argc, argv); 309340679Sbrian 309440679Sbrian return 0; 309540679Sbrian} 3096