command.c revision 49434
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 * 2049434Sbrian * $Id: command.c,v 1.204 1999/08/02 21:45:35 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 13647858Sbrian#define NEG_DNS 45 13747858Sbrian#define NEG_ENDDISC 46 13847858Sbrian#define NEG_LQR 47 13947858Sbrian#define NEG_PAP 48 14047858Sbrian#define NEG_PPPDDEFLATE 49 14147858Sbrian#define NEG_PRED1 50 14247858Sbrian#define NEG_PROTOCOMP 51 14347858Sbrian#define NEG_SHORTSEQ 52 14447858Sbrian#define NEG_VJCOMP 53 14536285Sbrian 14649434Sbrianconst char Version[] = "2.23"; 14749434Sbrianconst char VersionDate[] = "$Date: 1999/08/02 21:45:35 $"; 14836285Sbrian 14936285Sbrianstatic int ShowCommand(struct cmdargs const *); 15036285Sbrianstatic int TerminalCommand(struct cmdargs const *); 15136285Sbrianstatic int QuitCommand(struct cmdargs const *); 15236285Sbrianstatic int OpenCommand(struct cmdargs const *); 15336285Sbrianstatic int CloseCommand(struct cmdargs const *); 15436285Sbrianstatic int DownCommand(struct cmdargs const *); 15536285Sbrianstatic int SetCommand(struct cmdargs const *); 15636285Sbrianstatic int LinkCommand(struct cmdargs const *); 15736285Sbrianstatic int AddCommand(struct cmdargs const *); 15836285Sbrianstatic int DeleteCommand(struct cmdargs const *); 15936285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 16036934Sbrianstatic int ClearCommand(struct cmdargs const *); 16140561Sbrianstatic int RunListCommand(struct cmdargs const *); 16240561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 16340561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 16440561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 16540679Sbrianstatic int SetProcTitle(struct cmdargs const *); 16631343Sbrian#ifndef NOALIAS 16736285Sbrianstatic int AliasEnable(struct cmdargs const *); 16836285Sbrianstatic int AliasOption(struct cmdargs const *); 16931343Sbrian#endif 1706059Samurai 17136285Sbrianstatic const char * 17236285Sbrianshowcx(struct cmdtab const *cmd) 17336285Sbrian{ 17436285Sbrian if (cmd->lauth & LOCAL_CX) 17536285Sbrian return "(c)"; 17636285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 17736285Sbrian return "(o)"; 17836285Sbrian 17936285Sbrian return ""; 18036285Sbrian} 18136285Sbrian 1826059Samuraistatic int 18331343SbrianHelpCommand(struct cmdargs const *arg) 1846059Samurai{ 18528679Sbrian struct cmdtab const *cmd; 18636285Sbrian int n, cmax, dmax, cols, cxlen; 18736285Sbrian const char *cx; 1886059Samurai 18936285Sbrian if (!arg->prompt) { 19036285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 19126516Sbrian return 0; 19236285Sbrian } 19326516Sbrian 19436285Sbrian if (arg->argc > arg->argn) { 19536285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 19636285Sbrian if ((cmd->lauth & arg->prompt->auth) && 19736285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 19836285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 19936285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 20028679Sbrian return 0; 2016059Samurai } 20226516Sbrian return -1; 2036059Samurai } 20436285Sbrian 20531372Sbrian cmax = dmax = 0; 20636285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 20736285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 20836285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 20931372Sbrian cmax = n; 21031372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 21131372Sbrian dmax = n; 21231372Sbrian } 21331372Sbrian 21431372Sbrian cols = 80 / (dmax + cmax + 3); 2156059Samurai n = 0; 21636285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 21736285Sbrian " (c) = Context required\n"); 21836285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 21936285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22036285Sbrian cx = showcx(cmd); 22136285Sbrian cxlen = cmax - strlen(cmd->name); 22240482Sbrian if (n % cols != 0) 22340482Sbrian prompt_Printf(arg->prompt, " "); 22440482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 22536285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 22631372Sbrian if (++n % cols == 0) 22736285Sbrian prompt_Printf(arg->prompt, "\n"); 2286059Samurai } 22931372Sbrian if (n % cols != 0) 23036285Sbrian prompt_Printf(arg->prompt, "\n"); 23126516Sbrian 23226516Sbrian return 0; 2336059Samurai} 2346059Samurai 23536285Sbrianstatic int 23636285SbrianCloneCommand(struct cmdargs const *arg) 2376059Samurai{ 23836285Sbrian char namelist[LINE_LEN]; 23936285Sbrian char *name; 24036285Sbrian int f; 2416059Samurai 24236285Sbrian if (arg->argc == arg->argn) 24336285Sbrian return -1; 24436285Sbrian 24536285Sbrian namelist[sizeof namelist - 1] = '\0'; 24636285Sbrian for (f = arg->argn; f < arg->argc; f++) { 24736285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 24836285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 24936285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2506059Samurai } 25136285Sbrian 25236285Sbrian return 0; 2536059Samurai} 2546059Samurai 2556059Samuraistatic int 25636285SbrianRemoveCommand(struct cmdargs const *arg) 2576059Samurai{ 25836285Sbrian if (arg->argc != arg->argn) 25936285Sbrian return -1; 26011336Samurai 26136285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 26236285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 26336285Sbrian return 2; 2646059Samurai } 26526516Sbrian 26636285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 26736285Sbrian return 0; 26836285Sbrian} 26932711Sbrian 27036285Sbrianstatic int 27136285SbrianRenameCommand(struct cmdargs const *arg) 27236285Sbrian{ 27336285Sbrian if (arg->argc != arg->argn + 1) 27436285Sbrian return -1; 27531121Sbrian 27636285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 27736285Sbrian return 0; 27836285Sbrian 27936285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 28036285Sbrian arg->cx->name, arg->argv[arg->argn]); 28136285Sbrian return 1; 28236285Sbrian} 28336285Sbrian 28436285Sbrianint 28536285SbrianLoadCommand(struct cmdargs const *arg) 28636285Sbrian{ 28740797Sbrian const char *err; 28840797Sbrian int n, mode; 28936285Sbrian 29040797Sbrian mode = arg->bundle->phys_type.all; 29136285Sbrian 29240797Sbrian if (arg->argn < arg->argc) { 29340797Sbrian for (n = arg->argn; n < arg->argc; n++) 29440797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 29540797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 29640797Sbrian return 1; 29740797Sbrian } 29840797Sbrian 29940797Sbrian for (n = arg->argn; n < arg->argc; n++) { 30040797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 30140797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 30240797Sbrian } 30340797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 30440797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 30540797Sbrian log_Printf(LogWARN, "default: %s\n", err); 30636285Sbrian return 1; 30736285Sbrian } else { 30840797Sbrian bundle_SetLabel(arg->bundle, "default"); 30940797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 31040797Sbrian bundle_SetLabel(arg->bundle, "default"); 31136285Sbrian } 31240797Sbrian 31326516Sbrian return 0; 3146059Samurai} 3156059Samurai 31636285Sbrianint 31736285SbrianSaveCommand(struct cmdargs const *arg) 31836285Sbrian{ 31936285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 32036285Sbrian return 1; 32136285Sbrian} 32236285Sbrian 32310528Samuraistatic int 32436285SbrianDialCommand(struct cmdargs const *arg) 32528536Sbrian{ 32636285Sbrian int res; 32736285Sbrian 32836465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 32936465Sbrian || (!arg->cx && 33036928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 33136285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 33236285Sbrian " interactive links\n"); 33336285Sbrian return 1; 33434536Sbrian } 33536285Sbrian 33636285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 33736285Sbrian return res; 33836285Sbrian 33937993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 34036285Sbrian 34136285Sbrian return 0; 34228536Sbrian} 34328536Sbrian 34438628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 34538628Sbrian 34638628Sbrianstatic char * 34738628Sbrianstrstrword(char *big, const char *little) 34838628Sbrian{ 34938628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 35038628Sbrian char *pos; 35138628Sbrian int len; 35238628Sbrian 35338628Sbrian pos = big; 35438628Sbrian len = strlen(little); 35538628Sbrian 35638628Sbrian while ((pos = strstr(pos, little)) != NULL) 35747865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 35847865Sbrian pos++; 35947865Sbrian else if (pos != big && pos[-1] == '\\') 36047865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 36147865Sbrian else 36238628Sbrian break; 36338628Sbrian 36438628Sbrian return pos; 36538628Sbrian} 36638628Sbrian 36738628Sbrianstatic char * 36838628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 36938628Sbrian{ 37038628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 37138628Sbrian char *word, *ntgt; 37238628Sbrian int ltgt, loldstr, lnewstr, pos; 37338628Sbrian 37438628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 37538628Sbrian return tgt; 37638628Sbrian 37738628Sbrian ltgt = strlen(tgt) + 1; 37838628Sbrian loldstr = strlen(oldstr); 37938628Sbrian lnewstr = strlen(newstr); 38038628Sbrian do { 38138628Sbrian pos = word - tgt; 38238628Sbrian if (loldstr > lnewstr) 38338628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 38438628Sbrian if (loldstr != lnewstr) { 38538628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 38638628Sbrian if (ntgt == NULL) 38738628Sbrian break; /* Oh wonderful ! */ 38838628Sbrian word = ntgt + pos; 38938628Sbrian tgt = ntgt; 39038628Sbrian } 39138628Sbrian if (lnewstr > loldstr) 39238628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 39338628Sbrian bcopy(newstr, word, lnewstr); 39438628Sbrian } while ((word = strstrword(word, oldstr))); 39538628Sbrian 39638628Sbrian return tgt; 39738628Sbrian} 39838628Sbrian 39943888Sbrianvoid 40043888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 40147849Sbrian struct bundle *bundle, int inc0, pid_t pid) 40238628Sbrian{ 40338628Sbrian int arg; 40447849Sbrian char pidstr[12]; 40538628Sbrian 40641755Sbrian if (inc0) 40741755Sbrian arg = 0; /* Start at arg 0 */ 40841755Sbrian else { 40941755Sbrian nargv[0] = strdup(oargv[0]); 41041755Sbrian arg = 1; 41141755Sbrian } 41247849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 41341755Sbrian for (; arg < argc; arg++) { 41438629Sbrian nargv[arg] = strdup(oargv[arg]); 41538629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 41638628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 41738629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 41840561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 41938628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 42038629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 42138629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 42238629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 42338629Sbrian bundle->ncp.mp.peer.enddisc.address, 42438629Sbrian bundle->ncp.mp.peer.enddisc.len)); 42538629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 42638629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 42738629Sbrian bundle->ncp.mp.cfg.enddisc.address, 42838629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 42947849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 43038629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 43138628Sbrian } 43238628Sbrian nargv[arg] = NULL; 43338628Sbrian} 43438628Sbrian 43528536Sbrianstatic int 43631343SbrianShellCommand(struct cmdargs const *arg, int bg) 43710528Samurai{ 43810528Samurai const char *shell; 43947849Sbrian pid_t shpid, pid; 44020813Sjkh 44118856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 44226911Sbrian /* we're only allowed to shell when we run ppp interactively */ 44336285Sbrian if (arg->prompt && arg->prompt->owner) { 44436285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 44526516Sbrian return 1; 44610528Samurai } 44726911Sbrian#endif 44828679Sbrian 44936285Sbrian if (arg->argc == arg->argn) { 45036285Sbrian if (!arg->prompt) { 45136285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 45236285Sbrian " a config file\n"); 45328381Sbrian return 1; 45436285Sbrian } else if (arg->prompt->owner) { 45536285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 45636285Sbrian " a socket connection\n"); 45736285Sbrian return 1; 45828381Sbrian } else if (bg) { 45936285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 46028679Sbrian " the foreground mode\n"); 46128381Sbrian return 1; 46228381Sbrian } 46334536Sbrian } 46434536Sbrian 46547849Sbrian pid = getpid(); 46628679Sbrian if ((shpid = fork()) == 0) { 46736285Sbrian int i, fd; 46818531Sbde 46936285Sbrian if ((shell = getenv("SHELL")) == 0) 47036285Sbrian shell = _PATH_BSHELL; 47132017Sbrian 47236285Sbrian timer_TermService(); 47336285Sbrian 47436285Sbrian if (arg->prompt) 47536285Sbrian fd = arg->prompt->fd_out; 47636285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 47736285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 47836285Sbrian _PATH_DEVNULL, strerror(errno)); 47928679Sbrian exit(1); 48028679Sbrian } 48128679Sbrian for (i = 0; i < 3; i++) 48228679Sbrian dup2(fd, i); 48326516Sbrian 48436285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 48526516Sbrian 48631061Sbrian setuid(geteuid()); 48736285Sbrian if (arg->argc > arg->argn) { 48828679Sbrian /* substitute pseudo args */ 48938628Sbrian char *argv[MAXARGS]; 49038628Sbrian int argc = arg->argc - arg->argn; 49138628Sbrian 49238628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 49338628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 49438628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 49531343Sbrian } 49647849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 49728679Sbrian if (bg) { 49828679Sbrian pid_t p; 49910528Samurai 50028679Sbrian p = getpid(); 50128679Sbrian if (daemon(1, 1) == -1) { 50236832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 50328679Sbrian exit(1); 50428679Sbrian } 50536285Sbrian } else if (arg->prompt) 50636285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 50731343Sbrian execvp(argv[0], argv); 50830316Sbrian } else { 50936285Sbrian if (arg->prompt) 51032017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 51136285Sbrian prompt_TtyOldMode(arg->prompt); 51231343Sbrian execl(shell, shell, NULL); 51330316Sbrian } 51420813Sjkh 51540665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 51640665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 51740665Sbrian strerror(errno)); 51828679Sbrian exit(255); 51910528Samurai } 52036285Sbrian 52136285Sbrian if (shpid == (pid_t) - 1) 52236285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 52336285Sbrian else { 52410528Samurai int status; 52531343Sbrian waitpid(shpid, &status, 0); 52610528Samurai } 52720813Sjkh 52836285Sbrian if (arg->prompt && !arg->prompt->owner) 52936285Sbrian prompt_TtyCommandMode(arg->prompt); 53020813Sjkh 53136285Sbrian return 0; 53210528Samurai} 53310528Samurai 53431343Sbrianstatic int 53531343SbrianBgShellCommand(struct cmdargs const *arg) 53631343Sbrian{ 53736285Sbrian if (arg->argc == arg->argn) 53831343Sbrian return -1; 53931343Sbrian return ShellCommand(arg, 1); 54031343Sbrian} 54131343Sbrian 54231343Sbrianstatic int 54331343SbrianFgShellCommand(struct cmdargs const *arg) 54431343Sbrian{ 54531343Sbrian return ShellCommand(arg, 0); 54631343Sbrian} 54731343Sbrian 54840561Sbrian#ifndef NOALIAS 54940561Sbrianstatic struct cmdtab const AliasCommands[] = 55040561Sbrian{ 55140561Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 55240561Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 55340561Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 55440561Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 55540561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 55640561Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 55740561Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 55840561Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 55940561Sbrian "log aliasing link creation", "alias log [yes|no]", 56040561Sbrian (const void *) PKT_ALIAS_LOG}, 56145042Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, "port redirection", 56245042Sbrian "alias port proto localaddr:port[-port] aliasport[-aliasport]"}, 56344557Sbrian {"pptp", NULL, alias_Pptp, LOCAL_AUTH, 56444557Sbrian "Set the PPTP address", "alias pptp IP"}, 56544547Sbrian {"proxy", NULL, alias_ProxyRule, LOCAL_AUTH, 56644547Sbrian "proxy control", "alias proxy server host[:port] ..."}, 56740561Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 56840561Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 56940561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 57040561Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 57140561Sbrian "alias unregistered (private) IP address space only", 57240561Sbrian "alias unregistered_only [yes|no]", 57340561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 57440561Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 57540561Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 57640561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 57740561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 57840561Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 57940561Sbrian {NULL, NULL, NULL}, 58040561Sbrian}; 58140561Sbrian#endif 58240561Sbrian 58340561Sbrianstatic struct cmdtab const AllowCommands[] = { 58440561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 58540561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 58640561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 58740561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 58840561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 58940561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 59040561Sbrian {NULL, NULL, NULL}, 59140561Sbrian}; 59240561Sbrian 59340561Sbrianstatic struct cmdtab const IfaceCommands[] = 59440561Sbrian{ 59540561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 59640561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 59740561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 59840561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 59940561Sbrian (void *)1}, 60040561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 60140561Sbrian "Clear iface address(es)", "iface clear"}, 60240561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 60340561Sbrian "Delete iface address", "iface delete addr", NULL}, 60440561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 60540561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 60640561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 60740561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 60840561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 60940561Sbrian "Show iface address(es)", "iface show"}, 61040561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 61140561Sbrian "Display this message", "alias help|? [command]", IfaceCommands}, 61240561Sbrian {NULL, NULL, NULL}, 61340561Sbrian}; 61440561Sbrian 61530715Sbrianstatic struct cmdtab const Commands[] = { 61636285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61728679Sbrian "accept option request", "accept option .."}, 61828679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 61932109Sbrian "add route", "add dest mask gateway", NULL}, 62036285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 62132109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 62236285Sbrian#ifndef NOALIAS 62340561Sbrian {"alias", NULL, RunListCommand, LOCAL_AUTH, 62440561Sbrian "alias control", "alias option [yes|no]", AliasCommands}, 62536285Sbrian#endif 62640561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 62740561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 62828679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 62931372Sbrian "Run a background command", "[!]bg command"}, 63036934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63146686Sbrian "Clear throughput statistics", 63246686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 63336285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 63436285Sbrian "Clone a link", "clone newname..."}, 63536285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63636285Sbrian "Close an FSM", "close [lcp|ccp]"}, 63728679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 63832109Sbrian "delete route", "delete dest", NULL}, 63936285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 64032109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 64136285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64228679Sbrian "Deny option request", "deny option .."}, 64336285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64440797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 64536285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64628679Sbrian "Disable option", "disable option .."}, 64736285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64846686Sbrian "Generate a down event", "down [ccp|lcp]"}, 64936285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65028679Sbrian "Enable option", "enable option .."}, 65140561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 65240561Sbrian "interface control", "iface option ...", IfaceCommands}, 65336285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 65436285Sbrian "Link specific commands", "link name command ..."}, 65537008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65640797Sbrian "Load settings", "load [system ...]"}, 65736285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65837955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 65936285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 66036285Sbrian "Password for manipulation", "passwd LocalPassword"}, 66136285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 66236285Sbrian "Quit PPP program", "quit|bye [all]"}, 66336285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 66436285Sbrian "Remove a link", "remove"}, 66536285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 66636285Sbrian "Rename a link", "rename name"}, 66728679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 66828679Sbrian "Save settings", "save"}, 66936285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67028679Sbrian "Set parameters", "set[up] var value"}, 67128679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 67228679Sbrian "Run a subshell", "shell|! [sh command]"}, 67336285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67431372Sbrian "Show status and stats", "show var"}, 67536285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 67631372Sbrian "Enter terminal mode", "term"}, 67728679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 67831343Sbrian "Display this message", "help|? [command]", Commands}, 67928679Sbrian {NULL, NULL, NULL}, 6806059Samurai}; 6816059Samurai 68228536Sbrianstatic int 68331343SbrianShowEscape(struct cmdargs const *arg) 6846059Samurai{ 68536285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 68636285Sbrian int code, bit; 68736285Sbrian const char *sep = ""; 6886059Samurai 68926516Sbrian for (code = 0; code < 32; code++) 69036285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 69128679Sbrian for (bit = 0; bit < 8; bit++) 69236285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 69336285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 69436285Sbrian sep = ", "; 69536285Sbrian } 69636285Sbrian prompt_Printf(arg->prompt, "\n"); 6976059Samurai } 69831077Sbrian return 0; 6996059Samurai} 7006059Samurai 70128679Sbrianstatic int 70236285SbrianShowTimerList(struct cmdargs const *arg) 7036059Samurai{ 70436285Sbrian timer_Show(0, arg->prompt); 70531077Sbrian return 0; 7066059Samurai} 7076059Samurai 70828679Sbrianstatic int 70931343SbrianShowStopped(struct cmdargs const *arg) 71028327Sbrian{ 71136285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 71236285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 71336285Sbrian prompt_Printf(arg->prompt, "Disabled"); 71428327Sbrian else 71536285Sbrian prompt_Printf(arg->prompt, "%ld secs", 71636285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 71728461Sbrian 71836285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 71936285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 72036285Sbrian prompt_Printf(arg->prompt, "Disabled"); 72128461Sbrian else 72236285Sbrian prompt_Printf(arg->prompt, "%ld secs", 72336285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 72428461Sbrian 72536285Sbrian prompt_Printf(arg->prompt, "\n"); 72628461Sbrian 72731077Sbrian return 0; 72828327Sbrian} 72928327Sbrian 73028679Sbrianstatic int 73131343SbrianShowVersion(struct cmdargs const *arg) 7326059Samurai{ 73336285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 73431077Sbrian return 0; 7356059Samurai} 7366059Samurai 73728679Sbrianstatic int 73836285SbrianShowProtocolStats(struct cmdargs const *arg) 73926326Sbrian{ 74036285Sbrian struct link *l = command_ChooseLink(arg); 74126326Sbrian 74236285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 74336285Sbrian link_ReportProtocolStatus(l, arg->prompt); 74431077Sbrian return 0; 74526326Sbrian} 74626326Sbrian 74730715Sbrianstatic struct cmdtab const ShowCommands[] = { 74836285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 74936285Sbrian "bundle details", "show bundle"}, 75036285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 75136285Sbrian "CCP status", "show cpp"}, 75236285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 75336285Sbrian "VJ compression stats", "show compress"}, 75436285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 75536285Sbrian "escape characters", "show escape"}, 75636285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 75736285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 75836285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 75936285Sbrian "HDLC errors", "show hdlc"}, 76040561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 76140561Sbrian "Interface status", "show iface"}, 76236285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 76336285Sbrian "IPCP status", "show ipcp"}, 76447211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 76547211Sbrian "Protocol layers", "show layers"}, 76636285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 76736285Sbrian "LCP status", "show lcp"}, 76836285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 76936285Sbrian "(high-level) link info", "show link"}, 77036285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 77136285Sbrian "available link names", "show links"}, 77236285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 77336285Sbrian "log levels", "show log"}, 77436285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 77536285Sbrian "mbuf allocations", "show mem"}, 77646686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 77746686Sbrian "(low-level) link info", "show physical"}, 77836285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 77936285Sbrian "multilink setup", "show mp"}, 78036285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 78136285Sbrian "protocol summary", "show proto"}, 78236285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 78336285Sbrian "routing table", "show route"}, 78436285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 78536285Sbrian "STOPPED timeout", "show stopped"}, 78636285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 78736285Sbrian "alarm timers", "show timers"}, 78828679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 78936285Sbrian "version string", "show version"}, 79036285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 79136285Sbrian "client list", "show who"}, 79228679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 79331343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 79428679Sbrian {NULL, NULL, NULL}, 7956059Samurai}; 7966059Samurai 79730715Sbrianstatic struct cmdtab const * 79831343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 7996059Samurai{ 80026516Sbrian int nmatch; 80126516Sbrian int len; 80228679Sbrian struct cmdtab const *found; 8036059Samurai 80426516Sbrian found = NULL; 80526516Sbrian len = strlen(str); 80626516Sbrian nmatch = 0; 8076059Samurai while (cmds->func) { 80825566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 80926516Sbrian if (cmds->name[len] == '\0') { 81028679Sbrian *pmatch = 1; 81128679Sbrian return cmds; 81226516Sbrian } 8136059Samurai nmatch++; 8146059Samurai found = cmds; 81528679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 81626516Sbrian if (cmds->alias[len] == '\0') { 81728679Sbrian *pmatch = 1; 81828679Sbrian return cmds; 81926516Sbrian } 8206059Samurai nmatch++; 8216059Samurai found = cmds; 8226059Samurai } 8236059Samurai cmds++; 8246059Samurai } 8256059Samurai *pmatch = nmatch; 82626516Sbrian return found; 8276059Samurai} 8286059Samurai 82936285Sbrianstatic const char * 83036285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 83136285Sbrian{ 83236285Sbrian int f, tlen, len; 83336285Sbrian 83436285Sbrian tlen = 0; 83536285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 83636285Sbrian if (f) 83736285Sbrian tgt[tlen++] = ' '; 83836285Sbrian len = strlen(argv[f]); 83936285Sbrian if (len > sz - tlen - 1) 84036285Sbrian len = sz - tlen - 1; 84136285Sbrian strncpy(tgt+tlen, argv[f], len); 84236285Sbrian tlen += len; 84336285Sbrian } 84436285Sbrian tgt[tlen] = '\0'; 84536285Sbrian return tgt; 84636285Sbrian} 84736285Sbrian 84830715Sbrianstatic int 84936285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 85036285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8516059Samurai{ 85228679Sbrian struct cmdtab const *cmd; 8536059Samurai int val = 1; 8546059Samurai int nmatch; 85531343Sbrian struct cmdargs arg; 85636285Sbrian char prefix[100]; 8576059Samurai 85836285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8596059Samurai if (nmatch > 1) 86036285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 86136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 86236285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 86336285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 86436285Sbrian /* We've got no context, but we require it */ 86536285Sbrian cx = bundle2datalink(bundle, NULL); 86636285Sbrian 86736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 86836285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 86936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 87036285Sbrian else { 87136285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 87236285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 87336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 87436285Sbrian cx = NULL; 87536285Sbrian } 87636285Sbrian arg.cmdtab = cmds; 87736285Sbrian arg.cmd = cmd; 87836285Sbrian arg.argc = argc; 87936285Sbrian arg.argn = argn+1; 88036285Sbrian arg.argv = argv; 88136285Sbrian arg.bundle = bundle; 88236285Sbrian arg.cx = cx; 88336285Sbrian arg.prompt = prompt; 88436285Sbrian val = (*cmd->func) (&arg); 88536285Sbrian } 88631343Sbrian } else 88736285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 88836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 88926516Sbrian 89026516Sbrian if (val == -1) 89136285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 89228679Sbrian else if (val) 89336285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 89436285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 89526516Sbrian 89626516Sbrian return val; 8976059Samurai} 8986059Samurai 89937009Sbrianint 90037009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 9016059Samurai{ 9026059Samurai char *cp; 9036059Samurai 9046059Samurai if (nb > 0) { 9056059Samurai cp = buff + strcspn(buff, "\r\n"); 9066059Samurai if (cp) 9076059Samurai *cp = '\0'; 90837009Sbrian return MakeArgs(buff, argv, MAXARGS); 90937009Sbrian } 91037009Sbrian return 0; 91131121Sbrian} 9126059Samurai 91331822Sbrianstatic int 91431822Sbrianarghidden(int argc, char const *const *argv, int n) 91531822Sbrian{ 91631822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 91731828Sbrian 91831828Sbrian /* set authkey xxxxx */ 91931828Sbrian /* set key xxxxx */ 92031822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 92131822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 92231822Sbrian return 1; 92331822Sbrian 92431828Sbrian /* passwd xxxxx */ 92531828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 92631828Sbrian return 1; 92731828Sbrian 92836285Sbrian /* set server port xxxxx .... */ 92936285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 93036285Sbrian !strncasecmp(argv[1], "se", 2)) 93136285Sbrian return 1; 93236285Sbrian 93331822Sbrian return 0; 93431822Sbrian} 93531822Sbrian 93631121Sbrianvoid 93736285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 93837008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 93931121Sbrian{ 94031156Sbrian if (argc > 0) { 94136285Sbrian if (log_IsKept(LogCOMMAND)) { 94247844Sbrian char buf[LINE_LEN]; 94331156Sbrian int f, n; 94431156Sbrian 94531156Sbrian if (label) { 94631962Sbrian strncpy(buf, label, sizeof buf - 3); 94731962Sbrian buf[sizeof buf - 3] = '\0'; 94831156Sbrian strcat(buf, ": "); 94947844Sbrian n = strlen(buf); 95047844Sbrian } else { 95147844Sbrian *buf = '\0'; 95247844Sbrian n = 0; 95331156Sbrian } 95447844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 95547844Sbrian 95631156Sbrian for (f = 0; f < argc; f++) { 95731962Sbrian if (n < sizeof buf - 1 && f) 95831156Sbrian buf[n++] = ' '; 95931822Sbrian if (arghidden(argc, argv, f)) 96036285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 96131822Sbrian else 96231962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 96331156Sbrian n += strlen(buf+n); 96431156Sbrian } 96536285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 96631156Sbrian } 96737008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 96831156Sbrian } 9696059Samurai} 9706059Samurai 97131121Sbrianvoid 97236285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 97336285Sbrian const char *label) 97431121Sbrian{ 97531121Sbrian int argc; 97637009Sbrian char *argv[MAXARGS]; 97731121Sbrian 97837009Sbrian argc = command_Interpret(buff, nb, argv); 97937008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 98031121Sbrian} 98131121Sbrian 9826059Samuraistatic int 98331343SbrianShowCommand(struct cmdargs const *arg) 9846059Samurai{ 98536285Sbrian if (!arg->prompt) 98636285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 98736285Sbrian else if (arg->argc > arg->argn) 98836285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 98936285Sbrian arg->prompt, arg->cx); 9906059Samurai else 99136285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 99226516Sbrian 99326516Sbrian return 0; 9946059Samurai} 9956059Samurai 9966059Samuraistatic int 99731343SbrianTerminalCommand(struct cmdargs const *arg) 9986059Samurai{ 99936285Sbrian if (!arg->prompt) { 100036285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 100126516Sbrian return 1; 10026059Samurai } 100336285Sbrian 100436285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 100536285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 100636285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 100736285Sbrian return 1; 10086059Samurai } 100936285Sbrian 101036285Sbrian datalink_Up(arg->cx, 0, 0); 101136285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 101236285Sbrian return 0; 10136059Samurai} 10146059Samurai 10156059Samuraistatic int 101631343SbrianQuitCommand(struct cmdargs const *arg) 10176059Samurai{ 101836285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 101936285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 102036285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 102136285Sbrian Cleanup(EX_NORMAL); 102236285Sbrian if (arg->prompt) 102336285Sbrian prompt_Destroy(arg->prompt, 1); 102426516Sbrian 102526516Sbrian return 0; 10266059Samurai} 10276059Samurai 10286059Samuraistatic int 102936285SbrianOpenCommand(struct cmdargs const *arg) 10306059Samurai{ 103137160Sbrian if (arg->argc == arg->argn) 103237993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 103337160Sbrian else if (arg->argc == arg->argn + 1) { 103437160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 103537385Sbrian struct datalink *cx = arg->cx ? 103637385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 103737385Sbrian if (cx) { 103837385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 103937385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 104037160Sbrian else 104137993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 104237160Sbrian } else 104337160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 104437160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 104537160Sbrian struct fsm *fp; 10466059Samurai 104737210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 104837160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 104937160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 105037160Sbrian else if (fp->state == ST_OPENED) 105137160Sbrian fsm_Reopen(fp); 105237160Sbrian else { 105337160Sbrian fp->open_mode = 0; /* Not passive any more */ 105437160Sbrian if (fp->state == ST_STOPPED) { 105537160Sbrian fsm_Down(fp); 105637160Sbrian fsm_Up(fp); 105737160Sbrian } else { 105837160Sbrian fsm_Up(fp); 105937160Sbrian fsm_Open(fp); 106037160Sbrian } 106136285Sbrian } 106237160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 106337160Sbrian if (arg->cx) 106437160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 106537160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 106637160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 106737160Sbrian else 106837993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 106937160Sbrian } else 107037160Sbrian return -1; 107136285Sbrian } else 107236285Sbrian return -1; 107336285Sbrian 107426516Sbrian return 0; 10756059Samurai} 10766059Samurai 107725067Sbrianstatic int 107836285SbrianCloseCommand(struct cmdargs const *arg) 10796059Samurai{ 108037007Sbrian if (arg->argc == arg->argn) 108137007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 108237007Sbrian else if (arg->argc == arg->argn + 1) { 108337007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 108437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 108537007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 108637007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 108737007Sbrian struct fsm *fp; 10886059Samurai 108937210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 109037007Sbrian if (fp->state == ST_OPENED) { 109137007Sbrian fsm_Close(fp); 109237007Sbrian if (arg->argv[arg->argn][3] == '!') 109337007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 109437007Sbrian else 109537007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 109637007Sbrian } 109737007Sbrian } else 109836285Sbrian return -1; 109936285Sbrian } else 110036285Sbrian return -1; 110136285Sbrian 110236285Sbrian return 0; 11036059Samurai} 11046059Samurai 110525067Sbrianstatic int 110636285SbrianDownCommand(struct cmdargs const *arg) 110711336Samurai{ 110837018Sbrian if (arg->argc == arg->argn) { 110937018Sbrian if (arg->cx) 111037018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 111137018Sbrian else 111237018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 111337018Sbrian } else if (arg->argc == arg->argn + 1) { 111437018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 111537018Sbrian if (arg->cx) 111637018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 111737018Sbrian else 111837018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 111937018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 112037018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 112137018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 112237060Sbrian fsm2initial(fp); 112337018Sbrian } else 112437018Sbrian return -1; 112536285Sbrian } else 112636285Sbrian return -1; 112736285Sbrian 112836285Sbrian return 0; 112925067Sbrian} 113025067Sbrian 113125067Sbrianstatic int 113236285SbrianSetModemSpeed(struct cmdargs const *arg) 113325067Sbrian{ 113436285Sbrian long speed; 113536285Sbrian char *end; 113611336Samurai 113736285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 113836285Sbrian if (arg->argc > arg->argn+1) { 113936285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 114036285Sbrian return -1; 114111336Samurai } 114236285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 114336285Sbrian physical_SetSync(arg->cx->physical); 114436285Sbrian return 0; 114536285Sbrian } 114636285Sbrian end = NULL; 114736285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 114836285Sbrian if (*end) { 114936285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 115036285Sbrian arg->argv[arg->argn]); 115136285Sbrian return -1; 115236285Sbrian } 115336285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 115436285Sbrian return 0; 115536285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 115636285Sbrian } else 115736285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 115824939Sbrian 115926516Sbrian return -1; 116011336Samurai} 116111336Samurai 116225067Sbrianstatic int 116331343SbrianSetStoppedTimeout(struct cmdargs const *arg) 116428327Sbrian{ 116536285Sbrian struct link *l = &arg->cx->physical->link; 116636285Sbrian 116736285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 116836285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 116936285Sbrian if (arg->argc <= arg->argn+2) { 117036285Sbrian if (arg->argc > arg->argn) { 117136285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 117236285Sbrian if (arg->argc > arg->argn+1) 117336285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 117428461Sbrian } 117528327Sbrian return 0; 117628327Sbrian } 117728327Sbrian return -1; 117828327Sbrian} 117928327Sbrian 118031081Sbrian#define ismask(x) \ 118131081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 118231081Sbrian 118328327Sbrianstatic int 118431343SbrianSetServer(struct cmdargs const *arg) 118526940Sbrian{ 118626940Sbrian int res = -1; 118726940Sbrian 118836285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 118931081Sbrian const char *port, *passwd, *mask; 119031081Sbrian 119131081Sbrian /* What's what ? */ 119236285Sbrian port = arg->argv[arg->argn]; 119336285Sbrian if (arg->argc == arg->argn + 2) { 119436285Sbrian passwd = arg->argv[arg->argn+1]; 119536285Sbrian mask = NULL; 119636285Sbrian } else if (arg->argc == arg->argn + 3) { 119736285Sbrian passwd = arg->argv[arg->argn+1]; 119836285Sbrian mask = arg->argv[arg->argn+2]; 119931081Sbrian if (!ismask(mask)) 120031081Sbrian return -1; 120136285Sbrian } else if (strcasecmp(port, "none") == 0) { 120236285Sbrian if (server_Close(arg->bundle)) 120336285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 120436285Sbrian return 0; 120531081Sbrian } else 120636285Sbrian return -1; 120731081Sbrian 120836285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 120936285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 121031081Sbrian 121136285Sbrian if (*port == '/') { 121231081Sbrian mode_t imask; 121336285Sbrian char *ptr, name[LINE_LEN + 12]; 121428679Sbrian 121531081Sbrian if (mask != NULL) { 121628679Sbrian unsigned m; 121728679Sbrian 121831081Sbrian if (sscanf(mask, "%o", &m) == 1) 121931081Sbrian imask = m; 122031081Sbrian else 122131081Sbrian return -1; 122231081Sbrian } else 122331081Sbrian imask = (mode_t)-1; 122436285Sbrian 122536285Sbrian ptr = strstr(port, "%d"); 122636285Sbrian if (ptr) { 122736285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 122837210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 122936285Sbrian port = name; 123036285Sbrian } 123136285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 123227346Sbrian } else { 123336285Sbrian int iport, add = 0; 123428679Sbrian 123531081Sbrian if (mask != NULL) 123631081Sbrian return -1; 123728679Sbrian 123836285Sbrian if (*port == '+') { 123936285Sbrian port++; 124036285Sbrian add = 1; 124136285Sbrian } 124231081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 124331081Sbrian struct servent *s; 124431081Sbrian 124531081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 124631081Sbrian iport = 0; 124736285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 124828679Sbrian } else 124931081Sbrian iport = ntohs(s->s_port); 125027346Sbrian } else 125131081Sbrian iport = atoi(port); 125236285Sbrian 125336285Sbrian if (iport) { 125436285Sbrian if (add) 125536285Sbrian iport += arg->bundle->unit; 125636285Sbrian res = server_TcpOpen(arg->bundle, iport); 125736285Sbrian } else 125836285Sbrian res = -1; 125927346Sbrian } 126031081Sbrian } 126126940Sbrian 126226940Sbrian return res; 126326940Sbrian} 126426940Sbrian 126526940Sbrianstatic int 126631343SbrianSetEscape(struct cmdargs const *arg) 12676059Samurai{ 12686059Samurai int code; 126936285Sbrian int argc = arg->argc - arg->argn; 127036285Sbrian char const *const *argv = arg->argv + arg->argn; 12716059Samurai 12726059Samurai for (code = 0; code < 33; code++) 127336285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 127431343Sbrian 12756059Samurai while (argc-- > 0) { 12766059Samurai sscanf(*argv++, "%x", &code); 12776059Samurai code &= 0xff; 127836285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 127936285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 12806059Samurai } 128126516Sbrian return 0; 12826059Samurai} 12836059Samurai 12846059Samuraistatic int 128531343SbrianSetInterfaceAddr(struct cmdargs const *arg) 12866059Samurai{ 128736285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 128832267Sbrian const char *hisaddr; 128932267Sbrian 129040561Sbrian if (arg->argc > arg->argn + 4) 129140561Sbrian return -1; 129240561Sbrian 129332267Sbrian hisaddr = NULL; 129444874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 129544874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 129636285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 129736285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 129836285Sbrian iplist_reset(&ipcp->cfg.peer_list); 129928394Sbrian 130036285Sbrian if (arg->argc > arg->argn) { 130143313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 130236285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 130336285Sbrian &ipcp->cfg.my_range.width)) 130428679Sbrian return 1; 130536285Sbrian if (arg->argc > arg->argn+1) { 130636285Sbrian hisaddr = arg->argv[arg->argn+1]; 130736285Sbrian if (arg->argc > arg->argn+2) { 130844455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 130936285Sbrian if (arg->argc > arg->argn+3) { 131036285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 131136285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 13129440Samurai } 13136059Samurai } 13146059Samurai } 13156059Samurai } 131628394Sbrian 131740561Sbrian /* 0.0.0.0 means any address (0 bits) */ 131836285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 131936285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 132036285Sbrian ipcp->cfg.my_range.width = 0; 13216059Samurai } 132236285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 132347648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 132436285Sbrian 132536285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 132636928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 132732267Sbrian return 4; 132831121Sbrian 132926516Sbrian return 0; 13306059Samurai} 13316059Samurai 133218752Sjkhstatic int 133344305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 133444305Sbrian u_int *maxtrm, int def) 133544305Sbrian{ 133644305Sbrian if (argc == 0) { 133744305Sbrian *timeout = DEF_FSMRETRY; 133844305Sbrian *maxreq = def; 133944305Sbrian if (maxtrm != NULL) 134044305Sbrian *maxtrm = def; 134144305Sbrian } else { 134244305Sbrian long l = atol(argv[0]); 134344305Sbrian 134444305Sbrian if (l < MIN_FSMRETRY) { 134544305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 134644305Sbrian l, MIN_FSMRETRY); 134744305Sbrian return 1; 134844305Sbrian } else 134944305Sbrian *timeout = l; 135044305Sbrian 135144305Sbrian if (argc > 1) { 135244305Sbrian l = atol(argv[1]); 135344305Sbrian if (l < 1) { 135444305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 135544305Sbrian l = 1; 135644305Sbrian } 135744305Sbrian *maxreq = l; 135844305Sbrian 135944305Sbrian if (argc > 2 && maxtrm != NULL) { 136044305Sbrian l = atol(argv[2]); 136144305Sbrian if (l < 1) { 136244305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 136344305Sbrian l = 1; 136444305Sbrian } 136544305Sbrian *maxtrm = l; 136644305Sbrian } 136744305Sbrian } 136844305Sbrian } 136944305Sbrian 137044305Sbrian return 0; 137144305Sbrian} 137244305Sbrian 137344305Sbrianstatic int 137431343SbrianSetVariable(struct cmdargs const *arg) 13756059Samurai{ 137637210Sbrian long long_val, param = (long)arg->cmd->args; 137737210Sbrian int mode, dummyint; 137831343Sbrian const char *argp; 137936285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 138036285Sbrian const char *err = NULL; 138136285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 138236285Sbrian struct in_addr dummyaddr, *addr; 13836059Samurai 138436285Sbrian if (arg->argc > arg->argn) 138536285Sbrian argp = arg->argv[arg->argn]; 138626551Sbrian else 138731343Sbrian argp = ""; 138826551Sbrian 138936285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 139036285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 139136285Sbrian arg->cmd->name); 139236285Sbrian return 1; 139336285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 139436285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 139536285Sbrian arg->cmd->name, cx->name); 139636285Sbrian cx = NULL; 139736285Sbrian } 139836285Sbrian 139926551Sbrian switch (param) { 140028679Sbrian case VAR_AUTHKEY: 140140622Sbrian switch (bundle_Phase(arg->bundle)) { 140240622Sbrian case PHASE_DEAD: 140340622Sbrian case PHASE_ESTABLISH: 140440622Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 140540622Sbrian sizeof arg->bundle->cfg.auth.key - 1); 140640622Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 140740622Sbrian break; 140840622Sbrian default: 140940622Sbrian err = "set authkey: Only available at phase DEAD/ESTABLISH\n"; 141040622Sbrian log_Printf(LogWARN, err); 141140622Sbrian break; 141236285Sbrian } 141328679Sbrian break; 141437210Sbrian 141528679Sbrian case VAR_AUTHNAME: 141640622Sbrian switch (bundle_Phase(arg->bundle)) { 141740622Sbrian case PHASE_DEAD: 141840622Sbrian case PHASE_ESTABLISH: 141940622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 142040622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 142140622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 142240622Sbrian break; 142340622Sbrian default: 142440622Sbrian err = "set authname: Only available at phase DEAD/ESTABLISH\n"; 142540622Sbrian log_Printf(LogWARN, err); 142640622Sbrian break; 142736285Sbrian } 142828679Sbrian break; 142937210Sbrian 143036285Sbrian case VAR_AUTOLOAD: 143149434Sbrian if (arg->argc == arg->argn + 3) { 143249434Sbrian int v1, v2, v3; 143349434Sbrian char *end; 143449434Sbrian 143549434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 143649434Sbrian if (v1 < 0 || *end) { 143749434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 143849434Sbrian arg->argv[arg->argn]); 143949434Sbrian return 1; 144036285Sbrian } 144149434Sbrian 144249434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 144349434Sbrian if (v2 < 0 || *end) { 144449434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 144549434Sbrian arg->argv[arg->argn + 1]); 144649434Sbrian return 1; 144749434Sbrian } 144849434Sbrian if (v2 < v1) { 144949434Sbrian v3 = v1; 145049434Sbrian v1 = v2; 145149434Sbrian v2 = v3; 145249434Sbrian } 145349434Sbrian 145449434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 145549434Sbrian if (v3 <= 0 || *end) { 145649434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 145749434Sbrian arg->argv[arg->argn + 2]); 145849434Sbrian return 1; 145949434Sbrian } 146049434Sbrian 146149434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 146249434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 146349434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 146449434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 146536285Sbrian } else { 146649434Sbrian err = "Set autoload requires three arguments\n"; 146736285Sbrian log_Printf(LogWARN, err); 146836285Sbrian } 146936285Sbrian break; 147037210Sbrian 147128679Sbrian case VAR_DIAL: 147236285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 147336285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 147428679Sbrian break; 147537210Sbrian 147628679Sbrian case VAR_LOGIN: 147736285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 147836285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 147928679Sbrian break; 148037210Sbrian 148136285Sbrian case VAR_WINSIZE: 148236285Sbrian if (arg->argc > arg->argn) { 148336285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 148436285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 148536285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 148636285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 148736285Sbrian l->ccp.cfg.deflate.out.winsize); 148836285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 148936285Sbrian } 149036285Sbrian if (arg->argc > arg->argn+1) { 149136285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 149236285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 149336285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 149436285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 149536285Sbrian l->ccp.cfg.deflate.in.winsize); 149636285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 149736285Sbrian } 149836285Sbrian } else 149936285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 150036285Sbrian } else { 150136285Sbrian err = "No window size specified\n"; 150236285Sbrian log_Printf(LogWARN, err); 150336285Sbrian } 150436285Sbrian break; 150537210Sbrian 150628679Sbrian case VAR_DEVICE: 150736285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 150836285Sbrian arg->argv + arg->argn); 150936285Sbrian break; 151037210Sbrian 151136285Sbrian case VAR_ACCMAP: 151236285Sbrian if (arg->argc > arg->argn) { 151337210Sbrian u_long ulong_val; 151436285Sbrian sscanf(argp, "%lx", &ulong_val); 151537210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 151636285Sbrian } else { 151736285Sbrian err = "No accmap specified\n"; 151836285Sbrian log_Printf(LogWARN, err); 151936285Sbrian } 152036285Sbrian break; 152137210Sbrian 152236285Sbrian case VAR_MODE: 152336285Sbrian mode = Nam2mode(argp); 152436285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 152536285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 152636285Sbrian return -1; 152736285Sbrian } 152836285Sbrian bundle_SetMode(arg->bundle, cx, mode); 152936285Sbrian break; 153037210Sbrian 153136285Sbrian case VAR_MRRU: 153240622Sbrian switch (bundle_Phase(arg->bundle)) { 153340622Sbrian case PHASE_DEAD: 153440622Sbrian break; 153540622Sbrian case PHASE_ESTABLISH: 153640622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 153740622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 153840622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 153940622Sbrian return 1; 154040622Sbrian } 154140622Sbrian break; 154240622Sbrian default: 154340622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 154440622Sbrian return 1; 154529696Sbrian } 154637210Sbrian long_val = atol(argp); 154737210Sbrian if (long_val && long_val < MIN_MRU) { 154837210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 154937210Sbrian return 1; 155037210Sbrian } else if (long_val > MAX_MRU) { 155137210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 155237210Sbrian return 1; 155337210Sbrian } else 155437210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 155528679Sbrian break; 155637210Sbrian 155736285Sbrian case VAR_MRU: 155837210Sbrian long_val = atol(argp); 155937210Sbrian if (long_val == 0) 156037210Sbrian l->lcp.cfg.mru = DEF_MRU; 156137210Sbrian else if (long_val < MIN_MRU) { 156237210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 156337210Sbrian return 1; 156437210Sbrian } else if (long_val > MAX_MRU) { 156537210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 156637210Sbrian return 1; 156737210Sbrian } else 156837210Sbrian l->lcp.cfg.mru = long_val; 156928679Sbrian break; 157037210Sbrian 157136285Sbrian case VAR_MTU: 157237210Sbrian long_val = atol(argp); 157337210Sbrian if (long_val && long_val < MIN_MTU) { 157437210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 157537210Sbrian return 1; 157637210Sbrian } else if (long_val > MAX_MTU) { 157737210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 157837210Sbrian return 1; 157937210Sbrian } else 158037210Sbrian arg->bundle->cfg.mtu = long_val; 158136285Sbrian break; 158237210Sbrian 158336285Sbrian case VAR_OPENMODE: 158436285Sbrian if (strcasecmp(argp, "active") == 0) 158536285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 158636285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 158736285Sbrian else if (strcasecmp(argp, "passive") == 0) 158836285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 158936285Sbrian else { 159036285Sbrian err = "%s: Invalid openmode\n"; 159136285Sbrian log_Printf(LogWARN, err, argp); 159236285Sbrian } 159336285Sbrian break; 159437210Sbrian 159528679Sbrian case VAR_PHONE: 159636285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 159736285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 159838174Sbrian cx->phone.alt = cx->phone.next = NULL; 159928679Sbrian break; 160037210Sbrian 160128679Sbrian case VAR_HANGUP: 160236285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 160336285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 160428679Sbrian break; 160537210Sbrian 160636285Sbrian case VAR_IDLETIMEOUT: 160736285Sbrian if (arg->argc > arg->argn+1) 160836285Sbrian err = "Too many idle timeout values\n"; 160936285Sbrian else if (arg->argc == arg->argn+1) 161036285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 161136285Sbrian if (err) 161236285Sbrian log_Printf(LogWARN, err); 161329549Sbrian break; 161437210Sbrian 161536285Sbrian case VAR_LQRPERIOD: 161637210Sbrian long_val = atol(argp); 161737210Sbrian if (long_val < MIN_LQRPERIOD) { 161837210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 161937210Sbrian long_val, MIN_LQRPERIOD); 162037210Sbrian return 1; 162136285Sbrian } else 162237210Sbrian l->lcp.cfg.lqrperiod = long_val; 162336285Sbrian break; 162437210Sbrian 162536285Sbrian case VAR_LCPRETRY: 162644305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 162744305Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 162844305Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 162944305Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 163036285Sbrian break; 163137210Sbrian 163236285Sbrian case VAR_CHAPRETRY: 163344305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 163444305Sbrian &cx->chap.auth.cfg.fsm.timeout, 163544305Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 163636285Sbrian break; 163737210Sbrian 163836285Sbrian case VAR_PAPRETRY: 163944305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 164044305Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 164144305Sbrian NULL, DEF_FSMAUTHTRIES); 164236285Sbrian break; 164337210Sbrian 164436285Sbrian case VAR_CCPRETRY: 164544305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 164644305Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 164744305Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 164836285Sbrian break; 164937210Sbrian 165036285Sbrian case VAR_IPCPRETRY: 165144305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 165244305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 165344305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 165444305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 165536285Sbrian break; 165637210Sbrian 165736285Sbrian case VAR_NBNS: 165836285Sbrian case VAR_DNS: 165936285Sbrian if (param == VAR_DNS) 166036285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 166136285Sbrian else 166236285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 166336285Sbrian 166436285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 166536285Sbrian 166636285Sbrian if (arg->argc > arg->argn) { 166743313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 166836285Sbrian addr, &dummyaddr, &dummyint); 166936285Sbrian if (arg->argc > arg->argn+1) 167043313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 167136285Sbrian addr + 1, &dummyaddr, &dummyint); 167236285Sbrian 167336285Sbrian if (addr[1].s_addr == INADDR_ANY) 167436285Sbrian addr[1].s_addr = addr[0].s_addr; 167536285Sbrian if (addr[0].s_addr == INADDR_ANY) 167636285Sbrian addr[0].s_addr = addr[1].s_addr; 167736285Sbrian } 167836285Sbrian break; 167938174Sbrian 168038174Sbrian case VAR_CALLBACK: 168138174Sbrian cx->cfg.callback.opmask = 0; 168238174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 168338174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 168438174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 168538174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 168638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 168738174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 168838174Sbrian if (dummyint == arg->argc - 1) 168938174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 169038174Sbrian else { 169138174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 169238174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 169338174Sbrian sizeof cx->cfg.callback.msg - 1); 169438174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 169538174Sbrian } 169638174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 169738174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 169838174Sbrian else 169938174Sbrian return -1; 170038174Sbrian } 170138174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 170238174Sbrian cx->cfg.callback.opmask = 0; 170338174Sbrian break; 170438174Sbrian 170538174Sbrian case VAR_CBCP: 170638174Sbrian cx->cfg.cbcp.delay = 0; 170738174Sbrian *cx->cfg.cbcp.phone = '\0'; 170838174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 170938174Sbrian if (arg->argc > arg->argn) { 171038174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 171138174Sbrian sizeof cx->cfg.cbcp.phone - 1); 171238174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 171338174Sbrian if (arg->argc > arg->argn + 1) { 171438174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 171538174Sbrian if (arg->argc > arg->argn + 2) { 171638174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 171738174Sbrian if (long_val < MIN_FSMRETRY) 171838174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 171938174Sbrian long_val, MIN_FSMRETRY); 172038174Sbrian else 172138174Sbrian cx->cfg.cbcp.fsmretry = long_val; 172238174Sbrian } 172338174Sbrian } 172438174Sbrian } 172538174Sbrian break; 172638544Sbrian 172738544Sbrian case VAR_CHOKED: 172838544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 172938544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 173038544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 173138544Sbrian break; 173240665Sbrian 173340665Sbrian case VAR_SENDPIPE: 173440665Sbrian long_val = atol(argp); 173540665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 173640665Sbrian break; 173740665Sbrian 173840665Sbrian case VAR_RECVPIPE: 173940665Sbrian long_val = atol(argp); 174040665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 174140665Sbrian break; 174243313Sbrian 174343313Sbrian#ifndef NORADIUS 174443313Sbrian case VAR_RADIUS: 174543313Sbrian if (!*argp) 174643313Sbrian *arg->bundle->radius.cfg.file = '\0'; 174743313Sbrian else if (access(argp, R_OK)) { 174843313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 174943313Sbrian return 1; 175043313Sbrian } else { 175143313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 175243313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 175343313Sbrian arg->bundle->radius.cfg.file 175443313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 175543313Sbrian } 175643313Sbrian break; 175743313Sbrian#endif 175844073Sbrian 175944073Sbrian case VAR_CD: 176044073Sbrian if (*argp) { 176144073Sbrian long_val = atol(argp); 176244073Sbrian if (long_val < 0) 176344073Sbrian long_val = 0; 176444073Sbrian cx->physical->cfg.cd.delay = long_val; 176544073Sbrian cx->physical->cfg.cd.required = argp[strlen(argp)-1] == '!'; 176644073Sbrian } else { 176744073Sbrian cx->physical->cfg.cd.delay = DEF_CDDELAY; 176844073Sbrian cx->physical->cfg.cd.required = 0; 176944073Sbrian } 177044073Sbrian break; 177136285Sbrian 177246686Sbrian case VAR_PARITY: 177346686Sbrian if (arg->argc == arg->argn + 1) 177446686Sbrian return physical_SetParity(arg->cx->physical, argp); 177546686Sbrian else { 177646686Sbrian err = "Parity value must be odd, even or none\n"; 177746686Sbrian log_Printf(LogWARN, err); 177846686Sbrian } 177946686Sbrian break; 17806059Samurai 178146686Sbrian case VAR_CRTSCTS: 178246686Sbrian if (strcasecmp(argp, "on") == 0) 178336285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 178446686Sbrian else if (strcasecmp(argp, "off") == 0) 178536285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 178646686Sbrian else { 178746686Sbrian err = "RTS/CTS value must be on or off\n"; 178846686Sbrian log_Printf(LogWARN, err); 178946686Sbrian } 179046686Sbrian break; 179120812Sjkh } 179246686Sbrian 179346686Sbrian return err ? 1 : 0; 179420812Sjkh} 179520812Sjkh 179630715Sbrianstatic struct cmdtab const SetCommands[] = { 179736285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 179836285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 179928679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 180036285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 180128679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 180236285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 180336285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 180436285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 180536285Sbrian (const void *)VAR_AUTOLOAD}, 180638174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 180738174Sbrian "callback control", "set callback [none|auth|cbcp|" 180838174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 180938174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 181038174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 181138174Sbrian (const void *)VAR_CBCP}, 181244305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 181344305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 181444073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 181544073Sbrian "set cd value[!]", (const void *)VAR_CD}, 181644305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 181744305Sbrian "CHAP retries", "set chapretry value [attempts]", 181844305Sbrian (const void *)VAR_CHAPRETRY}, 181938544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 182038544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 182146686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 182246686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 182346686Sbrian (const char *)VAR_CRTSCTS}, 182436285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 182536285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 182636285Sbrian (const void *) VAR_WINSIZE}, 182736285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 182846686Sbrian "physical device name", "set device|line device-name[,device-name]", 182936285Sbrian (const void *) VAR_DEVICE}, 183036285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 183136285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 183236285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 183336285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 183436285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 183536285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 183636285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 183736285Sbrian "escape characters", "set escape hex-digit ..."}, 183836285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 183936285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 184049388Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 184148142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 184236285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 184336285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 184436285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 184531343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 184644305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 184744305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 184844305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 184944305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 185036712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 185138622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 185247699Sbrian "ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 185336285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 185436285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 185536285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 185636285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 185736285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 185836285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 185936285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 186036285Sbrian "set mrru value", (const void *)VAR_MRRU}, 186136285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 186236285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 186336285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 186436285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 186536285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 186636285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 186736285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 186836285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 186944305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 187044305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 187146686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 187246686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 187336285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 187436285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 187540679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 187640679Sbrian "Process title", "set proctitle [value]"}, 187743313Sbrian#ifndef NORADIUS 187843313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 187943313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 188043313Sbrian#endif 188136285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 188236285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 188340665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 188440665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 188536285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 188644468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 188740665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 188840665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 188928679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 189036774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 189136285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 189246686Sbrian "physical speed", "set speed value|sync"}, 189336285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 189436285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 189536285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 189636285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 189736285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 189836285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 189949434Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 190049434Sbrian "datalink bandwidth", "set bandwidth value"}, 190128679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 190231343Sbrian "Display this message", "set help|? [command]", SetCommands}, 190328679Sbrian {NULL, NULL, NULL}, 19046059Samurai}; 19056059Samurai 19066059Samuraistatic int 190731343SbrianSetCommand(struct cmdargs const *arg) 19086059Samurai{ 190936285Sbrian if (arg->argc > arg->argn) 191036285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 191136285Sbrian arg->prompt, arg->cx); 191236285Sbrian else if (arg->prompt) 191336285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 191426516Sbrian " syntax help.\n"); 19156059Samurai else 191636285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 191726516Sbrian 191826516Sbrian return 0; 19196059Samurai} 19206059Samurai 19216059Samuraistatic int 192231343SbrianAddCommand(struct cmdargs const *arg) 19236059Samurai{ 19246059Samurai struct in_addr dest, gateway, netmask; 192536285Sbrian int gw, addrs; 19266059Samurai 192736285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 192831598Sbrian return -1; 192931598Sbrian 193036285Sbrian addrs = 0; 193136285Sbrian if (arg->argc == arg->argn+2) { 193236285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 193336285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 193431598Sbrian else { 193536285Sbrian int width; 193636285Sbrian 193743313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 193836285Sbrian &dest, &netmask, &width)) 193936285Sbrian return -1; 194036285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 194136285Sbrian addrs = ROUTE_DSTMYADDR; 194236285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 194336285Sbrian addrs = ROUTE_DSTHISADDR; 194431598Sbrian } 194536285Sbrian gw = 1; 194634536Sbrian } else { 194736285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 194836285Sbrian addrs = ROUTE_DSTMYADDR; 194936285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 195036285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 195136285Sbrian addrs = ROUTE_DSTHISADDR; 195236285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 195336285Sbrian } else 195436285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 195536285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 195631598Sbrian gw = 2; 19576059Samurai } 195836285Sbrian 195936285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 196036285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 196136285Sbrian addrs |= ROUTE_GWHISADDR; 196240561Sbrian } else 196336285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 196436285Sbrian 196536285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 196643313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 196743313Sbrian && addrs != ROUTE_STATIC) 196836285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 196936285Sbrian 197031598Sbrian return 0; 19716059Samurai} 19726059Samurai 19736059Samuraistatic int 197431343SbrianDeleteCommand(struct cmdargs const *arg) 19756059Samurai{ 197631598Sbrian struct in_addr dest, none; 197736285Sbrian int addrs; 19786059Samurai 197936285Sbrian if (arg->argc == arg->argn+1) { 198036285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 198136285Sbrian route_IfDelete(arg->bundle, 0); 198236285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 198336285Sbrian } else { 198436285Sbrian addrs = 0; 198536285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 198636285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 198736285Sbrian addrs = ROUTE_DSTMYADDR; 198836285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 198936285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 199036285Sbrian addrs = ROUTE_DSTHISADDR; 199136285Sbrian } else { 199244279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 199344279Sbrian if (dest.s_addr == INADDR_NONE) { 199444279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 199544279Sbrian return -1; 199644279Sbrian } 199736285Sbrian addrs = ROUTE_STATIC; 199836285Sbrian } 199931598Sbrian none.s_addr = INADDR_ANY; 200036285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 200137927Sbrian arg->cmd->args ? 1 : 0, 0); 200236285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 200331598Sbrian } 200434536Sbrian } else 200526516Sbrian return -1; 200626516Sbrian 200726516Sbrian return 0; 20086059Samurai} 20096059Samurai 201031343Sbrian#ifndef NOALIAS 201126031Sbrianstatic int 201231343SbrianAliasEnable(struct cmdargs const *arg) 201326031Sbrian{ 201436285Sbrian if (arg->argc == arg->argn+1) { 201536285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 201646686Sbrian if (!arg->bundle->AliasEnabled) { 201746686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 201846686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 201946686Sbrian arg->bundle->AliasEnabled = 1; 202046686Sbrian } 202137191Sbrian return 0; 202236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 202337191Sbrian arg->bundle->AliasEnabled = 0; 202440561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 202540561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 202626516Sbrian return 0; 202726142Sbrian } 202835449Sbrian } 202936285Sbrian 203026516Sbrian return -1; 203126031Sbrian} 203226031Sbrian 203326031Sbrian 203426031Sbrianstatic int 203531343SbrianAliasOption(struct cmdargs const *arg) 203626031Sbrian{ 203738559Sbrian long param = (long)arg->cmd->args; 203838559Sbrian 203936285Sbrian if (arg->argc == arg->argn+1) { 204036285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 204137191Sbrian if (arg->bundle->AliasEnabled) { 204237191Sbrian PacketAliasSetMode(param, param); 204328679Sbrian return 0; 204428679Sbrian } 204536285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 204636285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 204737191Sbrian if (arg->bundle->AliasEnabled) { 204837191Sbrian PacketAliasSetMode(0, param); 204928679Sbrian return 0; 205028679Sbrian } 205136285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 205228679Sbrian } 205335449Sbrian } 205428679Sbrian return -1; 205526031Sbrian} 205631343Sbrian#endif /* #ifndef NOALIAS */ 205731121Sbrian 205831121Sbrianstatic int 205936285SbrianLinkCommand(struct cmdargs const *arg) 206036285Sbrian{ 206136285Sbrian if (arg->argc > arg->argn+1) { 206236285Sbrian char namelist[LINE_LEN]; 206336285Sbrian struct datalink *cx; 206436285Sbrian char *name; 206536285Sbrian int result = 0; 206636285Sbrian 206736285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 206836285Sbrian struct datalink *dl; 206936285Sbrian 207036285Sbrian cx = arg->bundle->links; 207136285Sbrian while (cx) { 207236285Sbrian /* Watch it, the command could be a ``remove'' */ 207336285Sbrian dl = cx->next; 207436285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 207536285Sbrian arg->prompt, cx); 207636285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 207736285Sbrian if (cx == dl) 207836285Sbrian break; /* Pointer's still valid ! */ 207936285Sbrian } 208036285Sbrian } else { 208136285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 208236285Sbrian namelist[sizeof namelist - 1] = '\0'; 208336285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 208436285Sbrian if (!bundle2datalink(arg->bundle, name)) { 208536285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 208636285Sbrian return 1; 208736285Sbrian } 208836285Sbrian 208936285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 209036285Sbrian namelist[sizeof namelist - 1] = '\0'; 209136285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 209236285Sbrian cx = bundle2datalink(arg->bundle, name); 209336285Sbrian if (cx) 209436285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 209536285Sbrian arg->prompt, cx); 209636285Sbrian else { 209736285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 209836285Sbrian result++; 209936285Sbrian } 210036285Sbrian } 210136285Sbrian } 210236285Sbrian return result; 210336285Sbrian } 210436285Sbrian 210536285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 210636285Sbrian return 2; 210736285Sbrian} 210836285Sbrian 210936285Sbrianstruct link * 211036285Sbriancommand_ChooseLink(struct cmdargs const *arg) 211136285Sbrian{ 211236285Sbrian if (arg->cx) 211336285Sbrian return &arg->cx->physical->link; 211437210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 211536285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 211637210Sbrian if (dl) 211737210Sbrian return &dl->physical->link; 211836285Sbrian } 211937210Sbrian return &arg->bundle->ncp.mp.link; 212036285Sbrian} 212136285Sbrian 212236285Sbrianstatic const char * 212336285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 212436285Sbrian{ 212536285Sbrian const char *result; 212636285Sbrian 212736285Sbrian switch (*cmd) { 212836285Sbrian case 'A': 212936285Sbrian case 'a': 213036285Sbrian result = "accept"; 213136285Sbrian *keep = NEG_MYMASK; 213236285Sbrian *add = NEG_ACCEPTED; 213336285Sbrian break; 213436285Sbrian case 'D': 213536285Sbrian case 'd': 213636285Sbrian switch (cmd[1]) { 213736285Sbrian case 'E': 213836285Sbrian case 'e': 213936285Sbrian result = "deny"; 214036285Sbrian *keep = NEG_MYMASK; 214136285Sbrian *add = 0; 214236285Sbrian break; 214336285Sbrian case 'I': 214436285Sbrian case 'i': 214536285Sbrian result = "disable"; 214636285Sbrian *keep = NEG_HISMASK; 214736285Sbrian *add = 0; 214836285Sbrian break; 214936285Sbrian default: 215036285Sbrian return NULL; 215136285Sbrian } 215236285Sbrian break; 215336285Sbrian case 'E': 215436285Sbrian case 'e': 215536285Sbrian result = "enable"; 215636285Sbrian *keep = NEG_HISMASK; 215736285Sbrian *add = NEG_ENABLED; 215836285Sbrian break; 215936285Sbrian default: 216036285Sbrian return NULL; 216136285Sbrian } 216236285Sbrian 216336285Sbrian return result; 216436285Sbrian} 216536285Sbrian 216636285Sbrianstatic int 216736285SbrianOptSet(struct cmdargs const *arg) 216836285Sbrian{ 216937574Sbrian int bit = (int)(long)arg->cmd->args; 217036285Sbrian const char *cmd; 217136285Sbrian unsigned keep; /* Keep these bits */ 217236285Sbrian unsigned add; /* Add these bits */ 217336285Sbrian 217436285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 217536285Sbrian return 1; 217636285Sbrian 217736285Sbrian if (add) 217836285Sbrian arg->bundle->cfg.opt |= bit; 217936285Sbrian else 218036285Sbrian arg->bundle->cfg.opt &= ~bit; 218136285Sbrian return 0; 218236285Sbrian} 218336285Sbrian 218436285Sbrianstatic int 218540561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 218640561Sbrian{ 218740561Sbrian unsigned save = arg->bundle->cfg.opt; 218840561Sbrian int result = OptSet(arg); 218940561Sbrian 219040561Sbrian if (result == 0) 219140561Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->AliasEnabled) { 219240561Sbrian arg->bundle->cfg.opt = save; 219340561Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without IP aliasing\n"); 219440561Sbrian result = 2; 219540561Sbrian } 219640561Sbrian 219740561Sbrian return result; 219840561Sbrian} 219940561Sbrian 220040561Sbrianstatic int 220136285SbrianNegotiateSet(struct cmdargs const *arg) 220236285Sbrian{ 220337210Sbrian long param = (long)arg->cmd->args; 220436285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 220536285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 220636285Sbrian const char *cmd; 220736285Sbrian unsigned keep; /* Keep these bits */ 220836285Sbrian unsigned add; /* Add these bits */ 220936285Sbrian 221036285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 221136285Sbrian return 1; 221236285Sbrian 221336285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 221436285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 221536285Sbrian cmd, arg->cmd->name); 221636285Sbrian return 2; 221736285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 221836285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 221936285Sbrian cmd, arg->cmd->name, cx->name); 222036285Sbrian cx = NULL; 222136285Sbrian } 222236285Sbrian 222336285Sbrian switch (param) { 222436285Sbrian case NEG_ACFCOMP: 222536285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 222636285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 222736285Sbrian break; 222844106Sbrian case NEG_CHAP05: 222944106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 223044106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 223136285Sbrian break; 223244106Sbrian#ifdef HAVE_DES 223344106Sbrian case NEG_CHAP80: 223444106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 223544106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 223644106Sbrian break; 223744106Sbrian case NEG_CHAP80LM: 223844106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 223944106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 224044106Sbrian break; 224144106Sbrian#endif 224236285Sbrian case NEG_DEFLATE: 224336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 224436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 224536285Sbrian break; 224636285Sbrian case NEG_DNS: 224736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 224836285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 224936285Sbrian break; 225047858Sbrian case NEG_ENDDISC: 225147858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 225247858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 225347858Sbrian break; 225436285Sbrian case NEG_LQR: 225536285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 225636285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 225736285Sbrian break; 225836285Sbrian case NEG_PAP: 225936285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 226036285Sbrian cx->physical->link.lcp.cfg.pap |= add; 226136285Sbrian break; 226236285Sbrian case NEG_PPPDDEFLATE: 226336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 226436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 226536285Sbrian break; 226636285Sbrian case NEG_PRED1: 226736285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 226836285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 226936285Sbrian break; 227036285Sbrian case NEG_PROTOCOMP: 227136285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 227236285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 227336285Sbrian break; 227436285Sbrian case NEG_SHORTSEQ: 227540622Sbrian switch (bundle_Phase(arg->bundle)) { 227640622Sbrian case PHASE_DEAD: 227740622Sbrian break; 227840622Sbrian case PHASE_ESTABLISH: 227940622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 228040622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 228140622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 228240622Sbrian " LCP negotiations\n"); 228340622Sbrian return 1; 228440622Sbrian } 228540622Sbrian break; 228640622Sbrian default: 228740622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 228840622Sbrian " DEAD/ESTABLISH\n"); 228940622Sbrian return 1; 229036285Sbrian } 229140622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 229240622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 229336285Sbrian break; 229436285Sbrian case NEG_VJCOMP: 229536285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 229636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 229736285Sbrian break; 229836285Sbrian } 229936285Sbrian 230036285Sbrian return 0; 230136285Sbrian} 230236285Sbrian 230336285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 230436285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 230536285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 230640666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 230740666Sbrian "retain interface addresses", "disable|enable", 230840666Sbrian (const void *)OPT_IFACEALIAS}, 230947689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 231047689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 231136285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 231236285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 231336285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 231436285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 231540665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 231636285Sbrian "disable|enable", (const void *)OPT_PROXY}, 231740665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 231840665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 231936285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 232036285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 232136285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 232236285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 232336285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 232436285Sbrian "disable|enable", (const void *)OPT_UTMP}, 232536285Sbrian 232647689Sbrian#define OPT_MAX 10 /* accept/deny allowed below and not above */ 232736285Sbrian 232836285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 232936285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 233036285Sbrian (const void *)NEG_ACFCOMP}, 233144106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 233236285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 233344106Sbrian (const void *)NEG_CHAP05}, 233444106Sbrian#ifdef HAVE_DES 233544106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 233644106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 233744106Sbrian (const void *)NEG_CHAP80}, 233844106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 233944106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 234044106Sbrian (const void *)NEG_CHAP80LM}, 234144106Sbrian#endif 234236285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 234336285Sbrian "Deflate compression", "accept|deny|disable|enable", 234436285Sbrian (const void *)NEG_DEFLATE}, 234536285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 234636285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 234736285Sbrian (const void *)NEG_PPPDDEFLATE}, 234836285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 234936285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 235047858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 235147858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 235236285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 235336285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 235436285Sbrian (const void *)NEG_LQR}, 235536285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 235636285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 235736285Sbrian (const void *)NEG_PAP}, 235836285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 235936285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 236036285Sbrian (const void *)NEG_PRED1}, 236136285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 236236285Sbrian "Protocol field compression", "accept|deny|disable|enable", 236336285Sbrian (const void *)NEG_PROTOCOMP}, 236436285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 236536285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 236636285Sbrian (const void *)NEG_SHORTSEQ}, 236736285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 236836285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 236936285Sbrian (const void *)NEG_VJCOMP}, 237036285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 237136285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 237236285Sbrian NegotiateCommands}, 237336285Sbrian {NULL, NULL, NULL}, 237436285Sbrian}; 237536285Sbrian 237636285Sbrianstatic int 237736285SbrianNegotiateCommand(struct cmdargs const *arg) 237836285Sbrian{ 237936285Sbrian if (arg->argc > arg->argn) { 238036285Sbrian char const *argv[3]; 238136285Sbrian unsigned keep, add; 238236285Sbrian int n; 238336285Sbrian 238436285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 238536285Sbrian return -1; 238636285Sbrian argv[2] = NULL; 238736285Sbrian 238836285Sbrian for (n = arg->argn; n < arg->argc; n++) { 238936285Sbrian argv[1] = arg->argv[n]; 239036285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 239136285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 239236285Sbrian } 239336285Sbrian } else if (arg->prompt) 239436285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 239536285Sbrian arg->argv[arg->argn-1]); 239636285Sbrian else 239736285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 239836285Sbrian arg->argv[arg->argn] ); 239936285Sbrian 240036285Sbrian return 0; 240136285Sbrian} 240236285Sbrian 240336285Sbrianconst char * 240436285Sbriancommand_ShowNegval(unsigned val) 240536285Sbrian{ 240636285Sbrian switch (val&3) { 240736285Sbrian case 1: return "disabled & accepted"; 240836285Sbrian case 2: return "enabled & denied"; 240936285Sbrian case 3: return "enabled & accepted"; 241036285Sbrian } 241136285Sbrian return "disabled & denied"; 241236285Sbrian} 241336934Sbrian 241436934Sbrianstatic int 241536934SbrianClearCommand(struct cmdargs const *arg) 241636934Sbrian{ 241736934Sbrian struct pppThroughput *t; 241836934Sbrian struct datalink *cx; 241936934Sbrian int i, clear_type; 242036934Sbrian 242136934Sbrian if (arg->argc < arg->argn + 1) 242236934Sbrian return -1; 242336934Sbrian 242446686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 242536934Sbrian cx = arg->cx; 242636934Sbrian if (!cx) 242736934Sbrian cx = bundle2datalink(arg->bundle, NULL); 242836934Sbrian if (!cx) { 242946686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 243036934Sbrian return 1; 243136934Sbrian } 243236934Sbrian t = &cx->physical->link.throughput; 243336934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 243436934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 243536934Sbrian else 243636934Sbrian return -1; 243736934Sbrian 243836934Sbrian if (arg->argc > arg->argn + 1) { 243936934Sbrian clear_type = 0; 244036934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 244136934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 244236934Sbrian clear_type |= THROUGHPUT_OVERALL; 244336934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 244436934Sbrian clear_type |= THROUGHPUT_CURRENT; 244536934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 244636934Sbrian clear_type |= THROUGHPUT_PEAK; 244736934Sbrian else 244836934Sbrian return -1; 244936934Sbrian } else 245036934Sbrian clear_type = THROUGHPUT_ALL; 245136934Sbrian 245236934Sbrian throughput_clear(t, clear_type, arg->prompt); 245336934Sbrian return 0; 245436934Sbrian} 245540561Sbrian 245640561Sbrianstatic int 245740561SbrianRunListCommand(struct cmdargs const *arg) 245840561Sbrian{ 245940561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 246040561Sbrian 246140561Sbrian if (arg->argc > arg->argn) 246240561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 246340561Sbrian arg->prompt, arg->cx); 246440561Sbrian else if (arg->prompt) 246540561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 246640561Sbrian " <option>' for syntax help.\n", cmd, cmd); 246740561Sbrian else 246840561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 246940561Sbrian 247040561Sbrian return 0; 247140561Sbrian} 247240561Sbrian 247340561Sbrianstatic int 247440561SbrianIfaceAddCommand(struct cmdargs const *arg) 247540561Sbrian{ 247640561Sbrian int bits, n, how; 247740561Sbrian struct in_addr ifa, mask, brd; 247840561Sbrian 247940664Sbrian if (arg->argc == arg->argn + 1) { 248043313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 248140561Sbrian return -1; 248240664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 248340664Sbrian } else { 248440664Sbrian if (arg->argc == arg->argn + 2) { 248543313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 248640664Sbrian return -1; 248740664Sbrian n = 1; 248840664Sbrian } else if (arg->argc == arg->argn + 3) { 248943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 249040664Sbrian return -1; 249143313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 249240664Sbrian return -1; 249340664Sbrian n = 2; 249440664Sbrian } else 249540561Sbrian return -1; 249640561Sbrian 249743313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 249840664Sbrian return -1; 249940664Sbrian } 250040561Sbrian 250140561Sbrian how = IFACE_ADD_LAST; 250240561Sbrian if (arg->cmd->args) 250340561Sbrian how |= IFACE_FORCE_ADD; 250440561Sbrian 250540561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 250640561Sbrian} 250740561Sbrian 250840561Sbrianstatic int 250940561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 251040561Sbrian{ 251140561Sbrian struct in_addr ifa; 251240561Sbrian int ok; 251340561Sbrian 251440561Sbrian if (arg->argc != arg->argn + 1) 251540561Sbrian return -1; 251640561Sbrian 251743313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 251840561Sbrian return -1; 251940561Sbrian 252040561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 252140561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 252240561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 252340561Sbrian inet_ntoa(ifa)); 252440561Sbrian return 1; 252540561Sbrian } 252640561Sbrian 252740561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 252840561Sbrian if (!ok) { 252940561Sbrian if (arg->cmd->args) 253040561Sbrian ok = 1; 253140561Sbrian else if (arg->prompt) 253240561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 253340561Sbrian else 253440561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 253540561Sbrian } 253640561Sbrian 253740561Sbrian return !ok; 253840561Sbrian} 253940561Sbrian 254040561Sbrianstatic int 254140561SbrianIfaceClearCommand(struct cmdargs const *arg) 254240561Sbrian{ 254340561Sbrian int how; 254440561Sbrian 254540561Sbrian if (arg->argc != arg->argn) 254640561Sbrian return -1; 254740561Sbrian 254840941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 254940941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 255040561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 255140561Sbrian iface_Clear(arg->bundle->iface, how); 255240561Sbrian 255340561Sbrian return 0; 255440561Sbrian} 255540679Sbrian 255640679Sbrianstatic int 255740679SbrianSetProcTitle(struct cmdargs const *arg) 255840679Sbrian{ 255940679Sbrian static char title[LINE_LEN]; 256040679Sbrian char *argv[MAXARGS], *ptr; 256140679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 256240679Sbrian 256340679Sbrian if (arg->argc == arg->argn) { 256440679Sbrian arg->bundle->argv[0] = arg->bundle->argv0; 256540679Sbrian arg->bundle->argv[1] = arg->bundle->argv1; 256640679Sbrian return 0; 256740679Sbrian } 256840679Sbrian 256940679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 257040679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 257140679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 257240679Sbrian } 257347849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 257440679Sbrian 257540679Sbrian ptr = title; 257640679Sbrian remaining = sizeof title - 1; 257740679Sbrian for (f = 0; f < argc && remaining; f++) { 257840679Sbrian if (f) { 257940679Sbrian *ptr++ = ' '; 258040679Sbrian remaining--; 258140679Sbrian } 258240679Sbrian len = strlen(argv[f]); 258340679Sbrian if (len > remaining) 258440679Sbrian len = remaining; 258540679Sbrian memcpy(ptr, argv[f], len); 258640679Sbrian remaining -= len; 258740679Sbrian ptr += len; 258840679Sbrian } 258940679Sbrian *ptr = '\0'; 259040679Sbrian 259140679Sbrian arg->bundle->argv[0] = title; 259240679Sbrian arg->bundle->argv[1] = NULL; 259340679Sbrian 259440679Sbrian return 0; 259540679Sbrian} 2596