command.c revision 71657
16059Samurai/* 26059Samurai * PPP User command processing module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2050479Speter * $FreeBSD: head/usr.sbin/ppp/command.c 71657 2001-01-26 01:41:34Z brian $ 218857Srgrimes * 226059Samurai */ 2343313Sbrian#include <sys/param.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3338628Sbrian#include <ctype.h> 3430715Sbrian#include <errno.h> 3526516Sbrian#include <fcntl.h> 3630715Sbrian#include <paths.h> 3730715Sbrian#include <stdio.h> 3830715Sbrian#include <stdlib.h> 3930715Sbrian#include <string.h> 4030715Sbrian#include <sys/wait.h> 4130715Sbrian#include <termios.h> 4230715Sbrian#include <unistd.h> 4330715Sbrian 4450059Sbrian#ifndef NONAT 4558037Sbrian#ifdef LOCALNAT 4658037Sbrian#include "alias.h" 4758037Sbrian#else 4846086Sbrian#include <alias.h> 4939395Sbrian#endif 5039395Sbrian#endif 5158037Sbrian 5246686Sbrian#include "layer.h" 5337009Sbrian#include "defs.h" 5431343Sbrian#include "command.h" 5530715Sbrian#include "mbuf.h" 5630715Sbrian#include "log.h" 5730715Sbrian#include "timer.h" 586059Samurai#include "fsm.h" 5931690Sbrian#include "iplist.h" 6036285Sbrian#include "throughput.h" 6136285Sbrian#include "slcompress.h" 6238557Sbrian#include "lqr.h" 6338557Sbrian#include "hdlc.h" 6463484Sbrian#include "lcp.h" 656059Samurai#include "ipcp.h" 6650059Sbrian#ifndef NONAT 6751075Sbrian#include "nat_cmd.h" 6831343Sbrian#endif 6925630Sbrian#include "systems.h" 7036285Sbrian#include "filter.h" 7136285Sbrian#include "descriptor.h" 7230715Sbrian#include "main.h" 7330715Sbrian#include "route.h" 7430715Sbrian#include "ccp.h" 7531080Sbrian#include "auth.h" 7636285Sbrian#include "async.h" 7736285Sbrian#include "link.h" 7836285Sbrian#include "physical.h" 7936285Sbrian#include "mp.h" 8043313Sbrian#ifndef NORADIUS 8143313Sbrian#include "radius.h" 8243313Sbrian#endif 8336285Sbrian#include "bundle.h" 8436285Sbrian#include "server.h" 8536285Sbrian#include "prompt.h" 8636285Sbrian#include "chat.h" 8736285Sbrian#include "chap.h" 8838174Sbrian#include "cbcp.h" 8936285Sbrian#include "datalink.h" 9040561Sbrian#include "iface.h" 9153298Sbrian#include "id.h" 926059Samurai 9336285Sbrian/* ``set'' values */ 9436285Sbrian#define VAR_AUTHKEY 0 9536285Sbrian#define VAR_DIAL 1 9636285Sbrian#define VAR_LOGIN 2 9736285Sbrian#define VAR_AUTHNAME 3 9836285Sbrian#define VAR_AUTOLOAD 4 9936285Sbrian#define VAR_WINSIZE 5 10036285Sbrian#define VAR_DEVICE 6 10136285Sbrian#define VAR_ACCMAP 7 10236285Sbrian#define VAR_MRRU 8 10336285Sbrian#define VAR_MRU 9 10436285Sbrian#define VAR_MTU 10 10536285Sbrian#define VAR_OPENMODE 11 10636285Sbrian#define VAR_PHONE 12 10736285Sbrian#define VAR_HANGUP 13 10836285Sbrian#define VAR_IDLETIMEOUT 14 10936285Sbrian#define VAR_LQRPERIOD 15 11036285Sbrian#define VAR_LCPRETRY 16 11136285Sbrian#define VAR_CHAPRETRY 17 11236285Sbrian#define VAR_PAPRETRY 18 11336285Sbrian#define VAR_CCPRETRY 19 11436285Sbrian#define VAR_IPCPRETRY 20 11536285Sbrian#define VAR_DNS 21 11636285Sbrian#define VAR_NBNS 22 11736285Sbrian#define VAR_MODE 23 11838174Sbrian#define VAR_CALLBACK 24 11938174Sbrian#define VAR_CBCP 25 12038544Sbrian#define VAR_CHOKED 26 12140665Sbrian#define VAR_SENDPIPE 27 12240665Sbrian#define VAR_RECVPIPE 28 12343313Sbrian#define VAR_RADIUS 29 12444073Sbrian#define VAR_CD 30 12546686Sbrian#define VAR_PARITY 31 12646686Sbrian#define VAR_CRTSCTS 32 12750867Sbrian#define VAR_URGENTPORTS 33 12852488Sbrian#define VAR_LOGOUT 34 12961534Sbrian#define VAR_IFQUEUE 35 13067910Sbrian#define VAR_KEYBITS 36 1316059Samurai 13236285Sbrian/* ``accept|deny|disable|enable'' masks */ 13336285Sbrian#define NEG_HISMASK (1) 13436285Sbrian#define NEG_MYMASK (2) 13536285Sbrian 13636285Sbrian/* ``accept|deny|disable|enable'' values */ 13736285Sbrian#define NEG_ACFCOMP 40 13844106Sbrian#define NEG_CHAP05 41 13944106Sbrian#define NEG_CHAP80 42 14044106Sbrian#define NEG_CHAP80LM 43 14144106Sbrian#define NEG_DEFLATE 44 14247858Sbrian#define NEG_DNS 45 14347858Sbrian#define NEG_ENDDISC 46 14447858Sbrian#define NEG_LQR 47 14547858Sbrian#define NEG_PAP 48 14647858Sbrian#define NEG_PPPDDEFLATE 49 14747858Sbrian#define NEG_PRED1 50 14847858Sbrian#define NEG_PROTOCOMP 51 14947858Sbrian#define NEG_SHORTSEQ 52 15047858Sbrian#define NEG_VJCOMP 53 15167910Sbrian#define NEG_MPPE 54 15267910Sbrian#define NEG_CHAP81 55 15336285Sbrian 15467915Sbrianconst char Version[] = "2.3"; 15536285Sbrian 15636285Sbrianstatic int ShowCommand(struct cmdargs const *); 15736285Sbrianstatic int TerminalCommand(struct cmdargs const *); 15836285Sbrianstatic int QuitCommand(struct cmdargs const *); 15936285Sbrianstatic int OpenCommand(struct cmdargs const *); 16036285Sbrianstatic int CloseCommand(struct cmdargs const *); 16136285Sbrianstatic int DownCommand(struct cmdargs const *); 16236285Sbrianstatic int SetCommand(struct cmdargs const *); 16336285Sbrianstatic int LinkCommand(struct cmdargs const *); 16436285Sbrianstatic int AddCommand(struct cmdargs const *); 16536285Sbrianstatic int DeleteCommand(struct cmdargs const *); 16636285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 16736934Sbrianstatic int ClearCommand(struct cmdargs const *); 16840561Sbrianstatic int RunListCommand(struct cmdargs const *); 16940561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 17040561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 17140561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 17240679Sbrianstatic int SetProcTitle(struct cmdargs const *); 17350059Sbrian#ifndef NONAT 17458867Sbrianstatic int NatEnable(struct cmdargs const *); 17558867Sbrianstatic int NatOption(struct cmdargs const *); 17631343Sbrian#endif 1776059Samurai 17836285Sbrianstatic const char * 17936285Sbrianshowcx(struct cmdtab const *cmd) 18036285Sbrian{ 18136285Sbrian if (cmd->lauth & LOCAL_CX) 18236285Sbrian return "(c)"; 18336285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 18436285Sbrian return "(o)"; 18536285Sbrian 18636285Sbrian return ""; 18736285Sbrian} 18836285Sbrian 1896059Samuraistatic int 19031343SbrianHelpCommand(struct cmdargs const *arg) 1916059Samurai{ 19228679Sbrian struct cmdtab const *cmd; 19336285Sbrian int n, cmax, dmax, cols, cxlen; 19436285Sbrian const char *cx; 1956059Samurai 19636285Sbrian if (!arg->prompt) { 19736285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 19826516Sbrian return 0; 19936285Sbrian } 20026516Sbrian 20136285Sbrian if (arg->argc > arg->argn) { 20236285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 20336285Sbrian if ((cmd->lauth & arg->prompt->auth) && 20436285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 20536285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 20636285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 20728679Sbrian return 0; 2086059Samurai } 20926516Sbrian return -1; 2106059Samurai } 21136285Sbrian 21231372Sbrian cmax = dmax = 0; 21336285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 21436285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 21536285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 21631372Sbrian cmax = n; 21731372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 21831372Sbrian dmax = n; 21931372Sbrian } 22031372Sbrian 22131372Sbrian cols = 80 / (dmax + cmax + 3); 2226059Samurai n = 0; 22336285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 22436285Sbrian " (c) = Context required\n"); 22536285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22636285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22736285Sbrian cx = showcx(cmd); 22836285Sbrian cxlen = cmax - strlen(cmd->name); 22940482Sbrian if (n % cols != 0) 23040482Sbrian prompt_Printf(arg->prompt, " "); 23140482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 23236285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 23331372Sbrian if (++n % cols == 0) 23436285Sbrian prompt_Printf(arg->prompt, "\n"); 2356059Samurai } 23631372Sbrian if (n % cols != 0) 23736285Sbrian prompt_Printf(arg->prompt, "\n"); 23826516Sbrian 23926516Sbrian return 0; 2406059Samurai} 2416059Samurai 24236285Sbrianstatic int 24363484SbrianIdentCommand(struct cmdargs const *arg) 24463484Sbrian{ 24563484Sbrian int f, pos; 24663484Sbrian 24763484Sbrian *arg->cx->physical->link.lcp.cfg.ident = '\0'; 24863484Sbrian 24963484Sbrian for (pos = 0, f = arg->argn; f < arg->argc; f++) 25063484Sbrian pos += snprintf(arg->cx->physical->link.lcp.cfg.ident + pos, 25163484Sbrian sizeof arg->cx->physical->link.lcp.cfg.ident - pos, "%s%s", 25263484Sbrian f == arg->argn ? "" : " ", arg->argv[f]); 25363484Sbrian 25463484Sbrian return 0; 25563484Sbrian} 25663484Sbrian 25763484Sbrianstatic int 25863484SbrianSendIdentification(struct cmdargs const *arg) 25963484Sbrian{ 26063484Sbrian if (arg->cx->state < DATALINK_LCP) { 26163484Sbrian log_Printf(LogWARN, "sendident: link has not reached LCP\n"); 26263484Sbrian return 2; 26363484Sbrian } 26463484Sbrian return lcp_SendIdentification(&arg->cx->physical->link.lcp) ? 0 : 1; 26563484Sbrian} 26663484Sbrian 26763484Sbrianstatic int 26836285SbrianCloneCommand(struct cmdargs const *arg) 2696059Samurai{ 27036285Sbrian char namelist[LINE_LEN]; 27136285Sbrian char *name; 27236285Sbrian int f; 2736059Samurai 27436285Sbrian if (arg->argc == arg->argn) 27536285Sbrian return -1; 27636285Sbrian 27736285Sbrian namelist[sizeof namelist - 1] = '\0'; 27836285Sbrian for (f = arg->argn; f < arg->argc; f++) { 27936285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 28036285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 28136285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2826059Samurai } 28336285Sbrian 28436285Sbrian return 0; 2856059Samurai} 2866059Samurai 2876059Samuraistatic int 28836285SbrianRemoveCommand(struct cmdargs const *arg) 2896059Samurai{ 29036285Sbrian if (arg->argc != arg->argn) 29136285Sbrian return -1; 29211336Samurai 29336285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 29436285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 29536285Sbrian return 2; 2966059Samurai } 29726516Sbrian 29836285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 29936285Sbrian return 0; 30036285Sbrian} 30132711Sbrian 30236285Sbrianstatic int 30336285SbrianRenameCommand(struct cmdargs const *arg) 30436285Sbrian{ 30536285Sbrian if (arg->argc != arg->argn + 1) 30636285Sbrian return -1; 30731121Sbrian 30836285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 30936285Sbrian return 0; 31036285Sbrian 31136285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 31236285Sbrian arg->cx->name, arg->argv[arg->argn]); 31336285Sbrian return 1; 31436285Sbrian} 31536285Sbrian 31636285Sbrianint 31736285SbrianLoadCommand(struct cmdargs const *arg) 31836285Sbrian{ 31940797Sbrian const char *err; 32040797Sbrian int n, mode; 32136285Sbrian 32240797Sbrian mode = arg->bundle->phys_type.all; 32336285Sbrian 32440797Sbrian if (arg->argn < arg->argc) { 32540797Sbrian for (n = arg->argn; n < arg->argc; n++) 32640797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 32740797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 32840797Sbrian return 1; 32940797Sbrian } 33040797Sbrian 33140797Sbrian for (n = arg->argn; n < arg->argc; n++) { 33240797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 33340797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 33440797Sbrian } 33540797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 33640797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 33740797Sbrian log_Printf(LogWARN, "default: %s\n", err); 33836285Sbrian return 1; 33936285Sbrian } else { 34040797Sbrian bundle_SetLabel(arg->bundle, "default"); 34140797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 34240797Sbrian bundle_SetLabel(arg->bundle, "default"); 34336285Sbrian } 34440797Sbrian 34526516Sbrian return 0; 3466059Samurai} 3476059Samurai 34836285Sbrianint 34936285SbrianSaveCommand(struct cmdargs const *arg) 35036285Sbrian{ 35136285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 35236285Sbrian return 1; 35336285Sbrian} 35436285Sbrian 35510528Samuraistatic int 35636285SbrianDialCommand(struct cmdargs const *arg) 35728536Sbrian{ 35836285Sbrian int res; 35936285Sbrian 36036465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 36136465Sbrian || (!arg->cx && 36236928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 36336285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 36436285Sbrian " interactive links\n"); 36536285Sbrian return 1; 36634536Sbrian } 36736285Sbrian 36836285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 36936285Sbrian return res; 37036285Sbrian 37137993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 37236285Sbrian 37336285Sbrian return 0; 37428536Sbrian} 37528536Sbrian 37638628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 37738628Sbrian 37838628Sbrianstatic char * 37938628Sbrianstrstrword(char *big, const char *little) 38038628Sbrian{ 38138628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 38238628Sbrian char *pos; 38338628Sbrian int len; 38438628Sbrian 38538628Sbrian pos = big; 38638628Sbrian len = strlen(little); 38738628Sbrian 38838628Sbrian while ((pos = strstr(pos, little)) != NULL) 38947865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 39047865Sbrian pos++; 39147865Sbrian else if (pos != big && pos[-1] == '\\') 39247865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 39347865Sbrian else 39438628Sbrian break; 39538628Sbrian 39638628Sbrian return pos; 39738628Sbrian} 39838628Sbrian 39938628Sbrianstatic char * 40038628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 40138628Sbrian{ 40238628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 40338628Sbrian char *word, *ntgt; 40438628Sbrian int ltgt, loldstr, lnewstr, pos; 40538628Sbrian 40638628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 40738628Sbrian return tgt; 40838628Sbrian 40938628Sbrian ltgt = strlen(tgt) + 1; 41038628Sbrian loldstr = strlen(oldstr); 41138628Sbrian lnewstr = strlen(newstr); 41238628Sbrian do { 41338628Sbrian pos = word - tgt; 41438628Sbrian if (loldstr > lnewstr) 41538628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 41638628Sbrian if (loldstr != lnewstr) { 41738628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 41838628Sbrian if (ntgt == NULL) 41938628Sbrian break; /* Oh wonderful ! */ 42038628Sbrian word = ntgt + pos; 42138628Sbrian tgt = ntgt; 42238628Sbrian } 42338628Sbrian if (lnewstr > loldstr) 42438628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 42538628Sbrian bcopy(newstr, word, lnewstr); 42638628Sbrian } while ((word = strstrword(word, oldstr))); 42738628Sbrian 42838628Sbrian return tgt; 42938628Sbrian} 43038628Sbrian 43143888Sbrianvoid 43243888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 43347849Sbrian struct bundle *bundle, int inc0, pid_t pid) 43438628Sbrian{ 43538628Sbrian int arg; 43647849Sbrian char pidstr[12]; 43738628Sbrian 43841755Sbrian if (inc0) 43941755Sbrian arg = 0; /* Start at arg 0 */ 44041755Sbrian else { 44141755Sbrian nargv[0] = strdup(oargv[0]); 44241755Sbrian arg = 1; 44341755Sbrian } 44447849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 44541755Sbrian for (; arg < argc; arg++) { 44638629Sbrian nargv[arg] = strdup(oargv[arg]); 44738629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 44838628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 44938629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 45040561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 45138628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 45238629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 45338629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 45438629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 45538629Sbrian bundle->ncp.mp.peer.enddisc.address, 45638629Sbrian bundle->ncp.mp.peer.enddisc.len)); 45738629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 45838629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 45938629Sbrian bundle->ncp.mp.cfg.enddisc.address, 46038629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 46147849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 46238629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 46358044Sbrian nargv[arg] = subst(nargv[arg], "DNS0", 46458044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); 46558044Sbrian nargv[arg] = subst(nargv[arg], "DNS1", 46658044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); 46763484Sbrian nargv[arg] = subst(nargv[arg], "VERSION", Version); 46863484Sbrian nargv[arg] = subst(nargv[arg], "COMPILATIONDATE", __DATE__); 46938628Sbrian } 47038628Sbrian nargv[arg] = NULL; 47138628Sbrian} 47238628Sbrian 47328536Sbrianstatic int 47431343SbrianShellCommand(struct cmdargs const *arg, int bg) 47510528Samurai{ 47610528Samurai const char *shell; 47747849Sbrian pid_t shpid, pid; 47820813Sjkh 47918856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 48026911Sbrian /* we're only allowed to shell when we run ppp interactively */ 48136285Sbrian if (arg->prompt && arg->prompt->owner) { 48236285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 48326516Sbrian return 1; 48410528Samurai } 48526911Sbrian#endif 48628679Sbrian 48736285Sbrian if (arg->argc == arg->argn) { 48836285Sbrian if (!arg->prompt) { 48936285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 49036285Sbrian " a config file\n"); 49128381Sbrian return 1; 49236285Sbrian } else if (arg->prompt->owner) { 49336285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 49436285Sbrian " a socket connection\n"); 49536285Sbrian return 1; 49628381Sbrian } else if (bg) { 49736285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 49828679Sbrian " the foreground mode\n"); 49928381Sbrian return 1; 50028381Sbrian } 50134536Sbrian } 50234536Sbrian 50347849Sbrian pid = getpid(); 50428679Sbrian if ((shpid = fork()) == 0) { 50536285Sbrian int i, fd; 50618531Sbde 50736285Sbrian if ((shell = getenv("SHELL")) == 0) 50836285Sbrian shell = _PATH_BSHELL; 50932017Sbrian 51036285Sbrian timer_TermService(); 51136285Sbrian 51236285Sbrian if (arg->prompt) 51336285Sbrian fd = arg->prompt->fd_out; 51436285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 51536285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 51636285Sbrian _PATH_DEVNULL, strerror(errno)); 51728679Sbrian exit(1); 51828679Sbrian } 51949976Sbrian dup2(fd, STDIN_FILENO); 52049976Sbrian dup2(fd, STDOUT_FILENO); 52149976Sbrian dup2(fd, STDERR_FILENO); 52249976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 52349976Sbrian fcntl(i, F_SETFD, 1); 52426516Sbrian 52564802Sbrian#ifndef NOSUID 52655252Sbrian setuid(ID0realuid()); 52764802Sbrian#endif 52836285Sbrian if (arg->argc > arg->argn) { 52928679Sbrian /* substitute pseudo args */ 53038628Sbrian char *argv[MAXARGS]; 53138628Sbrian int argc = arg->argc - arg->argn; 53238628Sbrian 53338628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 53438628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 53538628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 53631343Sbrian } 53747849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 53828679Sbrian if (bg) { 53928679Sbrian pid_t p; 54010528Samurai 54128679Sbrian p = getpid(); 54228679Sbrian if (daemon(1, 1) == -1) { 54336832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 54428679Sbrian exit(1); 54528679Sbrian } 54636285Sbrian } else if (arg->prompt) 54736285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 54831343Sbrian execvp(argv[0], argv); 54930316Sbrian } else { 55036285Sbrian if (arg->prompt) 55132017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 55236285Sbrian prompt_TtyOldMode(arg->prompt); 55331343Sbrian execl(shell, shell, NULL); 55430316Sbrian } 55520813Sjkh 55640665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 55740665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 55840665Sbrian strerror(errno)); 55949976Sbrian _exit(255); 56010528Samurai } 56136285Sbrian 56236285Sbrian if (shpid == (pid_t) - 1) 56336285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 56436285Sbrian else { 56510528Samurai int status; 56631343Sbrian waitpid(shpid, &status, 0); 56710528Samurai } 56820813Sjkh 56936285Sbrian if (arg->prompt && !arg->prompt->owner) 57036285Sbrian prompt_TtyCommandMode(arg->prompt); 57120813Sjkh 57236285Sbrian return 0; 57310528Samurai} 57410528Samurai 57531343Sbrianstatic int 57631343SbrianBgShellCommand(struct cmdargs const *arg) 57731343Sbrian{ 57836285Sbrian if (arg->argc == arg->argn) 57931343Sbrian return -1; 58031343Sbrian return ShellCommand(arg, 1); 58131343Sbrian} 58231343Sbrian 58331343Sbrianstatic int 58431343SbrianFgShellCommand(struct cmdargs const *arg) 58531343Sbrian{ 58631343Sbrian return ShellCommand(arg, 0); 58731343Sbrian} 58831343Sbrian 58958044Sbrianstatic int 59058044SbrianResolvCommand(struct cmdargs const *arg) 59158044Sbrian{ 59258044Sbrian if (arg->argc == arg->argn + 1) { 59358044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 59458044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 59558044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 59658044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 59758044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 59858044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 59958044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 60058044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 60158044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 60258044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 60358044Sbrian else 60458044Sbrian return -1; 60558044Sbrian 60658044Sbrian return 0; 60758044Sbrian } 60858044Sbrian 60958044Sbrian return -1; 61058044Sbrian} 61158044Sbrian 61250059Sbrian#ifndef NONAT 61358867Sbrianstatic struct cmdtab const NatCommands[] = 61440561Sbrian{ 61550059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 61650059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 61758867Sbrian {"deny_incoming", NULL, NatOption, LOCAL_AUTH, 61850059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 61940561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 62058867Sbrian {"enable", NULL, NatEnable, LOCAL_AUTH, 62150059Sbrian "enable NAT", "nat enable yes|no"}, 62258867Sbrian {"log", NULL, NatOption, LOCAL_AUTH, 62350059Sbrian "log NAT link creation", "nat log yes|no", 62440561Sbrian (const void *) PKT_ALIAS_LOG}, 62550059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 62650059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 62750059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 62850059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 62958867Sbrian {"same_ports", NULL, NatOption, LOCAL_AUTH, 63050059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 63140561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 63258867Sbrian {"target", NULL, nat_SetTarget, LOCAL_AUTH, 63358867Sbrian "Default address for incoming connections", "nat target addr" }, 63458867Sbrian {"unregistered_only", NULL, NatOption, LOCAL_AUTH, 63550059Sbrian "translate unregistered (private) IP address space only", 63650059Sbrian "nat unregistered_only yes|no", 63740561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 63858867Sbrian {"use_sockets", NULL, NatOption, LOCAL_AUTH, 63950059Sbrian "allocate host sockets", "nat use_sockets yes|no", 64040561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 64140561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 64258867Sbrian "Display this message", "nat help|? [command]", NatCommands}, 64340561Sbrian {NULL, NULL, NULL}, 64440561Sbrian}; 64540561Sbrian#endif 64640561Sbrian 64740561Sbrianstatic struct cmdtab const AllowCommands[] = { 64840561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 64940561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 65040561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 65140561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 65240561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 65340561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 65440561Sbrian {NULL, NULL, NULL}, 65540561Sbrian}; 65640561Sbrian 65740561Sbrianstatic struct cmdtab const IfaceCommands[] = 65840561Sbrian{ 65940561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 66040561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 66140561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 66240561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 66340561Sbrian (void *)1}, 66440561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 66540561Sbrian "Clear iface address(es)", "iface clear"}, 66640561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 66740561Sbrian "Delete iface address", "iface delete addr", NULL}, 66840561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 66940561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 67040561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 67140561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 67240561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 67340561Sbrian "Show iface address(es)", "iface show"}, 67440561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 67550059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 67640561Sbrian {NULL, NULL, NULL}, 67740561Sbrian}; 67840561Sbrian 67930715Sbrianstatic struct cmdtab const Commands[] = { 68036285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68128679Sbrian "accept option request", "accept option .."}, 68228679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 68332109Sbrian "add route", "add dest mask gateway", NULL}, 68436285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 68532109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 68640561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 68740561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 68828679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 68931372Sbrian "Run a background command", "[!]bg command"}, 69036934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 69146686Sbrian "Clear throughput statistics", 69246686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 69336285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 69436285Sbrian "Clone a link", "clone newname..."}, 69536285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 69636285Sbrian "Close an FSM", "close [lcp|ccp]"}, 69728679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 69832109Sbrian "delete route", "delete dest", NULL}, 69936285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 70032109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 70136285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70228679Sbrian "Deny option request", "deny option .."}, 70336285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70440797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 70536285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70628679Sbrian "Disable option", "disable option .."}, 70736285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70846686Sbrian "Generate a down event", "down [ccp|lcp]"}, 70936285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71028679Sbrian "Enable option", "enable option .."}, 71163484Sbrian {"ident", NULL, IdentCommand, LOCAL_AUTH | LOCAL_CX, 71263484Sbrian "Set the link identity", "ident text..."}, 71340561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 71440561Sbrian "interface control", "iface option ...", IfaceCommands}, 71536285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 71636285Sbrian "Link specific commands", "link name command ..."}, 71737008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71840797Sbrian "Load settings", "load [system ...]"}, 71950059Sbrian#ifndef NONAT 72050059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 72158867Sbrian "NAT control", "nat option yes|no", NatCommands}, 72250059Sbrian#endif 72336285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 72437955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 72536285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 72636285Sbrian "Password for manipulation", "passwd LocalPassword"}, 72736285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 72836285Sbrian "Quit PPP program", "quit|bye [all]"}, 72936285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 73036285Sbrian "Remove a link", "remove"}, 73136285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 73236285Sbrian "Rename a link", "rename name"}, 73358044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 73458044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 73528679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 73628679Sbrian "Save settings", "save"}, 73763484Sbrian {"sendident", NULL, SendIdentification, LOCAL_AUTH | LOCAL_CX, 73863484Sbrian "Transmit the link identity", "sendident"}, 73936285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 74028679Sbrian "Set parameters", "set[up] var value"}, 74128679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 74228679Sbrian "Run a subshell", "shell|! [sh command]"}, 74336285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 74431372Sbrian "Show status and stats", "show var"}, 74536285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 74631372Sbrian "Enter terminal mode", "term"}, 74728679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 74831343Sbrian "Display this message", "help|? [command]", Commands}, 74928679Sbrian {NULL, NULL, NULL}, 7506059Samurai}; 7516059Samurai 75228536Sbrianstatic int 75331343SbrianShowEscape(struct cmdargs const *arg) 7546059Samurai{ 75536285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 75636285Sbrian int code, bit; 75736285Sbrian const char *sep = ""; 7586059Samurai 75926516Sbrian for (code = 0; code < 32; code++) 76036285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 76128679Sbrian for (bit = 0; bit < 8; bit++) 76236285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 76336285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 76436285Sbrian sep = ", "; 76536285Sbrian } 76636285Sbrian prompt_Printf(arg->prompt, "\n"); 7676059Samurai } 76831077Sbrian return 0; 7696059Samurai} 7706059Samurai 77128679Sbrianstatic int 77236285SbrianShowTimerList(struct cmdargs const *arg) 7736059Samurai{ 77436285Sbrian timer_Show(0, arg->prompt); 77531077Sbrian return 0; 7766059Samurai} 7776059Samurai 77828679Sbrianstatic int 77931343SbrianShowStopped(struct cmdargs const *arg) 78028327Sbrian{ 78136285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 78236285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 78336285Sbrian prompt_Printf(arg->prompt, "Disabled"); 78428327Sbrian else 78536285Sbrian prompt_Printf(arg->prompt, "%ld secs", 78636285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 78728461Sbrian 78836285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 78936285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 79036285Sbrian prompt_Printf(arg->prompt, "Disabled"); 79128461Sbrian else 79236285Sbrian prompt_Printf(arg->prompt, "%ld secs", 79336285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 79428461Sbrian 79536285Sbrian prompt_Printf(arg->prompt, "\n"); 79628461Sbrian 79731077Sbrian return 0; 79828327Sbrian} 79928327Sbrian 80028679Sbrianstatic int 80131343SbrianShowVersion(struct cmdargs const *arg) 8026059Samurai{ 80351026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 80431077Sbrian return 0; 8056059Samurai} 8066059Samurai 80728679Sbrianstatic int 80836285SbrianShowProtocolStats(struct cmdargs const *arg) 80926326Sbrian{ 81036285Sbrian struct link *l = command_ChooseLink(arg); 81126326Sbrian 81236285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 81336285Sbrian link_ReportProtocolStatus(l, arg->prompt); 81431077Sbrian return 0; 81526326Sbrian} 81626326Sbrian 81730715Sbrianstatic struct cmdtab const ShowCommands[] = { 81836285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 81936285Sbrian "bundle details", "show bundle"}, 82036285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 82136285Sbrian "CCP status", "show cpp"}, 82236285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 82336285Sbrian "VJ compression stats", "show compress"}, 82436285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 82536285Sbrian "escape characters", "show escape"}, 82636285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 82736285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 82836285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 82936285Sbrian "HDLC errors", "show hdlc"}, 83040561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 83140561Sbrian "Interface status", "show iface"}, 83236285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 83336285Sbrian "IPCP status", "show ipcp"}, 83447211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 83547211Sbrian "Protocol layers", "show layers"}, 83636285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 83736285Sbrian "LCP status", "show lcp"}, 83836285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 83936285Sbrian "(high-level) link info", "show link"}, 84036285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 84136285Sbrian "available link names", "show links"}, 84236285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 84336285Sbrian "log levels", "show log"}, 84436285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 84536285Sbrian "mbuf allocations", "show mem"}, 84646686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 84746686Sbrian "(low-level) link info", "show physical"}, 84836285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 84936285Sbrian "multilink setup", "show mp"}, 85036285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 85136285Sbrian "protocol summary", "show proto"}, 85236285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 85336285Sbrian "routing table", "show route"}, 85436285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 85536285Sbrian "STOPPED timeout", "show stopped"}, 85636285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 85736285Sbrian "alarm timers", "show timers"}, 85828679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 85936285Sbrian "version string", "show version"}, 86036285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 86136285Sbrian "client list", "show who"}, 86228679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 86331343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 86428679Sbrian {NULL, NULL, NULL}, 8656059Samurai}; 8666059Samurai 86730715Sbrianstatic struct cmdtab const * 86831343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 8696059Samurai{ 87026516Sbrian int nmatch; 87126516Sbrian int len; 87228679Sbrian struct cmdtab const *found; 8736059Samurai 87426516Sbrian found = NULL; 87526516Sbrian len = strlen(str); 87626516Sbrian nmatch = 0; 8776059Samurai while (cmds->func) { 87825566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 87926516Sbrian if (cmds->name[len] == '\0') { 88028679Sbrian *pmatch = 1; 88128679Sbrian return cmds; 88226516Sbrian } 8836059Samurai nmatch++; 8846059Samurai found = cmds; 88528679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 88626516Sbrian if (cmds->alias[len] == '\0') { 88728679Sbrian *pmatch = 1; 88828679Sbrian return cmds; 88926516Sbrian } 8906059Samurai nmatch++; 8916059Samurai found = cmds; 8926059Samurai } 8936059Samurai cmds++; 8946059Samurai } 8956059Samurai *pmatch = nmatch; 89626516Sbrian return found; 8976059Samurai} 8986059Samurai 89936285Sbrianstatic const char * 90036285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 90136285Sbrian{ 90236285Sbrian int f, tlen, len; 90336285Sbrian 90436285Sbrian tlen = 0; 90536285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 90636285Sbrian if (f) 90736285Sbrian tgt[tlen++] = ' '; 90836285Sbrian len = strlen(argv[f]); 90936285Sbrian if (len > sz - tlen - 1) 91036285Sbrian len = sz - tlen - 1; 91136285Sbrian strncpy(tgt+tlen, argv[f], len); 91236285Sbrian tlen += len; 91336285Sbrian } 91436285Sbrian tgt[tlen] = '\0'; 91536285Sbrian return tgt; 91636285Sbrian} 91736285Sbrian 91830715Sbrianstatic int 91936285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 92036285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 9216059Samurai{ 92228679Sbrian struct cmdtab const *cmd; 9236059Samurai int val = 1; 9246059Samurai int nmatch; 92531343Sbrian struct cmdargs arg; 92636285Sbrian char prefix[100]; 9276059Samurai 92836285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 9296059Samurai if (nmatch > 1) 93036285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 93136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 93236285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 93336285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 93436285Sbrian /* We've got no context, but we require it */ 93536285Sbrian cx = bundle2datalink(bundle, NULL); 93636285Sbrian 93736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 93836285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 93936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 94036285Sbrian else { 94136285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 94236285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 94336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 94436285Sbrian cx = NULL; 94536285Sbrian } 94636285Sbrian arg.cmdtab = cmds; 94736285Sbrian arg.cmd = cmd; 94836285Sbrian arg.argc = argc; 94936285Sbrian arg.argn = argn+1; 95036285Sbrian arg.argv = argv; 95136285Sbrian arg.bundle = bundle; 95236285Sbrian arg.cx = cx; 95336285Sbrian arg.prompt = prompt; 95436285Sbrian val = (*cmd->func) (&arg); 95536285Sbrian } 95631343Sbrian } else 95736285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 95836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 95926516Sbrian 96026516Sbrian if (val == -1) 96136285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 96228679Sbrian else if (val) 96336285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 96436285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 96526516Sbrian 96626516Sbrian return val; 9676059Samurai} 9686059Samurai 96937009Sbrianint 97058045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 97158045Sbrian{ 97258045Sbrian char buff2[LINE_LEN-offset]; 97358045Sbrian 97458045Sbrian InterpretArg(buff, buff2); 97558045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 97658045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 97758045Sbrian 97858045Sbrian return command_Interpret(buff, nb, argv); 97958045Sbrian} 98058045Sbrian 98158045Sbrianint 98237009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 9836059Samurai{ 9846059Samurai char *cp; 9856059Samurai 9866059Samurai if (nb > 0) { 9876059Samurai cp = buff + strcspn(buff, "\r\n"); 9886059Samurai if (cp) 9896059Samurai *cp = '\0'; 99055145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 99137009Sbrian } 99237009Sbrian return 0; 99331121Sbrian} 9946059Samurai 99531822Sbrianstatic int 99631822Sbrianarghidden(int argc, char const *const *argv, int n) 99731822Sbrian{ 99831822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 99931828Sbrian 100031828Sbrian /* set authkey xxxxx */ 100131828Sbrian /* set key xxxxx */ 100231822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 100331822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 100431822Sbrian return 1; 100531822Sbrian 100631828Sbrian /* passwd xxxxx */ 100731828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 100831828Sbrian return 1; 100931828Sbrian 101036285Sbrian /* set server port xxxxx .... */ 101136285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 101236285Sbrian !strncasecmp(argv[1], "se", 2)) 101336285Sbrian return 1; 101436285Sbrian 101531822Sbrian return 0; 101631822Sbrian} 101731822Sbrian 101831121Sbrianvoid 101936285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 102037008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 102131121Sbrian{ 102231156Sbrian if (argc > 0) { 102336285Sbrian if (log_IsKept(LogCOMMAND)) { 102447844Sbrian char buf[LINE_LEN]; 102531156Sbrian int f, n; 102631156Sbrian 102731156Sbrian if (label) { 102831962Sbrian strncpy(buf, label, sizeof buf - 3); 102931962Sbrian buf[sizeof buf - 3] = '\0'; 103031156Sbrian strcat(buf, ": "); 103147844Sbrian n = strlen(buf); 103247844Sbrian } else { 103347844Sbrian *buf = '\0'; 103447844Sbrian n = 0; 103531156Sbrian } 103647844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 103747844Sbrian 103831156Sbrian for (f = 0; f < argc; f++) { 103931962Sbrian if (n < sizeof buf - 1 && f) 104031156Sbrian buf[n++] = ' '; 104131822Sbrian if (arghidden(argc, argv, f)) 104236285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 104331822Sbrian else 104431962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 104531156Sbrian n += strlen(buf+n); 104631156Sbrian } 104736285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 104831156Sbrian } 104937008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 105031156Sbrian } 10516059Samurai} 10526059Samurai 105354914Sbrianint 105436285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 105536285Sbrian const char *label) 105631121Sbrian{ 105731121Sbrian int argc; 105837009Sbrian char *argv[MAXARGS]; 105931121Sbrian 106058045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 106154914Sbrian return 0; 106254914Sbrian 106337008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 106454914Sbrian return 1; 106531121Sbrian} 106631121Sbrian 10676059Samuraistatic int 106831343SbrianShowCommand(struct cmdargs const *arg) 10696059Samurai{ 107036285Sbrian if (!arg->prompt) 107136285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 107236285Sbrian else if (arg->argc > arg->argn) 107336285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 107436285Sbrian arg->prompt, arg->cx); 10756059Samurai else 107636285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 107726516Sbrian 107826516Sbrian return 0; 10796059Samurai} 10806059Samurai 10816059Samuraistatic int 108231343SbrianTerminalCommand(struct cmdargs const *arg) 10836059Samurai{ 108436285Sbrian if (!arg->prompt) { 108536285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 108626516Sbrian return 1; 10876059Samurai } 108836285Sbrian 108936285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 109036285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 109136285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 109236285Sbrian return 1; 10936059Samurai } 109436285Sbrian 109536285Sbrian datalink_Up(arg->cx, 0, 0); 109636285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 109736285Sbrian return 0; 10986059Samurai} 10996059Samurai 11006059Samuraistatic int 110131343SbrianQuitCommand(struct cmdargs const *arg) 11026059Samurai{ 110336285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 110436285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 110536285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 110636285Sbrian Cleanup(EX_NORMAL); 110736285Sbrian if (arg->prompt) 110836285Sbrian prompt_Destroy(arg->prompt, 1); 110926516Sbrian 111026516Sbrian return 0; 11116059Samurai} 11126059Samurai 11136059Samuraistatic int 111436285SbrianOpenCommand(struct cmdargs const *arg) 11156059Samurai{ 111637160Sbrian if (arg->argc == arg->argn) 111737993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 111837160Sbrian else if (arg->argc == arg->argn + 1) { 111937160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 112037385Sbrian struct datalink *cx = arg->cx ? 112137385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 112237385Sbrian if (cx) { 112337385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 112437385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 112537160Sbrian else 112637993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 112737160Sbrian } else 112837160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 112937160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 113037160Sbrian struct fsm *fp; 11316059Samurai 113237210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 113337160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 113437160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 113537160Sbrian else if (fp->state == ST_OPENED) 113637160Sbrian fsm_Reopen(fp); 113737160Sbrian else { 113837160Sbrian fp->open_mode = 0; /* Not passive any more */ 113937160Sbrian if (fp->state == ST_STOPPED) { 114037160Sbrian fsm_Down(fp); 114137160Sbrian fsm_Up(fp); 114237160Sbrian } else { 114337160Sbrian fsm_Up(fp); 114437160Sbrian fsm_Open(fp); 114537160Sbrian } 114636285Sbrian } 114737160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 114837160Sbrian if (arg->cx) 114937160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 115037160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 115137160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 115237160Sbrian else 115337993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 115437160Sbrian } else 115537160Sbrian return -1; 115636285Sbrian } else 115736285Sbrian return -1; 115836285Sbrian 115926516Sbrian return 0; 11606059Samurai} 11616059Samurai 116225067Sbrianstatic int 116336285SbrianCloseCommand(struct cmdargs const *arg) 11646059Samurai{ 116537007Sbrian if (arg->argc == arg->argn) 116637007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 116737007Sbrian else if (arg->argc == arg->argn + 1) { 116837007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 116937007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 117037007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 117137007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 117237007Sbrian struct fsm *fp; 11736059Samurai 117437210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 117537007Sbrian if (fp->state == ST_OPENED) { 117637007Sbrian fsm_Close(fp); 117737007Sbrian if (arg->argv[arg->argn][3] == '!') 117837007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 117937007Sbrian else 118037007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 118137007Sbrian } 118237007Sbrian } else 118336285Sbrian return -1; 118436285Sbrian } else 118536285Sbrian return -1; 118636285Sbrian 118736285Sbrian return 0; 11886059Samurai} 11896059Samurai 119025067Sbrianstatic int 119136285SbrianDownCommand(struct cmdargs const *arg) 119211336Samurai{ 119337018Sbrian if (arg->argc == arg->argn) { 119437018Sbrian if (arg->cx) 119537018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 119637018Sbrian else 119737018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 119837018Sbrian } else if (arg->argc == arg->argn + 1) { 119937018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 120037018Sbrian if (arg->cx) 120137018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 120237018Sbrian else 120337018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 120437018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 120537018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 120637018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 120737060Sbrian fsm2initial(fp); 120837018Sbrian } else 120937018Sbrian return -1; 121036285Sbrian } else 121136285Sbrian return -1; 121236285Sbrian 121336285Sbrian return 0; 121425067Sbrian} 121525067Sbrian 121625067Sbrianstatic int 121736285SbrianSetModemSpeed(struct cmdargs const *arg) 121825067Sbrian{ 121936285Sbrian long speed; 122036285Sbrian char *end; 122111336Samurai 122236285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 122336285Sbrian if (arg->argc > arg->argn+1) { 122454917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 122536285Sbrian return -1; 122611336Samurai } 122736285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 122836285Sbrian physical_SetSync(arg->cx->physical); 122936285Sbrian return 0; 123036285Sbrian } 123136285Sbrian end = NULL; 123236285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 123336285Sbrian if (*end) { 123436285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 123536285Sbrian arg->argv[arg->argn]); 123636285Sbrian return -1; 123736285Sbrian } 123836285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 123936285Sbrian return 0; 124036285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 124136285Sbrian } else 124236285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 124324939Sbrian 124426516Sbrian return -1; 124511336Samurai} 124611336Samurai 124725067Sbrianstatic int 124831343SbrianSetStoppedTimeout(struct cmdargs const *arg) 124928327Sbrian{ 125036285Sbrian struct link *l = &arg->cx->physical->link; 125136285Sbrian 125236285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 125336285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 125436285Sbrian if (arg->argc <= arg->argn+2) { 125536285Sbrian if (arg->argc > arg->argn) { 125636285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 125736285Sbrian if (arg->argc > arg->argn+1) 125836285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 125928461Sbrian } 126028327Sbrian return 0; 126128327Sbrian } 126228327Sbrian return -1; 126328327Sbrian} 126428327Sbrian 126528327Sbrianstatic int 126631343SbrianSetServer(struct cmdargs const *arg) 126726940Sbrian{ 126826940Sbrian int res = -1; 126926940Sbrian 127036285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 127131081Sbrian const char *port, *passwd, *mask; 127253125Sbrian int mlen; 127331081Sbrian 127431081Sbrian /* What's what ? */ 127536285Sbrian port = arg->argv[arg->argn]; 127636285Sbrian if (arg->argc == arg->argn + 2) { 127736285Sbrian passwd = arg->argv[arg->argn+1]; 127836285Sbrian mask = NULL; 127936285Sbrian } else if (arg->argc == arg->argn + 3) { 128036285Sbrian passwd = arg->argv[arg->argn+1]; 128136285Sbrian mask = arg->argv[arg->argn+2]; 128253125Sbrian mlen = strlen(mask); 128353125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 128453125Sbrian (mlen == 4 && *mask != '0')) { 128553125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 128653125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 128731081Sbrian return -1; 128853125Sbrian } 128936285Sbrian } else if (strcasecmp(port, "none") == 0) { 129071657Sbrian if (server_Clear(arg->bundle)) 129171657Sbrian log_Printf(LogPHASE, "Disabled server socket\n"); 129271657Sbrian return 0; 129371657Sbrian } else if (strcasecmp(port, "open") == 0) { 129471657Sbrian switch (server_Reopen(arg->bundle)) { 129571657Sbrian case SERVER_OK: 129671657Sbrian return 0; 129771657Sbrian case SERVER_FAILED: 129871657Sbrian log_Printf(LogPHASE, "Failed to reopen server port\n"); 129971657Sbrian return 1; 130071657Sbrian case SERVER_UNSET: 130171657Sbrian log_Printf(LogPHASE, "Cannot reopen unset server socket\n"); 130271657Sbrian return 1; 130371657Sbrian default: 130471657Sbrian break; 130571657Sbrian } 130671657Sbrian return -1; 130771657Sbrian } else if (strcasecmp(port, "closed") == 0) { 130836285Sbrian if (server_Close(arg->bundle)) 130971657Sbrian log_Printf(LogPHASE, "Closed server socket\n"); 131071657Sbrian else 131171657Sbrian log_Printf(LogWARN, "Server socket not open\n"); 131271657Sbrian 131336285Sbrian return 0; 131431081Sbrian } else 131536285Sbrian return -1; 131631081Sbrian 131771657Sbrian strncpy(server.cfg.passwd, passwd, sizeof server.cfg.passwd - 1); 131871657Sbrian server.cfg.passwd[sizeof server.cfg.passwd - 1] = '\0'; 131931081Sbrian 132036285Sbrian if (*port == '/') { 132131081Sbrian mode_t imask; 132236285Sbrian char *ptr, name[LINE_LEN + 12]; 132328679Sbrian 132453125Sbrian if (mask == NULL) 132531081Sbrian imask = (mode_t)-1; 132653125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 132753125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 132836285Sbrian 132936285Sbrian ptr = strstr(port, "%d"); 133036285Sbrian if (ptr) { 133136285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 133237210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 133336285Sbrian port = name; 133436285Sbrian } 133536285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 133627346Sbrian } else { 133736285Sbrian int iport, add = 0; 133828679Sbrian 133931081Sbrian if (mask != NULL) 134031081Sbrian return -1; 134128679Sbrian 134236285Sbrian if (*port == '+') { 134336285Sbrian port++; 134436285Sbrian add = 1; 134536285Sbrian } 134631081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 134731081Sbrian struct servent *s; 134831081Sbrian 134931081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 135031081Sbrian iport = 0; 135136285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 135228679Sbrian } else 135331081Sbrian iport = ntohs(s->s_port); 135427346Sbrian } else 135531081Sbrian iport = atoi(port); 135636285Sbrian 135736285Sbrian if (iport) { 135836285Sbrian if (add) 135936285Sbrian iport += arg->bundle->unit; 136036285Sbrian res = server_TcpOpen(arg->bundle, iport); 136136285Sbrian } else 136236285Sbrian res = -1; 136327346Sbrian } 136431081Sbrian } 136526940Sbrian 136626940Sbrian return res; 136726940Sbrian} 136826940Sbrian 136926940Sbrianstatic int 137031343SbrianSetEscape(struct cmdargs const *arg) 13716059Samurai{ 13726059Samurai int code; 137336285Sbrian int argc = arg->argc - arg->argn; 137436285Sbrian char const *const *argv = arg->argv + arg->argn; 13756059Samurai 13766059Samurai for (code = 0; code < 33; code++) 137736285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 137831343Sbrian 13796059Samurai while (argc-- > 0) { 13806059Samurai sscanf(*argv++, "%x", &code); 13816059Samurai code &= 0xff; 138236285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 138336285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 13846059Samurai } 138526516Sbrian return 0; 13866059Samurai} 13876059Samurai 13886059Samuraistatic int 138931343SbrianSetInterfaceAddr(struct cmdargs const *arg) 13906059Samurai{ 139136285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 139232267Sbrian const char *hisaddr; 139332267Sbrian 139440561Sbrian if (arg->argc > arg->argn + 4) 139540561Sbrian return -1; 139640561Sbrian 139732267Sbrian hisaddr = NULL; 139844874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 139944874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 140036285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 140136285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 140236285Sbrian iplist_reset(&ipcp->cfg.peer_list); 140328394Sbrian 140436285Sbrian if (arg->argc > arg->argn) { 140543313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 140636285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 140736285Sbrian &ipcp->cfg.my_range.width)) 140828679Sbrian return 1; 140936285Sbrian if (arg->argc > arg->argn+1) { 141036285Sbrian hisaddr = arg->argv[arg->argn+1]; 141136285Sbrian if (arg->argc > arg->argn+2) { 141244455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 141336285Sbrian if (arg->argc > arg->argn+3) { 141436285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 141536285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 14169440Samurai } 14176059Samurai } 14186059Samurai } 14196059Samurai } 142028394Sbrian 142140561Sbrian /* 0.0.0.0 means any address (0 bits) */ 142236285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 142336285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 142436285Sbrian ipcp->cfg.my_range.width = 0; 14256059Samurai } 142636285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 142747648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 142836285Sbrian 142936285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 143036928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 143132267Sbrian return 4; 143231121Sbrian 143326516Sbrian return 0; 14346059Samurai} 14356059Samurai 143618752Sjkhstatic int 143744305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 143844305Sbrian u_int *maxtrm, int def) 143944305Sbrian{ 144044305Sbrian if (argc == 0) { 144144305Sbrian *timeout = DEF_FSMRETRY; 144244305Sbrian *maxreq = def; 144344305Sbrian if (maxtrm != NULL) 144444305Sbrian *maxtrm = def; 144544305Sbrian } else { 144644305Sbrian long l = atol(argv[0]); 144744305Sbrian 144844305Sbrian if (l < MIN_FSMRETRY) { 144944305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 145044305Sbrian l, MIN_FSMRETRY); 145144305Sbrian return 1; 145244305Sbrian } else 145344305Sbrian *timeout = l; 145444305Sbrian 145544305Sbrian if (argc > 1) { 145644305Sbrian l = atol(argv[1]); 145744305Sbrian if (l < 1) { 145844305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 145944305Sbrian l = 1; 146044305Sbrian } 146144305Sbrian *maxreq = l; 146244305Sbrian 146344305Sbrian if (argc > 2 && maxtrm != NULL) { 146444305Sbrian l = atol(argv[2]); 146544305Sbrian if (l < 1) { 146644305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 146744305Sbrian l = 1; 146844305Sbrian } 146944305Sbrian *maxtrm = l; 147044305Sbrian } 147144305Sbrian } 147244305Sbrian } 147344305Sbrian 147444305Sbrian return 0; 147544305Sbrian} 147644305Sbrian 147744305Sbrianstatic int 147831343SbrianSetVariable(struct cmdargs const *arg) 14796059Samurai{ 148037210Sbrian long long_val, param = (long)arg->cmd->args; 148151048Sbrian int mode, dummyint, f, first; 148231343Sbrian const char *argp; 148336285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 148436285Sbrian const char *err = NULL; 148536285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 148636285Sbrian struct in_addr dummyaddr, *addr; 14876059Samurai 148836285Sbrian if (arg->argc > arg->argn) 148936285Sbrian argp = arg->argv[arg->argn]; 149026551Sbrian else 149131343Sbrian argp = ""; 149226551Sbrian 149336285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 149436285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 149536285Sbrian arg->cmd->name); 149636285Sbrian return 1; 149736285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 149836285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 149936285Sbrian arg->cmd->name, cx->name); 150036285Sbrian cx = NULL; 150136285Sbrian } 150236285Sbrian 150326551Sbrian switch (param) { 150428679Sbrian case VAR_AUTHKEY: 150550139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 150650139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 150750139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 150828679Sbrian break; 150937210Sbrian 151028679Sbrian case VAR_AUTHNAME: 151140622Sbrian switch (bundle_Phase(arg->bundle)) { 151258880Sbrian default: 151358880Sbrian log_Printf(LogWARN, "Altering authname while at phase %s\n", 151458880Sbrian bundle_PhaseName(arg->bundle)); 151558880Sbrian /* drop through */ 151640622Sbrian case PHASE_DEAD: 151740622Sbrian case PHASE_ESTABLISH: 151840622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 151940622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 152040622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 152140622Sbrian break; 152236285Sbrian } 152328679Sbrian break; 152437210Sbrian 152536285Sbrian case VAR_AUTOLOAD: 152649434Sbrian if (arg->argc == arg->argn + 3) { 152749434Sbrian int v1, v2, v3; 152849434Sbrian char *end; 152949434Sbrian 153049434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 153149434Sbrian if (v1 < 0 || *end) { 153249434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 153349434Sbrian arg->argv[arg->argn]); 153449434Sbrian return 1; 153536285Sbrian } 153649434Sbrian 153749434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 153849434Sbrian if (v2 < 0 || *end) { 153949434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 154049434Sbrian arg->argv[arg->argn + 1]); 154149434Sbrian return 1; 154249434Sbrian } 154349434Sbrian if (v2 < v1) { 154449434Sbrian v3 = v1; 154549434Sbrian v1 = v2; 154649434Sbrian v2 = v3; 154749434Sbrian } 154849434Sbrian 154949434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 155049434Sbrian if (v3 <= 0 || *end) { 155149434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 155249434Sbrian arg->argv[arg->argn + 2]); 155349434Sbrian return 1; 155449434Sbrian } 155549434Sbrian 155649434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 155749434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 155849434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 155949434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 156036285Sbrian } else { 156149434Sbrian err = "Set autoload requires three arguments\n"; 156236285Sbrian log_Printf(LogWARN, err); 156336285Sbrian } 156436285Sbrian break; 156537210Sbrian 156628679Sbrian case VAR_DIAL: 156736285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 156836285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 156928679Sbrian break; 157037210Sbrian 157128679Sbrian case VAR_LOGIN: 157236285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 157336285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 157428679Sbrian break; 157537210Sbrian 157636285Sbrian case VAR_WINSIZE: 157736285Sbrian if (arg->argc > arg->argn) { 157836285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 157936285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 158036285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 158136285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 158236285Sbrian l->ccp.cfg.deflate.out.winsize); 158336285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 158436285Sbrian } 158536285Sbrian if (arg->argc > arg->argn+1) { 158636285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 158736285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 158836285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 158936285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 159036285Sbrian l->ccp.cfg.deflate.in.winsize); 159136285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 159236285Sbrian } 159336285Sbrian } else 159436285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 159536285Sbrian } else { 159636285Sbrian err = "No window size specified\n"; 159736285Sbrian log_Printf(LogWARN, err); 159836285Sbrian } 159936285Sbrian break; 160037210Sbrian 160167910Sbrian#ifdef HAVE_DES 160267910Sbrian case VAR_KEYBITS: 160367910Sbrian if (arg->argc > arg->argn) { 160467910Sbrian l->ccp.cfg.mppe.keybits = atoi(arg->argv[arg->argn]); 160567910Sbrian if (l->ccp.cfg.mppe.keybits != 40 && 160667910Sbrian l->ccp.cfg.mppe.keybits != 56 && 160767910Sbrian l->ccp.cfg.mppe.keybits != 128 ) { 160867910Sbrian log_Printf(LogWARN, "%d: Invalid bits number\n", 160967910Sbrian l->ccp.cfg.mppe.keybits); 161067910Sbrian l->ccp.cfg.mppe.keybits = 40; 161167910Sbrian } 161267910Sbrian } else { 161367910Sbrian err = "No bits number pecified\n"; 161467910Sbrian log_Printf(LogWARN, err); 161567910Sbrian } 161667910Sbrian break; 161767910Sbrian#endif 161867910Sbrian 161928679Sbrian case VAR_DEVICE: 162036285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 162136285Sbrian arg->argv + arg->argn); 162236285Sbrian break; 162337210Sbrian 162436285Sbrian case VAR_ACCMAP: 162536285Sbrian if (arg->argc > arg->argn) { 162637210Sbrian u_long ulong_val; 162736285Sbrian sscanf(argp, "%lx", &ulong_val); 162837210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 162936285Sbrian } else { 163036285Sbrian err = "No accmap specified\n"; 163136285Sbrian log_Printf(LogWARN, err); 163236285Sbrian } 163336285Sbrian break; 163437210Sbrian 163536285Sbrian case VAR_MODE: 163636285Sbrian mode = Nam2mode(argp); 163736285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 163836285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 163936285Sbrian return -1; 164036285Sbrian } 164136285Sbrian bundle_SetMode(arg->bundle, cx, mode); 164236285Sbrian break; 164337210Sbrian 164436285Sbrian case VAR_MRRU: 164540622Sbrian switch (bundle_Phase(arg->bundle)) { 164640622Sbrian case PHASE_DEAD: 164740622Sbrian break; 164840622Sbrian case PHASE_ESTABLISH: 164940622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 165040622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 165140622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 165240622Sbrian return 1; 165340622Sbrian } 165440622Sbrian break; 165540622Sbrian default: 165640622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 165740622Sbrian return 1; 165829696Sbrian } 165937210Sbrian long_val = atol(argp); 166037210Sbrian if (long_val && long_val < MIN_MRU) { 166137210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 166237210Sbrian return 1; 166337210Sbrian } else if (long_val > MAX_MRU) { 166437210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 166537210Sbrian return 1; 166637210Sbrian } else 166737210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 166828679Sbrian break; 166937210Sbrian 167036285Sbrian case VAR_MRU: 167137210Sbrian long_val = atol(argp); 167237210Sbrian if (long_val == 0) 167337210Sbrian l->lcp.cfg.mru = DEF_MRU; 167437210Sbrian else if (long_val < MIN_MRU) { 167537210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 167637210Sbrian return 1; 167737210Sbrian } else if (long_val > MAX_MRU) { 167837210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 167937210Sbrian return 1; 168037210Sbrian } else 168137210Sbrian l->lcp.cfg.mru = long_val; 168228679Sbrian break; 168337210Sbrian 168436285Sbrian case VAR_MTU: 168537210Sbrian long_val = atol(argp); 168637210Sbrian if (long_val && long_val < MIN_MTU) { 168737210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 168837210Sbrian return 1; 168937210Sbrian } else if (long_val > MAX_MTU) { 169037210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 169137210Sbrian return 1; 169237210Sbrian } else 169337210Sbrian arg->bundle->cfg.mtu = long_val; 169436285Sbrian break; 169537210Sbrian 169636285Sbrian case VAR_OPENMODE: 169736285Sbrian if (strcasecmp(argp, "active") == 0) 169836285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 169936285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 170036285Sbrian else if (strcasecmp(argp, "passive") == 0) 170136285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 170236285Sbrian else { 170336285Sbrian err = "%s: Invalid openmode\n"; 170436285Sbrian log_Printf(LogWARN, err, argp); 170536285Sbrian } 170636285Sbrian break; 170737210Sbrian 170828679Sbrian case VAR_PHONE: 170936285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 171036285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 171138174Sbrian cx->phone.alt = cx->phone.next = NULL; 171228679Sbrian break; 171337210Sbrian 171428679Sbrian case VAR_HANGUP: 171536285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 171636285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 171728679Sbrian break; 171837210Sbrian 171961534Sbrian case VAR_IFQUEUE: 172061534Sbrian long_val = atol(argp); 172161534Sbrian arg->bundle->cfg.ifqueue = long_val < 0 ? 0 : long_val; 172261534Sbrian break; 172361534Sbrian 172452488Sbrian case VAR_LOGOUT: 172552488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 172652488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 172752488Sbrian break; 172852488Sbrian 172936285Sbrian case VAR_IDLETIMEOUT: 173049978Sbrian if (arg->argc > arg->argn+2) 173136285Sbrian err = "Too many idle timeout values\n"; 173249978Sbrian else if (arg->argc == arg->argn) 173349978Sbrian err = "Too few idle timeout values\n"; 173449978Sbrian else { 173549978Sbrian int timeout, min; 173649978Sbrian 173749978Sbrian timeout = atoi(argp); 173849978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 173949978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 174049978Sbrian } 174136285Sbrian if (err) 174236285Sbrian log_Printf(LogWARN, err); 174329549Sbrian break; 174437210Sbrian 174536285Sbrian case VAR_LQRPERIOD: 174637210Sbrian long_val = atol(argp); 174737210Sbrian if (long_val < MIN_LQRPERIOD) { 174837210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 174937210Sbrian long_val, MIN_LQRPERIOD); 175037210Sbrian return 1; 175136285Sbrian } else 175237210Sbrian l->lcp.cfg.lqrperiod = long_val; 175336285Sbrian break; 175437210Sbrian 175536285Sbrian case VAR_LCPRETRY: 175644305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 175744305Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 175844305Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 175944305Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 176036285Sbrian break; 176137210Sbrian 176236285Sbrian case VAR_CHAPRETRY: 176344305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 176444305Sbrian &cx->chap.auth.cfg.fsm.timeout, 176544305Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 176636285Sbrian break; 176737210Sbrian 176836285Sbrian case VAR_PAPRETRY: 176944305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 177044305Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 177144305Sbrian NULL, DEF_FSMAUTHTRIES); 177236285Sbrian break; 177337210Sbrian 177436285Sbrian case VAR_CCPRETRY: 177544305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 177644305Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 177744305Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 177836285Sbrian break; 177937210Sbrian 178036285Sbrian case VAR_IPCPRETRY: 178144305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 178244305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 178344305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 178444305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 178536285Sbrian break; 178637210Sbrian 178736285Sbrian case VAR_NBNS: 178836285Sbrian case VAR_DNS: 178958044Sbrian if (param == VAR_DNS) { 179036285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 179158044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_NONE; 179258044Sbrian } else { 179336285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 179458044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 179558044Sbrian } 179636285Sbrian 179736285Sbrian if (arg->argc > arg->argn) { 179843313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 179936285Sbrian addr, &dummyaddr, &dummyint); 180036285Sbrian if (arg->argc > arg->argn+1) 180143313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 180236285Sbrian addr + 1, &dummyaddr, &dummyint); 180336285Sbrian 180458044Sbrian if (addr[0].s_addr == INADDR_ANY) { 180536285Sbrian addr[0].s_addr = addr[1].s_addr; 180658044Sbrian addr[1].s_addr = INADDR_ANY; 180758044Sbrian } 180858044Sbrian if (addr[0].s_addr == INADDR_NONE) { 180958044Sbrian addr[0].s_addr = addr[1].s_addr; 181058044Sbrian addr[1].s_addr = INADDR_NONE; 181158044Sbrian } 181236285Sbrian } 181336285Sbrian break; 181438174Sbrian 181538174Sbrian case VAR_CALLBACK: 181638174Sbrian cx->cfg.callback.opmask = 0; 181738174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 181838174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 181938174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 182038174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 182138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 182238174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 182338174Sbrian if (dummyint == arg->argc - 1) 182438174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 182538174Sbrian else { 182638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 182738174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 182838174Sbrian sizeof cx->cfg.callback.msg - 1); 182938174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 183038174Sbrian } 183138174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 183238174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 183338174Sbrian else 183438174Sbrian return -1; 183538174Sbrian } 183638174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 183738174Sbrian cx->cfg.callback.opmask = 0; 183838174Sbrian break; 183938174Sbrian 184038174Sbrian case VAR_CBCP: 184138174Sbrian cx->cfg.cbcp.delay = 0; 184238174Sbrian *cx->cfg.cbcp.phone = '\0'; 184338174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 184438174Sbrian if (arg->argc > arg->argn) { 184538174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 184638174Sbrian sizeof cx->cfg.cbcp.phone - 1); 184738174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 184838174Sbrian if (arg->argc > arg->argn + 1) { 184938174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 185038174Sbrian if (arg->argc > arg->argn + 2) { 185138174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 185238174Sbrian if (long_val < MIN_FSMRETRY) 185338174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 185438174Sbrian long_val, MIN_FSMRETRY); 185538174Sbrian else 185638174Sbrian cx->cfg.cbcp.fsmretry = long_val; 185738174Sbrian } 185838174Sbrian } 185938174Sbrian } 186038174Sbrian break; 186138544Sbrian 186238544Sbrian case VAR_CHOKED: 186338544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 186438544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 186538544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 186638544Sbrian break; 186740665Sbrian 186840665Sbrian case VAR_SENDPIPE: 186940665Sbrian long_val = atol(argp); 187040665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 187140665Sbrian break; 187240665Sbrian 187340665Sbrian case VAR_RECVPIPE: 187440665Sbrian long_val = atol(argp); 187540665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 187640665Sbrian break; 187743313Sbrian 187843313Sbrian#ifndef NORADIUS 187943313Sbrian case VAR_RADIUS: 188043313Sbrian if (!*argp) 188143313Sbrian *arg->bundle->radius.cfg.file = '\0'; 188243313Sbrian else if (access(argp, R_OK)) { 188343313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 188443313Sbrian return 1; 188543313Sbrian } else { 188643313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 188743313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 188843313Sbrian arg->bundle->radius.cfg.file 188943313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 189043313Sbrian } 189143313Sbrian break; 189243313Sbrian#endif 189344073Sbrian 189444073Sbrian case VAR_CD: 189544073Sbrian if (*argp) { 189651699Sbrian if (strcasecmp(argp, "off")) { 189751699Sbrian long_val = atol(argp); 189851699Sbrian if (long_val < 0) 189951699Sbrian long_val = 0; 190051699Sbrian cx->physical->cfg.cd.delay = long_val; 190151699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 190251699Sbrian CD_REQUIRED : CD_VARIABLE; 190351699Sbrian } else 190451699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 190544073Sbrian } else { 190653733Sbrian cx->physical->cfg.cd.delay = 0; 190753733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 190844073Sbrian } 190944073Sbrian break; 191036285Sbrian 191146686Sbrian case VAR_PARITY: 191246686Sbrian if (arg->argc == arg->argn + 1) 191346686Sbrian return physical_SetParity(arg->cx->physical, argp); 191446686Sbrian else { 191546686Sbrian err = "Parity value must be odd, even or none\n"; 191646686Sbrian log_Printf(LogWARN, err); 191746686Sbrian } 191846686Sbrian break; 19196059Samurai 192046686Sbrian case VAR_CRTSCTS: 192146686Sbrian if (strcasecmp(argp, "on") == 0) 192236285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 192346686Sbrian else if (strcasecmp(argp, "off") == 0) 192436285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 192546686Sbrian else { 192646686Sbrian err = "RTS/CTS value must be on or off\n"; 192746686Sbrian log_Printf(LogWARN, err); 192846686Sbrian } 192946686Sbrian break; 193050867Sbrian 193150867Sbrian case VAR_URGENTPORTS: 193251048Sbrian if (arg->argn == arg->argc) { 193361430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 193451048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 193551048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 193651048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 193761430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 193851048Sbrian if (arg->argn == arg->argc - 1) 193951048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 194051048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 194151048Sbrian if (*arg->argv[f] == '+') 194251048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 194351048Sbrian else if (*arg->argv[f] == '-') 194451048Sbrian ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp, 194551048Sbrian atoi(arg->argv[f] + 1)); 194651048Sbrian else { 194751048Sbrian if (f == arg->argn) 194851048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 194951048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 195051048Sbrian } 195161430Sbrian } else if (arg->argn == arg->argc - 1 && 195261430Sbrian !strcasecmp(arg->argv[arg->argn], "none")) { 195361430Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 195461430Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 195561430Sbrian ipcp_ClearUrgentTOS(&arg->bundle->ncp.ipcp); 195651048Sbrian } else { 195761430Sbrian ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp); 195851048Sbrian first = arg->argn; 195951048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 196051048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 196151048Sbrian 196251048Sbrian for (f = first; f < arg->argc; f++) 196351048Sbrian if (*arg->argv[f] == '+') 196451048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 196551048Sbrian else if (*arg->argv[f] == '-') 196651048Sbrian ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp, 196751048Sbrian atoi(arg->argv[f] + 1)); 196851048Sbrian else { 196951048Sbrian if (f == first) 197051048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 197151048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 197251048Sbrian } 197351048Sbrian } 197450867Sbrian break; 197520812Sjkh } 197646686Sbrian 197746686Sbrian return err ? 1 : 0; 197820812Sjkh} 197920812Sjkh 198030715Sbrianstatic struct cmdtab const SetCommands[] = { 198136285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 198236285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 198328679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 198436285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 198528679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 198636285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 198736285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 198836285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 198936285Sbrian (const void *)VAR_AUTOLOAD}, 199050867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 199150867Sbrian "datalink bandwidth", "set bandwidth value"}, 199238174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 199338174Sbrian "callback control", "set callback [none|auth|cbcp|" 199438174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 199538174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 199638174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 199738174Sbrian (const void *)VAR_CBCP}, 199844305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 199944305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 200044073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 200144073Sbrian "set cd value[!]", (const void *)VAR_CD}, 200244305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 200344305Sbrian "CHAP retries", "set chapretry value [attempts]", 200444305Sbrian (const void *)VAR_CHAPRETRY}, 200538544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 200638544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 200746686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 200846686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 200946686Sbrian (const char *)VAR_CRTSCTS}, 201036285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 201136285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 201236285Sbrian (const void *) VAR_WINSIZE}, 201367910Sbrian#ifdef HAVE_DES 201467910Sbrian {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 201567910Sbrian "MPPE key size", "set mppe {40|56|128}", 201667910Sbrian (const void *) VAR_KEYBITS}, 201767910Sbrian#endif 201836285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 201946686Sbrian "physical device name", "set device|line device-name[,device-name]", 202036285Sbrian (const void *) VAR_DEVICE}, 202136285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 202236285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 202336285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 202436285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 202536285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 202636285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 202736285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 202836285Sbrian "escape characters", "set escape hex-digit ..."}, 202936285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 203036285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 203149388Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 203248142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 203336285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 203436285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 203536285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 203631343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 203761534Sbrian {"ifqueue", NULL, SetVariable, LOCAL_AUTH, "interface queue", 203861534Sbrian "set ifqueue packets", (const void *)VAR_IFQUEUE}, 203944305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 204044305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 204144305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 204244305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 204336712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 204467916Sbrian "set log [local] [+|-]all|async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 204558033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 204636285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 204736285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 204852488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 204952488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 205036285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 205136285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 205236285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 205336285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 205436285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 205536285Sbrian "set mrru value", (const void *)VAR_MRRU}, 205636285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 205736285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 205836285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 205936285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 206036285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 206136285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 206236285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 206336285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 206444305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 206544305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 206646686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 206746686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 206836285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 206936285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 207040679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 207140679Sbrian "Process title", "set proctitle [value]"}, 207243313Sbrian#ifndef NORADIUS 207343313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 207443313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 207543313Sbrian#endif 207636285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 207736285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 207840665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 207940665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 208036285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 208144468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 208240665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 208340665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 208471657Sbrian {"server", "socket", SetServer, LOCAL_AUTH, "diagnostic port", 208571657Sbrian "set server|socket TcpPort|LocalName|none|open|closed [password [mask]]"}, 208636285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 208746686Sbrian "physical speed", "set speed value|sync"}, 208836285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 208936285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 209036285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 209136285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 209251048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 209351048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 209436285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 209536285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 209628679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 209731343Sbrian "Display this message", "set help|? [command]", SetCommands}, 209828679Sbrian {NULL, NULL, NULL}, 20996059Samurai}; 21006059Samurai 21016059Samuraistatic int 210231343SbrianSetCommand(struct cmdargs const *arg) 21036059Samurai{ 210436285Sbrian if (arg->argc > arg->argn) 210536285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 210636285Sbrian arg->prompt, arg->cx); 210736285Sbrian else if (arg->prompt) 210836285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 210958044Sbrian " syntax help.\n"); 21106059Samurai else 211136285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 211226516Sbrian 211326516Sbrian return 0; 21146059Samurai} 21156059Samurai 21166059Samuraistatic int 211731343SbrianAddCommand(struct cmdargs const *arg) 21186059Samurai{ 21196059Samurai struct in_addr dest, gateway, netmask; 212036285Sbrian int gw, addrs; 21216059Samurai 212236285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 212331598Sbrian return -1; 212431598Sbrian 212536285Sbrian addrs = 0; 212636285Sbrian if (arg->argc == arg->argn+2) { 212736285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 212836285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 212931598Sbrian else { 213036285Sbrian int width; 213136285Sbrian 213243313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 213336285Sbrian &dest, &netmask, &width)) 213436285Sbrian return -1; 213536285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 213636285Sbrian addrs = ROUTE_DSTMYADDR; 213736285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 213836285Sbrian addrs = ROUTE_DSTHISADDR; 213958044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 214058044Sbrian addrs = ROUTE_DSTDNS0; 214158044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 214258044Sbrian addrs = ROUTE_DSTDNS1; 214331598Sbrian } 214436285Sbrian gw = 1; 214534536Sbrian } else { 214636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 214736285Sbrian addrs = ROUTE_DSTMYADDR; 214836285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 214936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 215036285Sbrian addrs = ROUTE_DSTHISADDR; 215136285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 215258044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 215358044Sbrian addrs = ROUTE_DSTDNS0; 215458044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 215558044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 215658044Sbrian addrs = ROUTE_DSTDNS1; 215758044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 215865263Sbrian } else { 215936285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 216065263Sbrian if (dest.s_addr == INADDR_NONE) { 216165263Sbrian log_Printf(LogWARN, "%s: Invalid destination address\n", 216265263Sbrian arg->argv[arg->argn]); 216365263Sbrian return -1; 216465263Sbrian } 216565263Sbrian } 216636285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 216731598Sbrian gw = 2; 21686059Samurai } 216936285Sbrian 217036285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 217136285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 217236285Sbrian addrs |= ROUTE_GWHISADDR; 217365263Sbrian } else { 217436285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 217565263Sbrian if (gateway.s_addr == INADDR_NONE) { 217665263Sbrian log_Printf(LogWARN, "%s: Invalid gateway address\n", 217765263Sbrian arg->argv[arg->argn + gw]); 217865263Sbrian return -1; 217965263Sbrian } 218065263Sbrian } 218136285Sbrian 218236285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 218343313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 218443313Sbrian && addrs != ROUTE_STATIC) 218536285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 218636285Sbrian 218731598Sbrian return 0; 21886059Samurai} 21896059Samurai 21906059Samuraistatic int 219131343SbrianDeleteCommand(struct cmdargs const *arg) 21926059Samurai{ 219331598Sbrian struct in_addr dest, none; 219436285Sbrian int addrs; 21956059Samurai 219636285Sbrian if (arg->argc == arg->argn+1) { 219736285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 219836285Sbrian route_IfDelete(arg->bundle, 0); 219936285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 220036285Sbrian } else { 220136285Sbrian addrs = 0; 220236285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 220336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 220436285Sbrian addrs = ROUTE_DSTMYADDR; 220536285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 220636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 220736285Sbrian addrs = ROUTE_DSTHISADDR; 220858044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 220958044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 221058044Sbrian addrs = ROUTE_DSTDNS0; 221158044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 221258044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 221358044Sbrian addrs = ROUTE_DSTDNS1; 221436285Sbrian } else { 221544279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 221644279Sbrian if (dest.s_addr == INADDR_NONE) { 221744279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 221844279Sbrian return -1; 221944279Sbrian } 222036285Sbrian addrs = ROUTE_STATIC; 222136285Sbrian } 222231598Sbrian none.s_addr = INADDR_ANY; 222336285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 222437927Sbrian arg->cmd->args ? 1 : 0, 0); 222536285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 222631598Sbrian } 222734536Sbrian } else 222826516Sbrian return -1; 222926516Sbrian 223026516Sbrian return 0; 22316059Samurai} 22326059Samurai 223350059Sbrian#ifndef NONAT 223426031Sbrianstatic int 223558867SbrianNatEnable(struct cmdargs const *arg) 223626031Sbrian{ 223736285Sbrian if (arg->argc == arg->argn+1) { 223836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 223950059Sbrian if (!arg->bundle->NatEnabled) { 224046686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 224146686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 224250059Sbrian arg->bundle->NatEnabled = 1; 224346686Sbrian } 224437191Sbrian return 0; 224536285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 224650059Sbrian arg->bundle->NatEnabled = 0; 224740561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 224840561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 224926516Sbrian return 0; 225026142Sbrian } 225135449Sbrian } 225236285Sbrian 225326516Sbrian return -1; 225426031Sbrian} 225526031Sbrian 225626031Sbrian 225726031Sbrianstatic int 225858867SbrianNatOption(struct cmdargs const *arg) 225926031Sbrian{ 226038559Sbrian long param = (long)arg->cmd->args; 226138559Sbrian 226236285Sbrian if (arg->argc == arg->argn+1) { 226336285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 226450059Sbrian if (arg->bundle->NatEnabled) { 226537191Sbrian PacketAliasSetMode(param, param); 226628679Sbrian return 0; 226728679Sbrian } 226850059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 226936285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 227050059Sbrian if (arg->bundle->NatEnabled) { 227137191Sbrian PacketAliasSetMode(0, param); 227228679Sbrian return 0; 227328679Sbrian } 227450059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 227528679Sbrian } 227635449Sbrian } 227728679Sbrian return -1; 227826031Sbrian} 227950059Sbrian#endif /* #ifndef NONAT */ 228031121Sbrian 228131121Sbrianstatic int 228236285SbrianLinkCommand(struct cmdargs const *arg) 228336285Sbrian{ 228436285Sbrian if (arg->argc > arg->argn+1) { 228536285Sbrian char namelist[LINE_LEN]; 228636285Sbrian struct datalink *cx; 228736285Sbrian char *name; 228836285Sbrian int result = 0; 228936285Sbrian 229036285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 229136285Sbrian struct datalink *dl; 229236285Sbrian 229336285Sbrian cx = arg->bundle->links; 229436285Sbrian while (cx) { 229536285Sbrian /* Watch it, the command could be a ``remove'' */ 229636285Sbrian dl = cx->next; 229736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 229836285Sbrian arg->prompt, cx); 229936285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 230036285Sbrian if (cx == dl) 230136285Sbrian break; /* Pointer's still valid ! */ 230236285Sbrian } 230336285Sbrian } else { 230436285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 230536285Sbrian namelist[sizeof namelist - 1] = '\0'; 230636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 230736285Sbrian if (!bundle2datalink(arg->bundle, name)) { 230836285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 230936285Sbrian return 1; 231036285Sbrian } 231136285Sbrian 231236285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 231336285Sbrian namelist[sizeof namelist - 1] = '\0'; 231436285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 231536285Sbrian cx = bundle2datalink(arg->bundle, name); 231636285Sbrian if (cx) 231736285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 231836285Sbrian arg->prompt, cx); 231936285Sbrian else { 232036285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 232136285Sbrian result++; 232236285Sbrian } 232336285Sbrian } 232436285Sbrian } 232536285Sbrian return result; 232636285Sbrian } 232736285Sbrian 232836285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 232936285Sbrian return 2; 233036285Sbrian} 233136285Sbrian 233236285Sbrianstruct link * 233336285Sbriancommand_ChooseLink(struct cmdargs const *arg) 233436285Sbrian{ 233536285Sbrian if (arg->cx) 233636285Sbrian return &arg->cx->physical->link; 233737210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 233836285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 233937210Sbrian if (dl) 234037210Sbrian return &dl->physical->link; 234136285Sbrian } 234237210Sbrian return &arg->bundle->ncp.mp.link; 234336285Sbrian} 234436285Sbrian 234536285Sbrianstatic const char * 234636285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 234736285Sbrian{ 234836285Sbrian const char *result; 234936285Sbrian 235036285Sbrian switch (*cmd) { 235136285Sbrian case 'A': 235236285Sbrian case 'a': 235336285Sbrian result = "accept"; 235436285Sbrian *keep = NEG_MYMASK; 235536285Sbrian *add = NEG_ACCEPTED; 235636285Sbrian break; 235736285Sbrian case 'D': 235836285Sbrian case 'd': 235936285Sbrian switch (cmd[1]) { 236036285Sbrian case 'E': 236136285Sbrian case 'e': 236236285Sbrian result = "deny"; 236336285Sbrian *keep = NEG_MYMASK; 236436285Sbrian *add = 0; 236536285Sbrian break; 236636285Sbrian case 'I': 236736285Sbrian case 'i': 236836285Sbrian result = "disable"; 236936285Sbrian *keep = NEG_HISMASK; 237036285Sbrian *add = 0; 237136285Sbrian break; 237236285Sbrian default: 237336285Sbrian return NULL; 237436285Sbrian } 237536285Sbrian break; 237636285Sbrian case 'E': 237736285Sbrian case 'e': 237836285Sbrian result = "enable"; 237936285Sbrian *keep = NEG_HISMASK; 238036285Sbrian *add = NEG_ENABLED; 238136285Sbrian break; 238236285Sbrian default: 238336285Sbrian return NULL; 238436285Sbrian } 238536285Sbrian 238636285Sbrian return result; 238736285Sbrian} 238836285Sbrian 238936285Sbrianstatic int 239036285SbrianOptSet(struct cmdargs const *arg) 239136285Sbrian{ 239237574Sbrian int bit = (int)(long)arg->cmd->args; 239336285Sbrian const char *cmd; 239436285Sbrian unsigned keep; /* Keep these bits */ 239536285Sbrian unsigned add; /* Add these bits */ 239636285Sbrian 239736285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 239836285Sbrian return 1; 239936285Sbrian 240036285Sbrian if (add) 240136285Sbrian arg->bundle->cfg.opt |= bit; 240236285Sbrian else 240336285Sbrian arg->bundle->cfg.opt &= ~bit; 240436285Sbrian return 0; 240536285Sbrian} 240636285Sbrian 240736285Sbrianstatic int 240840561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 240940561Sbrian{ 241040561Sbrian unsigned save = arg->bundle->cfg.opt; 241140561Sbrian int result = OptSet(arg); 241240561Sbrian 241340561Sbrian if (result == 0) 241450059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 241540561Sbrian arg->bundle->cfg.opt = save; 241650059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 241740561Sbrian result = 2; 241840561Sbrian } 241940561Sbrian 242040561Sbrian return result; 242140561Sbrian} 242240561Sbrian 242340561Sbrianstatic int 242436285SbrianNegotiateSet(struct cmdargs const *arg) 242536285Sbrian{ 242637210Sbrian long param = (long)arg->cmd->args; 242736285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 242836285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 242936285Sbrian const char *cmd; 243036285Sbrian unsigned keep; /* Keep these bits */ 243136285Sbrian unsigned add; /* Add these bits */ 243236285Sbrian 243336285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 243436285Sbrian return 1; 243536285Sbrian 243636285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 243736285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 243836285Sbrian cmd, arg->cmd->name); 243936285Sbrian return 2; 244036285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 244136285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 244236285Sbrian cmd, arg->cmd->name, cx->name); 244336285Sbrian cx = NULL; 244436285Sbrian } 244536285Sbrian 244636285Sbrian switch (param) { 244736285Sbrian case NEG_ACFCOMP: 244836285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 244936285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 245036285Sbrian break; 245144106Sbrian case NEG_CHAP05: 245244106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 245344106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 245436285Sbrian break; 245544106Sbrian#ifdef HAVE_DES 245644106Sbrian case NEG_CHAP80: 245744106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 245844106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 245944106Sbrian break; 246044106Sbrian case NEG_CHAP80LM: 246144106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 246244106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 246344106Sbrian break; 246467910Sbrian case NEG_CHAP81: 246567910Sbrian cx->physical->link.lcp.cfg.chap81 &= keep; 246667910Sbrian cx->physical->link.lcp.cfg.chap81 |= add; 246767910Sbrian break; 246867910Sbrian case NEG_MPPE: 246967910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep; 247067910Sbrian l->ccp.cfg.neg[CCP_NEG_MPPE] |= add; 247167910Sbrian break; 247244106Sbrian#endif 247336285Sbrian case NEG_DEFLATE: 247436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 247536285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 247636285Sbrian break; 247736285Sbrian case NEG_DNS: 247836285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 247936285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 248036285Sbrian break; 248147858Sbrian case NEG_ENDDISC: 248247858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 248347858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 248447858Sbrian break; 248536285Sbrian case NEG_LQR: 248636285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 248736285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 248836285Sbrian break; 248936285Sbrian case NEG_PAP: 249036285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 249136285Sbrian cx->physical->link.lcp.cfg.pap |= add; 249236285Sbrian break; 249336285Sbrian case NEG_PPPDDEFLATE: 249436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 249536285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 249636285Sbrian break; 249736285Sbrian case NEG_PRED1: 249836285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 249936285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 250036285Sbrian break; 250136285Sbrian case NEG_PROTOCOMP: 250236285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 250336285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 250436285Sbrian break; 250536285Sbrian case NEG_SHORTSEQ: 250640622Sbrian switch (bundle_Phase(arg->bundle)) { 250740622Sbrian case PHASE_DEAD: 250840622Sbrian break; 250940622Sbrian case PHASE_ESTABLISH: 251040622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 251140622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 251240622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 251340622Sbrian " LCP negotiations\n"); 251440622Sbrian return 1; 251540622Sbrian } 251640622Sbrian break; 251740622Sbrian default: 251840622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 251940622Sbrian " DEAD/ESTABLISH\n"); 252040622Sbrian return 1; 252136285Sbrian } 252240622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 252340622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 252436285Sbrian break; 252536285Sbrian case NEG_VJCOMP: 252636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 252736285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 252836285Sbrian break; 252936285Sbrian } 253036285Sbrian 253136285Sbrian return 0; 253236285Sbrian} 253336285Sbrian 253436285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 253562778Sbrian {"filter-decapsulation", NULL, OptSet, LOCAL_AUTH, 253662778Sbrian "filter on PPPoUDP payloads", "disable|enable", 253762778Sbrian (const void *)OPT_FILTERDECAP}, 253836285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 253936285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 254040666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 254162778Sbrian "retain interface addresses", "disable|enable", 254262778Sbrian (const void *)OPT_IFACEALIAS}, 254347689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 254447689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 254536285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 254636285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 254736285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 254836285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 254940665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 255036285Sbrian "disable|enable", (const void *)OPT_PROXY}, 255140665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 255240665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 255336285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 255436285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 255569303Sbrian {"tcpmssfixup", "mssfixup", OptSet, LOCAL_AUTH, "Modify MSS options", 255669303Sbrian "disable|enable", (const void *)OPT_TCPMSSFIXUP}, 255736285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 255836285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 255936285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 256036285Sbrian "disable|enable", (const void *)OPT_UTMP}, 256136285Sbrian 256269303Sbrian#define OPT_MAX 11 /* accept/deny allowed below and not above */ 256336285Sbrian 256436285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 256536285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 256636285Sbrian (const void *)NEG_ACFCOMP}, 256744106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 256836285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 256944106Sbrian (const void *)NEG_CHAP05}, 257044106Sbrian#ifdef HAVE_DES 257144106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 257244106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 257344106Sbrian (const void *)NEG_CHAP80}, 257444106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 257544106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 257644106Sbrian (const void *)NEG_CHAP80LM}, 257767910Sbrian {"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 257867910Sbrian "Microsoft CHAP v2", "accept|deny|disable|enable", 257967910Sbrian (const void *)NEG_CHAP81}, 258067910Sbrian {"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 258167910Sbrian "MPPE encryption", "accept|deny|disable|enable", 258267910Sbrian (const void *)NEG_MPPE}, 258344106Sbrian#endif 258436285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 258536285Sbrian "Deflate compression", "accept|deny|disable|enable", 258636285Sbrian (const void *)NEG_DEFLATE}, 258736285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 258836285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 258936285Sbrian (const void *)NEG_PPPDDEFLATE}, 259036285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 259136285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 259247858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 259347858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 259436285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 259536285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 259636285Sbrian (const void *)NEG_LQR}, 259736285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 259836285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 259936285Sbrian (const void *)NEG_PAP}, 260036285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 260136285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 260236285Sbrian (const void *)NEG_PRED1}, 260336285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 260436285Sbrian "Protocol field compression", "accept|deny|disable|enable", 260536285Sbrian (const void *)NEG_PROTOCOMP}, 260636285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 260736285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 260836285Sbrian (const void *)NEG_SHORTSEQ}, 260936285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 261036285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 261136285Sbrian (const void *)NEG_VJCOMP}, 261236285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 261336285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 261436285Sbrian NegotiateCommands}, 261536285Sbrian {NULL, NULL, NULL}, 261636285Sbrian}; 261736285Sbrian 261836285Sbrianstatic int 261936285SbrianNegotiateCommand(struct cmdargs const *arg) 262036285Sbrian{ 262136285Sbrian if (arg->argc > arg->argn) { 262236285Sbrian char const *argv[3]; 262336285Sbrian unsigned keep, add; 262436285Sbrian int n; 262536285Sbrian 262636285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 262736285Sbrian return -1; 262836285Sbrian argv[2] = NULL; 262936285Sbrian 263036285Sbrian for (n = arg->argn; n < arg->argc; n++) { 263136285Sbrian argv[1] = arg->argv[n]; 263236285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 263336285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 263436285Sbrian } 263536285Sbrian } else if (arg->prompt) 263636285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 263736285Sbrian arg->argv[arg->argn-1]); 263836285Sbrian else 263936285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 264036285Sbrian arg->argv[arg->argn] ); 264136285Sbrian 264236285Sbrian return 0; 264336285Sbrian} 264436285Sbrian 264536285Sbrianconst char * 264636285Sbriancommand_ShowNegval(unsigned val) 264736285Sbrian{ 264836285Sbrian switch (val&3) { 264936285Sbrian case 1: return "disabled & accepted"; 265036285Sbrian case 2: return "enabled & denied"; 265136285Sbrian case 3: return "enabled & accepted"; 265236285Sbrian } 265336285Sbrian return "disabled & denied"; 265436285Sbrian} 265536934Sbrian 265636934Sbrianstatic int 265736934SbrianClearCommand(struct cmdargs const *arg) 265836934Sbrian{ 265936934Sbrian struct pppThroughput *t; 266036934Sbrian struct datalink *cx; 266136934Sbrian int i, clear_type; 266236934Sbrian 266336934Sbrian if (arg->argc < arg->argn + 1) 266436934Sbrian return -1; 266536934Sbrian 266646686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 266736934Sbrian cx = arg->cx; 266836934Sbrian if (!cx) 266936934Sbrian cx = bundle2datalink(arg->bundle, NULL); 267036934Sbrian if (!cx) { 267146686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 267236934Sbrian return 1; 267336934Sbrian } 267464652Sbrian t = &cx->physical->link.stats.total; 267536934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 267636934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 267736934Sbrian else 267836934Sbrian return -1; 267936934Sbrian 268036934Sbrian if (arg->argc > arg->argn + 1) { 268136934Sbrian clear_type = 0; 268236934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 268336934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 268436934Sbrian clear_type |= THROUGHPUT_OVERALL; 268536934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 268636934Sbrian clear_type |= THROUGHPUT_CURRENT; 268736934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 268836934Sbrian clear_type |= THROUGHPUT_PEAK; 268936934Sbrian else 269036934Sbrian return -1; 269136934Sbrian } else 269236934Sbrian clear_type = THROUGHPUT_ALL; 269336934Sbrian 269436934Sbrian throughput_clear(t, clear_type, arg->prompt); 269536934Sbrian return 0; 269636934Sbrian} 269740561Sbrian 269840561Sbrianstatic int 269940561SbrianRunListCommand(struct cmdargs const *arg) 270040561Sbrian{ 270140561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 270240561Sbrian 270364801Sbrian#ifndef NONAT 270464801Sbrian if (arg->cmd->args == NatCommands && 270564801Sbrian tolower(*arg->argv[arg->argn - 1]) == 'a') { 270664801Sbrian if (arg->prompt) 270765550Sbrian prompt_Printf(arg->prompt, "The alias command is deprecated\n"); 270864801Sbrian else 270965550Sbrian log_Printf(LogWARN, "The alias command is deprecated\n"); 271064801Sbrian } 271164801Sbrian#endif 271264801Sbrian 271340561Sbrian if (arg->argc > arg->argn) 271440561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 271540561Sbrian arg->prompt, arg->cx); 271640561Sbrian else if (arg->prompt) 271740561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 271840561Sbrian " <option>' for syntax help.\n", cmd, cmd); 271940561Sbrian else 272040561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 272140561Sbrian 272240561Sbrian return 0; 272340561Sbrian} 272440561Sbrian 272540561Sbrianstatic int 272640561SbrianIfaceAddCommand(struct cmdargs const *arg) 272740561Sbrian{ 272840561Sbrian int bits, n, how; 272940561Sbrian struct in_addr ifa, mask, brd; 273040561Sbrian 273140664Sbrian if (arg->argc == arg->argn + 1) { 273243313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 273340561Sbrian return -1; 273440664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 273540664Sbrian } else { 273640664Sbrian if (arg->argc == arg->argn + 2) { 273743313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 273840664Sbrian return -1; 273940664Sbrian n = 1; 274040664Sbrian } else if (arg->argc == arg->argn + 3) { 274143313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 274240664Sbrian return -1; 274343313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 274440664Sbrian return -1; 274540664Sbrian n = 2; 274640664Sbrian } else 274740561Sbrian return -1; 274840561Sbrian 274943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 275040664Sbrian return -1; 275140664Sbrian } 275240561Sbrian 275340561Sbrian how = IFACE_ADD_LAST; 275440561Sbrian if (arg->cmd->args) 275540561Sbrian how |= IFACE_FORCE_ADD; 275640561Sbrian 275740561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 275840561Sbrian} 275940561Sbrian 276040561Sbrianstatic int 276140561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 276240561Sbrian{ 276340561Sbrian struct in_addr ifa; 276440561Sbrian int ok; 276540561Sbrian 276640561Sbrian if (arg->argc != arg->argn + 1) 276740561Sbrian return -1; 276840561Sbrian 276943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 277040561Sbrian return -1; 277140561Sbrian 277240561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 277340561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 277440561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 277540561Sbrian inet_ntoa(ifa)); 277640561Sbrian return 1; 277740561Sbrian } 277840561Sbrian 277940561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 278040561Sbrian if (!ok) { 278140561Sbrian if (arg->cmd->args) 278240561Sbrian ok = 1; 278340561Sbrian else if (arg->prompt) 278440561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 278540561Sbrian else 278640561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 278740561Sbrian } 278840561Sbrian 278940561Sbrian return !ok; 279040561Sbrian} 279140561Sbrian 279240561Sbrianstatic int 279340561SbrianIfaceClearCommand(struct cmdargs const *arg) 279440561Sbrian{ 279540561Sbrian int how; 279640561Sbrian 279740561Sbrian if (arg->argc != arg->argn) 279840561Sbrian return -1; 279940561Sbrian 280040941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 280140941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 280240561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 280340561Sbrian iface_Clear(arg->bundle->iface, how); 280440561Sbrian 280540561Sbrian return 0; 280640561Sbrian} 280740679Sbrian 280840679Sbrianstatic int 280940679SbrianSetProcTitle(struct cmdargs const *arg) 281040679Sbrian{ 281140679Sbrian static char title[LINE_LEN]; 281240679Sbrian char *argv[MAXARGS], *ptr; 281340679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 281440679Sbrian 281540679Sbrian if (arg->argc == arg->argn) { 281664698Sbrian SetTitle(NULL); 281740679Sbrian return 0; 281840679Sbrian } 281940679Sbrian 282040679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 282140679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 282240679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 282340679Sbrian } 282447849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 282540679Sbrian 282640679Sbrian ptr = title; 282740679Sbrian remaining = sizeof title - 1; 282840679Sbrian for (f = 0; f < argc && remaining; f++) { 282940679Sbrian if (f) { 283040679Sbrian *ptr++ = ' '; 283140679Sbrian remaining--; 283240679Sbrian } 283340679Sbrian len = strlen(argv[f]); 283440679Sbrian if (len > remaining) 283540679Sbrian len = remaining; 283640679Sbrian memcpy(ptr, argv[f], len); 283740679Sbrian remaining -= len; 283840679Sbrian ptr += len; 283940679Sbrian } 284040679Sbrian *ptr = '\0'; 284140679Sbrian 284264698Sbrian SetTitle(title); 284340679Sbrian 284440679Sbrian return 0; 284540679Sbrian} 2846