command.c revision 47849
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 * 2047849Sbrian * $Id: command.c,v 1.199 1999/06/08 20:11:57 brian Exp $ 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 4439395Sbrian#ifndef NOALIAS 4546086Sbrian#ifdef __FreeBSD__ 4646086Sbrian#include <alias.h> 4746086Sbrian#else 4839395Sbrian#include "alias.h" 4939395Sbrian#endif 5039395Sbrian#endif 5146686Sbrian#include "layer.h" 5237009Sbrian#include "defs.h" 5331343Sbrian#include "command.h" 5430715Sbrian#include "mbuf.h" 5530715Sbrian#include "log.h" 5630715Sbrian#include "timer.h" 576059Samurai#include "fsm.h" 586059Samurai#include "lcp.h" 5931690Sbrian#include "iplist.h" 6036285Sbrian#include "throughput.h" 6136285Sbrian#include "slcompress.h" 6238557Sbrian#include "lqr.h" 6338557Sbrian#include "hdlc.h" 646059Samurai#include "ipcp.h" 6531343Sbrian#ifndef NOALIAS 6626031Sbrian#include "alias_cmd.h" 6731343Sbrian#endif 6825630Sbrian#include "systems.h" 6936285Sbrian#include "filter.h" 7036285Sbrian#include "descriptor.h" 7130715Sbrian#include "main.h" 7230715Sbrian#include "route.h" 7330715Sbrian#include "ccp.h" 7431080Sbrian#include "auth.h" 7536285Sbrian#include "async.h" 7636285Sbrian#include "link.h" 7736285Sbrian#include "physical.h" 7836285Sbrian#include "mp.h" 7943313Sbrian#ifndef NORADIUS 8043313Sbrian#include "radius.h" 8143313Sbrian#endif 8236285Sbrian#include "bundle.h" 8336285Sbrian#include "server.h" 8436285Sbrian#include "prompt.h" 8536285Sbrian#include "chat.h" 8636285Sbrian#include "chap.h" 8738174Sbrian#include "cbcp.h" 8836285Sbrian#include "datalink.h" 8940561Sbrian#include "iface.h" 906059Samurai 9136285Sbrian/* ``set'' values */ 9236285Sbrian#define VAR_AUTHKEY 0 9336285Sbrian#define VAR_DIAL 1 9436285Sbrian#define VAR_LOGIN 2 9536285Sbrian#define VAR_AUTHNAME 3 9636285Sbrian#define VAR_AUTOLOAD 4 9736285Sbrian#define VAR_WINSIZE 5 9836285Sbrian#define VAR_DEVICE 6 9936285Sbrian#define VAR_ACCMAP 7 10036285Sbrian#define VAR_MRRU 8 10136285Sbrian#define VAR_MRU 9 10236285Sbrian#define VAR_MTU 10 10336285Sbrian#define VAR_OPENMODE 11 10436285Sbrian#define VAR_PHONE 12 10536285Sbrian#define VAR_HANGUP 13 10636285Sbrian#define VAR_IDLETIMEOUT 14 10736285Sbrian#define VAR_LQRPERIOD 15 10836285Sbrian#define VAR_LCPRETRY 16 10936285Sbrian#define VAR_CHAPRETRY 17 11036285Sbrian#define VAR_PAPRETRY 18 11136285Sbrian#define VAR_CCPRETRY 19 11236285Sbrian#define VAR_IPCPRETRY 20 11336285Sbrian#define VAR_DNS 21 11436285Sbrian#define VAR_NBNS 22 11536285Sbrian#define VAR_MODE 23 11638174Sbrian#define VAR_CALLBACK 24 11738174Sbrian#define VAR_CBCP 25 11838544Sbrian#define VAR_CHOKED 26 11940665Sbrian#define VAR_SENDPIPE 27 12040665Sbrian#define VAR_RECVPIPE 28 12143313Sbrian#define VAR_RADIUS 29 12244073Sbrian#define VAR_CD 30 12346686Sbrian#define VAR_PARITY 31 12446686Sbrian#define VAR_CRTSCTS 32 1256059Samurai 12636285Sbrian/* ``accept|deny|disable|enable'' masks */ 12736285Sbrian#define NEG_HISMASK (1) 12836285Sbrian#define NEG_MYMASK (2) 12936285Sbrian 13036285Sbrian/* ``accept|deny|disable|enable'' values */ 13136285Sbrian#define NEG_ACFCOMP 40 13244106Sbrian#define NEG_CHAP05 41 13344106Sbrian#define NEG_CHAP80 42 13444106Sbrian#define NEG_CHAP80LM 43 13544106Sbrian#define NEG_DEFLATE 44 13644106Sbrian#define NEG_LQR 45 13744106Sbrian#define NEG_PAP 46 13844106Sbrian#define NEG_PPPDDEFLATE 47 13944106Sbrian#define NEG_PRED1 48 14044106Sbrian#define NEG_PROTOCOMP 49 14144106Sbrian#define NEG_SHORTSEQ 50 14244106Sbrian#define NEG_VJCOMP 51 14344106Sbrian#define NEG_DNS 52 14436285Sbrian 14547769Sbrianconst char Version[] = "2.22"; 14647849Sbrianconst char VersionDate[] = "$Date: 1999/06/08 20:11:57 $"; 14736285Sbrian 14836285Sbrianstatic int ShowCommand(struct cmdargs const *); 14936285Sbrianstatic int TerminalCommand(struct cmdargs const *); 15036285Sbrianstatic int QuitCommand(struct cmdargs const *); 15136285Sbrianstatic int OpenCommand(struct cmdargs const *); 15236285Sbrianstatic int CloseCommand(struct cmdargs const *); 15336285Sbrianstatic int DownCommand(struct cmdargs const *); 15436285Sbrianstatic int SetCommand(struct cmdargs const *); 15536285Sbrianstatic int LinkCommand(struct cmdargs const *); 15636285Sbrianstatic int AddCommand(struct cmdargs const *); 15736285Sbrianstatic int DeleteCommand(struct cmdargs const *); 15836285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 15936934Sbrianstatic int ClearCommand(struct cmdargs const *); 16040561Sbrianstatic int RunListCommand(struct cmdargs const *); 16140561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 16240561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 16340561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 16440679Sbrianstatic int SetProcTitle(struct cmdargs const *); 16531343Sbrian#ifndef NOALIAS 16636285Sbrianstatic int AliasEnable(struct cmdargs const *); 16736285Sbrianstatic int AliasOption(struct cmdargs const *); 16831343Sbrian#endif 1696059Samurai 17036285Sbrianstatic const char * 17136285Sbrianshowcx(struct cmdtab const *cmd) 17236285Sbrian{ 17336285Sbrian if (cmd->lauth & LOCAL_CX) 17436285Sbrian return "(c)"; 17536285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 17636285Sbrian return "(o)"; 17736285Sbrian 17836285Sbrian return ""; 17936285Sbrian} 18036285Sbrian 1816059Samuraistatic int 18231343SbrianHelpCommand(struct cmdargs const *arg) 1836059Samurai{ 18428679Sbrian struct cmdtab const *cmd; 18536285Sbrian int n, cmax, dmax, cols, cxlen; 18636285Sbrian const char *cx; 1876059Samurai 18836285Sbrian if (!arg->prompt) { 18936285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 19026516Sbrian return 0; 19136285Sbrian } 19226516Sbrian 19336285Sbrian if (arg->argc > arg->argn) { 19436285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 19536285Sbrian if ((cmd->lauth & arg->prompt->auth) && 19636285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 19736285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 19836285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 19928679Sbrian return 0; 2006059Samurai } 20126516Sbrian return -1; 2026059Samurai } 20336285Sbrian 20431372Sbrian cmax = dmax = 0; 20536285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 20636285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 20736285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 20831372Sbrian cmax = n; 20931372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 21031372Sbrian dmax = n; 21131372Sbrian } 21231372Sbrian 21331372Sbrian cols = 80 / (dmax + cmax + 3); 2146059Samurai n = 0; 21536285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 21636285Sbrian " (c) = Context required\n"); 21736285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 21836285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 21936285Sbrian cx = showcx(cmd); 22036285Sbrian cxlen = cmax - strlen(cmd->name); 22140482Sbrian if (n % cols != 0) 22240482Sbrian prompt_Printf(arg->prompt, " "); 22340482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 22436285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 22531372Sbrian if (++n % cols == 0) 22636285Sbrian prompt_Printf(arg->prompt, "\n"); 2276059Samurai } 22831372Sbrian if (n % cols != 0) 22936285Sbrian prompt_Printf(arg->prompt, "\n"); 23026516Sbrian 23126516Sbrian return 0; 2326059Samurai} 2336059Samurai 23436285Sbrianstatic int 23536285SbrianCloneCommand(struct cmdargs const *arg) 2366059Samurai{ 23736285Sbrian char namelist[LINE_LEN]; 23836285Sbrian char *name; 23936285Sbrian int f; 2406059Samurai 24136285Sbrian if (arg->argc == arg->argn) 24236285Sbrian return -1; 24336285Sbrian 24436285Sbrian namelist[sizeof namelist - 1] = '\0'; 24536285Sbrian for (f = arg->argn; f < arg->argc; f++) { 24636285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 24736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 24836285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2496059Samurai } 25036285Sbrian 25136285Sbrian return 0; 2526059Samurai} 2536059Samurai 2546059Samuraistatic int 25536285SbrianRemoveCommand(struct cmdargs const *arg) 2566059Samurai{ 25736285Sbrian if (arg->argc != arg->argn) 25836285Sbrian return -1; 25911336Samurai 26036285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 26136285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 26236285Sbrian return 2; 2636059Samurai } 26426516Sbrian 26536285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 26636285Sbrian return 0; 26736285Sbrian} 26832711Sbrian 26936285Sbrianstatic int 27036285SbrianRenameCommand(struct cmdargs const *arg) 27136285Sbrian{ 27236285Sbrian if (arg->argc != arg->argn + 1) 27336285Sbrian return -1; 27431121Sbrian 27536285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 27636285Sbrian return 0; 27736285Sbrian 27836285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 27936285Sbrian arg->cx->name, arg->argv[arg->argn]); 28036285Sbrian return 1; 28136285Sbrian} 28236285Sbrian 28336285Sbrianint 28436285SbrianLoadCommand(struct cmdargs const *arg) 28536285Sbrian{ 28640797Sbrian const char *err; 28740797Sbrian int n, mode; 28836285Sbrian 28940797Sbrian mode = arg->bundle->phys_type.all; 29036285Sbrian 29140797Sbrian if (arg->argn < arg->argc) { 29240797Sbrian for (n = arg->argn; n < arg->argc; n++) 29340797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 29440797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 29540797Sbrian return 1; 29640797Sbrian } 29740797Sbrian 29840797Sbrian for (n = arg->argn; n < arg->argc; n++) { 29940797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 30040797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 30140797Sbrian } 30240797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 30340797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 30440797Sbrian log_Printf(LogWARN, "default: %s\n", err); 30536285Sbrian return 1; 30636285Sbrian } else { 30740797Sbrian bundle_SetLabel(arg->bundle, "default"); 30840797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 30940797Sbrian bundle_SetLabel(arg->bundle, "default"); 31036285Sbrian } 31140797Sbrian 31226516Sbrian return 0; 3136059Samurai} 3146059Samurai 31536285Sbrianint 31636285SbrianSaveCommand(struct cmdargs const *arg) 31736285Sbrian{ 31836285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 31936285Sbrian return 1; 32036285Sbrian} 32136285Sbrian 32210528Samuraistatic int 32336285SbrianDialCommand(struct cmdargs const *arg) 32428536Sbrian{ 32536285Sbrian int res; 32636285Sbrian 32736465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 32836465Sbrian || (!arg->cx && 32936928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 33036285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 33136285Sbrian " interactive links\n"); 33236285Sbrian return 1; 33334536Sbrian } 33436285Sbrian 33536285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 33636285Sbrian return res; 33736285Sbrian 33837993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 33936285Sbrian 34036285Sbrian return 0; 34128536Sbrian} 34228536Sbrian 34338628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 34438628Sbrian 34538628Sbrianstatic char * 34638628Sbrianstrstrword(char *big, const char *little) 34738628Sbrian{ 34838628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 34938628Sbrian char *pos; 35038628Sbrian int len; 35138628Sbrian 35238628Sbrian pos = big; 35338628Sbrian len = strlen(little); 35438628Sbrian 35538628Sbrian while ((pos = strstr(pos, little)) != NULL) 35638628Sbrian if ((pos == big || !isinword(pos[-1])) && !isinword(pos[len])) 35738628Sbrian break; 35838628Sbrian else 35938628Sbrian pos++; 36038628Sbrian 36138628Sbrian return pos; 36238628Sbrian} 36338628Sbrian 36438628Sbrianstatic char * 36538628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 36638628Sbrian{ 36738628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 36838628Sbrian char *word, *ntgt; 36938628Sbrian int ltgt, loldstr, lnewstr, pos; 37038628Sbrian 37138628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 37238628Sbrian return tgt; 37338628Sbrian 37438628Sbrian ltgt = strlen(tgt) + 1; 37538628Sbrian loldstr = strlen(oldstr); 37638628Sbrian lnewstr = strlen(newstr); 37738628Sbrian do { 37838628Sbrian pos = word - tgt; 37938628Sbrian if (loldstr > lnewstr) 38038628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 38138628Sbrian if (loldstr != lnewstr) { 38238628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 38338628Sbrian if (ntgt == NULL) 38438628Sbrian break; /* Oh wonderful ! */ 38538628Sbrian word = ntgt + pos; 38638628Sbrian tgt = ntgt; 38738628Sbrian } 38838628Sbrian if (lnewstr > loldstr) 38938628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 39038628Sbrian bcopy(newstr, word, lnewstr); 39138628Sbrian } while ((word = strstrword(word, oldstr))); 39238628Sbrian 39338628Sbrian return tgt; 39438628Sbrian} 39538628Sbrian 39643888Sbrianvoid 39743888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 39847849Sbrian struct bundle *bundle, int inc0, pid_t pid) 39938628Sbrian{ 40038628Sbrian int arg; 40147849Sbrian char pidstr[12]; 40238628Sbrian 40341755Sbrian if (inc0) 40441755Sbrian arg = 0; /* Start at arg 0 */ 40541755Sbrian else { 40641755Sbrian nargv[0] = strdup(oargv[0]); 40741755Sbrian arg = 1; 40841755Sbrian } 40947849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 41041755Sbrian for (; arg < argc; arg++) { 41138629Sbrian nargv[arg] = strdup(oargv[arg]); 41238629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 41338628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 41438629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 41540561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 41638628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 41738629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 41838629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 41938629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 42038629Sbrian bundle->ncp.mp.peer.enddisc.address, 42138629Sbrian bundle->ncp.mp.peer.enddisc.len)); 42238629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 42338629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 42438629Sbrian bundle->ncp.mp.cfg.enddisc.address, 42538629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 42647849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 42738629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 42838628Sbrian } 42938628Sbrian nargv[arg] = NULL; 43038628Sbrian} 43138628Sbrian 43228536Sbrianstatic int 43331343SbrianShellCommand(struct cmdargs const *arg, int bg) 43410528Samurai{ 43510528Samurai const char *shell; 43647849Sbrian pid_t shpid, pid; 43720813Sjkh 43818856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 43926911Sbrian /* we're only allowed to shell when we run ppp interactively */ 44036285Sbrian if (arg->prompt && arg->prompt->owner) { 44136285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 44226516Sbrian return 1; 44310528Samurai } 44426911Sbrian#endif 44528679Sbrian 44636285Sbrian if (arg->argc == arg->argn) { 44736285Sbrian if (!arg->prompt) { 44836285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 44936285Sbrian " a config file\n"); 45028381Sbrian return 1; 45136285Sbrian } else if (arg->prompt->owner) { 45236285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 45336285Sbrian " a socket connection\n"); 45436285Sbrian return 1; 45528381Sbrian } else if (bg) { 45636285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 45728679Sbrian " the foreground mode\n"); 45828381Sbrian return 1; 45928381Sbrian } 46034536Sbrian } 46134536Sbrian 46247849Sbrian pid = getpid(); 46328679Sbrian if ((shpid = fork()) == 0) { 46436285Sbrian int i, fd; 46518531Sbde 46636285Sbrian if ((shell = getenv("SHELL")) == 0) 46736285Sbrian shell = _PATH_BSHELL; 46832017Sbrian 46936285Sbrian timer_TermService(); 47036285Sbrian 47136285Sbrian if (arg->prompt) 47236285Sbrian fd = arg->prompt->fd_out; 47336285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 47436285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 47536285Sbrian _PATH_DEVNULL, strerror(errno)); 47628679Sbrian exit(1); 47728679Sbrian } 47828679Sbrian for (i = 0; i < 3; i++) 47928679Sbrian dup2(fd, i); 48026516Sbrian 48136285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 48226516Sbrian 48331061Sbrian setuid(geteuid()); 48436285Sbrian if (arg->argc > arg->argn) { 48528679Sbrian /* substitute pseudo args */ 48638628Sbrian char *argv[MAXARGS]; 48738628Sbrian int argc = arg->argc - arg->argn; 48838628Sbrian 48938628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 49038628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 49138628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 49231343Sbrian } 49347849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 49428679Sbrian if (bg) { 49528679Sbrian pid_t p; 49610528Samurai 49728679Sbrian p = getpid(); 49828679Sbrian if (daemon(1, 1) == -1) { 49936832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 50028679Sbrian exit(1); 50128679Sbrian } 50236285Sbrian } else if (arg->prompt) 50336285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 50431343Sbrian execvp(argv[0], argv); 50530316Sbrian } else { 50636285Sbrian if (arg->prompt) 50732017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 50836285Sbrian prompt_TtyOldMode(arg->prompt); 50931343Sbrian execl(shell, shell, NULL); 51030316Sbrian } 51120813Sjkh 51240665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 51340665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 51440665Sbrian strerror(errno)); 51528679Sbrian exit(255); 51610528Samurai } 51736285Sbrian 51836285Sbrian if (shpid == (pid_t) - 1) 51936285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 52036285Sbrian else { 52110528Samurai int status; 52231343Sbrian waitpid(shpid, &status, 0); 52310528Samurai } 52420813Sjkh 52536285Sbrian if (arg->prompt && !arg->prompt->owner) 52636285Sbrian prompt_TtyCommandMode(arg->prompt); 52720813Sjkh 52836285Sbrian return 0; 52910528Samurai} 53010528Samurai 53131343Sbrianstatic int 53231343SbrianBgShellCommand(struct cmdargs const *arg) 53331343Sbrian{ 53436285Sbrian if (arg->argc == arg->argn) 53531343Sbrian return -1; 53631343Sbrian return ShellCommand(arg, 1); 53731343Sbrian} 53831343Sbrian 53931343Sbrianstatic int 54031343SbrianFgShellCommand(struct cmdargs const *arg) 54131343Sbrian{ 54231343Sbrian return ShellCommand(arg, 0); 54331343Sbrian} 54431343Sbrian 54540561Sbrian#ifndef NOALIAS 54640561Sbrianstatic struct cmdtab const AliasCommands[] = 54740561Sbrian{ 54840561Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 54940561Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 55040561Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 55140561Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 55240561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 55340561Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 55440561Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 55540561Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 55640561Sbrian "log aliasing link creation", "alias log [yes|no]", 55740561Sbrian (const void *) PKT_ALIAS_LOG}, 55845042Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, "port redirection", 55945042Sbrian "alias port proto localaddr:port[-port] aliasport[-aliasport]"}, 56044557Sbrian {"pptp", NULL, alias_Pptp, LOCAL_AUTH, 56144557Sbrian "Set the PPTP address", "alias pptp IP"}, 56244547Sbrian {"proxy", NULL, alias_ProxyRule, LOCAL_AUTH, 56344547Sbrian "proxy control", "alias proxy server host[:port] ..."}, 56440561Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 56540561Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 56640561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 56740561Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 56840561Sbrian "alias unregistered (private) IP address space only", 56940561Sbrian "alias unregistered_only [yes|no]", 57040561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 57140561Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 57240561Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 57340561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 57440561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 57540561Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 57640561Sbrian {NULL, NULL, NULL}, 57740561Sbrian}; 57840561Sbrian#endif 57940561Sbrian 58040561Sbrianstatic struct cmdtab const AllowCommands[] = { 58140561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 58240561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 58340561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 58440561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 58540561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 58640561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 58740561Sbrian {NULL, NULL, NULL}, 58840561Sbrian}; 58940561Sbrian 59040561Sbrianstatic struct cmdtab const IfaceCommands[] = 59140561Sbrian{ 59240561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 59340561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 59440561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 59540561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 59640561Sbrian (void *)1}, 59740561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 59840561Sbrian "Clear iface address(es)", "iface clear"}, 59940561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 60040561Sbrian "Delete iface address", "iface delete addr", NULL}, 60140561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 60240561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 60340561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 60440561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 60540561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 60640561Sbrian "Show iface address(es)", "iface show"}, 60740561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 60840561Sbrian "Display this message", "alias help|? [command]", IfaceCommands}, 60940561Sbrian {NULL, NULL, NULL}, 61040561Sbrian}; 61140561Sbrian 61230715Sbrianstatic struct cmdtab const Commands[] = { 61336285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61428679Sbrian "accept option request", "accept option .."}, 61528679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 61632109Sbrian "add route", "add dest mask gateway", NULL}, 61736285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 61832109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 61936285Sbrian#ifndef NOALIAS 62040561Sbrian {"alias", NULL, RunListCommand, LOCAL_AUTH, 62140561Sbrian "alias control", "alias option [yes|no]", AliasCommands}, 62236285Sbrian#endif 62340561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 62440561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 62528679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 62631372Sbrian "Run a background command", "[!]bg command"}, 62736934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 62846686Sbrian "Clear throughput statistics", 62946686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 63036285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 63136285Sbrian "Clone a link", "clone newname..."}, 63236285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63336285Sbrian "Close an FSM", "close [lcp|ccp]"}, 63428679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 63532109Sbrian "delete route", "delete dest", NULL}, 63636285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 63732109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 63836285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63928679Sbrian "Deny option request", "deny option .."}, 64036285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64140797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 64236285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64328679Sbrian "Disable option", "disable option .."}, 64436285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64546686Sbrian "Generate a down event", "down [ccp|lcp]"}, 64636285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64728679Sbrian "Enable option", "enable option .."}, 64840561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 64940561Sbrian "interface control", "iface option ...", IfaceCommands}, 65036285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 65136285Sbrian "Link specific commands", "link name command ..."}, 65237008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65340797Sbrian "Load settings", "load [system ...]"}, 65436285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65537955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 65636285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 65736285Sbrian "Password for manipulation", "passwd LocalPassword"}, 65836285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 65936285Sbrian "Quit PPP program", "quit|bye [all]"}, 66036285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 66136285Sbrian "Remove a link", "remove"}, 66236285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 66336285Sbrian "Rename a link", "rename name"}, 66428679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 66528679Sbrian "Save settings", "save"}, 66636285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66728679Sbrian "Set parameters", "set[up] var value"}, 66828679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 66928679Sbrian "Run a subshell", "shell|! [sh command]"}, 67036285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67131372Sbrian "Show status and stats", "show var"}, 67236285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 67331372Sbrian "Enter terminal mode", "term"}, 67428679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 67531343Sbrian "Display this message", "help|? [command]", Commands}, 67628679Sbrian {NULL, NULL, NULL}, 6776059Samurai}; 6786059Samurai 67928536Sbrianstatic int 68031343SbrianShowEscape(struct cmdargs const *arg) 6816059Samurai{ 68236285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 68336285Sbrian int code, bit; 68436285Sbrian const char *sep = ""; 6856059Samurai 68626516Sbrian for (code = 0; code < 32; code++) 68736285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 68828679Sbrian for (bit = 0; bit < 8; bit++) 68936285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 69036285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 69136285Sbrian sep = ", "; 69236285Sbrian } 69336285Sbrian prompt_Printf(arg->prompt, "\n"); 6946059Samurai } 69531077Sbrian return 0; 6966059Samurai} 6976059Samurai 69828679Sbrianstatic int 69936285SbrianShowTimerList(struct cmdargs const *arg) 7006059Samurai{ 70136285Sbrian timer_Show(0, arg->prompt); 70231077Sbrian return 0; 7036059Samurai} 7046059Samurai 70528679Sbrianstatic int 70631343SbrianShowStopped(struct cmdargs const *arg) 70728327Sbrian{ 70836285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 70936285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 71036285Sbrian prompt_Printf(arg->prompt, "Disabled"); 71128327Sbrian else 71236285Sbrian prompt_Printf(arg->prompt, "%ld secs", 71336285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 71428461Sbrian 71536285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 71636285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 71736285Sbrian prompt_Printf(arg->prompt, "Disabled"); 71828461Sbrian else 71936285Sbrian prompt_Printf(arg->prompt, "%ld secs", 72036285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 72128461Sbrian 72236285Sbrian prompt_Printf(arg->prompt, "\n"); 72328461Sbrian 72431077Sbrian return 0; 72528327Sbrian} 72628327Sbrian 72728679Sbrianstatic int 72831343SbrianShowVersion(struct cmdargs const *arg) 7296059Samurai{ 73036285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 73131077Sbrian return 0; 7326059Samurai} 7336059Samurai 73428679Sbrianstatic int 73536285SbrianShowProtocolStats(struct cmdargs const *arg) 73626326Sbrian{ 73736285Sbrian struct link *l = command_ChooseLink(arg); 73826326Sbrian 73936285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 74036285Sbrian link_ReportProtocolStatus(l, arg->prompt); 74131077Sbrian return 0; 74226326Sbrian} 74326326Sbrian 74430715Sbrianstatic struct cmdtab const ShowCommands[] = { 74536285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 74636285Sbrian "bundle details", "show bundle"}, 74736285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 74836285Sbrian "CCP status", "show cpp"}, 74936285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 75036285Sbrian "VJ compression stats", "show compress"}, 75136285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 75236285Sbrian "escape characters", "show escape"}, 75336285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 75436285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 75536285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 75636285Sbrian "HDLC errors", "show hdlc"}, 75740561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 75840561Sbrian "Interface status", "show iface"}, 75936285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 76036285Sbrian "IPCP status", "show ipcp"}, 76147211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 76247211Sbrian "Protocol layers", "show layers"}, 76336285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 76436285Sbrian "LCP status", "show lcp"}, 76536285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 76636285Sbrian "(high-level) link info", "show link"}, 76736285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 76836285Sbrian "available link names", "show links"}, 76936285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 77036285Sbrian "log levels", "show log"}, 77136285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 77236285Sbrian "mbuf allocations", "show mem"}, 77346686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 77446686Sbrian "(low-level) link info", "show physical"}, 77536285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 77636285Sbrian "multilink setup", "show mp"}, 77736285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 77836285Sbrian "protocol summary", "show proto"}, 77936285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 78036285Sbrian "routing table", "show route"}, 78136285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 78236285Sbrian "STOPPED timeout", "show stopped"}, 78336285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 78436285Sbrian "alarm timers", "show timers"}, 78528679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 78636285Sbrian "version string", "show version"}, 78736285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 78836285Sbrian "client list", "show who"}, 78928679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 79031343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 79128679Sbrian {NULL, NULL, NULL}, 7926059Samurai}; 7936059Samurai 79430715Sbrianstatic struct cmdtab const * 79531343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 7966059Samurai{ 79726516Sbrian int nmatch; 79826516Sbrian int len; 79928679Sbrian struct cmdtab const *found; 8006059Samurai 80126516Sbrian found = NULL; 80226516Sbrian len = strlen(str); 80326516Sbrian nmatch = 0; 8046059Samurai while (cmds->func) { 80525566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 80626516Sbrian if (cmds->name[len] == '\0') { 80728679Sbrian *pmatch = 1; 80828679Sbrian return cmds; 80926516Sbrian } 8106059Samurai nmatch++; 8116059Samurai found = cmds; 81228679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 81326516Sbrian if (cmds->alias[len] == '\0') { 81428679Sbrian *pmatch = 1; 81528679Sbrian return cmds; 81626516Sbrian } 8176059Samurai nmatch++; 8186059Samurai found = cmds; 8196059Samurai } 8206059Samurai cmds++; 8216059Samurai } 8226059Samurai *pmatch = nmatch; 82326516Sbrian return found; 8246059Samurai} 8256059Samurai 82636285Sbrianstatic const char * 82736285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 82836285Sbrian{ 82936285Sbrian int f, tlen, len; 83036285Sbrian 83136285Sbrian tlen = 0; 83236285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 83336285Sbrian if (f) 83436285Sbrian tgt[tlen++] = ' '; 83536285Sbrian len = strlen(argv[f]); 83636285Sbrian if (len > sz - tlen - 1) 83736285Sbrian len = sz - tlen - 1; 83836285Sbrian strncpy(tgt+tlen, argv[f], len); 83936285Sbrian tlen += len; 84036285Sbrian } 84136285Sbrian tgt[tlen] = '\0'; 84236285Sbrian return tgt; 84336285Sbrian} 84436285Sbrian 84530715Sbrianstatic int 84636285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 84736285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8486059Samurai{ 84928679Sbrian struct cmdtab const *cmd; 8506059Samurai int val = 1; 8516059Samurai int nmatch; 85231343Sbrian struct cmdargs arg; 85336285Sbrian char prefix[100]; 8546059Samurai 85536285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8566059Samurai if (nmatch > 1) 85736285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 85836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 85936285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 86036285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 86136285Sbrian /* We've got no context, but we require it */ 86236285Sbrian cx = bundle2datalink(bundle, NULL); 86336285Sbrian 86436285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 86536285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 86636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 86736285Sbrian else { 86836285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 86936285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 87036285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 87136285Sbrian cx = NULL; 87236285Sbrian } 87336285Sbrian arg.cmdtab = cmds; 87436285Sbrian arg.cmd = cmd; 87536285Sbrian arg.argc = argc; 87636285Sbrian arg.argn = argn+1; 87736285Sbrian arg.argv = argv; 87836285Sbrian arg.bundle = bundle; 87936285Sbrian arg.cx = cx; 88036285Sbrian arg.prompt = prompt; 88136285Sbrian val = (*cmd->func) (&arg); 88236285Sbrian } 88331343Sbrian } else 88436285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 88536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 88626516Sbrian 88726516Sbrian if (val == -1) 88836285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 88928679Sbrian else if (val) 89036285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 89136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 89226516Sbrian 89326516Sbrian return val; 8946059Samurai} 8956059Samurai 89637009Sbrianint 89737009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 8986059Samurai{ 8996059Samurai char *cp; 9006059Samurai 9016059Samurai if (nb > 0) { 9026059Samurai cp = buff + strcspn(buff, "\r\n"); 9036059Samurai if (cp) 9046059Samurai *cp = '\0'; 90537009Sbrian return MakeArgs(buff, argv, MAXARGS); 90637009Sbrian } 90737009Sbrian return 0; 90831121Sbrian} 9096059Samurai 91031822Sbrianstatic int 91131822Sbrianarghidden(int argc, char const *const *argv, int n) 91231822Sbrian{ 91331822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 91431828Sbrian 91531828Sbrian /* set authkey xxxxx */ 91631828Sbrian /* set key xxxxx */ 91731822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 91831822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 91931822Sbrian return 1; 92031822Sbrian 92131828Sbrian /* passwd xxxxx */ 92231828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 92331828Sbrian return 1; 92431828Sbrian 92536285Sbrian /* set server port xxxxx .... */ 92636285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 92736285Sbrian !strncasecmp(argv[1], "se", 2)) 92836285Sbrian return 1; 92936285Sbrian 93031822Sbrian return 0; 93131822Sbrian} 93231822Sbrian 93331121Sbrianvoid 93436285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 93537008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 93631121Sbrian{ 93731156Sbrian if (argc > 0) { 93836285Sbrian if (log_IsKept(LogCOMMAND)) { 93947844Sbrian char buf[LINE_LEN]; 94031156Sbrian int f, n; 94131156Sbrian 94231156Sbrian if (label) { 94331962Sbrian strncpy(buf, label, sizeof buf - 3); 94431962Sbrian buf[sizeof buf - 3] = '\0'; 94531156Sbrian strcat(buf, ": "); 94647844Sbrian n = strlen(buf); 94747844Sbrian } else { 94847844Sbrian *buf = '\0'; 94947844Sbrian n = 0; 95031156Sbrian } 95147844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 95247844Sbrian 95331156Sbrian for (f = 0; f < argc; f++) { 95431962Sbrian if (n < sizeof buf - 1 && f) 95531156Sbrian buf[n++] = ' '; 95631822Sbrian if (arghidden(argc, argv, f)) 95736285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 95831822Sbrian else 95931962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 96031156Sbrian n += strlen(buf+n); 96131156Sbrian } 96236285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 96331156Sbrian } 96437008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 96531156Sbrian } 9666059Samurai} 9676059Samurai 96831121Sbrianvoid 96936285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 97036285Sbrian const char *label) 97131121Sbrian{ 97231121Sbrian int argc; 97337009Sbrian char *argv[MAXARGS]; 97431121Sbrian 97537009Sbrian argc = command_Interpret(buff, nb, argv); 97637008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 97731121Sbrian} 97831121Sbrian 9796059Samuraistatic int 98031343SbrianShowCommand(struct cmdargs const *arg) 9816059Samurai{ 98236285Sbrian if (!arg->prompt) 98336285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 98436285Sbrian else if (arg->argc > arg->argn) 98536285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 98636285Sbrian arg->prompt, arg->cx); 9876059Samurai else 98836285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 98926516Sbrian 99026516Sbrian return 0; 9916059Samurai} 9926059Samurai 9936059Samuraistatic int 99431343SbrianTerminalCommand(struct cmdargs const *arg) 9956059Samurai{ 99636285Sbrian if (!arg->prompt) { 99736285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 99826516Sbrian return 1; 9996059Samurai } 100036285Sbrian 100136285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 100236285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 100336285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 100436285Sbrian return 1; 10056059Samurai } 100636285Sbrian 100736285Sbrian datalink_Up(arg->cx, 0, 0); 100836285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 100936285Sbrian return 0; 10106059Samurai} 10116059Samurai 10126059Samuraistatic int 101331343SbrianQuitCommand(struct cmdargs const *arg) 10146059Samurai{ 101536285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 101636285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 101736285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 101836285Sbrian Cleanup(EX_NORMAL); 101936285Sbrian if (arg->prompt) 102036285Sbrian prompt_Destroy(arg->prompt, 1); 102126516Sbrian 102226516Sbrian return 0; 10236059Samurai} 10246059Samurai 10256059Samuraistatic int 102636285SbrianOpenCommand(struct cmdargs const *arg) 10276059Samurai{ 102837160Sbrian if (arg->argc == arg->argn) 102937993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 103037160Sbrian else if (arg->argc == arg->argn + 1) { 103137160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 103237385Sbrian struct datalink *cx = arg->cx ? 103337385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 103437385Sbrian if (cx) { 103537385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 103637385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 103737160Sbrian else 103837993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 103937160Sbrian } else 104037160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 104137160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 104237160Sbrian struct fsm *fp; 10436059Samurai 104437210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 104537160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 104637160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 104737160Sbrian else if (fp->state == ST_OPENED) 104837160Sbrian fsm_Reopen(fp); 104937160Sbrian else { 105037160Sbrian fp->open_mode = 0; /* Not passive any more */ 105137160Sbrian if (fp->state == ST_STOPPED) { 105237160Sbrian fsm_Down(fp); 105337160Sbrian fsm_Up(fp); 105437160Sbrian } else { 105537160Sbrian fsm_Up(fp); 105637160Sbrian fsm_Open(fp); 105737160Sbrian } 105836285Sbrian } 105937160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 106037160Sbrian if (arg->cx) 106137160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 106237160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 106337160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 106437160Sbrian else 106537993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 106637160Sbrian } else 106737160Sbrian return -1; 106836285Sbrian } else 106936285Sbrian return -1; 107036285Sbrian 107126516Sbrian return 0; 10726059Samurai} 10736059Samurai 107425067Sbrianstatic int 107536285SbrianCloseCommand(struct cmdargs const *arg) 10766059Samurai{ 107737007Sbrian if (arg->argc == arg->argn) 107837007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 107937007Sbrian else if (arg->argc == arg->argn + 1) { 108037007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 108137007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 108237007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 108337007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 108437007Sbrian struct fsm *fp; 10856059Samurai 108637210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 108737007Sbrian if (fp->state == ST_OPENED) { 108837007Sbrian fsm_Close(fp); 108937007Sbrian if (arg->argv[arg->argn][3] == '!') 109037007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 109137007Sbrian else 109237007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 109337007Sbrian } 109437007Sbrian } else 109536285Sbrian return -1; 109636285Sbrian } else 109736285Sbrian return -1; 109836285Sbrian 109936285Sbrian return 0; 11006059Samurai} 11016059Samurai 110225067Sbrianstatic int 110336285SbrianDownCommand(struct cmdargs const *arg) 110411336Samurai{ 110537018Sbrian if (arg->argc == arg->argn) { 110637018Sbrian if (arg->cx) 110737018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 110837018Sbrian else 110937018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 111037018Sbrian } else if (arg->argc == arg->argn + 1) { 111137018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 111237018Sbrian if (arg->cx) 111337018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 111437018Sbrian else 111537018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 111637018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 111737018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 111837018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 111937060Sbrian fsm2initial(fp); 112037018Sbrian } else 112137018Sbrian return -1; 112236285Sbrian } else 112336285Sbrian return -1; 112436285Sbrian 112536285Sbrian return 0; 112625067Sbrian} 112725067Sbrian 112825067Sbrianstatic int 112936285SbrianSetModemSpeed(struct cmdargs const *arg) 113025067Sbrian{ 113136285Sbrian long speed; 113236285Sbrian char *end; 113311336Samurai 113436285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 113536285Sbrian if (arg->argc > arg->argn+1) { 113636285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 113736285Sbrian return -1; 113811336Samurai } 113936285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 114036285Sbrian physical_SetSync(arg->cx->physical); 114136285Sbrian return 0; 114236285Sbrian } 114336285Sbrian end = NULL; 114436285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 114536285Sbrian if (*end) { 114636285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 114736285Sbrian arg->argv[arg->argn]); 114836285Sbrian return -1; 114936285Sbrian } 115036285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 115136285Sbrian return 0; 115236285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 115336285Sbrian } else 115436285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 115524939Sbrian 115626516Sbrian return -1; 115711336Samurai} 115811336Samurai 115925067Sbrianstatic int 116031343SbrianSetStoppedTimeout(struct cmdargs const *arg) 116128327Sbrian{ 116236285Sbrian struct link *l = &arg->cx->physical->link; 116336285Sbrian 116436285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 116536285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 116636285Sbrian if (arg->argc <= arg->argn+2) { 116736285Sbrian if (arg->argc > arg->argn) { 116836285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 116936285Sbrian if (arg->argc > arg->argn+1) 117036285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 117128461Sbrian } 117228327Sbrian return 0; 117328327Sbrian } 117428327Sbrian return -1; 117528327Sbrian} 117628327Sbrian 117731081Sbrian#define ismask(x) \ 117831081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 117931081Sbrian 118028327Sbrianstatic int 118131343SbrianSetServer(struct cmdargs const *arg) 118226940Sbrian{ 118326940Sbrian int res = -1; 118426940Sbrian 118536285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 118631081Sbrian const char *port, *passwd, *mask; 118731081Sbrian 118831081Sbrian /* What's what ? */ 118936285Sbrian port = arg->argv[arg->argn]; 119036285Sbrian if (arg->argc == arg->argn + 2) { 119136285Sbrian passwd = arg->argv[arg->argn+1]; 119236285Sbrian mask = NULL; 119336285Sbrian } else if (arg->argc == arg->argn + 3) { 119436285Sbrian passwd = arg->argv[arg->argn+1]; 119536285Sbrian mask = arg->argv[arg->argn+2]; 119631081Sbrian if (!ismask(mask)) 119731081Sbrian return -1; 119836285Sbrian } else if (strcasecmp(port, "none") == 0) { 119936285Sbrian if (server_Close(arg->bundle)) 120036285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 120136285Sbrian return 0; 120231081Sbrian } else 120336285Sbrian return -1; 120431081Sbrian 120536285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 120636285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 120731081Sbrian 120836285Sbrian if (*port == '/') { 120931081Sbrian mode_t imask; 121036285Sbrian char *ptr, name[LINE_LEN + 12]; 121128679Sbrian 121231081Sbrian if (mask != NULL) { 121328679Sbrian unsigned m; 121428679Sbrian 121531081Sbrian if (sscanf(mask, "%o", &m) == 1) 121631081Sbrian imask = m; 121731081Sbrian else 121831081Sbrian return -1; 121931081Sbrian } else 122031081Sbrian imask = (mode_t)-1; 122136285Sbrian 122236285Sbrian ptr = strstr(port, "%d"); 122336285Sbrian if (ptr) { 122436285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 122537210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 122636285Sbrian port = name; 122736285Sbrian } 122836285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 122927346Sbrian } else { 123036285Sbrian int iport, add = 0; 123128679Sbrian 123231081Sbrian if (mask != NULL) 123331081Sbrian return -1; 123428679Sbrian 123536285Sbrian if (*port == '+') { 123636285Sbrian port++; 123736285Sbrian add = 1; 123836285Sbrian } 123931081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 124031081Sbrian struct servent *s; 124131081Sbrian 124231081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 124331081Sbrian iport = 0; 124436285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 124528679Sbrian } else 124631081Sbrian iport = ntohs(s->s_port); 124727346Sbrian } else 124831081Sbrian iport = atoi(port); 124936285Sbrian 125036285Sbrian if (iport) { 125136285Sbrian if (add) 125236285Sbrian iport += arg->bundle->unit; 125336285Sbrian res = server_TcpOpen(arg->bundle, iport); 125436285Sbrian } else 125536285Sbrian res = -1; 125627346Sbrian } 125731081Sbrian } 125826940Sbrian 125926940Sbrian return res; 126026940Sbrian} 126126940Sbrian 126226940Sbrianstatic int 126331343SbrianSetEscape(struct cmdargs const *arg) 12646059Samurai{ 12656059Samurai int code; 126636285Sbrian int argc = arg->argc - arg->argn; 126736285Sbrian char const *const *argv = arg->argv + arg->argn; 12686059Samurai 12696059Samurai for (code = 0; code < 33; code++) 127036285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 127131343Sbrian 12726059Samurai while (argc-- > 0) { 12736059Samurai sscanf(*argv++, "%x", &code); 12746059Samurai code &= 0xff; 127536285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 127636285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 12776059Samurai } 127826516Sbrian return 0; 12796059Samurai} 12806059Samurai 12816059Samuraistatic int 128231343SbrianSetInterfaceAddr(struct cmdargs const *arg) 12836059Samurai{ 128436285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 128532267Sbrian const char *hisaddr; 128632267Sbrian 128740561Sbrian if (arg->argc > arg->argn + 4) 128840561Sbrian return -1; 128940561Sbrian 129032267Sbrian hisaddr = NULL; 129144874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 129244874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 129336285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 129436285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 129536285Sbrian iplist_reset(&ipcp->cfg.peer_list); 129628394Sbrian 129736285Sbrian if (arg->argc > arg->argn) { 129843313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 129936285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 130036285Sbrian &ipcp->cfg.my_range.width)) 130128679Sbrian return 1; 130236285Sbrian if (arg->argc > arg->argn+1) { 130336285Sbrian hisaddr = arg->argv[arg->argn+1]; 130436285Sbrian if (arg->argc > arg->argn+2) { 130544455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 130636285Sbrian if (arg->argc > arg->argn+3) { 130736285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 130836285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 13099440Samurai } 13106059Samurai } 13116059Samurai } 13126059Samurai } 131328394Sbrian 131440561Sbrian /* 0.0.0.0 means any address (0 bits) */ 131536285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 131636285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 131736285Sbrian ipcp->cfg.my_range.width = 0; 13186059Samurai } 131936285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 132047648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 132136285Sbrian 132236285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 132336928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 132432267Sbrian return 4; 132531121Sbrian 132626516Sbrian return 0; 13276059Samurai} 13286059Samurai 132918752Sjkhstatic int 133044305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 133144305Sbrian u_int *maxtrm, int def) 133244305Sbrian{ 133344305Sbrian if (argc == 0) { 133444305Sbrian *timeout = DEF_FSMRETRY; 133544305Sbrian *maxreq = def; 133644305Sbrian if (maxtrm != NULL) 133744305Sbrian *maxtrm = def; 133844305Sbrian } else { 133944305Sbrian long l = atol(argv[0]); 134044305Sbrian 134144305Sbrian if (l < MIN_FSMRETRY) { 134244305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 134344305Sbrian l, MIN_FSMRETRY); 134444305Sbrian return 1; 134544305Sbrian } else 134644305Sbrian *timeout = l; 134744305Sbrian 134844305Sbrian if (argc > 1) { 134944305Sbrian l = atol(argv[1]); 135044305Sbrian if (l < 1) { 135144305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 135244305Sbrian l = 1; 135344305Sbrian } 135444305Sbrian *maxreq = l; 135544305Sbrian 135644305Sbrian if (argc > 2 && maxtrm != NULL) { 135744305Sbrian l = atol(argv[2]); 135844305Sbrian if (l < 1) { 135944305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 136044305Sbrian l = 1; 136144305Sbrian } 136244305Sbrian *maxtrm = l; 136344305Sbrian } 136444305Sbrian } 136544305Sbrian } 136644305Sbrian 136744305Sbrian return 0; 136844305Sbrian} 136944305Sbrian 137044305Sbrianstatic int 137131343SbrianSetVariable(struct cmdargs const *arg) 13726059Samurai{ 137337210Sbrian long long_val, param = (long)arg->cmd->args; 137437210Sbrian int mode, dummyint; 137531343Sbrian const char *argp; 137636285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 137736285Sbrian const char *err = NULL; 137836285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 137936285Sbrian struct in_addr dummyaddr, *addr; 13806059Samurai 138136285Sbrian if (arg->argc > arg->argn) 138236285Sbrian argp = arg->argv[arg->argn]; 138326551Sbrian else 138431343Sbrian argp = ""; 138526551Sbrian 138636285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 138736285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 138836285Sbrian arg->cmd->name); 138936285Sbrian return 1; 139036285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 139136285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 139236285Sbrian arg->cmd->name, cx->name); 139336285Sbrian cx = NULL; 139436285Sbrian } 139536285Sbrian 139626551Sbrian switch (param) { 139728679Sbrian case VAR_AUTHKEY: 139840622Sbrian switch (bundle_Phase(arg->bundle)) { 139940622Sbrian case PHASE_DEAD: 140040622Sbrian case PHASE_ESTABLISH: 140140622Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 140240622Sbrian sizeof arg->bundle->cfg.auth.key - 1); 140340622Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 140440622Sbrian break; 140540622Sbrian default: 140640622Sbrian err = "set authkey: Only available at phase DEAD/ESTABLISH\n"; 140740622Sbrian log_Printf(LogWARN, err); 140840622Sbrian break; 140936285Sbrian } 141028679Sbrian break; 141137210Sbrian 141228679Sbrian case VAR_AUTHNAME: 141340622Sbrian switch (bundle_Phase(arg->bundle)) { 141440622Sbrian case PHASE_DEAD: 141540622Sbrian case PHASE_ESTABLISH: 141640622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 141740622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 141840622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 141940622Sbrian break; 142040622Sbrian default: 142140622Sbrian err = "set authname: Only available at phase DEAD/ESTABLISH\n"; 142240622Sbrian log_Printf(LogWARN, err); 142340622Sbrian break; 142436285Sbrian } 142528679Sbrian break; 142637210Sbrian 142736285Sbrian case VAR_AUTOLOAD: 142836285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 142936285Sbrian arg->bundle->autoload.running = 1; 143036285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 143136285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 143236285Sbrian if (arg->argc == arg->argn + 4) { 143336285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 143436285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 143536285Sbrian } else { 143636285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 143736285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 143836285Sbrian } 143936285Sbrian } else { 144036285Sbrian err = "Set autoload requires two or four arguments\n"; 144136285Sbrian log_Printf(LogWARN, err); 144236285Sbrian } 144336285Sbrian break; 144437210Sbrian 144528679Sbrian case VAR_DIAL: 144636285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 144736285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 144828679Sbrian break; 144937210Sbrian 145028679Sbrian case VAR_LOGIN: 145136285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 145236285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 145328679Sbrian break; 145437210Sbrian 145536285Sbrian case VAR_WINSIZE: 145636285Sbrian if (arg->argc > arg->argn) { 145736285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 145836285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 145936285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 146036285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 146136285Sbrian l->ccp.cfg.deflate.out.winsize); 146236285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 146336285Sbrian } 146436285Sbrian if (arg->argc > arg->argn+1) { 146536285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 146636285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 146736285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 146836285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 146936285Sbrian l->ccp.cfg.deflate.in.winsize); 147036285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 147136285Sbrian } 147236285Sbrian } else 147336285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 147436285Sbrian } else { 147536285Sbrian err = "No window size specified\n"; 147636285Sbrian log_Printf(LogWARN, err); 147736285Sbrian } 147836285Sbrian break; 147937210Sbrian 148028679Sbrian case VAR_DEVICE: 148136285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 148236285Sbrian arg->argv + arg->argn); 148336285Sbrian break; 148437210Sbrian 148536285Sbrian case VAR_ACCMAP: 148636285Sbrian if (arg->argc > arg->argn) { 148737210Sbrian u_long ulong_val; 148836285Sbrian sscanf(argp, "%lx", &ulong_val); 148937210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 149036285Sbrian } else { 149136285Sbrian err = "No accmap specified\n"; 149236285Sbrian log_Printf(LogWARN, err); 149336285Sbrian } 149436285Sbrian break; 149537210Sbrian 149636285Sbrian case VAR_MODE: 149736285Sbrian mode = Nam2mode(argp); 149836285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 149936285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 150036285Sbrian return -1; 150136285Sbrian } 150236285Sbrian bundle_SetMode(arg->bundle, cx, mode); 150336285Sbrian break; 150437210Sbrian 150536285Sbrian case VAR_MRRU: 150640622Sbrian switch (bundle_Phase(arg->bundle)) { 150740622Sbrian case PHASE_DEAD: 150840622Sbrian break; 150940622Sbrian case PHASE_ESTABLISH: 151040622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 151140622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 151240622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 151340622Sbrian return 1; 151440622Sbrian } 151540622Sbrian break; 151640622Sbrian default: 151740622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 151840622Sbrian return 1; 151929696Sbrian } 152037210Sbrian long_val = atol(argp); 152137210Sbrian if (long_val && long_val < MIN_MRU) { 152237210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 152337210Sbrian return 1; 152437210Sbrian } else if (long_val > MAX_MRU) { 152537210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 152637210Sbrian return 1; 152737210Sbrian } else 152837210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 152928679Sbrian break; 153037210Sbrian 153136285Sbrian case VAR_MRU: 153237210Sbrian long_val = atol(argp); 153337210Sbrian if (long_val == 0) 153437210Sbrian l->lcp.cfg.mru = DEF_MRU; 153537210Sbrian else if (long_val < MIN_MRU) { 153637210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 153737210Sbrian return 1; 153837210Sbrian } else if (long_val > MAX_MRU) { 153937210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 154037210Sbrian return 1; 154137210Sbrian } else 154237210Sbrian l->lcp.cfg.mru = long_val; 154328679Sbrian break; 154437210Sbrian 154536285Sbrian case VAR_MTU: 154637210Sbrian long_val = atol(argp); 154737210Sbrian if (long_val && long_val < MIN_MTU) { 154837210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 154937210Sbrian return 1; 155037210Sbrian } else if (long_val > MAX_MTU) { 155137210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 155237210Sbrian return 1; 155337210Sbrian } else 155437210Sbrian arg->bundle->cfg.mtu = long_val; 155536285Sbrian break; 155637210Sbrian 155736285Sbrian case VAR_OPENMODE: 155836285Sbrian if (strcasecmp(argp, "active") == 0) 155936285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 156036285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 156136285Sbrian else if (strcasecmp(argp, "passive") == 0) 156236285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 156336285Sbrian else { 156436285Sbrian err = "%s: Invalid openmode\n"; 156536285Sbrian log_Printf(LogWARN, err, argp); 156636285Sbrian } 156736285Sbrian break; 156837210Sbrian 156928679Sbrian case VAR_PHONE: 157036285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 157136285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 157238174Sbrian cx->phone.alt = cx->phone.next = NULL; 157328679Sbrian break; 157437210Sbrian 157528679Sbrian case VAR_HANGUP: 157636285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 157736285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 157828679Sbrian break; 157937210Sbrian 158036285Sbrian case VAR_IDLETIMEOUT: 158136285Sbrian if (arg->argc > arg->argn+1) 158236285Sbrian err = "Too many idle timeout values\n"; 158336285Sbrian else if (arg->argc == arg->argn+1) 158436285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 158536285Sbrian if (err) 158636285Sbrian log_Printf(LogWARN, err); 158729549Sbrian break; 158837210Sbrian 158936285Sbrian case VAR_LQRPERIOD: 159037210Sbrian long_val = atol(argp); 159137210Sbrian if (long_val < MIN_LQRPERIOD) { 159237210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 159337210Sbrian long_val, MIN_LQRPERIOD); 159437210Sbrian return 1; 159536285Sbrian } else 159637210Sbrian l->lcp.cfg.lqrperiod = long_val; 159736285Sbrian break; 159837210Sbrian 159936285Sbrian case VAR_LCPRETRY: 160044305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 160144305Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 160244305Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 160344305Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 160436285Sbrian break; 160537210Sbrian 160636285Sbrian case VAR_CHAPRETRY: 160744305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 160844305Sbrian &cx->chap.auth.cfg.fsm.timeout, 160944305Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 161036285Sbrian break; 161137210Sbrian 161236285Sbrian case VAR_PAPRETRY: 161344305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 161444305Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 161544305Sbrian NULL, DEF_FSMAUTHTRIES); 161636285Sbrian break; 161737210Sbrian 161836285Sbrian case VAR_CCPRETRY: 161944305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 162044305Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 162144305Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 162236285Sbrian break; 162337210Sbrian 162436285Sbrian case VAR_IPCPRETRY: 162544305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 162644305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 162744305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 162844305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 162936285Sbrian break; 163037210Sbrian 163136285Sbrian case VAR_NBNS: 163236285Sbrian case VAR_DNS: 163336285Sbrian if (param == VAR_DNS) 163436285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 163536285Sbrian else 163636285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 163736285Sbrian 163836285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 163936285Sbrian 164036285Sbrian if (arg->argc > arg->argn) { 164143313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 164236285Sbrian addr, &dummyaddr, &dummyint); 164336285Sbrian if (arg->argc > arg->argn+1) 164443313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 164536285Sbrian addr + 1, &dummyaddr, &dummyint); 164636285Sbrian 164736285Sbrian if (addr[1].s_addr == INADDR_ANY) 164836285Sbrian addr[1].s_addr = addr[0].s_addr; 164936285Sbrian if (addr[0].s_addr == INADDR_ANY) 165036285Sbrian addr[0].s_addr = addr[1].s_addr; 165136285Sbrian } 165236285Sbrian break; 165338174Sbrian 165438174Sbrian case VAR_CALLBACK: 165538174Sbrian cx->cfg.callback.opmask = 0; 165638174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 165738174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 165838174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 165938174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 166038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 166138174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 166238174Sbrian if (dummyint == arg->argc - 1) 166338174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 166438174Sbrian else { 166538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 166638174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 166738174Sbrian sizeof cx->cfg.callback.msg - 1); 166838174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 166938174Sbrian } 167038174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 167138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 167238174Sbrian else 167338174Sbrian return -1; 167438174Sbrian } 167538174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 167638174Sbrian cx->cfg.callback.opmask = 0; 167738174Sbrian break; 167838174Sbrian 167938174Sbrian case VAR_CBCP: 168038174Sbrian cx->cfg.cbcp.delay = 0; 168138174Sbrian *cx->cfg.cbcp.phone = '\0'; 168238174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 168338174Sbrian if (arg->argc > arg->argn) { 168438174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 168538174Sbrian sizeof cx->cfg.cbcp.phone - 1); 168638174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 168738174Sbrian if (arg->argc > arg->argn + 1) { 168838174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 168938174Sbrian if (arg->argc > arg->argn + 2) { 169038174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 169138174Sbrian if (long_val < MIN_FSMRETRY) 169238174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 169338174Sbrian long_val, MIN_FSMRETRY); 169438174Sbrian else 169538174Sbrian cx->cfg.cbcp.fsmretry = long_val; 169638174Sbrian } 169738174Sbrian } 169838174Sbrian } 169938174Sbrian break; 170038544Sbrian 170138544Sbrian case VAR_CHOKED: 170238544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 170338544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 170438544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 170538544Sbrian break; 170640665Sbrian 170740665Sbrian case VAR_SENDPIPE: 170840665Sbrian long_val = atol(argp); 170940665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 171040665Sbrian break; 171140665Sbrian 171240665Sbrian case VAR_RECVPIPE: 171340665Sbrian long_val = atol(argp); 171440665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 171540665Sbrian break; 171643313Sbrian 171743313Sbrian#ifndef NORADIUS 171843313Sbrian case VAR_RADIUS: 171943313Sbrian if (!*argp) 172043313Sbrian *arg->bundle->radius.cfg.file = '\0'; 172143313Sbrian else if (access(argp, R_OK)) { 172243313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 172343313Sbrian return 1; 172443313Sbrian } else { 172543313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 172643313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 172743313Sbrian arg->bundle->radius.cfg.file 172843313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 172943313Sbrian } 173043313Sbrian break; 173143313Sbrian#endif 173244073Sbrian 173344073Sbrian case VAR_CD: 173444073Sbrian if (*argp) { 173544073Sbrian long_val = atol(argp); 173644073Sbrian if (long_val < 0) 173744073Sbrian long_val = 0; 173844073Sbrian cx->physical->cfg.cd.delay = long_val; 173944073Sbrian cx->physical->cfg.cd.required = argp[strlen(argp)-1] == '!'; 174044073Sbrian } else { 174144073Sbrian cx->physical->cfg.cd.delay = DEF_CDDELAY; 174244073Sbrian cx->physical->cfg.cd.required = 0; 174344073Sbrian } 174444073Sbrian break; 174536285Sbrian 174646686Sbrian case VAR_PARITY: 174746686Sbrian if (arg->argc == arg->argn + 1) 174846686Sbrian return physical_SetParity(arg->cx->physical, argp); 174946686Sbrian else { 175046686Sbrian err = "Parity value must be odd, even or none\n"; 175146686Sbrian log_Printf(LogWARN, err); 175246686Sbrian } 175346686Sbrian break; 17546059Samurai 175546686Sbrian case VAR_CRTSCTS: 175646686Sbrian if (strcasecmp(argp, "on") == 0) 175736285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 175846686Sbrian else if (strcasecmp(argp, "off") == 0) 175936285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 176046686Sbrian else { 176146686Sbrian err = "RTS/CTS value must be on or off\n"; 176246686Sbrian log_Printf(LogWARN, err); 176346686Sbrian } 176446686Sbrian break; 176520812Sjkh } 176646686Sbrian 176746686Sbrian return err ? 1 : 0; 176820812Sjkh} 176920812Sjkh 177030715Sbrianstatic struct cmdtab const SetCommands[] = { 177136285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 177236285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 177328679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 177436285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 177528679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 177636285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 177736285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 177836285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 177936285Sbrian (const void *)VAR_AUTOLOAD}, 178038174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 178138174Sbrian "callback control", "set callback [none|auth|cbcp|" 178238174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 178338174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 178438174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 178538174Sbrian (const void *)VAR_CBCP}, 178644305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 178744305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 178844073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 178944073Sbrian "set cd value[!]", (const void *)VAR_CD}, 179044305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 179144305Sbrian "CHAP retries", "set chapretry value [attempts]", 179244305Sbrian (const void *)VAR_CHAPRETRY}, 179338544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 179438544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 179546686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 179646686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 179746686Sbrian (const char *)VAR_CRTSCTS}, 179836285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 179936285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 180036285Sbrian (const void *) VAR_WINSIZE}, 180136285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 180246686Sbrian "physical device name", "set device|line device-name[,device-name]", 180336285Sbrian (const void *) VAR_DEVICE}, 180436285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 180536285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 180636285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 180736285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 180836285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 180936285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 181036285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 181136285Sbrian "escape characters", "set escape hex-digit ..."}, 181236285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 181336285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 181436285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 181536285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 181636285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 181736285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 181836285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 181931343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 182044305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 182144305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 182244305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 182344305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 182436712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 182538622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 182647699Sbrian "ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 182736285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 182836285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 182936285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 183036285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 183136285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 183236285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 183336285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 183436285Sbrian "set mrru value", (const void *)VAR_MRRU}, 183536285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 183636285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 183736285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 183836285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 183936285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 184036285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 184136285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 184236285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 184344305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 184444305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 184546686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 184646686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 184736285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 184836285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 184940679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 185040679Sbrian "Process title", "set proctitle [value]"}, 185143313Sbrian#ifndef NORADIUS 185243313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 185343313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 185443313Sbrian#endif 185536285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 185636285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 185740665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 185840665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 185936285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 186044468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 186140665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 186240665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 186328679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 186436774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 186536285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 186646686Sbrian "physical speed", "set speed value|sync"}, 186736285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 186836285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 186936285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 187036285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 187136285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 187236285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 187336285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 187436285Sbrian "datalink weighting", "set weight n"}, 187528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 187631343Sbrian "Display this message", "set help|? [command]", SetCommands}, 187728679Sbrian {NULL, NULL, NULL}, 18786059Samurai}; 18796059Samurai 18806059Samuraistatic int 188131343SbrianSetCommand(struct cmdargs const *arg) 18826059Samurai{ 188336285Sbrian if (arg->argc > arg->argn) 188436285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 188536285Sbrian arg->prompt, arg->cx); 188636285Sbrian else if (arg->prompt) 188736285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 188826516Sbrian " syntax help.\n"); 18896059Samurai else 189036285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 189126516Sbrian 189226516Sbrian return 0; 18936059Samurai} 18946059Samurai 18956059Samuraistatic int 189631343SbrianAddCommand(struct cmdargs const *arg) 18976059Samurai{ 18986059Samurai struct in_addr dest, gateway, netmask; 189936285Sbrian int gw, addrs; 19006059Samurai 190136285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 190231598Sbrian return -1; 190331598Sbrian 190436285Sbrian addrs = 0; 190536285Sbrian if (arg->argc == arg->argn+2) { 190636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 190736285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 190831598Sbrian else { 190936285Sbrian int width; 191036285Sbrian 191143313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 191236285Sbrian &dest, &netmask, &width)) 191336285Sbrian return -1; 191436285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 191536285Sbrian addrs = ROUTE_DSTMYADDR; 191636285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 191736285Sbrian addrs = ROUTE_DSTHISADDR; 191831598Sbrian } 191936285Sbrian gw = 1; 192034536Sbrian } else { 192136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 192236285Sbrian addrs = ROUTE_DSTMYADDR; 192336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 192436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 192536285Sbrian addrs = ROUTE_DSTHISADDR; 192636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 192736285Sbrian } else 192836285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 192936285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 193031598Sbrian gw = 2; 19316059Samurai } 193236285Sbrian 193336285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 193436285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 193536285Sbrian addrs |= ROUTE_GWHISADDR; 193640561Sbrian } else 193736285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 193836285Sbrian 193936285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 194043313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 194143313Sbrian && addrs != ROUTE_STATIC) 194236285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 194336285Sbrian 194431598Sbrian return 0; 19456059Samurai} 19466059Samurai 19476059Samuraistatic int 194831343SbrianDeleteCommand(struct cmdargs const *arg) 19496059Samurai{ 195031598Sbrian struct in_addr dest, none; 195136285Sbrian int addrs; 19526059Samurai 195336285Sbrian if (arg->argc == arg->argn+1) { 195436285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 195536285Sbrian route_IfDelete(arg->bundle, 0); 195636285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 195736285Sbrian } else { 195836285Sbrian addrs = 0; 195936285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 196036285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 196136285Sbrian addrs = ROUTE_DSTMYADDR; 196236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 196336285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 196436285Sbrian addrs = ROUTE_DSTHISADDR; 196536285Sbrian } else { 196644279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 196744279Sbrian if (dest.s_addr == INADDR_NONE) { 196844279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 196944279Sbrian return -1; 197044279Sbrian } 197136285Sbrian addrs = ROUTE_STATIC; 197236285Sbrian } 197331598Sbrian none.s_addr = INADDR_ANY; 197436285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 197537927Sbrian arg->cmd->args ? 1 : 0, 0); 197636285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 197731598Sbrian } 197834536Sbrian } else 197926516Sbrian return -1; 198026516Sbrian 198126516Sbrian return 0; 19826059Samurai} 19836059Samurai 198431343Sbrian#ifndef NOALIAS 198526031Sbrianstatic int 198631343SbrianAliasEnable(struct cmdargs const *arg) 198726031Sbrian{ 198836285Sbrian if (arg->argc == arg->argn+1) { 198936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 199046686Sbrian if (!arg->bundle->AliasEnabled) { 199146686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 199246686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 199346686Sbrian arg->bundle->AliasEnabled = 1; 199446686Sbrian } 199537191Sbrian return 0; 199636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 199737191Sbrian arg->bundle->AliasEnabled = 0; 199840561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 199940561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 200026516Sbrian return 0; 200126142Sbrian } 200235449Sbrian } 200336285Sbrian 200426516Sbrian return -1; 200526031Sbrian} 200626031Sbrian 200726031Sbrian 200826031Sbrianstatic int 200931343SbrianAliasOption(struct cmdargs const *arg) 201026031Sbrian{ 201138559Sbrian long param = (long)arg->cmd->args; 201238559Sbrian 201336285Sbrian if (arg->argc == arg->argn+1) { 201436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 201537191Sbrian if (arg->bundle->AliasEnabled) { 201637191Sbrian PacketAliasSetMode(param, param); 201728679Sbrian return 0; 201828679Sbrian } 201936285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 202036285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 202137191Sbrian if (arg->bundle->AliasEnabled) { 202237191Sbrian PacketAliasSetMode(0, param); 202328679Sbrian return 0; 202428679Sbrian } 202536285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 202628679Sbrian } 202735449Sbrian } 202828679Sbrian return -1; 202926031Sbrian} 203031343Sbrian#endif /* #ifndef NOALIAS */ 203131121Sbrian 203231121Sbrianstatic int 203336285SbrianLinkCommand(struct cmdargs const *arg) 203436285Sbrian{ 203536285Sbrian if (arg->argc > arg->argn+1) { 203636285Sbrian char namelist[LINE_LEN]; 203736285Sbrian struct datalink *cx; 203836285Sbrian char *name; 203936285Sbrian int result = 0; 204036285Sbrian 204136285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 204236285Sbrian struct datalink *dl; 204336285Sbrian 204436285Sbrian cx = arg->bundle->links; 204536285Sbrian while (cx) { 204636285Sbrian /* Watch it, the command could be a ``remove'' */ 204736285Sbrian dl = cx->next; 204836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 204936285Sbrian arg->prompt, cx); 205036285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 205136285Sbrian if (cx == dl) 205236285Sbrian break; /* Pointer's still valid ! */ 205336285Sbrian } 205436285Sbrian } else { 205536285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 205636285Sbrian namelist[sizeof namelist - 1] = '\0'; 205736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 205836285Sbrian if (!bundle2datalink(arg->bundle, name)) { 205936285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 206036285Sbrian return 1; 206136285Sbrian } 206236285Sbrian 206336285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 206436285Sbrian namelist[sizeof namelist - 1] = '\0'; 206536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 206636285Sbrian cx = bundle2datalink(arg->bundle, name); 206736285Sbrian if (cx) 206836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 206936285Sbrian arg->prompt, cx); 207036285Sbrian else { 207136285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 207236285Sbrian result++; 207336285Sbrian } 207436285Sbrian } 207536285Sbrian } 207636285Sbrian return result; 207736285Sbrian } 207836285Sbrian 207936285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 208036285Sbrian return 2; 208136285Sbrian} 208236285Sbrian 208336285Sbrianstruct link * 208436285Sbriancommand_ChooseLink(struct cmdargs const *arg) 208536285Sbrian{ 208636285Sbrian if (arg->cx) 208736285Sbrian return &arg->cx->physical->link; 208837210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 208936285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 209037210Sbrian if (dl) 209137210Sbrian return &dl->physical->link; 209236285Sbrian } 209337210Sbrian return &arg->bundle->ncp.mp.link; 209436285Sbrian} 209536285Sbrian 209636285Sbrianstatic const char * 209736285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 209836285Sbrian{ 209936285Sbrian const char *result; 210036285Sbrian 210136285Sbrian switch (*cmd) { 210236285Sbrian case 'A': 210336285Sbrian case 'a': 210436285Sbrian result = "accept"; 210536285Sbrian *keep = NEG_MYMASK; 210636285Sbrian *add = NEG_ACCEPTED; 210736285Sbrian break; 210836285Sbrian case 'D': 210936285Sbrian case 'd': 211036285Sbrian switch (cmd[1]) { 211136285Sbrian case 'E': 211236285Sbrian case 'e': 211336285Sbrian result = "deny"; 211436285Sbrian *keep = NEG_MYMASK; 211536285Sbrian *add = 0; 211636285Sbrian break; 211736285Sbrian case 'I': 211836285Sbrian case 'i': 211936285Sbrian result = "disable"; 212036285Sbrian *keep = NEG_HISMASK; 212136285Sbrian *add = 0; 212236285Sbrian break; 212336285Sbrian default: 212436285Sbrian return NULL; 212536285Sbrian } 212636285Sbrian break; 212736285Sbrian case 'E': 212836285Sbrian case 'e': 212936285Sbrian result = "enable"; 213036285Sbrian *keep = NEG_HISMASK; 213136285Sbrian *add = NEG_ENABLED; 213236285Sbrian break; 213336285Sbrian default: 213436285Sbrian return NULL; 213536285Sbrian } 213636285Sbrian 213736285Sbrian return result; 213836285Sbrian} 213936285Sbrian 214036285Sbrianstatic int 214136285SbrianOptSet(struct cmdargs const *arg) 214236285Sbrian{ 214337574Sbrian int bit = (int)(long)arg->cmd->args; 214436285Sbrian const char *cmd; 214536285Sbrian unsigned keep; /* Keep these bits */ 214636285Sbrian unsigned add; /* Add these bits */ 214736285Sbrian 214836285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 214936285Sbrian return 1; 215036285Sbrian 215136285Sbrian if (add) 215236285Sbrian arg->bundle->cfg.opt |= bit; 215336285Sbrian else 215436285Sbrian arg->bundle->cfg.opt &= ~bit; 215536285Sbrian return 0; 215636285Sbrian} 215736285Sbrian 215836285Sbrianstatic int 215940561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 216040561Sbrian{ 216140561Sbrian unsigned save = arg->bundle->cfg.opt; 216240561Sbrian int result = OptSet(arg); 216340561Sbrian 216440561Sbrian if (result == 0) 216540561Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->AliasEnabled) { 216640561Sbrian arg->bundle->cfg.opt = save; 216740561Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without IP aliasing\n"); 216840561Sbrian result = 2; 216940561Sbrian } 217040561Sbrian 217140561Sbrian return result; 217240561Sbrian} 217340561Sbrian 217440561Sbrianstatic int 217536285SbrianNegotiateSet(struct cmdargs const *arg) 217636285Sbrian{ 217737210Sbrian long param = (long)arg->cmd->args; 217836285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 217936285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 218036285Sbrian const char *cmd; 218136285Sbrian unsigned keep; /* Keep these bits */ 218236285Sbrian unsigned add; /* Add these bits */ 218336285Sbrian 218436285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 218536285Sbrian return 1; 218636285Sbrian 218736285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 218836285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 218936285Sbrian cmd, arg->cmd->name); 219036285Sbrian return 2; 219136285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 219236285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 219336285Sbrian cmd, arg->cmd->name, cx->name); 219436285Sbrian cx = NULL; 219536285Sbrian } 219636285Sbrian 219736285Sbrian switch (param) { 219836285Sbrian case NEG_ACFCOMP: 219936285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 220036285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 220136285Sbrian break; 220244106Sbrian case NEG_CHAP05: 220344106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 220444106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 220536285Sbrian break; 220644106Sbrian#ifdef HAVE_DES 220744106Sbrian case NEG_CHAP80: 220844106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 220944106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 221044106Sbrian break; 221144106Sbrian case NEG_CHAP80LM: 221244106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 221344106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 221444106Sbrian break; 221544106Sbrian#endif 221636285Sbrian case NEG_DEFLATE: 221736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 221836285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 221936285Sbrian break; 222036285Sbrian case NEG_DNS: 222136285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 222236285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 222336285Sbrian break; 222436285Sbrian case NEG_LQR: 222536285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 222636285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 222736285Sbrian break; 222836285Sbrian case NEG_PAP: 222936285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 223036285Sbrian cx->physical->link.lcp.cfg.pap |= add; 223136285Sbrian break; 223236285Sbrian case NEG_PPPDDEFLATE: 223336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 223436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 223536285Sbrian break; 223636285Sbrian case NEG_PRED1: 223736285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 223836285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 223936285Sbrian break; 224036285Sbrian case NEG_PROTOCOMP: 224136285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 224236285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 224336285Sbrian break; 224436285Sbrian case NEG_SHORTSEQ: 224540622Sbrian switch (bundle_Phase(arg->bundle)) { 224640622Sbrian case PHASE_DEAD: 224740622Sbrian break; 224840622Sbrian case PHASE_ESTABLISH: 224940622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 225040622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 225140622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 225240622Sbrian " LCP negotiations\n"); 225340622Sbrian return 1; 225440622Sbrian } 225540622Sbrian break; 225640622Sbrian default: 225740622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 225840622Sbrian " DEAD/ESTABLISH\n"); 225940622Sbrian return 1; 226036285Sbrian } 226140622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 226240622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 226336285Sbrian break; 226436285Sbrian case NEG_VJCOMP: 226536285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 226636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 226736285Sbrian break; 226836285Sbrian } 226936285Sbrian 227036285Sbrian return 0; 227136285Sbrian} 227236285Sbrian 227336285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 227436285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 227536285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 227640666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 227740666Sbrian "retain interface addresses", "disable|enable", 227840666Sbrian (const void *)OPT_IFACEALIAS}, 227947689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 228047689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 228136285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 228236285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 228336285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 228436285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 228540665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 228636285Sbrian "disable|enable", (const void *)OPT_PROXY}, 228740665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 228840665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 228936285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 229036285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 229136285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 229236285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 229336285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 229436285Sbrian "disable|enable", (const void *)OPT_UTMP}, 229536285Sbrian 229647689Sbrian#define OPT_MAX 10 /* accept/deny allowed below and not above */ 229736285Sbrian 229836285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 229936285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 230036285Sbrian (const void *)NEG_ACFCOMP}, 230144106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 230236285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 230344106Sbrian (const void *)NEG_CHAP05}, 230444106Sbrian#ifdef HAVE_DES 230544106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 230644106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 230744106Sbrian (const void *)NEG_CHAP80}, 230844106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 230944106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 231044106Sbrian (const void *)NEG_CHAP80LM}, 231144106Sbrian#endif 231236285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 231336285Sbrian "Deflate compression", "accept|deny|disable|enable", 231436285Sbrian (const void *)NEG_DEFLATE}, 231536285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 231636285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 231736285Sbrian (const void *)NEG_PPPDDEFLATE}, 231836285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 231936285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 232036285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 232136285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 232236285Sbrian (const void *)NEG_LQR}, 232336285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 232436285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 232536285Sbrian (const void *)NEG_PAP}, 232636285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 232736285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 232836285Sbrian (const void *)NEG_PRED1}, 232936285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 233036285Sbrian "Protocol field compression", "accept|deny|disable|enable", 233136285Sbrian (const void *)NEG_PROTOCOMP}, 233236285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 233336285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 233436285Sbrian (const void *)NEG_SHORTSEQ}, 233536285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 233636285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 233736285Sbrian (const void *)NEG_VJCOMP}, 233836285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 233936285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 234036285Sbrian NegotiateCommands}, 234136285Sbrian {NULL, NULL, NULL}, 234236285Sbrian}; 234336285Sbrian 234436285Sbrianstatic int 234536285SbrianNegotiateCommand(struct cmdargs const *arg) 234636285Sbrian{ 234736285Sbrian if (arg->argc > arg->argn) { 234836285Sbrian char const *argv[3]; 234936285Sbrian unsigned keep, add; 235036285Sbrian int n; 235136285Sbrian 235236285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 235336285Sbrian return -1; 235436285Sbrian argv[2] = NULL; 235536285Sbrian 235636285Sbrian for (n = arg->argn; n < arg->argc; n++) { 235736285Sbrian argv[1] = arg->argv[n]; 235836285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 235936285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 236036285Sbrian } 236136285Sbrian } else if (arg->prompt) 236236285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 236336285Sbrian arg->argv[arg->argn-1]); 236436285Sbrian else 236536285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 236636285Sbrian arg->argv[arg->argn] ); 236736285Sbrian 236836285Sbrian return 0; 236936285Sbrian} 237036285Sbrian 237136285Sbrianconst char * 237236285Sbriancommand_ShowNegval(unsigned val) 237336285Sbrian{ 237436285Sbrian switch (val&3) { 237536285Sbrian case 1: return "disabled & accepted"; 237636285Sbrian case 2: return "enabled & denied"; 237736285Sbrian case 3: return "enabled & accepted"; 237836285Sbrian } 237936285Sbrian return "disabled & denied"; 238036285Sbrian} 238136934Sbrian 238236934Sbrianstatic int 238336934SbrianClearCommand(struct cmdargs const *arg) 238436934Sbrian{ 238536934Sbrian struct pppThroughput *t; 238636934Sbrian struct datalink *cx; 238736934Sbrian int i, clear_type; 238836934Sbrian 238936934Sbrian if (arg->argc < arg->argn + 1) 239036934Sbrian return -1; 239136934Sbrian 239246686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 239336934Sbrian cx = arg->cx; 239436934Sbrian if (!cx) 239536934Sbrian cx = bundle2datalink(arg->bundle, NULL); 239636934Sbrian if (!cx) { 239746686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 239836934Sbrian return 1; 239936934Sbrian } 240036934Sbrian t = &cx->physical->link.throughput; 240136934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 240236934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 240336934Sbrian else 240436934Sbrian return -1; 240536934Sbrian 240636934Sbrian if (arg->argc > arg->argn + 1) { 240736934Sbrian clear_type = 0; 240836934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 240936934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 241036934Sbrian clear_type |= THROUGHPUT_OVERALL; 241136934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 241236934Sbrian clear_type |= THROUGHPUT_CURRENT; 241336934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 241436934Sbrian clear_type |= THROUGHPUT_PEAK; 241536934Sbrian else 241636934Sbrian return -1; 241736934Sbrian } else 241836934Sbrian clear_type = THROUGHPUT_ALL; 241936934Sbrian 242036934Sbrian throughput_clear(t, clear_type, arg->prompt); 242136934Sbrian return 0; 242236934Sbrian} 242340561Sbrian 242440561Sbrianstatic int 242540561SbrianRunListCommand(struct cmdargs const *arg) 242640561Sbrian{ 242740561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 242840561Sbrian 242940561Sbrian if (arg->argc > arg->argn) 243040561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 243140561Sbrian arg->prompt, arg->cx); 243240561Sbrian else if (arg->prompt) 243340561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 243440561Sbrian " <option>' for syntax help.\n", cmd, cmd); 243540561Sbrian else 243640561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 243740561Sbrian 243840561Sbrian return 0; 243940561Sbrian} 244040561Sbrian 244140561Sbrianstatic int 244240561SbrianIfaceAddCommand(struct cmdargs const *arg) 244340561Sbrian{ 244440561Sbrian int bits, n, how; 244540561Sbrian struct in_addr ifa, mask, brd; 244640561Sbrian 244740664Sbrian if (arg->argc == arg->argn + 1) { 244843313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 244940561Sbrian return -1; 245040664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 245140664Sbrian } else { 245240664Sbrian if (arg->argc == arg->argn + 2) { 245343313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 245440664Sbrian return -1; 245540664Sbrian n = 1; 245640664Sbrian } else if (arg->argc == arg->argn + 3) { 245743313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 245840664Sbrian return -1; 245943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 246040664Sbrian return -1; 246140664Sbrian n = 2; 246240664Sbrian } else 246340561Sbrian return -1; 246440561Sbrian 246543313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 246640664Sbrian return -1; 246740664Sbrian } 246840561Sbrian 246940561Sbrian how = IFACE_ADD_LAST; 247040561Sbrian if (arg->cmd->args) 247140561Sbrian how |= IFACE_FORCE_ADD; 247240561Sbrian 247340561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 247440561Sbrian} 247540561Sbrian 247640561Sbrianstatic int 247740561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 247840561Sbrian{ 247940561Sbrian struct in_addr ifa; 248040561Sbrian int ok; 248140561Sbrian 248240561Sbrian if (arg->argc != arg->argn + 1) 248340561Sbrian return -1; 248440561Sbrian 248543313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 248640561Sbrian return -1; 248740561Sbrian 248840561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 248940561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 249040561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 249140561Sbrian inet_ntoa(ifa)); 249240561Sbrian return 1; 249340561Sbrian } 249440561Sbrian 249540561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 249640561Sbrian if (!ok) { 249740561Sbrian if (arg->cmd->args) 249840561Sbrian ok = 1; 249940561Sbrian else if (arg->prompt) 250040561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 250140561Sbrian else 250240561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 250340561Sbrian } 250440561Sbrian 250540561Sbrian return !ok; 250640561Sbrian} 250740561Sbrian 250840561Sbrianstatic int 250940561SbrianIfaceClearCommand(struct cmdargs const *arg) 251040561Sbrian{ 251140561Sbrian int how; 251240561Sbrian 251340561Sbrian if (arg->argc != arg->argn) 251440561Sbrian return -1; 251540561Sbrian 251640941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 251740941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 251840561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 251940561Sbrian iface_Clear(arg->bundle->iface, how); 252040561Sbrian 252140561Sbrian return 0; 252240561Sbrian} 252340679Sbrian 252440679Sbrianstatic int 252540679SbrianSetProcTitle(struct cmdargs const *arg) 252640679Sbrian{ 252740679Sbrian static char title[LINE_LEN]; 252840679Sbrian char *argv[MAXARGS], *ptr; 252940679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 253040679Sbrian 253140679Sbrian if (arg->argc == arg->argn) { 253240679Sbrian arg->bundle->argv[0] = arg->bundle->argv0; 253340679Sbrian arg->bundle->argv[1] = arg->bundle->argv1; 253440679Sbrian return 0; 253540679Sbrian } 253640679Sbrian 253740679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 253840679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 253940679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 254040679Sbrian } 254147849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 254240679Sbrian 254340679Sbrian ptr = title; 254440679Sbrian remaining = sizeof title - 1; 254540679Sbrian for (f = 0; f < argc && remaining; f++) { 254640679Sbrian if (f) { 254740679Sbrian *ptr++ = ' '; 254840679Sbrian remaining--; 254940679Sbrian } 255040679Sbrian len = strlen(argv[f]); 255140679Sbrian if (len > remaining) 255240679Sbrian len = remaining; 255340679Sbrian memcpy(ptr, argv[f], len); 255440679Sbrian remaining -= len; 255540679Sbrian ptr += len; 255640679Sbrian } 255740679Sbrian *ptr = '\0'; 255840679Sbrian 255940679Sbrian arg->bundle->argv[0] = title; 256040679Sbrian arg->bundle->argv[1] = NULL; 256140679Sbrian 256240679Sbrian return 0; 256340679Sbrian} 2564