command.c revision 134789
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 134789 2004-09-05 01:46:52Z 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> 45102500Sbrian#include <stdarg.h> 4630715Sbrian#include <stdio.h> 4730715Sbrian#include <stdlib.h> 4830715Sbrian#include <string.h> 4930715Sbrian#include <sys/wait.h> 5030715Sbrian#include <termios.h> 5130715Sbrian#include <unistd.h> 5230715Sbrian 5350059Sbrian#ifndef NONAT 5458037Sbrian#ifdef LOCALNAT 5558037Sbrian#include "alias.h" 5658037Sbrian#else 5746086Sbrian#include <alias.h> 5839395Sbrian#endif 5939395Sbrian#endif 6058037Sbrian 6146686Sbrian#include "layer.h" 6237009Sbrian#include "defs.h" 6331343Sbrian#include "command.h" 6430715Sbrian#include "mbuf.h" 6530715Sbrian#include "log.h" 6630715Sbrian#include "timer.h" 676059Samurai#include "fsm.h" 6831690Sbrian#include "iplist.h" 6936285Sbrian#include "throughput.h" 7036285Sbrian#include "slcompress.h" 7138557Sbrian#include "lqr.h" 7238557Sbrian#include "hdlc.h" 7363484Sbrian#include "lcp.h" 7481634Sbrian#include "ncpaddr.h" 756059Samurai#include "ipcp.h" 7650059Sbrian#ifndef NONAT 7751075Sbrian#include "nat_cmd.h" 7831343Sbrian#endif 7925630Sbrian#include "systems.h" 8036285Sbrian#include "filter.h" 8136285Sbrian#include "descriptor.h" 8230715Sbrian#include "main.h" 8330715Sbrian#include "route.h" 8430715Sbrian#include "ccp.h" 8531080Sbrian#include "auth.h" 8636285Sbrian#include "async.h" 8736285Sbrian#include "link.h" 8836285Sbrian#include "physical.h" 8936285Sbrian#include "mp.h" 9043313Sbrian#ifndef NORADIUS 9143313Sbrian#include "radius.h" 9243313Sbrian#endif 9381634Sbrian#include "ipv6cp.h" 9481634Sbrian#include "ncp.h" 9536285Sbrian#include "bundle.h" 9636285Sbrian#include "server.h" 9736285Sbrian#include "prompt.h" 9836285Sbrian#include "chat.h" 9936285Sbrian#include "chap.h" 10038174Sbrian#include "cbcp.h" 10136285Sbrian#include "datalink.h" 10240561Sbrian#include "iface.h" 10353298Sbrian#include "id.h" 10481697Sbrian#include "probe.h" 1056059Samurai 10636285Sbrian/* ``set'' values */ 10736285Sbrian#define VAR_AUTHKEY 0 10836285Sbrian#define VAR_DIAL 1 10936285Sbrian#define VAR_LOGIN 2 11036285Sbrian#define VAR_AUTHNAME 3 11136285Sbrian#define VAR_AUTOLOAD 4 11236285Sbrian#define VAR_WINSIZE 5 11336285Sbrian#define VAR_DEVICE 6 11436285Sbrian#define VAR_ACCMAP 7 11536285Sbrian#define VAR_MRRU 8 11636285Sbrian#define VAR_MRU 9 11736285Sbrian#define VAR_MTU 10 11836285Sbrian#define VAR_OPENMODE 11 11936285Sbrian#define VAR_PHONE 12 12036285Sbrian#define VAR_HANGUP 13 12136285Sbrian#define VAR_IDLETIMEOUT 14 12236285Sbrian#define VAR_LQRPERIOD 15 12336285Sbrian#define VAR_LCPRETRY 16 12436285Sbrian#define VAR_CHAPRETRY 17 12536285Sbrian#define VAR_PAPRETRY 18 12636285Sbrian#define VAR_CCPRETRY 19 12736285Sbrian#define VAR_IPCPRETRY 20 12836285Sbrian#define VAR_DNS 21 12936285Sbrian#define VAR_NBNS 22 13036285Sbrian#define VAR_MODE 23 13138174Sbrian#define VAR_CALLBACK 24 13238174Sbrian#define VAR_CBCP 25 13338544Sbrian#define VAR_CHOKED 26 13440665Sbrian#define VAR_SENDPIPE 27 13540665Sbrian#define VAR_RECVPIPE 28 13643313Sbrian#define VAR_RADIUS 29 13744073Sbrian#define VAR_CD 30 13846686Sbrian#define VAR_PARITY 31 13946686Sbrian#define VAR_CRTSCTS 32 14050867Sbrian#define VAR_URGENTPORTS 33 14152488Sbrian#define VAR_LOGOUT 34 14261534Sbrian#define VAR_IFQUEUE 35 14378411Sbrian#define VAR_MPPE 36 144102558Sbrian#define VAR_IPV6CPRETRY 37 145132273Sbrian#define VAR_RAD_ALIVE 38 146132818Sglebius#define VAR_PPPOE 39 1476059Samurai 14836285Sbrian/* ``accept|deny|disable|enable'' masks */ 14936285Sbrian#define NEG_HISMASK (1) 15036285Sbrian#define NEG_MYMASK (2) 15136285Sbrian 15236285Sbrian/* ``accept|deny|disable|enable'' values */ 15336285Sbrian#define NEG_ACFCOMP 40 15444106Sbrian#define NEG_CHAP05 41 15544106Sbrian#define NEG_CHAP80 42 15644106Sbrian#define NEG_CHAP80LM 43 15744106Sbrian#define NEG_DEFLATE 44 15847858Sbrian#define NEG_DNS 45 15947858Sbrian#define NEG_ENDDISC 46 16047858Sbrian#define NEG_LQR 47 16147858Sbrian#define NEG_PAP 48 16247858Sbrian#define NEG_PPPDDEFLATE 49 16347858Sbrian#define NEG_PRED1 50 16447858Sbrian#define NEG_PROTOCOMP 51 16547858Sbrian#define NEG_SHORTSEQ 52 16647858Sbrian#define NEG_VJCOMP 53 16767910Sbrian#define NEG_MPPE 54 16867910Sbrian#define NEG_CHAP81 55 16936285Sbrian 170134789Sbrianconst char Version[] = "3.3"; 17136285Sbrian 17236285Sbrianstatic int ShowCommand(struct cmdargs const *); 17336285Sbrianstatic int TerminalCommand(struct cmdargs const *); 17436285Sbrianstatic int QuitCommand(struct cmdargs const *); 17536285Sbrianstatic int OpenCommand(struct cmdargs const *); 17636285Sbrianstatic int CloseCommand(struct cmdargs const *); 17736285Sbrianstatic int DownCommand(struct cmdargs const *); 17836285Sbrianstatic int SetCommand(struct cmdargs const *); 17936285Sbrianstatic int LinkCommand(struct cmdargs const *); 18036285Sbrianstatic int AddCommand(struct cmdargs const *); 18136285Sbrianstatic int DeleteCommand(struct cmdargs const *); 18236285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 18336934Sbrianstatic int ClearCommand(struct cmdargs const *); 18440561Sbrianstatic int RunListCommand(struct cmdargs const *); 18540561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 18640561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 18740561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 18840679Sbrianstatic int SetProcTitle(struct cmdargs const *); 18950059Sbrian#ifndef NONAT 19058867Sbrianstatic int NatEnable(struct cmdargs const *); 19158867Sbrianstatic int NatOption(struct cmdargs const *); 19231343Sbrian#endif 1936059Samurai 19436285Sbrianstatic const char * 19536285Sbrianshowcx(struct cmdtab const *cmd) 19636285Sbrian{ 19736285Sbrian if (cmd->lauth & LOCAL_CX) 19836285Sbrian return "(c)"; 19936285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 20036285Sbrian return "(o)"; 20136285Sbrian 20236285Sbrian return ""; 20336285Sbrian} 20436285Sbrian 2056059Samuraistatic int 20631343SbrianHelpCommand(struct cmdargs const *arg) 2076059Samurai{ 20828679Sbrian struct cmdtab const *cmd; 20936285Sbrian int n, cmax, dmax, cols, cxlen; 21036285Sbrian const char *cx; 2116059Samurai 21236285Sbrian if (!arg->prompt) { 21336285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 21426516Sbrian return 0; 21536285Sbrian } 21626516Sbrian 21736285Sbrian if (arg->argc > arg->argn) { 21836285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 21936285Sbrian if ((cmd->lauth & arg->prompt->auth) && 22036285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 22136285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 22236285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 22328679Sbrian return 0; 2246059Samurai } 22526516Sbrian return -1; 2266059Samurai } 22736285Sbrian 22831372Sbrian cmax = dmax = 0; 22936285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 23036285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 23136285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 23231372Sbrian cmax = n; 23331372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 23431372Sbrian dmax = n; 23531372Sbrian } 23631372Sbrian 23731372Sbrian cols = 80 / (dmax + cmax + 3); 2386059Samurai n = 0; 23936285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 24036285Sbrian " (c) = Context required\n"); 24136285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 24236285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 24336285Sbrian cx = showcx(cmd); 24436285Sbrian cxlen = cmax - strlen(cmd->name); 24540482Sbrian if (n % cols != 0) 24640482Sbrian prompt_Printf(arg->prompt, " "); 24740482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 24836285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 24931372Sbrian if (++n % cols == 0) 25036285Sbrian prompt_Printf(arg->prompt, "\n"); 2516059Samurai } 25231372Sbrian if (n % cols != 0) 25336285Sbrian prompt_Printf(arg->prompt, "\n"); 25426516Sbrian 25526516Sbrian return 0; 2566059Samurai} 2576059Samurai 25836285Sbrianstatic int 25963484SbrianIdentCommand(struct cmdargs const *arg) 26063484Sbrian{ 26185991Sbrian Concatinate(arg->cx->physical->link.lcp.cfg.ident, 26285991Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident, 26385991Sbrian arg->argc - arg->argn, arg->argv + arg->argn); 26463484Sbrian return 0; 26563484Sbrian} 26663484Sbrian 26763484Sbrianstatic int 26863484SbrianSendIdentification(struct cmdargs const *arg) 26963484Sbrian{ 27063484Sbrian if (arg->cx->state < DATALINK_LCP) { 27163484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 27263484Sbrian return 2; 27363484Sbrian } 27463484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 27563484Sbrian} 27663484Sbrian 27763484Sbrianstatic int 27836285SbrianCloneCommand(struct cmdargs const *arg) 2796059Samurai{ 28036285Sbrian char namelist[LINE_LEN]; 28136285Sbrian char *name; 28236285Sbrian int f; 2836059Samurai 28436285Sbrian if (arg->argc == arg->argn) 28536285Sbrian return -1; 28636285Sbrian 28736285Sbrian namelist[sizeof namelist - 1] = '\0'; 28836285Sbrian for (f = arg->argn; f < arg->argc; f++) { 28936285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 29036285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 29136285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2926059Samurai } 29336285Sbrian 29436285Sbrian return 0; 2956059Samurai} 2966059Samurai 2976059Samuraistatic int 29836285SbrianRemoveCommand(struct cmdargs const *arg) 2996059Samurai{ 30036285Sbrian if (arg->argc != arg->argn) 30136285Sbrian return -1; 30211336Samurai 30336285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 30436285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 30536285Sbrian return 2; 3066059Samurai } 30726516Sbrian 30836285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 30936285Sbrian return 0; 31036285Sbrian} 31132711Sbrian 31236285Sbrianstatic int 31336285SbrianRenameCommand(struct cmdargs const *arg) 31436285Sbrian{ 31536285Sbrian if (arg->argc != arg->argn + 1) 31636285Sbrian return -1; 31731121Sbrian 31836285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 31936285Sbrian return 0; 32036285Sbrian 32198243Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 32236285Sbrian arg->cx->name, arg->argv[arg->argn]); 32336285Sbrian return 1; 32436285Sbrian} 32536285Sbrian 32685991Sbrianstatic int 32736285SbrianLoadCommand(struct cmdargs const *arg) 32836285Sbrian{ 32940797Sbrian const char *err; 33040797Sbrian int n, mode; 33136285Sbrian 33240797Sbrian mode = arg->bundle->phys_type.all; 33336285Sbrian 33440797Sbrian if (arg->argn < arg->argc) { 33540797Sbrian for (n = arg->argn; n < arg->argc; n++) 33640797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 33740797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 33840797Sbrian return 1; 33940797Sbrian } 34040797Sbrian 34140797Sbrian for (n = arg->argn; n < arg->argc; n++) { 34240797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34340797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 34440797Sbrian } 34540797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 34640797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 34740797Sbrian log_Printf(LogWARN, "default: %s\n", err); 34836285Sbrian return 1; 34936285Sbrian } else { 35040797Sbrian bundle_SetLabel(arg->bundle, "default"); 35140797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 35240797Sbrian bundle_SetLabel(arg->bundle, "default"); 35336285Sbrian } 35440797Sbrian 35526516Sbrian return 0; 3566059Samurai} 3576059Samurai 35885991Sbrianstatic int 35985991SbrianLogCommand(struct cmdargs const *arg) 36085991Sbrian{ 36185991Sbrian char buf[LINE_LEN]; 36285991Sbrian 36385991Sbrian if (arg->argn < arg->argc) { 36485991Sbrian char *argv[MAXARGS]; 36585991Sbrian int argc = arg->argc - arg->argn; 36685991Sbrian 367134789Sbrian if (argc >= (int)(sizeof argv / sizeof argv[0])) { 36885991Sbrian argc = sizeof argv / sizeof argv[0] - 1; 36985991Sbrian log_Printf(LogWARN, "Truncating log command to %d args\n", argc); 37085991Sbrian } 37186760Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 37285991Sbrian Concatinate(buf, sizeof buf, argc, (const char *const *)argv); 37385991Sbrian log_Printf(LogLOG, "%s\n", buf); 37485991Sbrian command_Free(argc, argv); 37585991Sbrian return 0; 37685991Sbrian } 37785991Sbrian 37885991Sbrian return -1; 37985991Sbrian} 38085991Sbrian 38185991Sbrianstatic int 382134789SbrianSaveCommand(struct cmdargs const *arg __unused) 38336285Sbrian{ 38485991Sbrian log_Printf(LogWARN, "save command is not yet implemented.\n"); 38536285Sbrian return 1; 38636285Sbrian} 38736285Sbrian 38810528Samuraistatic int 38936285SbrianDialCommand(struct cmdargs const *arg) 39028536Sbrian{ 39136285Sbrian int res; 39236285Sbrian 39336465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 39436465Sbrian || (!arg->cx && 39536928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 39636285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 39736285Sbrian " interactive links\n"); 39836285Sbrian return 1; 39934536Sbrian } 40036285Sbrian 40136285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 40236285Sbrian return res; 40336285Sbrian 40437993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 40536285Sbrian 40636285Sbrian return 0; 40728536Sbrian} 40828536Sbrian 40938628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 41038628Sbrian 41138628Sbrianstatic char * 41238628Sbrianstrstrword(char *big, const char *little) 41338628Sbrian{ 41438628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 41538628Sbrian char *pos; 41638628Sbrian int len; 41738628Sbrian 41838628Sbrian pos = big; 41938628Sbrian len = strlen(little); 42038628Sbrian 42138628Sbrian while ((pos = strstr(pos, little)) != NULL) 42247865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 42347865Sbrian pos++; 42447865Sbrian else if (pos != big && pos[-1] == '\\') 42547865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 42647865Sbrian else 42738628Sbrian break; 42838628Sbrian 42938628Sbrian return pos; 43038628Sbrian} 43138628Sbrian 43238628Sbrianstatic char * 43338628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 43438628Sbrian{ 43538628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 43638628Sbrian char *word, *ntgt; 43738628Sbrian int ltgt, loldstr, lnewstr, pos; 43838628Sbrian 43938628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 44038628Sbrian return tgt; 44138628Sbrian 44238628Sbrian ltgt = strlen(tgt) + 1; 44338628Sbrian loldstr = strlen(oldstr); 44438628Sbrian lnewstr = strlen(newstr); 44538628Sbrian do { 44638628Sbrian pos = word - tgt; 44738628Sbrian if (loldstr > lnewstr) 44838628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 44938628Sbrian if (loldstr != lnewstr) { 45038628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 45138628Sbrian if (ntgt == NULL) 45238628Sbrian break; /* Oh wonderful ! */ 45338628Sbrian word = ntgt + pos; 45438628Sbrian tgt = ntgt; 45538628Sbrian } 45638628Sbrian if (lnewstr > loldstr) 45738628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 45838628Sbrian bcopy(newstr, word, lnewstr); 45938628Sbrian } while ((word = strstrword(word, oldstr))); 46038628Sbrian 46138628Sbrian return tgt; 46238628Sbrian} 46338628Sbrian 46494934Sbrianstatic char * 46594934Sbriansubstip(char *tgt, const char *oldstr, struct in_addr ip) 46694934Sbrian{ 46794934Sbrian return subst(tgt, oldstr, inet_ntoa(ip)); 46894934Sbrian} 46994934Sbrian 47094934Sbrianstatic char * 47197360Sbriansubstlong(char *tgt, const char *oldstr, long l) 47294934Sbrian{ 47397360Sbrian char buf[23]; 47494934Sbrian 47597360Sbrian snprintf(buf, sizeof buf, "%ld", l); 47694934Sbrian 47794934Sbrian return subst(tgt, oldstr, buf); 47894934Sbrian} 47994934Sbrian 48094934Sbrianstatic char * 48194934Sbriansubstull(char *tgt, const char *oldstr, unsigned long long ull) 48294934Sbrian{ 48394934Sbrian char buf[21]; 48494934Sbrian 48594934Sbrian snprintf(buf, sizeof buf, "%llu", ull); 48694934Sbrian 48794934Sbrian return subst(tgt, oldstr, buf); 48894934Sbrian} 48994934Sbrian 49094934Sbrian 49194934Sbrian#ifndef NOINET6 49294934Sbrianstatic char * 49394934Sbriansubstipv6(char *tgt, const char *oldstr, const struct ncpaddr *ip) 49494934Sbrian{ 49594934Sbrian return subst(tgt, oldstr, ncpaddr_ntoa(ip)); 49694934Sbrian} 497116622Sume 498116622Sume#ifndef NORADIUS 499116622Sumestatic char * 500116622Sumesubstipv6prefix(char *tgt, const char *oldstr, const uint8_t *ipv6prefix) 501116622Sume{ 502116622Sume uint8_t ipv6addr[INET6_ADDRSTRLEN]; 503116622Sume uint8_t prefix[INET6_ADDRSTRLEN + sizeof("/128") - 1]; 504116622Sume 505116622Sume if (ipv6prefix) { 506116622Sume inet_ntop(AF_INET6, &ipv6prefix[2], ipv6addr, sizeof(ipv6addr)); 507116622Sume snprintf(prefix, sizeof(prefix), "%s/%d", ipv6addr, ipv6prefix[1]); 508116622Sume } else 509116622Sume prefix[0] = '\0'; 510116622Sume return subst(tgt, oldstr, prefix); 511116622Sume} 51294934Sbrian#endif 513116622Sume#endif 51494934Sbrian 51543888Sbrianvoid 51643888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 51747849Sbrian struct bundle *bundle, int inc0, pid_t pid) 51838628Sbrian{ 51985991Sbrian int arg, secs; 52094934Sbrian char uptime[20]; 52194934Sbrian unsigned long long oin, oout, pin, pout; 52238628Sbrian 52341755Sbrian if (inc0) 52441755Sbrian arg = 0; /* Start at arg 0 */ 52541755Sbrian else { 52641755Sbrian nargv[0] = strdup(oargv[0]); 52741755Sbrian arg = 1; 52841755Sbrian } 52994934Sbrian 53094934Sbrian secs = bundle_Uptime(bundle); 53194934Sbrian snprintf(uptime, sizeof uptime, "%d:%02d:%02d", 53294934Sbrian secs / 3600, (secs / 60) % 60, secs % 60); 53394934Sbrian oin = bundle->ncp.ipcp.throughput.OctetsIn; 53494934Sbrian oout = bundle->ncp.ipcp.throughput.OctetsOut; 53594934Sbrian pin = bundle->ncp.ipcp.throughput.PacketsIn; 53694934Sbrian pout = bundle->ncp.ipcp.throughput.PacketsOut; 53794934Sbrian#ifndef NOINET6 53894934Sbrian oin += bundle->ncp.ipv6cp.throughput.OctetsIn; 53994934Sbrian oout += bundle->ncp.ipv6cp.throughput.OctetsOut; 54094934Sbrian pin += bundle->ncp.ipv6cp.throughput.PacketsIn; 54194934Sbrian pout += bundle->ncp.ipv6cp.throughput.PacketsOut; 54294934Sbrian#endif 54394934Sbrian 54441755Sbrian for (; arg < argc; arg++) { 54538629Sbrian nargv[arg] = strdup(oargv[arg]); 54694934Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 54794934Sbrian nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 54894934Sbrian nargv[arg] = substip(nargv[arg], "DNS0", bundle->ncp.ipcp.ns.dns[0]); 54994934Sbrian nargv[arg] = substip(nargv[arg], "DNS1", bundle->ncp.ipcp.ns.dns[1]); 55098243Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 55194934Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 55294934Sbrian bundle->ncp.mp.cfg.enddisc.address, 55394934Sbrian bundle->ncp.mp.cfg.enddisc.len)); 55494934Sbrian nargv[arg] = substip(nargv[arg], "HISADDR", bundle->ncp.ipcp.peer_ip); 55581634Sbrian#ifndef NOINET6 55694934Sbrian nargv[arg] = substipv6(nargv[arg], "HISADDR6", &bundle->ncp.ipv6cp.hisaddr); 55781634Sbrian#endif 55840561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 55994934Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSIN", 56094934Sbrian bundle->ncp.ipcp.throughput.OctetsIn); 56198243Sbrian nargv[arg] = substull(nargv[arg], "IPOCTETSOUT", 56294934Sbrian bundle->ncp.ipcp.throughput.OctetsOut); 56398243Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSIN", 56494934Sbrian bundle->ncp.ipcp.throughput.PacketsIn); 56598243Sbrian nargv[arg] = substull(nargv[arg], "IPPACKETSOUT", 56694934Sbrian bundle->ncp.ipcp.throughput.PacketsOut); 56781634Sbrian#ifndef NOINET6 56898243Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSIN", 56994934Sbrian bundle->ncp.ipv6cp.throughput.OctetsIn); 57098243Sbrian nargv[arg] = substull(nargv[arg], "IPV6OCTETSOUT", 57194934Sbrian bundle->ncp.ipv6cp.throughput.OctetsOut); 57298243Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSIN", 57394934Sbrian bundle->ncp.ipv6cp.throughput.PacketsIn); 57498243Sbrian nargv[arg] = substull(nargv[arg], "IPV6PACKETSOUT", 57594934Sbrian bundle->ncp.ipv6cp.throughput.PacketsOut); 57681634Sbrian#endif 57794934Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 57894934Sbrian nargv[arg] = substip(nargv[arg], "MYADDR", bundle->ncp.ipcp.my_ip); 57994934Sbrian#ifndef NOINET6 58094934Sbrian nargv[arg] = substipv6(nargv[arg], "MYADDR6", &bundle->ncp.ipv6cp.myaddr); 581116622Sume#ifndef NORADIUS 582116622Sume nargv[arg] = substipv6prefix(nargv[arg], "IPV6PREFIX", 583116622Sume bundle->radius.ipv6prefix); 58494934Sbrian#endif 585116622Sume#endif 58694934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSIN", oin); 58794934Sbrian nargv[arg] = substull(nargv[arg], "OCTETSOUT", oout); 58894934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSIN", pin); 58994934Sbrian nargv[arg] = substull(nargv[arg], "PACKETSOUT", pout); 59038629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 59138629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 59238629Sbrian bundle->ncp.mp.peer.enddisc.address, 59338629Sbrian bundle->ncp.mp.peer.enddisc.len)); 59497360Sbrian nargv[arg] = substlong(nargv[arg], "PROCESSID", pid); 59594934Sbrian if (server.cfg.port) 59697360Sbrian nargv[arg] = substlong(nargv[arg], "SOCKNAME", server.cfg.port); 59794934Sbrian else 59894934Sbrian nargv[arg] = subst(nargv[arg], "SOCKNAME", server.cfg.sockname); 59994934Sbrian nargv[arg] = subst(nargv[arg], "UPTIME", uptime); 60094934Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 60163484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 60238628Sbrian } 60338628Sbrian nargv[arg] = NULL; 60438628Sbrian} 60538628Sbrian 60685991Sbrianvoid 60785991Sbriancommand_Free(int argc, char **argv) 60885991Sbrian{ 60985991Sbrian while (argc) { 61085991Sbrian free(*argv); 61185991Sbrian argc--; 61285991Sbrian argv++; 61385991Sbrian } 61485991Sbrian} 61585991Sbrian 61628536Sbrianstatic int 61731343SbrianShellCommand(struct cmdargs const *arg, int bg) 61810528Samurai{ 61910528Samurai const char *shell; 62047849Sbrian pid_t shpid, pid; 62120813Sjkh 62218856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 62326911Sbrian /* we're only allowed to shell when we run ppp interactively */ 62436285Sbrian if (arg->prompt && arg->prompt->owner) { 62536285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 62626516Sbrian return 1; 62710528Samurai } 62826911Sbrian#endif 62928679Sbrian 63036285Sbrian if (arg->argc == arg->argn) { 63136285Sbrian if (!arg->prompt) { 63236285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 63336285Sbrian " a config file\n"); 63428381Sbrian return 1; 63536285Sbrian } else if (arg->prompt->owner) { 63636285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 63736285Sbrian " a socket connection\n"); 63836285Sbrian return 1; 63928381Sbrian } else if (bg) { 64036285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 64128679Sbrian " the foreground mode\n"); 64228381Sbrian return 1; 64328381Sbrian } 64434536Sbrian } 64534536Sbrian 64647849Sbrian pid = getpid(); 64728679Sbrian if ((shpid = fork()) == 0) { 64836285Sbrian int i, fd; 64918531Sbde 65036285Sbrian if ((shell = getenv("SHELL")) == 0) 65136285Sbrian shell = _PATH_BSHELL; 65232017Sbrian 65336285Sbrian timer_TermService(); 65436285Sbrian 65536285Sbrian if (arg->prompt) 65636285Sbrian fd = arg->prompt->fd_out; 65736285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 65836285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 65936285Sbrian _PATH_DEVNULL, strerror(errno)); 66028679Sbrian exit(1); 66128679Sbrian } 66249976Sbrian dup2(fd, STDIN_FILENO); 66349976Sbrian dup2(fd, STDOUT_FILENO); 66449976Sbrian dup2(fd, STDERR_FILENO); 66549976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 66649976Sbrian fcntl(i, F_SETFD, 1); 66726516Sbrian 66864802Sbrian#ifndef NOSUID 66955252Sbrian setuid(ID0realuid()); 67064802Sbrian#endif 67136285Sbrian if (arg->argc > arg->argn) { 67228679Sbrian /* substitute pseudo args */ 67338628Sbrian char *argv[MAXARGS]; 67438628Sbrian int argc = arg->argc - arg->argn; 67538628Sbrian 676134789Sbrian if (argc >= (int)(sizeof argv / sizeof argv[0])) { 67738628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 67838628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 67931343Sbrian } 68047849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 68128679Sbrian if (bg) { 68228679Sbrian pid_t p; 68310528Samurai 68428679Sbrian p = getpid(); 68528679Sbrian if (daemon(1, 1) == -1) { 68697360Sbrian log_Printf(LogERROR, "%ld: daemon: %s\n", (long)p, strerror(errno)); 68728679Sbrian exit(1); 68828679Sbrian } 68936285Sbrian } else if (arg->prompt) 69036285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 69131343Sbrian execvp(argv[0], argv); 69230316Sbrian } else { 69336285Sbrian if (arg->prompt) 69432017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 69536285Sbrian prompt_TtyOldMode(arg->prompt); 69679450Sbrian execl(shell, shell, (char *)NULL); 69730316Sbrian } 69820813Sjkh 69940665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 70040665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 70140665Sbrian strerror(errno)); 70249976Sbrian _exit(255); 70310528Samurai } 70436285Sbrian 70597360Sbrian if (shpid == (pid_t)-1) 70636285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 70736285Sbrian else { 70810528Samurai int status; 70931343Sbrian waitpid(shpid, &status, 0); 71010528Samurai } 71120813Sjkh 71236285Sbrian if (arg->prompt && !arg->prompt->owner) 71336285Sbrian prompt_TtyCommandMode(arg->prompt); 71420813Sjkh 71536285Sbrian return 0; 71610528Samurai} 71710528Samurai 71831343Sbrianstatic int 71931343SbrianBgShellCommand(struct cmdargs const *arg) 72031343Sbrian{ 72136285Sbrian if (arg->argc == arg->argn) 72231343Sbrian return -1; 72331343Sbrian return ShellCommand(arg, 1); 72431343Sbrian} 72531343Sbrian 72631343Sbrianstatic int 72731343SbrianFgShellCommand(struct cmdargs const *arg) 72831343Sbrian{ 72931343Sbrian return ShellCommand(arg, 0); 73031343Sbrian} 73131343Sbrian 73258044Sbrianstatic int 73358044SbrianResolvCommand(struct cmdargs const *arg) 73458044Sbrian{ 73558044Sbrian if (arg->argc == arg->argn + 1) { 73658044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 73758044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 73858044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 73958044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 74058044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 74158044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 74258044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 74358044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 74458044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 74558044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 74658044Sbrian else 74758044Sbrian return -1; 74858044Sbrian 74958044Sbrian return 0; 75058044Sbrian } 75158044Sbrian 75258044Sbrian return -1; 75358044Sbrian} 75458044Sbrian 75550059Sbrian#ifndef NONAT 75658867Sbrianstatic struct cmdtab const NatCommands[] = 75740561Sbrian{ 75850059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 759134789Sbrian "static address translation", "nat addr [addr_local addr_alias]", NULL}, 76058867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 76150059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 76240561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 76358867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 764134789Sbrian "enable NAT", "nat enable yes|no", NULL}, 76558867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 76650059Sbrian "log NAT link creation", "nat log yes|no", 76740561Sbrian (const void *) PKT_ALIAS_LOG}, 76850059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 769134789Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]", NULL}, 77079433Sbrian {"proto", NULL, nat_RedirectProto, LOCAL_AUTH, "protocol redirection", 771134789Sbrian "nat proto proto localIP [publicIP [remoteIP]]", NULL}, 77250059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 773134789Sbrian "proxy control", "nat proxy server host[:port] ...", NULL}, 77481033Sbrian#ifndef NO_FW_PUNCH 77581033Sbrian {"punch_fw", NULL, nat_PunchFW, LOCAL_AUTH, 776134789Sbrian "firewall control", "nat punch_fw [base count]", NULL}, 77781033Sbrian#endif 778120372Smarcus {"skinny_port", NULL, nat_SkinnyPort, LOCAL_AUTH, 779134789Sbrian "TCP port used by Skinny Station protocol", "nat skinny_port [port]", NULL}, 78058867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 78150059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 78240561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 78358867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 784134789Sbrian "Default address for incoming connections", "nat target addr", NULL}, 78558867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 78650059Sbrian "translate unregistered (private) IP address space only", 78750059Sbrian "nat unregistered_only yes|no", 78840561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 78958867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 79050059Sbrian "allocate host sockets", "nat use_sockets yes|no", 79140561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 79240561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 79358867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 794134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 79540561Sbrian}; 79640561Sbrian#endif 79740561Sbrian 79840561Sbrianstatic struct cmdtab const AllowCommands[] = { 79940561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 800134789Sbrian "Only allow certain ppp modes", "allow modes mode...", NULL}, 80140561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 802134789Sbrian "Only allow ppp access to certain users", "allow users logname...", NULL}, 80340561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 80440561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 805134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 80640561Sbrian}; 80740561Sbrian 80840561Sbrianstatic struct cmdtab const IfaceCommands[] = 80940561Sbrian{ 81040561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 81140561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 81240561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 81340561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 81440561Sbrian (void *)1}, 81540561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 816134789Sbrian "Clear iface address(es)", "iface clear [INET | INET6]", NULL}, 81740561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 81840561Sbrian "Delete iface address", "iface delete addr", NULL}, 81940561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 82040561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 82140561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 82240561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 82340561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 824134789Sbrian "Show iface address(es)", "iface show", NULL}, 82540561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 82650059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 827134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 82840561Sbrian}; 82940561Sbrian 83030715Sbrianstatic struct cmdtab const Commands[] = { 83136285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 832134789Sbrian "accept option request", "accept option ..", NULL}, 83328679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 83432109Sbrian "add route", "add dest mask gateway", NULL}, 83536285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 83632109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 83740561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 83840561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 83928679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 840134789Sbrian "Run a background command", "[!]bg command", NULL}, 84136934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 84246686Sbrian "Clear throughput statistics", 843134789Sbrian "clear ipcp|ipv6cp|physical [current|overall|peak]...", NULL}, 84436285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 845134789Sbrian "Clone a link", "clone newname...", NULL}, 84636285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 847134789Sbrian "Close an FSM", "close [lcp|ccp]", NULL}, 84828679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 84932109Sbrian "delete route", "delete dest", NULL}, 85036285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 85132109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 85236285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 853134789Sbrian "Deny option request", "deny option ..", NULL}, 85436285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 85540797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 85636285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 857134789Sbrian "Disable option", "disable option ..", NULL}, 85836285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 859134789Sbrian "Generate a down event", "down [ccp|lcp]", NULL}, 86036285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 861134789Sbrian "Enable option", "enable option ..", NULL}, 86263484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 863134789Sbrian "Set the link identity", "ident text...", NULL}, 86440561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 86540561Sbrian "interface control", "iface option ...", IfaceCommands}, 86636285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 867134789Sbrian "Link specific commands", "link name command ...", NULL}, 86837008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 869134789Sbrian "Load settings", "load [system ...]", NULL}, 87085991Sbrian {"log", NULL, LogCommand, LOCAL_AUTH | LOCAL_CX_OPT, 871134789Sbrian "log information", "log word ...", NULL}, 87250059Sbrian#ifndef NONAT 87350059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 87458867Sbrian "NAT control", "nat option yes|no", NatCommands}, 87550059Sbrian#endif 87636285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 87737955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 87836285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 879134789Sbrian "Password for manipulation", "passwd LocalPassword", NULL}, 88036285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 881134789Sbrian "Quit PPP program", "quit|bye [all]", NULL}, 88236285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 883134789Sbrian "Remove a link", "remove", NULL}, 88436285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 885134789Sbrian "Rename a link", "rename name", NULL}, 88658044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 887134789Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable", 888134789Sbrian NULL}, 88928679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 890134789Sbrian "Save settings", "save", NULL}, 89163484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 892134789Sbrian "Transmit the link identity", "sendident", NULL}, 89336285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 894134789Sbrian "Set parameters", "set[up] var value", NULL}, 89528679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 896134789Sbrian "Run a subshell", "shell|! [sh command]", NULL}, 89736285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 898134789Sbrian "Show status and stats", "show var", NULL}, 89936285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 900134789Sbrian "Enter terminal mode", "term", NULL}, 90128679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 90231343Sbrian "Display this message", "help|? [command]", Commands}, 903134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 9046059Samurai}; 9056059Samurai 90628536Sbrianstatic int 90731343SbrianShowEscape(struct cmdargs const *arg) 9086059Samurai{ 90936285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 91036285Sbrian int code, bit; 91136285Sbrian const char *sep = ""; 9126059Samurai 91326516Sbrian for (code = 0; code < 32; code++) 91436285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 91528679Sbrian for (bit = 0; bit < 8; bit++) 91636285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 91736285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 91836285Sbrian sep = ", "; 91936285Sbrian } 92036285Sbrian prompt_Printf(arg->prompt, "\n"); 9216059Samurai } 92231077Sbrian return 0; 9236059Samurai} 9246059Samurai 92528679Sbrianstatic int 92636285SbrianShowTimerList(struct cmdargs const *arg) 9276059Samurai{ 92836285Sbrian timer_Show(0, arg->prompt); 92931077Sbrian return 0; 9306059Samurai} 9316059Samurai 93228679Sbrianstatic int 93331343SbrianShowStopped(struct cmdargs const *arg) 93428327Sbrian{ 93536285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 93636285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 93736285Sbrian prompt_Printf(arg->prompt, "Disabled"); 93828327Sbrian else 93936285Sbrian prompt_Printf(arg->prompt, "%ld secs", 94036285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 94128461Sbrian 94236285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 94336285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 94436285Sbrian prompt_Printf(arg->prompt, "Disabled"); 94528461Sbrian else 94636285Sbrian prompt_Printf(arg->prompt, "%ld secs", 94736285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 94828461Sbrian 94936285Sbrian prompt_Printf(arg->prompt, "\n"); 95028461Sbrian 95131077Sbrian return 0; 95228327Sbrian} 95328327Sbrian 95428679Sbrianstatic int 95531343SbrianShowVersion(struct cmdargs const *arg) 9566059Samurai{ 95751026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 95831077Sbrian return 0; 9596059Samurai} 9606059Samurai 96128679Sbrianstatic int 96236285SbrianShowProtocolStats(struct cmdargs const *arg) 96326326Sbrian{ 96436285Sbrian struct link *l = command_ChooseLink(arg); 96526326Sbrian 96636285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 96736285Sbrian link_ReportProtocolStatus(l, arg->prompt); 96831077Sbrian return 0; 96926326Sbrian} 97026326Sbrian 97130715Sbrianstatic struct cmdtab const ShowCommands[] = { 97236285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 973134789Sbrian "bundle details", "show bundle", NULL}, 97436285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 975134789Sbrian "CCP status", "show cpp", NULL}, 97636285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 977134789Sbrian "VJ compression stats", "show compress", NULL}, 97836285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 979134789Sbrian "escape characters", "show escape", NULL}, 98036285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 981134789Sbrian "packet filters", "show filter [in|out|dial|alive]", NULL}, 98236285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 983134789Sbrian "HDLC errors", "show hdlc", NULL}, 98440561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 985134789Sbrian "Interface status", "show iface", NULL}, 98636285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 987134789Sbrian "IPCP status", "show ipcp", NULL}, 98881634Sbrian#ifndef NOINET6 98981634Sbrian {"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH, 990134789Sbrian "IPV6CP status", "show ipv6cp", NULL}, 99181634Sbrian#endif 99247211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 993134789Sbrian "Protocol layers", "show layers", NULL}, 99436285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 995134789Sbrian "LCP status", "show lcp", NULL}, 99636285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 997134789Sbrian "(high-level) link info", "show link", NULL}, 99836285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 999134789Sbrian "available link names", "show links", NULL}, 100036285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 1001134789Sbrian "log levels", "show log", NULL}, 100236285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 1003134789Sbrian "mbuf allocations", "show mem", NULL}, 100481634Sbrian {"ncp", NULL, ncp_Show, LOCAL_AUTH, 1005134789Sbrian "NCP status", "show ncp", NULL}, 100646686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 1007134789Sbrian "(low-level) link info", "show physical", NULL}, 100836285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 1009134789Sbrian "multilink setup", "show mp", NULL}, 101036285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 1011134789Sbrian "protocol summary", "show proto", NULL}, 101236285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 1013134789Sbrian "routing table", "show route", NULL}, 101436285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 1015134789Sbrian "STOPPED timeout", "show stopped", NULL}, 101636285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 1017134789Sbrian "alarm timers", "show timers", NULL}, 101828679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 1019134789Sbrian "version string", "show version", NULL}, 102036285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 1021134789Sbrian "client list", "show who", NULL}, 102228679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 102331343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 1024134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 10256059Samurai}; 10266059Samurai 102730715Sbrianstatic struct cmdtab const * 102831343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 10296059Samurai{ 103026516Sbrian int nmatch; 103126516Sbrian int len; 103228679Sbrian struct cmdtab const *found; 10336059Samurai 103426516Sbrian found = NULL; 103526516Sbrian len = strlen(str); 103626516Sbrian nmatch = 0; 10376059Samurai while (cmds->func) { 103825566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 103926516Sbrian if (cmds->name[len] == '\0') { 104028679Sbrian *pmatch = 1; 104128679Sbrian return cmds; 104226516Sbrian } 10436059Samurai nmatch++; 10446059Samurai found = cmds; 104528679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 104626516Sbrian if (cmds->alias[len] == '\0') { 104728679Sbrian *pmatch = 1; 104828679Sbrian return cmds; 104926516Sbrian } 10506059Samurai nmatch++; 10516059Samurai found = cmds; 10526059Samurai } 10536059Samurai cmds++; 10546059Samurai } 10556059Samurai *pmatch = nmatch; 105626516Sbrian return found; 10576059Samurai} 10586059Samurai 105936285Sbrianstatic const char * 106036285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 106136285Sbrian{ 106236285Sbrian int f, tlen, len; 106336285Sbrian 106436285Sbrian tlen = 0; 106536285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 106636285Sbrian if (f) 106736285Sbrian tgt[tlen++] = ' '; 106836285Sbrian len = strlen(argv[f]); 106936285Sbrian if (len > sz - tlen - 1) 107036285Sbrian len = sz - tlen - 1; 107136285Sbrian strncpy(tgt+tlen, argv[f], len); 107236285Sbrian tlen += len; 107336285Sbrian } 107436285Sbrian tgt[tlen] = '\0'; 107536285Sbrian return tgt; 107636285Sbrian} 107736285Sbrian 107830715Sbrianstatic int 107936285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 108036285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 10816059Samurai{ 108228679Sbrian struct cmdtab const *cmd; 10836059Samurai int val = 1; 10846059Samurai int nmatch; 108531343Sbrian struct cmdargs arg; 108636285Sbrian char prefix[100]; 10876059Samurai 108836285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 10896059Samurai if (nmatch > 1) 109036285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 109136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 109236285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 109336285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 109436285Sbrian /* We've got no context, but we require it */ 109536285Sbrian cx = bundle2datalink(bundle, NULL); 109636285Sbrian 109736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 109836285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 109936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 110036285Sbrian else { 110136285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 110236285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 110336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 110436285Sbrian cx = NULL; 110536285Sbrian } 110636285Sbrian arg.cmdtab = cmds; 110736285Sbrian arg.cmd = cmd; 110836285Sbrian arg.argc = argc; 110936285Sbrian arg.argn = argn+1; 111036285Sbrian arg.argv = argv; 111136285Sbrian arg.bundle = bundle; 111236285Sbrian arg.cx = cx; 111336285Sbrian arg.prompt = prompt; 111436285Sbrian val = (*cmd->func) (&arg); 111536285Sbrian } 111631343Sbrian } else 111736285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 111836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 111926516Sbrian 112026516Sbrian if (val == -1) 112195258Sdes log_Printf(LogWARN, "usage: %s\n", cmd->syntax); 112228679Sbrian else if (val) 112336285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 112436285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 112526516Sbrian 112626516Sbrian return val; 11276059Samurai} 11286059Samurai 112937009Sbrianint 113058045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 113158045Sbrian{ 113258045Sbrian char buff2[LINE_LEN-offset]; 113358045Sbrian 113458045Sbrian InterpretArg(buff, buff2); 113558045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 113658045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 113758045Sbrian 113858045Sbrian return command_Interpret(buff, nb, argv); 113958045Sbrian} 114058045Sbrian 114158045Sbrianint 114237009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 11436059Samurai{ 11446059Samurai char *cp; 11456059Samurai 11466059Samurai if (nb > 0) { 11476059Samurai cp = buff + strcspn(buff, "\r\n"); 11486059Samurai if (cp) 11496059Samurai *cp = '\0'; 115055145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 115137009Sbrian } 115237009Sbrian return 0; 115331121Sbrian} 11546059Samurai 115531822Sbrianstatic int 1156134789Sbrianarghidden(char const *const *argv, int n) 115731822Sbrian{ 115831822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 115931828Sbrian 116031828Sbrian /* set authkey xxxxx */ 116131828Sbrian /* set key xxxxx */ 116231822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 116331822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 116431822Sbrian return 1; 116531822Sbrian 116631828Sbrian /* passwd xxxxx */ 116731828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 116831828Sbrian return 1; 116931828Sbrian 117036285Sbrian /* set server port xxxxx .... */ 117136285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 117236285Sbrian !strncasecmp(argv[1], "se", 2)) 117336285Sbrian return 1; 117436285Sbrian 117531822Sbrian return 0; 117631822Sbrian} 117731822Sbrian 117831121Sbrianvoid 117936285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 118037008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 118131121Sbrian{ 118231156Sbrian if (argc > 0) { 118336285Sbrian if (log_IsKept(LogCOMMAND)) { 118447844Sbrian char buf[LINE_LEN]; 1185134789Sbrian int f; 1186134789Sbrian size_t n; 118731156Sbrian 118831156Sbrian if (label) { 118931962Sbrian strncpy(buf, label, sizeof buf - 3); 119031962Sbrian buf[sizeof buf - 3] = '\0'; 119131156Sbrian strcat(buf, ": "); 119247844Sbrian n = strlen(buf); 119347844Sbrian } else { 119447844Sbrian *buf = '\0'; 119547844Sbrian n = 0; 119631156Sbrian } 119747844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 119847844Sbrian 119931156Sbrian for (f = 0; f < argc; f++) { 120031962Sbrian if (n < sizeof buf - 1 && f) 120131156Sbrian buf[n++] = ' '; 1202134789Sbrian if (arghidden(argv, f)) 120336285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 120431822Sbrian else 120531962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 120631156Sbrian n += strlen(buf+n); 120731156Sbrian } 120836285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 120931156Sbrian } 121037008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 121131156Sbrian } 12126059Samurai} 12136059Samurai 121454914Sbrianint 121536285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 121636285Sbrian const char *label) 121731121Sbrian{ 121831121Sbrian int argc; 121937009Sbrian char *argv[MAXARGS]; 122031121Sbrian 122158045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 122254914Sbrian return 0; 122354914Sbrian 122437008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 122554914Sbrian return 1; 122631121Sbrian} 122731121Sbrian 12286059Samuraistatic int 122931343SbrianShowCommand(struct cmdargs const *arg) 12306059Samurai{ 123136285Sbrian if (!arg->prompt) 123236285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 123336285Sbrian else if (arg->argc > arg->argn) 123436285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 123536285Sbrian arg->prompt, arg->cx); 12366059Samurai else 123736285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 123826516Sbrian 123926516Sbrian return 0; 12406059Samurai} 12416059Samurai 12426059Samuraistatic int 124331343SbrianTerminalCommand(struct cmdargs const *arg) 12446059Samurai{ 124536285Sbrian if (!arg->prompt) { 124636285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 124726516Sbrian return 1; 12486059Samurai } 124936285Sbrian 125036285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 125136285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 125236285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 125336285Sbrian return 1; 12546059Samurai } 125536285Sbrian 125636285Sbrian datalink_Up(arg->cx, 0, 0); 125736285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 125836285Sbrian return 0; 12596059Samurai} 12606059Samurai 12616059Samuraistatic int 126231343SbrianQuitCommand(struct cmdargs const *arg) 12636059Samurai{ 126436285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 126536285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 126636285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 1267134789Sbrian Cleanup(); 126836285Sbrian if (arg->prompt) 126936285Sbrian prompt_Destroy(arg->prompt, 1); 127026516Sbrian 127126516Sbrian return 0; 12726059Samurai} 12736059Samurai 12746059Samuraistatic int 127536285SbrianOpenCommand(struct cmdargs const *arg) 12766059Samurai{ 127737160Sbrian if (arg->argc == arg->argn) 127837993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 127937160Sbrian else if (arg->argc == arg->argn + 1) { 128037160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 128137385Sbrian struct datalink *cx = arg->cx ? 128237385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 128337385Sbrian if (cx) { 128437385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 128537385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 128637160Sbrian else 128737993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 128837160Sbrian } else 128937160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 129037160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 129137160Sbrian struct fsm *fp; 12926059Samurai 129337210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 129437160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 129537160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 129637160Sbrian else if (fp->state == ST_OPENED) 129737160Sbrian fsm_Reopen(fp); 129837160Sbrian else { 129937160Sbrian fp->open_mode = 0; /* Not passive any more */ 130037160Sbrian if (fp->state == ST_STOPPED) { 130137160Sbrian fsm_Down(fp); 130237160Sbrian fsm_Up(fp); 130337160Sbrian } else { 130437160Sbrian fsm_Up(fp); 130537160Sbrian fsm_Open(fp); 130637160Sbrian } 130736285Sbrian } 130837160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 130937160Sbrian if (arg->cx) 131037160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 131137160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 131237160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 131337160Sbrian else 131437993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 131537160Sbrian } else 131637160Sbrian return -1; 131736285Sbrian } else 131836285Sbrian return -1; 131936285Sbrian 132026516Sbrian return 0; 13216059Samurai} 13226059Samurai 132325067Sbrianstatic int 132436285SbrianCloseCommand(struct cmdargs const *arg) 13256059Samurai{ 132637007Sbrian if (arg->argc == arg->argn) 132737007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 132837007Sbrian else if (arg->argc == arg->argn + 1) { 132937007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 133037007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 133137007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 133237007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 133337007Sbrian struct fsm *fp; 13346059Samurai 133537210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 133637007Sbrian if (fp->state == ST_OPENED) { 133737007Sbrian fsm_Close(fp); 133837007Sbrian if (arg->argv[arg->argn][3] == '!') 133937007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 134037007Sbrian else 134137007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 134237007Sbrian } 134337007Sbrian } else 134436285Sbrian return -1; 134536285Sbrian } else 134636285Sbrian return -1; 134736285Sbrian 134836285Sbrian return 0; 13496059Samurai} 13506059Samurai 135125067Sbrianstatic int 135236285SbrianDownCommand(struct cmdargs const *arg) 135311336Samurai{ 135437018Sbrian if (arg->argc == arg->argn) { 135537018Sbrian if (arg->cx) 135637018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 135737018Sbrian else 135837018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 135937018Sbrian } else if (arg->argc == arg->argn + 1) { 136037018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 136137018Sbrian if (arg->cx) 136237018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 136337018Sbrian else 136437018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 136537018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 136637018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 136737018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 136837060Sbrian fsm2initial(fp); 136937018Sbrian } else 137037018Sbrian return -1; 137136285Sbrian } else 137236285Sbrian return -1; 137336285Sbrian 137436285Sbrian return 0; 137525067Sbrian} 137625067Sbrian 137725067Sbrianstatic int 137836285SbrianSetModemSpeed(struct cmdargs const *arg) 137925067Sbrian{ 138036285Sbrian long speed; 138136285Sbrian char *end; 138211336Samurai 138336285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 138436285Sbrian if (arg->argc > arg->argn+1) { 138554917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 138636285Sbrian return -1; 138711336Samurai } 138836285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 138936285Sbrian physical_SetSync(arg->cx->physical); 139036285Sbrian return 0; 139136285Sbrian } 139236285Sbrian end = NULL; 139336285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 1394134789Sbrian if (*end || speed < 0) { 139536285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 139636285Sbrian arg->argv[arg->argn]); 139736285Sbrian return -1; 139836285Sbrian } 139936285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 140036285Sbrian return 0; 140136285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 140236285Sbrian } else 140336285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 140424939Sbrian 140526516Sbrian return -1; 140611336Samurai} 140711336Samurai 140825067Sbrianstatic int 140931343SbrianSetStoppedTimeout(struct cmdargs const *arg) 141028327Sbrian{ 141136285Sbrian struct link *l = &arg->cx->physical->link; 141236285Sbrian 141336285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 141436285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 141536285Sbrian if (arg->argc <= arg->argn+2) { 141636285Sbrian if (arg->argc > arg->argn) { 141736285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 141836285Sbrian if (arg->argc > arg->argn+1) 141936285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 142028461Sbrian } 142128327Sbrian return 0; 142228327Sbrian } 142328327Sbrian return -1; 142428327Sbrian} 142528327Sbrian 142628327Sbrianstatic int 142731343SbrianSetServer(struct cmdargs const *arg) 142826940Sbrian{ 142926940Sbrian int res = -1; 143026940Sbrian 143136285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 143231081Sbrian const char *port, *passwd, *mask; 1433134789Sbrian size_t mlen; 143431081Sbrian 143531081Sbrian /* What's what ? */ 143636285Sbrian port = arg->argv[arg->argn]; 143736285Sbrian if (arg->argc == arg->argn + 2) { 143836285Sbrian passwd = arg->argv[arg->argn+1]; 143936285Sbrian mask = NULL; 144036285Sbrian } else if (arg->argc == arg->argn + 3) { 144136285Sbrian passwd = arg->argv[arg->argn+1]; 144236285Sbrian mask = arg->argv[arg->argn+2]; 144353125Sbrian mlen = strlen(mask); 144453125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 144553125Sbrian (mlen == 4 && *mask != '0')) { 144653125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 144753125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 144831081Sbrian return -1; 144953125Sbrian } 145071764Sbrian } else if (arg->argc != arg->argn + 1) 145171764Sbrian return -1; 145271764Sbrian else if (strcasecmp(port, "none") == 0) { 145371657Sbrian if (server_Clear(arg->bundle)) 145471657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 145571657Sbrian return 0; 145671657Sbrian } else if (strcasecmp(port, "open") == 0) { 145771657Sbrian switch (server_Reopen(arg->bundle)) { 145871657Sbrian case SERVER_OK: 145971657Sbrian return 0; 146071657Sbrian case SERVER_FAILED: 146171764Sbrian log_Printf(LogWARN, "Failed to reopen server port\n"); 146271657Sbrian return 1; 146371657Sbrian case SERVER_UNSET: 146471764Sbrian log_Printf(LogWARN, "Cannot reopen unset server socket\n"); 146571657Sbrian return 1; 146671657Sbrian default: 146771657Sbrian break; 146871657Sbrian } 146971657Sbrian return -1; 147071657Sbrian } else if (strcasecmp(port, "closed") == 0) { 147136285Sbrian if (server_Close(arg->bundle)) 147271657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 147371657Sbrian else 147471657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 147571657Sbrian 147636285Sbrian return 0; 147731081Sbrian } else 147836285Sbrian return -1; 147931081Sbrian 148071657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 148171657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 148231081Sbrian 148336285Sbrian if (*port == '/') { 148431081Sbrian mode_t imask; 148536285Sbrian char *ptr, name[LINE_LEN + 12]; 148628679Sbrian 148753125Sbrian if (mask == NULL) 148831081Sbrian imask = (mode_t)-1; 148953125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 149053125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 149136285Sbrian 149236285Sbrian ptr = strstr(port, "%d"); 149336285Sbrian if (ptr) { 149436285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 149537210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 149636285Sbrian port = name; 149736285Sbrian } 149836285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 149927346Sbrian } else { 150036285Sbrian int iport, add = 0; 150128679Sbrian 150231081Sbrian if (mask != NULL) 150331081Sbrian return -1; 150428679Sbrian 150536285Sbrian if (*port == '+') { 150636285Sbrian port++; 150736285Sbrian add = 1; 150836285Sbrian } 150931081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 151031081Sbrian struct servent *s; 151131081Sbrian 151231081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 151331081Sbrian iport = 0; 151436285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 151528679Sbrian } else 151631081Sbrian iport = ntohs(s->s_port); 151727346Sbrian } else 151831081Sbrian iport = atoi(port); 151936285Sbrian 152036285Sbrian if (iport) { 152136285Sbrian if (add) 152236285Sbrian iport += arg->bundle->unit; 152336285Sbrian res = server_TcpOpen(arg->bundle, iport); 152436285Sbrian } else 152536285Sbrian res = -1; 152627346Sbrian } 152731081Sbrian } 152826940Sbrian 152926940Sbrian return res; 153026940Sbrian} 153126940Sbrian 153226940Sbrianstatic int 153331343SbrianSetEscape(struct cmdargs const *arg) 15346059Samurai{ 15356059Samurai int code; 153636285Sbrian int argc = arg->argc - arg->argn; 153736285Sbrian char const *const *argv = arg->argv + arg->argn; 15386059Samurai 15396059Samurai for (code = 0; code < 33; code++) 154036285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 154131343Sbrian 15426059Samurai while (argc-- > 0) { 15436059Samurai sscanf(*argv++, "%x", &code); 15446059Samurai code &= 0xff; 154536285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 154636285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 15476059Samurai } 154826516Sbrian return 0; 15496059Samurai} 15506059Samurai 15516059Samuraistatic int 155231343SbrianSetInterfaceAddr(struct cmdargs const *arg) 15536059Samurai{ 155481634Sbrian struct ncp *ncp = &arg->bundle->ncp; 155581634Sbrian struct ncpaddr ncpaddr; 155632267Sbrian const char *hisaddr; 155732267Sbrian 155840561Sbrian if (arg->argc > arg->argn + 4) 155940561Sbrian return -1; 156040561Sbrian 156132267Sbrian hisaddr = NULL; 156281634Sbrian memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range); 156381634Sbrian memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range); 156481634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 0; 156581634Sbrian ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY; 156681634Sbrian iplist_reset(&ncp->ipcp.cfg.peer_list); 156728394Sbrian 156836285Sbrian if (arg->argc > arg->argn) { 156981634Sbrian if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn])) 157028679Sbrian return 1; 157136285Sbrian if (arg->argc > arg->argn+1) { 157236285Sbrian hisaddr = arg->argv[arg->argn+1]; 157336285Sbrian if (arg->argc > arg->argn+2) { 157481634Sbrian ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask = 157581634Sbrian GetIpAddr(arg->argv[arg->argn+2]); 157636285Sbrian if (arg->argc > arg->argn+3) { 157781634Sbrian ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 157881634Sbrian ncp->ipcp.cfg.HaveTriggerAddress = 1; 15799440Samurai } 15806059Samurai } 15816059Samurai } 15826059Samurai } 158328394Sbrian 158440561Sbrian /* 0.0.0.0 means any address (0 bits) */ 1585132204Sbrian ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr); 158681634Sbrian ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip); 158781634Sbrian if (ncp->ipcp.my_ip.s_addr == INADDR_ANY) 158881634Sbrian ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0); 158981634Sbrian bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL); 159036285Sbrian 159136285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 159236928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 159332267Sbrian return 4; 159431121Sbrian 159526516Sbrian return 0; 15966059Samurai} 15976059Samurai 159818752Sjkhstatic int 159944305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 160044305Sbrian u_int *maxtrm, int def) 160144305Sbrian{ 160244305Sbrian if (argc == 0) { 160344305Sbrian *timeout = DEF_FSMRETRY; 160444305Sbrian *maxreq = def; 160544305Sbrian if (maxtrm != NULL) 160644305Sbrian *maxtrm = def; 160744305Sbrian } else { 160844305Sbrian long l = atol(argv[0]); 160944305Sbrian 161044305Sbrian if (l < MIN_FSMRETRY) { 161144305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 161244305Sbrian l, MIN_FSMRETRY); 161344305Sbrian return 1; 161444305Sbrian } else 161544305Sbrian *timeout = l; 161644305Sbrian 161744305Sbrian if (argc > 1) { 161844305Sbrian l = atol(argv[1]); 161944305Sbrian if (l < 1) { 162044305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 162144305Sbrian l = 1; 162244305Sbrian } 162344305Sbrian *maxreq = l; 162444305Sbrian 162544305Sbrian if (argc > 2 && maxtrm != NULL) { 162644305Sbrian l = atol(argv[2]); 162744305Sbrian if (l < 1) { 162844305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 162944305Sbrian l = 1; 163044305Sbrian } 163144305Sbrian *maxtrm = l; 163244305Sbrian } 163344305Sbrian } 163444305Sbrian } 163544305Sbrian 163644305Sbrian return 0; 163744305Sbrian} 163844305Sbrian 163944305Sbrianstatic int 164031343SbrianSetVariable(struct cmdargs const *arg) 16416059Samurai{ 164237210Sbrian long long_val, param = (long)arg->cmd->args; 164379119Sbrian int mode, dummyint, f, first, res; 164478410Sbrian u_short *change; 164531343Sbrian const char *argp; 164636285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 164736285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 164881634Sbrian struct in_addr *ipaddr; 164981634Sbrian struct ncpaddr ncpaddr[2]; 16506059Samurai 165136285Sbrian if (arg->argc > arg->argn) 165236285Sbrian argp = arg->argv[arg->argn]; 165326551Sbrian else 165431343Sbrian argp = ""; 165526551Sbrian 165679119Sbrian res = 0; 165779119Sbrian 165836285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 165936285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 166036285Sbrian arg->cmd->name); 166136285Sbrian return 1; 166236285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 166336285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 166436285Sbrian arg->cmd->name, cx->name); 166536285Sbrian cx = NULL; 166636285Sbrian } 166736285Sbrian 166826551Sbrian switch (param) { 166928679Sbrian case VAR_AUTHKEY: 167050139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 167150139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 167250139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 167328679Sbrian break; 167437210Sbrian 167528679Sbrian case VAR_AUTHNAME: 167640622Sbrian switch (bundle_Phase(arg->bundle)) { 167758880Sbrian default: 167858880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 167958880Sbrian bundle_PhaseName(arg->bundle)); 168058880Sbrian /* drop through */ 168140622Sbrian case PHASE_DEAD: 168240622Sbrian case PHASE_ESTABLISH: 168340622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 168440622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 168540622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 168640622Sbrian break; 168736285Sbrian } 168828679Sbrian break; 168937210Sbrian 169036285Sbrian case VAR_AUTOLOAD: 169149434Sbrian if (arg->argc == arg->argn + 3) { 169298243Sbrian int v1, v2, v3; 169349434Sbrian char *end; 169449434Sbrian 169549434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 169649434Sbrian if (v1 < 0 || *end) { 169749434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 169849434Sbrian arg->argv[arg->argn]); 169979119Sbrian res = 1; 170079119Sbrian break; 170136285Sbrian } 170249434Sbrian 170349434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 170449434Sbrian if (v2 < 0 || *end) { 170549434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 170649434Sbrian arg->argv[arg->argn + 1]); 170779119Sbrian res = 1; 170879119Sbrian break; 170949434Sbrian } 171049434Sbrian if (v2 < v1) { 171149434Sbrian v3 = v1; 171249434Sbrian v1 = v2; 171349434Sbrian v2 = v3; 171449434Sbrian } 171549434Sbrian 171649434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 171749434Sbrian if (v3 <= 0 || *end) { 171849434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 171949434Sbrian arg->argv[arg->argn + 2]); 172079119Sbrian res = 1; 172179119Sbrian break; 172249434Sbrian } 172349434Sbrian 172449434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 172549434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 172649434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 172749434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 172836285Sbrian } else { 172979119Sbrian log_Printf(LogWARN, "Set autoload requires three arguments\n"); 173079119Sbrian res = 1; 173136285Sbrian } 173236285Sbrian break; 173337210Sbrian 173428679Sbrian case VAR_DIAL: 173536285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 173636285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 173728679Sbrian break; 173837210Sbrian 173928679Sbrian case VAR_LOGIN: 174036285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 174136285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 174228679Sbrian break; 174337210Sbrian 174436285Sbrian case VAR_WINSIZE: 174536285Sbrian if (arg->argc > arg->argn) { 174636285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 174736285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 174836285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 174936285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 175036285Sbrian l->ccp.cfg.deflate.out.winsize); 175136285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 175236285Sbrian } 175336285Sbrian if (arg->argc > arg->argn+1) { 175436285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 175536285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 175636285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 175736285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 175836285Sbrian l->ccp.cfg.deflate.in.winsize); 175936285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 176036285Sbrian } 176136285Sbrian } else 176236285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 176336285Sbrian } else { 176479119Sbrian log_Printf(LogWARN, "No window size specified\n"); 176579119Sbrian res = 1; 176636285Sbrian } 176736285Sbrian break; 176837210Sbrian 176993418Sbrian#ifndef NODES 177078411Sbrian case VAR_MPPE: 177179119Sbrian if (arg->argc > arg->argn + 2) { 177279119Sbrian res = -1; 177379119Sbrian break; 177479119Sbrian } 177578411Sbrian 177678411Sbrian if (arg->argc == arg->argn) { 177778411Sbrian l->ccp.cfg.mppe.keybits = 0; 177878411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 177978411Sbrian l->ccp.cfg.mppe.required = 0; 178078411Sbrian break; 178178411Sbrian } 178278411Sbrian 178378411Sbrian if (!strcmp(argp, "*")) 178478411Sbrian long_val = 0; 178578411Sbrian else { 178678411Sbrian long_val = atol(argp); 178778411Sbrian if (long_val != 40 && long_val != 56 && long_val != 128) { 178878411Sbrian log_Printf(LogWARN, "%s: Invalid bits value\n", argp); 178979119Sbrian res = -1; 179079119Sbrian break; 179167910Sbrian } 179267910Sbrian } 179378411Sbrian 179478411Sbrian if (arg->argc == arg->argn + 2) { 179578411Sbrian if (!strcmp(arg->argv[arg->argn + 1], "*")) 179678411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 179778411Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) 179878411Sbrian l->ccp.cfg.mppe.state = MPPE_STATELESS; 179979370Sbrian else if (!strcasecmp(arg->argv[arg->argn + 1], "stateful")) 180078411Sbrian l->ccp.cfg.mppe.state = MPPE_STATEFUL; 180178411Sbrian else { 180278411Sbrian log_Printf(LogWARN, "%s: Invalid state value\n", 180378411Sbrian arg->argv[arg->argn + 1]); 180479119Sbrian res = -1; 180579119Sbrian break; 180678411Sbrian } 180778411Sbrian } else 180878411Sbrian l->ccp.cfg.mppe.state = MPPE_ANYSTATE; 180978411Sbrian l->ccp.cfg.mppe.keybits = long_val; 181078411Sbrian l->ccp.cfg.mppe.required = 1; 181167910Sbrian break; 181267910Sbrian#endif 181367910Sbrian 181428679Sbrian case VAR_DEVICE: 181536285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 181636285Sbrian arg->argv + arg->argn); 181736285Sbrian break; 181837210Sbrian 181936285Sbrian case VAR_ACCMAP: 182036285Sbrian if (arg->argc > arg->argn) { 182137210Sbrian u_long ulong_val; 182236285Sbrian sscanf(argp, "%lx", &ulong_val); 182337210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 182436285Sbrian } else { 182579119Sbrian log_Printf(LogWARN, "No accmap specified\n"); 182679119Sbrian res = 1; 182736285Sbrian } 182836285Sbrian break; 182937210Sbrian 183036285Sbrian case VAR_MODE: 183136285Sbrian mode = Nam2mode(argp); 183236285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 183336285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 183479119Sbrian res = -1; 183579119Sbrian break; 183636285Sbrian } 183736285Sbrian bundle_SetMode(arg->bundle, cx, mode); 183836285Sbrian break; 183937210Sbrian 184036285Sbrian case VAR_MRRU: 184140622Sbrian switch (bundle_Phase(arg->bundle)) { 184240622Sbrian case PHASE_DEAD: 184340622Sbrian break; 184440622Sbrian case PHASE_ESTABLISH: 184540622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 184640622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 184740622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 184879119Sbrian res = 1; 184979119Sbrian break; 185040622Sbrian } 185140622Sbrian break; 185240622Sbrian default: 185340622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 185479119Sbrian res = 1; 185579119Sbrian break; 185629696Sbrian } 185779119Sbrian if (res != 0) 185879119Sbrian break; 185937210Sbrian long_val = atol(argp); 186037210Sbrian if (long_val && long_val < MIN_MRU) { 186137210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 186279119Sbrian res = 1; 186379119Sbrian break; 186437210Sbrian } else if (long_val > MAX_MRU) { 186537210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 186679119Sbrian res = 1; 186779119Sbrian break; 186837210Sbrian } else 186937210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 187028679Sbrian break; 187137210Sbrian 187236285Sbrian case VAR_MRU: 187379163Sbrian long_val = 0; /* silence gcc */ 187479163Sbrian change = NULL; /* silence gcc */ 187578410Sbrian switch(arg->argc - arg->argn) { 187678410Sbrian case 1: 187779119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 187879119Sbrian res = -1; 187979119Sbrian break; 188079119Sbrian } 188179119Sbrian /*FALLTHRU*/ 188278410Sbrian case 0: 188378410Sbrian long_val = atol(argp); 188478410Sbrian change = &l->lcp.cfg.mru; 188578410Sbrian if (long_val > l->lcp.cfg.max_mru) { 188678410Sbrian log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, 188778410Sbrian l->lcp.cfg.max_mru); 188879119Sbrian res = 1; 188979119Sbrian break; 189078410Sbrian } 189178410Sbrian break; 189278410Sbrian case 2: 189379119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 189479119Sbrian res = -1; 189579119Sbrian break; 189679119Sbrian } 189778410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 189878410Sbrian change = &l->lcp.cfg.max_mru; 189978410Sbrian if (long_val > MAX_MRU) { 190078410Sbrian log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, 190178410Sbrian MAX_MRU); 190279119Sbrian res = 1; 190379119Sbrian break; 190478410Sbrian } 190578410Sbrian break; 190678410Sbrian default: 190779119Sbrian res = -1; 190879119Sbrian break; 190978410Sbrian } 191079119Sbrian if (res != 0) 191179119Sbrian break; 191278410Sbrian 191337210Sbrian if (long_val == 0) 191480385Sbrian *change = 0; 191537210Sbrian else if (long_val < MIN_MRU) { 191637210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 191779119Sbrian res = 1; 191879119Sbrian break; 191937210Sbrian } else if (long_val > MAX_MRU) { 192037210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 192179119Sbrian res = 1; 192279119Sbrian break; 192337210Sbrian } else 192478410Sbrian *change = long_val; 192578410Sbrian if (l->lcp.cfg.mru > *change) 192678410Sbrian l->lcp.cfg.mru = *change; 192728679Sbrian break; 192837210Sbrian 192936285Sbrian case VAR_MTU: 193079163Sbrian long_val = 0; /* silence gcc */ 193179163Sbrian change = NULL; /* silence gcc */ 193278410Sbrian switch(arg->argc - arg->argn) { 193378410Sbrian case 1: 193479119Sbrian if (argp[strspn(argp, "0123456789")] != '\0') { 193579119Sbrian res = -1; 193679119Sbrian break; 193779119Sbrian } 193879119Sbrian /*FALLTHRU*/ 193978410Sbrian case 0: 194078410Sbrian long_val = atol(argp); 194178410Sbrian change = &l->lcp.cfg.mtu; 194278410Sbrian if (long_val > l->lcp.cfg.max_mtu) { 194378410Sbrian log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, 194478410Sbrian l->lcp.cfg.max_mtu); 194579119Sbrian res = 1; 194679119Sbrian break; 194778410Sbrian } 194878410Sbrian break; 194978410Sbrian case 2: 195079119Sbrian if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { 195179119Sbrian res = -1; 195279119Sbrian break; 195379119Sbrian } 195478410Sbrian long_val = atol(arg->argv[arg->argn + 1]); 195578410Sbrian change = &l->lcp.cfg.max_mtu; 195678410Sbrian if (long_val > MAX_MTU) { 195778410Sbrian log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, 195878410Sbrian MAX_MTU); 195979119Sbrian res = 1; 196079119Sbrian break; 196178410Sbrian } 196278410Sbrian break; 196378410Sbrian default: 196479119Sbrian res = -1; 196579119Sbrian break; 196678410Sbrian } 196778410Sbrian 196879119Sbrian if (res != 0) 196979119Sbrian break; 197079119Sbrian 197137210Sbrian if (long_val && long_val < MIN_MTU) { 197237210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 197379119Sbrian res = 1; 197479119Sbrian break; 197537210Sbrian } else if (long_val > MAX_MTU) { 197637210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 197779119Sbrian res = 1; 197879119Sbrian break; 197937210Sbrian } else 198078410Sbrian *change = long_val; 198178410Sbrian if (l->lcp.cfg.mtu > *change) 198278410Sbrian l->lcp.cfg.mtu = *change; 198336285Sbrian break; 198437210Sbrian 198536285Sbrian case VAR_OPENMODE: 198636285Sbrian if (strcasecmp(argp, "active") == 0) 198736285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 198836285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 198936285Sbrian else if (strcasecmp(argp, "passive") == 0) 199036285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 199136285Sbrian else { 199279119Sbrian log_Printf(LogWARN, "%s: Invalid openmode\n", argp); 199379119Sbrian res = 1; 199436285Sbrian } 199536285Sbrian break; 199637210Sbrian 199728679Sbrian case VAR_PHONE: 199836285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 199936285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 200038174Sbrian cx->phone.alt = cx->phone.next = NULL; 200128679Sbrian break; 200237210Sbrian 200328679Sbrian case VAR_HANGUP: 200436285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 200536285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 200628679Sbrian break; 200737210Sbrian 200861534Sbrian case VAR_IFQUEUE: 200961534Sbrian long_val = atol(argp); 201061534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 201161534Sbrian break; 201261534Sbrian 201352488Sbrian case VAR_LOGOUT: 201452488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 201552488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 201652488Sbrian break; 201752488Sbrian 201836285Sbrian case VAR_IDLETIMEOUT: 201979119Sbrian if (arg->argc > arg->argn+2) { 202079119Sbrian log_Printf(LogWARN, "Too many idle timeout values\n"); 202179119Sbrian res = 1; 202279119Sbrian } else if (arg->argc == arg->argn) { 202379119Sbrian log_Printf(LogWARN, "Too few idle timeout values\n"); 202479119Sbrian res = 1; 202579119Sbrian } else { 2026134789Sbrian unsigned long timeout, min; 202749978Sbrian 2028134789Sbrian timeout = strtoul(argp, NULL, 10); 2029134789Sbrian min = arg->bundle->cfg.idle.min_timeout; 2030134789Sbrian if (arg->argc == arg->argn + 2) 2031134789Sbrian min = strtoul(arg->argv[arg->argn + 1], NULL, 10); 203249978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 203349978Sbrian } 203429549Sbrian break; 2035132273Sbrian 2036132273Sbrian#ifndef NORADIUS 2037132273Sbrian case VAR_RAD_ALIVE: 2038132273Sbrian if (arg->argc > arg->argn + 2) { 2039132273Sbrian log_Printf(LogWARN, "Too many RADIUS alive interval values\n"); 2040132273Sbrian res = 1; 2041132273Sbrian } else if (arg->argc == arg->argn) { 2042132273Sbrian log_Printf(LogWARN, "Too few RADIUS alive interval values\n"); 2043132273Sbrian res = 1; 2044132273Sbrian } else { 2045132273Sbrian arg->bundle->radius.alive.interval = atoi(argp); 2046132273Sbrian if (arg->bundle->radius.alive.interval && !arg->bundle->radius.cfg.file) { 2047132273Sbrian log_Printf(LogWARN, "rad_alive requires radius to be configured\n"); 2048132273Sbrian res = 1; 2049132273Sbrian } else if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) { 2050132273Sbrian if (arg->bundle->radius.alive.interval) 2051132273Sbrian radius_StartTimer(arg->bundle); 2052132273Sbrian else 2053132273Sbrian radius_StopTimer(&arg->bundle->radius); 2054132273Sbrian } 2055132273Sbrian } 2056132273Sbrian break; 2057132273Sbrian#endif 2058132273Sbrian 205936285Sbrian case VAR_LQRPERIOD: 206037210Sbrian long_val = atol(argp); 206137210Sbrian if (long_val < MIN_LQRPERIOD) { 206237210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 206337210Sbrian long_val, MIN_LQRPERIOD); 206479119Sbrian res = 1; 206536285Sbrian } else 206637210Sbrian l->lcp.cfg.lqrperiod = long_val; 206736285Sbrian break; 206837210Sbrian 206936285Sbrian case VAR_LCPRETRY: 207079119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 207179119Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 207279119Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 207379119Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 207436285Sbrian break; 207537210Sbrian 207636285Sbrian case VAR_CHAPRETRY: 207779119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 207879119Sbrian &cx->chap.auth.cfg.fsm.timeout, 207979119Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 208036285Sbrian break; 208137210Sbrian 208236285Sbrian case VAR_PAPRETRY: 208379119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 208479119Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 208579119Sbrian NULL, DEF_FSMAUTHTRIES); 208636285Sbrian break; 208737210Sbrian 208836285Sbrian case VAR_CCPRETRY: 208979119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 209079119Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 209179119Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 209236285Sbrian break; 209337210Sbrian 209436285Sbrian case VAR_IPCPRETRY: 209579119Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 209679119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 209779119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 209879119Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 209936285Sbrian break; 210037210Sbrian 2101102855Sbrian#ifndef NOINET6 2102102558Sbrian case VAR_IPV6CPRETRY: 2103102558Sbrian res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 2104102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.timeout, 2105102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.maxreq, 2106102558Sbrian &arg->bundle->ncp.ipv6cp.cfg.fsm.maxtrm, DEF_FSMTRIES); 2107102558Sbrian break; 2108102855Sbrian#endif 2109102558Sbrian 211036285Sbrian case VAR_NBNS: 211136285Sbrian case VAR_DNS: 211258044Sbrian if (param == VAR_DNS) { 211381634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns; 211481634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE; 211558044Sbrian } else { 211681634Sbrian ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 211781634Sbrian ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY; 211858044Sbrian } 211936285Sbrian 212036285Sbrian if (arg->argc > arg->argn) { 212181634Sbrian ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]); 212281634Sbrian if (!ncpaddr_getip4(ncpaddr, ipaddr)) 212381634Sbrian return -1; 212481634Sbrian if (arg->argc > arg->argn+1) { 212581634Sbrian ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]); 212681634Sbrian if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1)) 212781634Sbrian return -1; 212881634Sbrian } 212936285Sbrian 213081634Sbrian if (ipaddr[0].s_addr == INADDR_ANY) { 213181634Sbrian ipaddr[0] = ipaddr[1]; 213281634Sbrian ipaddr[1].s_addr = INADDR_ANY; 213358044Sbrian } 213481634Sbrian if (ipaddr[0].s_addr == INADDR_NONE) { 213581634Sbrian ipaddr[0] = ipaddr[1]; 213681634Sbrian ipaddr[1].s_addr = INADDR_NONE; 213758044Sbrian } 213836285Sbrian } 213936285Sbrian break; 214038174Sbrian 214138174Sbrian case VAR_CALLBACK: 214238174Sbrian cx->cfg.callback.opmask = 0; 214338174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 214438174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 214538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 214638174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 214738174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 214838174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 214938174Sbrian if (dummyint == arg->argc - 1) 215038174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 215138174Sbrian else { 215238174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 215338174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 215438174Sbrian sizeof cx->cfg.callback.msg - 1); 215538174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 215638174Sbrian } 215738174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 215838174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 215979119Sbrian else { 216079119Sbrian res = -1; 216179119Sbrian break; 216279119Sbrian } 216338174Sbrian } 216438174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 216538174Sbrian cx->cfg.callback.opmask = 0; 216638174Sbrian break; 216738174Sbrian 216838174Sbrian case VAR_CBCP: 216938174Sbrian cx->cfg.cbcp.delay = 0; 217038174Sbrian *cx->cfg.cbcp.phone = '\0'; 217138174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 217238174Sbrian if (arg->argc > arg->argn) { 217338174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 217438174Sbrian sizeof cx->cfg.cbcp.phone - 1); 217538174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 217638174Sbrian if (arg->argc > arg->argn + 1) { 217738174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 217838174Sbrian if (arg->argc > arg->argn + 2) { 217938174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 218038174Sbrian if (long_val < MIN_FSMRETRY) 218138174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 218238174Sbrian long_val, MIN_FSMRETRY); 218338174Sbrian else 218438174Sbrian cx->cfg.cbcp.fsmretry = long_val; 218538174Sbrian } 218638174Sbrian } 218738174Sbrian } 218838174Sbrian break; 218938544Sbrian 219038544Sbrian case VAR_CHOKED: 219138544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 219238544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 219338544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 219438544Sbrian break; 219540665Sbrian 219640665Sbrian case VAR_SENDPIPE: 219740665Sbrian long_val = atol(argp); 219881634Sbrian arg->bundle->ncp.cfg.sendpipe = long_val; 219940665Sbrian break; 220040665Sbrian 220140665Sbrian case VAR_RECVPIPE: 220240665Sbrian long_val = atol(argp); 220381634Sbrian arg->bundle->ncp.cfg.recvpipe = long_val; 220440665Sbrian break; 220543313Sbrian 220643313Sbrian#ifndef NORADIUS 220743313Sbrian case VAR_RADIUS: 220843313Sbrian if (!*argp) 220943313Sbrian *arg->bundle->radius.cfg.file = '\0'; 221043313Sbrian else if (access(argp, R_OK)) { 221143313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 221279119Sbrian res = 1; 221379119Sbrian break; 221443313Sbrian } else { 221543313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 221643313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 221743313Sbrian arg->bundle->radius.cfg.file 221843313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 221943313Sbrian } 222043313Sbrian break; 222143313Sbrian#endif 222244073Sbrian 222344073Sbrian case VAR_CD: 222444073Sbrian if (*argp) { 222551699Sbrian if (strcasecmp(argp, "off")) { 222651699Sbrian long_val = atol(argp); 222751699Sbrian if (long_val < 0) 222851699Sbrian long_val = 0; 222951699Sbrian cx->physical->cfg.cd.delay = long_val; 223051699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 223151699Sbrian CD_REQUIRED : CD_VARIABLE; 223251699Sbrian } else 223351699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 223444073Sbrian } else { 223553733Sbrian cx->physical->cfg.cd.delay = 0; 223653733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 223744073Sbrian } 223844073Sbrian break; 223936285Sbrian 224046686Sbrian case VAR_PARITY: 224146686Sbrian if (arg->argc == arg->argn + 1) 224279119Sbrian res = physical_SetParity(arg->cx->physical, argp); 224346686Sbrian else { 224479119Sbrian log_Printf(LogWARN, "Parity value must be odd, even or none\n"); 224579119Sbrian res = 1; 224646686Sbrian } 224746686Sbrian break; 22486059Samurai 224946686Sbrian case VAR_CRTSCTS: 225046686Sbrian if (strcasecmp(argp, "on") == 0) 225136285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 225246686Sbrian else if (strcasecmp(argp, "off") == 0) 225336285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 225446686Sbrian else { 225579119Sbrian log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); 225679119Sbrian res = 1; 225746686Sbrian } 225846686Sbrian break; 225950867Sbrian 226050867Sbrian case VAR_URGENTPORTS: 226151048Sbrian if (arg->argn == arg->argc) { 226281634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 226381634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 226481634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 226551048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 226681634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 226751048Sbrian if (arg->argn == arg->argc - 1) 226881634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 226951048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 227051048Sbrian if (*arg->argv[f] == '+') 227181634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 227251048Sbrian else if (*arg->argv[f] == '-') 227381634Sbrian ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 227451048Sbrian else { 227551048Sbrian if (f == arg->argn) 227681634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 227781634Sbrian ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 227851048Sbrian } 227961430Sbrian } else if (arg->argn == arg->argc - 1 && 228061430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 228181634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 228281634Sbrian ncp_ClearUrgentUdpPorts(&arg->bundle->ncp); 228381634Sbrian ncp_ClearUrgentTOS(&arg->bundle->ncp); 228451048Sbrian } else { 228581634Sbrian ncp_SetUrgentTOS(&arg->bundle->ncp); 228651048Sbrian first = arg->argn; 228751048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 228881634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 228951048Sbrian 229051048Sbrian for (f = first; f < arg->argc; f++) 229151048Sbrian if (*arg->argv[f] == '+') 229281634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 229351048Sbrian else if (*arg->argv[f] == '-') 229481634Sbrian ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1)); 229551048Sbrian else { 229651048Sbrian if (f == first) 229781634Sbrian ncp_ClearUrgentTcpPorts(&arg->bundle->ncp); 229881634Sbrian ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f])); 229951048Sbrian } 230051048Sbrian } 230150867Sbrian break; 2302132818Sglebius 2303132818Sglebius case VAR_PPPOE: 2304132818Sglebius if (strcasecmp(argp, "3Com") == 0) 2305132818Sglebius physical_SetPPPoEnonstandard(arg->cx->physical, 1); 2306132818Sglebius else if (strcasecmp(argp, "standard") == 0) 2307132818Sglebius physical_SetPPPoEnonstandard(arg->cx->physical, 0); 2308132818Sglebius else { 2309132818Sglebius log_Printf(LogWARN, "PPPoE standard value must be \"standard\" or \"3Com\"\n"); 2310132818Sglebius res = 1; 2311132818Sglebius } 2312132818Sglebius break; 2313132818Sglebius 231420812Sjkh } 231546686Sbrian 231679119Sbrian return res; 231720812Sjkh} 231820812Sjkh 231930715Sbrianstatic struct cmdtab const SetCommands[] = { 232036285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 232136285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 232228679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 232336285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 232428679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 232536285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 232636285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 232736285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 232836285Sbrian (const void *)VAR_AUTOLOAD}, 232950867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 2330134789Sbrian "datalink bandwidth", "set bandwidth value", NULL}, 233138174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 233238174Sbrian "callback control", "set callback [none|auth|cbcp|" 233338174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 233438174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 233598243Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 233638174Sbrian (const void *)VAR_CBCP}, 233744305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 233844305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 233944073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 234044073Sbrian "set cd value[!]", (const void *)VAR_CD}, 234144305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 234244305Sbrian "CHAP retries", "set chapretry value [attempts]", 234344305Sbrian (const void *)VAR_CHAPRETRY}, 234438544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 234538544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 234646686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 234746686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 234846686Sbrian (const char *)VAR_CRTSCTS}, 234936285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 235036285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 235136285Sbrian (const void *) VAR_WINSIZE}, 235293418Sbrian#ifndef NODES 235367910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 235498243Sbrian "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", 235578411Sbrian (const void *) VAR_MPPE}, 235667910Sbrian#endif 235736285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 235846686Sbrian "physical device name", "set device|line device-name[,device-name]", 235936285Sbrian (const void *) VAR_DEVICE}, 236036285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 236136285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 236236285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 236336285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 236436285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 2365134789Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]", NULL}, 236636285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 2367134789Sbrian "escape characters", "set escape hex-digit ...", NULL}, 236836285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 236936285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 237081634Sbrian "[src_addr[/width]] [dst_addr[/width]] [proto " 2371134789Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]", NULL}, 237236285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 237336285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 237436285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 2375134789Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]", NULL}, 237661534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 237761534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 237844305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 237944305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 2380102558Sbrian {"ipv6cpretry", "ipv6cpretries", SetVariable, LOCAL_AUTH, "IPV6CP retries", 2381102558Sbrian "set ipv6cpretry value [attempts]", (const void *)VAR_IPV6CPRETRY}, 238244305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 238344305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 238436712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 238567916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 2386134789Sbrian "id0|ipcp|lcp|lqm|phase|physical|radius|sync|tcp/ip|timer|tun...", NULL}, 238736285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 238836285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 238952488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 239052488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 239136285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 239236285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 239336285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 239436285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 239536285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 239636285Sbrian "set mrru value", (const void *)VAR_MRRU}, 239796038Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 239878410Sbrian "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, 239978410Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 240078410Sbrian "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, 240136285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 240236285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 240336285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 240436285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 240544305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 240644305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 240746686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 240846686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 240936285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 241036285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 241140679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 2412134789Sbrian "Process title", "set proctitle [value]", NULL}, 241343313Sbrian#ifndef NORADIUS 241443313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 241543313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 2416132273Sbrian {"rad_alive", NULL, SetVariable, LOCAL_AUTH, 2417132273Sbrian "Raduis alive interval", "set rad_alive value", 2418132273Sbrian (const void *)VAR_RAD_ALIVE}, 241943313Sbrian#endif 242036285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 2421134789Sbrian "Reconnect timeout", "set reconnect value ntries", NULL}, 242240665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 242340665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 242436285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 2425134789Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]", NULL}, 242640665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 242740665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 242871657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 2429134789Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]", 2430134789Sbrian NULL}, 243136285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 2432134789Sbrian "physical speed", "set speed value|sync", NULL}, 243336285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 2434134789Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]", NULL}, 243536285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 243636285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 243751048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 243851048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 243936285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 2440134789Sbrian "vj values", "set vj slots|slotcomp [value]", NULL}, 244128679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 244231343Sbrian "Display this message", "set help|? [command]", SetCommands}, 2443132818Sglebius {"pppoe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 2444132818Sglebius "Connect using standard/3Com mode", "set pppoe [standard|3Com]", 2445132818Sglebius (const char *)VAR_PPPOE}, 2446134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 24476059Samurai}; 24486059Samurai 24496059Samuraistatic int 245031343SbrianSetCommand(struct cmdargs const *arg) 24516059Samurai{ 245236285Sbrian if (arg->argc > arg->argn) 245336285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 245436285Sbrian arg->prompt, arg->cx); 245536285Sbrian else if (arg->prompt) 245636285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 245758044Sbrian " syntax help.\n"); 24586059Samurai else 245936285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 246026516Sbrian 246126516Sbrian return 0; 24626059Samurai} 24636059Samurai 24646059Samuraistatic int 246531343SbrianAddCommand(struct cmdargs const *arg) 24666059Samurai{ 246781634Sbrian struct ncpaddr gw; 246881634Sbrian struct ncprange dest; 246981634Sbrian struct in_addr host; 2470112673Sume#ifndef NOINET6 2471112673Sume struct in6_addr host6; 2472112673Sume#endif 247381634Sbrian int dest_default, gw_arg, addrs; 24746059Samurai 247536285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 247631598Sbrian return -1; 247731598Sbrian 247836285Sbrian addrs = 0; 247981634Sbrian dest_default = 0; 248081634Sbrian if (arg->argc == arg->argn + 2) { 248136285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 248281634Sbrian dest_default = 1; 248331598Sbrian else { 248481634Sbrian if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn])) 248536285Sbrian return -1; 248636285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 248736285Sbrian addrs = ROUTE_DSTMYADDR; 248881634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7)) 248981634Sbrian addrs = ROUTE_DSTMYADDR6; 249036285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 249136285Sbrian addrs = ROUTE_DSTHISADDR; 249281634Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8)) 249381634Sbrian addrs = ROUTE_DSTHISADDR6; 249458044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 249558044Sbrian addrs = ROUTE_DSTDNS0; 249658044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 249758044Sbrian addrs = ROUTE_DSTDNS1; 249831598Sbrian } 249981634Sbrian gw_arg = 1; 250034536Sbrian } else { 250136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 250236285Sbrian addrs = ROUTE_DSTMYADDR; 250381634Sbrian host = arg->bundle->ncp.ipcp.my_ip; 250436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 250536285Sbrian addrs = ROUTE_DSTHISADDR; 250681634Sbrian host = arg->bundle->ncp.ipcp.peer_ip; 250758044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 250858044Sbrian addrs = ROUTE_DSTDNS0; 250981634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[0]; 251058044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 251158044Sbrian addrs = ROUTE_DSTDNS1; 251281634Sbrian host = arg->bundle->ncp.ipcp.ns.dns[1]; 251365263Sbrian } else { 251481634Sbrian host = GetIpAddr(arg->argv[arg->argn]); 251581634Sbrian if (host.s_addr == INADDR_NONE) { 251665263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 251765263Sbrian arg->argv[arg->argn]); 251865263Sbrian return -1; 251965263Sbrian } 252065263Sbrian } 252181634Sbrian ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1])); 252281634Sbrian gw_arg = 2; 25236059Samurai } 252436285Sbrian 252581634Sbrian if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) { 252681634Sbrian ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip); 252736285Sbrian addrs |= ROUTE_GWHISADDR; 252881634Sbrian#ifndef NOINET6 252981897Sbrian } else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) { 2530112673Sume if (!ncpaddr_getip6(&arg->bundle->ncp.ipv6cp.hisaddr, &host6)) 2531112673Sume memset(&host6, '\0', sizeof host6); 2532112673Sume ncpaddr_setip6(&gw, &host6); 253381634Sbrian addrs |= ROUTE_GWHISADDR6; 253481634Sbrian#endif 253565263Sbrian } else { 253681634Sbrian if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) { 253765263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 253881634Sbrian arg->argv[arg->argn + gw_arg]); 253965263Sbrian return -1; 254065263Sbrian } 254165263Sbrian } 254236285Sbrian 254381634Sbrian if (dest_default) 254481634Sbrian ncprange_setdefault(&dest, ncpaddr_family(&gw)); 254581634Sbrian 254681634Sbrian if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0, 254781634Sbrian ((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0) 254843313Sbrian && addrs != ROUTE_STATIC) 254981634Sbrian route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw); 255036285Sbrian 255131598Sbrian return 0; 25526059Samurai} 25536059Samurai 25546059Samuraistatic int 255531343SbrianDeleteCommand(struct cmdargs const *arg) 25566059Samurai{ 255781634Sbrian struct ncprange dest; 255836285Sbrian int addrs; 25596059Samurai 256036285Sbrian if (arg->argc == arg->argn+1) { 256136285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 256236285Sbrian route_IfDelete(arg->bundle, 0); 256381634Sbrian route_DeleteAll(&arg->bundle->ncp.route); 256436285Sbrian } else { 256536285Sbrian addrs = 0; 256636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 256781634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip); 256836285Sbrian addrs = ROUTE_DSTMYADDR; 256981634Sbrian#ifndef NOINET6 257081897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) { 257181634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr); 257281634Sbrian addrs = ROUTE_DSTMYADDR6; 257381634Sbrian#endif 257436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 257581634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip); 257636285Sbrian addrs = ROUTE_DSTHISADDR; 257781634Sbrian#ifndef NOINET6 257881897Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) { 257981634Sbrian ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr); 258081634Sbrian addrs = ROUTE_DSTHISADDR6; 258181634Sbrian#endif 258258044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 258381634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]); 258458044Sbrian addrs = ROUTE_DSTDNS0; 258558044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 258681634Sbrian ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]); 258758044Sbrian addrs = ROUTE_DSTDNS1; 258836285Sbrian } else { 258981634Sbrian ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]); 259036285Sbrian addrs = ROUTE_STATIC; 259136285Sbrian } 259281634Sbrian rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0); 259381634Sbrian route_Delete(&arg->bundle->ncp.route, addrs, &dest); 259431598Sbrian } 259534536Sbrian } else 259626516Sbrian return -1; 259726516Sbrian 259826516Sbrian return 0; 25996059Samurai} 26006059Samurai 260150059Sbrian#ifndef NONAT 260226031Sbrianstatic int 260358867SbrianNatEnable(struct cmdargs const *arg) 260426031Sbrian{ 260536285Sbrian if (arg->argc == arg->argn+1) { 260636285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 260750059Sbrian if (!arg->bundle->NatEnabled) { 260846686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 260946686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 261050059Sbrian arg->bundle->NatEnabled = 1; 261146686Sbrian } 261237191Sbrian return 0; 261336285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 261450059Sbrian arg->bundle->NatEnabled = 0; 261540561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 261640561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 261726516Sbrian return 0; 261826142Sbrian } 261935449Sbrian } 262036285Sbrian 262126516Sbrian return -1; 262226031Sbrian} 262326031Sbrian 262426031Sbrian 262526031Sbrianstatic int 262658867SbrianNatOption(struct cmdargs const *arg) 262726031Sbrian{ 262838559Sbrian long param = (long)arg->cmd->args; 262938559Sbrian 263036285Sbrian if (arg->argc == arg->argn+1) { 263136285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 263250059Sbrian if (arg->bundle->NatEnabled) { 263337191Sbrian PacketAliasSetMode(param, param); 263428679Sbrian return 0; 263528679Sbrian } 263650059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 263736285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 263850059Sbrian if (arg->bundle->NatEnabled) { 263937191Sbrian PacketAliasSetMode(0, param); 264028679Sbrian return 0; 264128679Sbrian } 264250059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 264328679Sbrian } 264435449Sbrian } 264528679Sbrian return -1; 264626031Sbrian} 264750059Sbrian#endif /* #ifndef NONAT */ 264831121Sbrian 264931121Sbrianstatic int 265036285SbrianLinkCommand(struct cmdargs const *arg) 265136285Sbrian{ 265236285Sbrian if (arg->argc > arg->argn+1) { 265336285Sbrian char namelist[LINE_LEN]; 265436285Sbrian struct datalink *cx; 265536285Sbrian char *name; 265636285Sbrian int result = 0; 265736285Sbrian 265836285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 265936285Sbrian struct datalink *dl; 266036285Sbrian 266136285Sbrian cx = arg->bundle->links; 266236285Sbrian while (cx) { 266336285Sbrian /* Watch it, the command could be a ``remove'' */ 266436285Sbrian dl = cx->next; 266536285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 266636285Sbrian arg->prompt, cx); 266736285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 266836285Sbrian if (cx == dl) 266936285Sbrian break; /* Pointer's still valid ! */ 267036285Sbrian } 267136285Sbrian } else { 267236285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 267336285Sbrian namelist[sizeof namelist - 1] = '\0'; 267436285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 267536285Sbrian if (!bundle2datalink(arg->bundle, name)) { 267636285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 267736285Sbrian return 1; 267836285Sbrian } 267936285Sbrian 268036285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 268136285Sbrian namelist[sizeof namelist - 1] = '\0'; 268236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 268336285Sbrian cx = bundle2datalink(arg->bundle, name); 268436285Sbrian if (cx) 268536285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 268636285Sbrian arg->prompt, cx); 268736285Sbrian else { 268836285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 268936285Sbrian result++; 269036285Sbrian } 269136285Sbrian } 269236285Sbrian } 269336285Sbrian return result; 269436285Sbrian } 269536285Sbrian 269695258Sdes log_Printf(LogWARN, "usage: %s\n", arg->cmd->syntax); 269736285Sbrian return 2; 269836285Sbrian} 269936285Sbrian 270036285Sbrianstruct link * 270136285Sbriancommand_ChooseLink(struct cmdargs const *arg) 270236285Sbrian{ 270336285Sbrian if (arg->cx) 270436285Sbrian return &arg->cx->physical->link; 270537210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 270636285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 270737210Sbrian if (dl) 270837210Sbrian return &dl->physical->link; 270936285Sbrian } 271037210Sbrian return &arg->bundle->ncp.mp.link; 271136285Sbrian} 271236285Sbrian 271336285Sbrianstatic const char * 271436285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 271536285Sbrian{ 271636285Sbrian const char *result; 271736285Sbrian 271836285Sbrian switch (*cmd) { 271936285Sbrian case 'A': 272036285Sbrian case 'a': 272136285Sbrian result = "accept"; 272236285Sbrian *keep = NEG_MYMASK; 272336285Sbrian *add = NEG_ACCEPTED; 272436285Sbrian break; 272536285Sbrian case 'D': 272636285Sbrian case 'd': 272736285Sbrian switch (cmd[1]) { 272836285Sbrian case 'E': 272936285Sbrian case 'e': 273036285Sbrian result = "deny"; 273136285Sbrian *keep = NEG_MYMASK; 273236285Sbrian *add = 0; 273336285Sbrian break; 273436285Sbrian case 'I': 273536285Sbrian case 'i': 273636285Sbrian result = "disable"; 273736285Sbrian *keep = NEG_HISMASK; 273836285Sbrian *add = 0; 273936285Sbrian break; 274036285Sbrian default: 274136285Sbrian return NULL; 274236285Sbrian } 274336285Sbrian break; 274436285Sbrian case 'E': 274536285Sbrian case 'e': 274636285Sbrian result = "enable"; 274736285Sbrian *keep = NEG_HISMASK; 274836285Sbrian *add = NEG_ENABLED; 274936285Sbrian break; 275036285Sbrian default: 275136285Sbrian return NULL; 275236285Sbrian } 275336285Sbrian 275436285Sbrian return result; 275536285Sbrian} 275636285Sbrian 275736285Sbrianstatic int 275836285SbrianOptSet(struct cmdargs const *arg) 275936285Sbrian{ 276037574Sbrian int bit = (int)(long)arg->cmd->args; 276136285Sbrian unsigned keep; /* Keep these bits */ 276236285Sbrian unsigned add; /* Add these bits */ 276336285Sbrian 276481697Sbrian if (ident_cmd(arg->argv[arg->argn - 2], &keep, &add) == NULL) 276536285Sbrian return 1; 276636285Sbrian 276781885Sbrian#ifndef NOINET6 276881697Sbrian if (add == NEG_ENABLED && bit == OPT_IPV6CP && !probe.ipv6_available) { 276981697Sbrian log_Printf(LogWARN, "IPv6 is not available on this machine\n"); 277081697Sbrian return 1; 277181697Sbrian } 277281885Sbrian#endif 277381697Sbrian 277436285Sbrian if (add) 277536285Sbrian arg->bundle->cfg.opt |= bit; 277636285Sbrian else 277736285Sbrian arg->bundle->cfg.opt &= ~bit; 277881697Sbrian 277936285Sbrian return 0; 278036285Sbrian} 278136285Sbrian 278236285Sbrianstatic int 278340561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 278440561Sbrian{ 278540561Sbrian unsigned save = arg->bundle->cfg.opt; 278640561Sbrian int result = OptSet(arg); 278740561Sbrian 278840561Sbrian if (result == 0) 278950059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 279040561Sbrian arg->bundle->cfg.opt = save; 279150059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 279240561Sbrian result = 2; 279340561Sbrian } 279440561Sbrian 279540561Sbrian return result; 279640561Sbrian} 279740561Sbrian 279840561Sbrianstatic int 279936285SbrianNegotiateSet(struct cmdargs const *arg) 280036285Sbrian{ 280137210Sbrian long param = (long)arg->cmd->args; 280236285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 280336285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 280436285Sbrian const char *cmd; 280536285Sbrian unsigned keep; /* Keep these bits */ 280636285Sbrian unsigned add; /* Add these bits */ 280736285Sbrian 280836285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 280936285Sbrian return 1; 281036285Sbrian 281136285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 281236285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 281336285Sbrian cmd, arg->cmd->name); 281436285Sbrian return 2; 281536285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 281636285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 281736285Sbrian cmd, arg->cmd->name, cx->name); 281836285Sbrian cx = NULL; 281936285Sbrian } 282036285Sbrian 282136285Sbrian switch (param) { 282236285Sbrian case NEG_ACFCOMP: 282336285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 282436285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 282536285Sbrian break; 282644106Sbrian case NEG_CHAP05: 282744106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 282844106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 282936285Sbrian break; 283093418Sbrian#ifndef NODES 283144106Sbrian case NEG_CHAP80: 283244106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 283344106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 283444106Sbrian break; 283544106Sbrian case NEG_CHAP80LM: 283644106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 283744106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 283844106Sbrian break; 283967910Sbrian case NEG_CHAP81: 284067910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 284167910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 284267910Sbrian break; 284367910Sbrian case NEG_MPPE: 284467910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 284567910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 284667910Sbrian break; 284744106Sbrian#endif 284836285Sbrian case NEG_DEFLATE: 284936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 285036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 285136285Sbrian break; 285236285Sbrian case NEG_DNS: 285336285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 285436285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 285536285Sbrian break; 285647858Sbrian case NEG_ENDDISC: 285747858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 285847858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 285947858Sbrian break; 286036285Sbrian case NEG_LQR: 286136285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 286236285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 286336285Sbrian break; 286436285Sbrian case NEG_PAP: 286536285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 286636285Sbrian cx->physical->link.lcp.cfg.pap |= add; 286736285Sbrian break; 286836285Sbrian case NEG_PPPDDEFLATE: 286936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 287036285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 287136285Sbrian break; 287236285Sbrian case NEG_PRED1: 287336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 287436285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 287536285Sbrian break; 287636285Sbrian case NEG_PROTOCOMP: 287736285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 287836285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 287936285Sbrian break; 288036285Sbrian case NEG_SHORTSEQ: 288140622Sbrian switch (bundle_Phase(arg->bundle)) { 288240622Sbrian case PHASE_DEAD: 288340622Sbrian break; 288440622Sbrian case PHASE_ESTABLISH: 288540622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 288640622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 288740622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 288840622Sbrian " LCP negotiations\n"); 288940622Sbrian return 1; 289040622Sbrian } 289140622Sbrian break; 289240622Sbrian default: 289340622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 289440622Sbrian " DEAD/ESTABLISH\n"); 289540622Sbrian return 1; 289636285Sbrian } 289740622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 289840622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 289936285Sbrian break; 290036285Sbrian case NEG_VJCOMP: 290136285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 290236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 290336285Sbrian break; 290436285Sbrian } 290536285Sbrian 290636285Sbrian return 0; 290736285Sbrian} 290836285Sbrian 290936285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 291062778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 291162778Sbrian "filter on PPPoUDP payloads", "disable|enable", 291262778Sbrian (const void *)OPT_FILTERDECAP}, 2913112659Sbrian {"force-scripts", NULL, OptSet, LOCAL_AUTH, 2914112659Sbrian "Force execution of the configured chat scripts", "disable|enable", 2915112659Sbrian (const void *)OPT_FORCE_SCRIPTS}, 291636285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 291736285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 291840666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 291962778Sbrian "retain interface addresses", "disable|enable", 292062778Sbrian (const void *)OPT_IFACEALIAS}, 292181634Sbrian#ifndef NOINET6 292281634Sbrian {"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol", 292381634Sbrian "disable|enable", (const void *)OPT_IPCP}, 292481634Sbrian {"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol", 292581634Sbrian "disable|enable", (const void *)OPT_IPV6CP}, 292681634Sbrian#endif 292747689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 292847689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 292936285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 293036285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 293136285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 293236285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 293340665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 293436285Sbrian "disable|enable", (const void *)OPT_PROXY}, 293540665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 293640665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 293736285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 293836285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 293969303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 294069303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 294136285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 294236285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 294336285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 294436285Sbrian "disable|enable", (const void *)OPT_UTMP}, 294536285Sbrian 294681634Sbrian#ifndef NOINET6 2947112659Sbrian#define OPT_MAX 14 /* accept/deny allowed below and not above */ 294881634Sbrian#else 2949112659Sbrian#define OPT_MAX 12 295081634Sbrian#endif 295136285Sbrian 295236285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 295336285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 295436285Sbrian (const void *)NEG_ACFCOMP}, 295544106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 295636285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 295744106Sbrian (const void *)NEG_CHAP05}, 295893418Sbrian#ifndef NODES 295944106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 296044106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 296144106Sbrian (const void *)NEG_CHAP80}, 296244106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 296344106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 296444106Sbrian (const void *)NEG_CHAP80LM}, 296567910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 296667910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 296767910Sbrian (const void *)NEG_CHAP81}, 296867910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 296967910Sbrian "MPPE encryption", "accept|deny|disable|enable", 297067910Sbrian (const void *)NEG_MPPE}, 297144106Sbrian#endif 297236285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 297336285Sbrian "Deflate compression", "accept|deny|disable|enable", 297436285Sbrian (const void *)NEG_DEFLATE}, 297536285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 297636285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 297736285Sbrian (const void *)NEG_PPPDDEFLATE}, 297836285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 297936285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 298047858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 298147858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 298236285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 298336285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 298436285Sbrian (const void *)NEG_LQR}, 298536285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 298636285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 298736285Sbrian (const void *)NEG_PAP}, 298836285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 298936285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 299036285Sbrian (const void *)NEG_PRED1}, 299136285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 299236285Sbrian "Protocol field compression", "accept|deny|disable|enable", 299336285Sbrian (const void *)NEG_PROTOCOMP}, 299436285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 299536285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 299636285Sbrian (const void *)NEG_SHORTSEQ}, 299736285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 299836285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 299936285Sbrian (const void *)NEG_VJCOMP}, 300036285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 300136285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 300236285Sbrian NegotiateCommands}, 3003134789Sbrian {NULL, NULL, NULL, 0, NULL, NULL, NULL}, 300436285Sbrian}; 300536285Sbrian 300636285Sbrianstatic int 300736285SbrianNegotiateCommand(struct cmdargs const *arg) 300836285Sbrian{ 300936285Sbrian if (arg->argc > arg->argn) { 301036285Sbrian char const *argv[3]; 301136285Sbrian unsigned keep, add; 301236285Sbrian int n; 301336285Sbrian 301436285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 301536285Sbrian return -1; 301636285Sbrian argv[2] = NULL; 301736285Sbrian 301836285Sbrian for (n = arg->argn; n < arg->argc; n++) { 301936285Sbrian argv[1] = arg->argv[n]; 302036285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 302136285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 302236285Sbrian } 302336285Sbrian } else if (arg->prompt) 302436285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 302536285Sbrian arg->argv[arg->argn-1]); 302636285Sbrian else 302736285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 302836285Sbrian arg->argv[arg->argn] ); 302936285Sbrian 303036285Sbrian return 0; 303136285Sbrian} 303236285Sbrian 303336285Sbrianconst char * 303436285Sbriancommand_ShowNegval(unsigned val) 303536285Sbrian{ 303636285Sbrian switch (val&3) { 303736285Sbrian case 1: return "disabled & accepted"; 303836285Sbrian case 2: return "enabled & denied"; 303936285Sbrian case 3: return "enabled & accepted"; 304036285Sbrian } 304136285Sbrian return "disabled & denied"; 304236285Sbrian} 304336934Sbrian 304436934Sbrianstatic int 304536934SbrianClearCommand(struct cmdargs const *arg) 304636934Sbrian{ 304736934Sbrian struct pppThroughput *t; 304836934Sbrian struct datalink *cx; 304936934Sbrian int i, clear_type; 305036934Sbrian 305136934Sbrian if (arg->argc < arg->argn + 1) 305236934Sbrian return -1; 305336934Sbrian 305446686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 305536934Sbrian cx = arg->cx; 305636934Sbrian if (!cx) 305736934Sbrian cx = bundle2datalink(arg->bundle, NULL); 305836934Sbrian if (!cx) { 305946686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 306036934Sbrian return 1; 306136934Sbrian } 306264652Sbrian t = &cx->physical->link.stats.total; 306336934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 306436934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 306581634Sbrian#ifndef NOINET6 306681897Sbrian else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0) 306781634Sbrian t = &arg->bundle->ncp.ipv6cp.throughput; 306881634Sbrian#endif 306936934Sbrian else 307036934Sbrian return -1; 307136934Sbrian 307236934Sbrian if (arg->argc > arg->argn + 1) { 307336934Sbrian clear_type = 0; 307436934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 307536934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 307636934Sbrian clear_type |= THROUGHPUT_OVERALL; 307736934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 307836934Sbrian clear_type |= THROUGHPUT_CURRENT; 307936934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 308036934Sbrian clear_type |= THROUGHPUT_PEAK; 308136934Sbrian else 308236934Sbrian return -1; 308398243Sbrian } else 308436934Sbrian clear_type = THROUGHPUT_ALL; 308536934Sbrian 308636934Sbrian throughput_clear(t, clear_type, arg->prompt); 308736934Sbrian return 0; 308836934Sbrian} 308940561Sbrian 309040561Sbrianstatic int 309140561SbrianRunListCommand(struct cmdargs const *arg) 309240561Sbrian{ 309340561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 309440561Sbrian 309564801Sbrian#ifndef NONAT 309664801Sbrian if (arg->cmd->args == NatCommands && 309764801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 309864801Sbrian if (arg->prompt) 309965550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 310064801Sbrian else 310165550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 310264801Sbrian } 310364801Sbrian#endif 310464801Sbrian 310540561Sbrian if (arg->argc > arg->argn) 310640561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 310740561Sbrian arg->prompt, arg->cx); 310840561Sbrian else if (arg->prompt) 310940561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 311040561Sbrian " <option>' for syntax help.\n", cmd, cmd); 311140561Sbrian else 311240561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 311340561Sbrian 311440561Sbrian return 0; 311540561Sbrian} 311640561Sbrian 311740561Sbrianstatic int 311840561SbrianIfaceAddCommand(struct cmdargs const *arg) 311940561Sbrian{ 312081634Sbrian struct ncpaddr peer, addr; 312181634Sbrian struct ncprange ifa; 312281634Sbrian struct in_addr mask; 312381634Sbrian int n, how; 312440561Sbrian 312540664Sbrian if (arg->argc == arg->argn + 1) { 312681634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 312740561Sbrian return -1; 312881634Sbrian ncpaddr_init(&peer); 312940664Sbrian } else { 313040664Sbrian if (arg->argc == arg->argn + 2) { 313181634Sbrian if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn])) 313240664Sbrian return -1; 313340664Sbrian n = 1; 313440664Sbrian } else if (arg->argc == arg->argn + 3) { 313581634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn])) 313640664Sbrian return -1; 313781634Sbrian if (ncpaddr_family(&addr) != AF_INET) 313840664Sbrian return -1; 313981634Sbrian ncprange_sethost(&ifa, &addr); 314081634Sbrian if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1])) 314181634Sbrian return -1; 314281634Sbrian if (!ncpaddr_getip4(&addr, &mask)) 314381634Sbrian return -1; 314481634Sbrian if (!ncprange_setip4mask(&ifa, mask)) 314581634Sbrian return -1; 314640664Sbrian n = 2; 314740664Sbrian } else 314840561Sbrian return -1; 314940561Sbrian 315081634Sbrian if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n])) 315140664Sbrian return -1; 315281634Sbrian 315381634Sbrian if (ncprange_family(&ifa) != ncpaddr_family(&peer)) { 315481634Sbrian log_Printf(LogWARN, "IfaceAddCommand: src and dst address families" 315581634Sbrian " differ\n"); 315681634Sbrian return -1; 315781634Sbrian } 315840664Sbrian } 315940561Sbrian 316040561Sbrian how = IFACE_ADD_LAST; 316140561Sbrian if (arg->cmd->args) 316240561Sbrian how |= IFACE_FORCE_ADD; 316340561Sbrian 316481634Sbrian return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how); 316540561Sbrian} 316640561Sbrian 316740561Sbrianstatic int 316840561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 316940561Sbrian{ 317081634Sbrian struct ncpaddr ifa; 317181634Sbrian struct in_addr ifa4; 317240561Sbrian int ok; 317340561Sbrian 317440561Sbrian if (arg->argc != arg->argn + 1) 317540561Sbrian return -1; 317640561Sbrian 317781634Sbrian if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn])) 317840561Sbrian return -1; 317940561Sbrian 318040561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 318181634Sbrian ncpaddr_getip4(&ifa, &ifa4) && 318281634Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) { 318340561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 318481634Sbrian ncpaddr_ntoa(&ifa)); 318540561Sbrian return 1; 318640561Sbrian } 318740561Sbrian 318881634Sbrian ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa); 318940561Sbrian if (!ok) { 319040561Sbrian if (arg->cmd->args) 319140561Sbrian ok = 1; 319240561Sbrian else if (arg->prompt) 319381634Sbrian prompt_Printf(arg->prompt, "%s: No such interface address\n", 319481634Sbrian ncpaddr_ntoa(&ifa)); 319540561Sbrian else 319681634Sbrian log_Printf(LogWARN, "%s: No such interface address\n", 319781634Sbrian ncpaddr_ntoa(&ifa)); 319840561Sbrian } 319940561Sbrian 320040561Sbrian return !ok; 320140561Sbrian} 320240561Sbrian 320340561Sbrianstatic int 320440561SbrianIfaceClearCommand(struct cmdargs const *arg) 320540561Sbrian{ 320681634Sbrian int family, how; 320740561Sbrian 320881634Sbrian family = 0; 320981634Sbrian if (arg->argc == arg->argn + 1) { 321081634Sbrian if (strcasecmp(arg->argv[arg->argn], "inet") == 0) 321181634Sbrian family = AF_INET; 321281634Sbrian#ifndef NOINET6 321381897Sbrian else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0) 321481634Sbrian family = AF_INET6; 321581634Sbrian#endif 321681634Sbrian else 321781634Sbrian return -1; 321881634Sbrian } else if (arg->argc != arg->argn) 321940561Sbrian return -1; 322040561Sbrian 322140941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 322240941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 322340561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 322481634Sbrian iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how); 322540561Sbrian 322640561Sbrian return 0; 322740561Sbrian} 322840679Sbrian 322940679Sbrianstatic int 323040679SbrianSetProcTitle(struct cmdargs const *arg) 323140679Sbrian{ 323240679Sbrian static char title[LINE_LEN]; 323386028Sbrian char *argv[MAXARGS]; 323486028Sbrian int argc = arg->argc - arg->argn; 323540679Sbrian 3236134789Sbrian if (arg->argc <= arg->argn) { 323764698Sbrian SetTitle(NULL); 323840679Sbrian return 0; 323940679Sbrian } 324040679Sbrian 3241134789Sbrian if ((unsigned)argc >= sizeof argv / sizeof argv[0]) { 324240679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 324340679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 324440679Sbrian } 324547849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 324685991Sbrian Concatinate(title, sizeof title, argc, (const char *const *)argv); 324764698Sbrian SetTitle(title); 324885991Sbrian command_Free(argc, argv); 324940679Sbrian 325040679Sbrian return 0; 325140679Sbrian} 3252