command.c revision 50479
16059Samurai/* 26059Samurai * PPP User command processing module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2050479Speter * $FreeBSD: head/usr.sbin/ppp/command.c 50479 1999-08-28 01:35:59Z peter $ 218857Srgrimes * 226059Samurai */ 2343313Sbrian#include <sys/param.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3338628Sbrian#include <ctype.h> 3430715Sbrian#include <errno.h> 3526516Sbrian#include <fcntl.h> 3630715Sbrian#include <paths.h> 3730715Sbrian#include <stdio.h> 3830715Sbrian#include <stdlib.h> 3930715Sbrian#include <string.h> 4030715Sbrian#include <sys/wait.h> 4130715Sbrian#include <termios.h> 4230715Sbrian#include <unistd.h> 4330715Sbrian 4450059Sbrian#ifndef NONAT 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" 6550059Sbrian#ifndef NONAT 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"; 14750479Speterconst char VersionDate[] = "$Date: 1999/08/22 01:29:53 $"; 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 *); 16650059Sbrian#ifndef NONAT 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 } 48149976Sbrian dup2(fd, STDIN_FILENO); 48249976Sbrian dup2(fd, STDOUT_FILENO); 48349976Sbrian dup2(fd, STDERR_FILENO); 48449976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 48549976Sbrian fcntl(i, F_SETFD, 1); 48626516Sbrian 48731061Sbrian setuid(geteuid()); 48836285Sbrian if (arg->argc > arg->argn) { 48928679Sbrian /* substitute pseudo args */ 49038628Sbrian char *argv[MAXARGS]; 49138628Sbrian int argc = arg->argc - arg->argn; 49238628Sbrian 49338628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 49438628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 49538628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 49631343Sbrian } 49747849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 49828679Sbrian if (bg) { 49928679Sbrian pid_t p; 50010528Samurai 50128679Sbrian p = getpid(); 50228679Sbrian if (daemon(1, 1) == -1) { 50336832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 50428679Sbrian exit(1); 50528679Sbrian } 50636285Sbrian } else if (arg->prompt) 50736285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 50831343Sbrian execvp(argv[0], argv); 50930316Sbrian } else { 51036285Sbrian if (arg->prompt) 51132017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 51236285Sbrian prompt_TtyOldMode(arg->prompt); 51331343Sbrian execl(shell, shell, NULL); 51430316Sbrian } 51520813Sjkh 51640665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 51740665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 51840665Sbrian strerror(errno)); 51949976Sbrian _exit(255); 52010528Samurai } 52136285Sbrian 52236285Sbrian if (shpid == (pid_t) - 1) 52336285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 52436285Sbrian else { 52510528Samurai int status; 52631343Sbrian waitpid(shpid, &status, 0); 52710528Samurai } 52820813Sjkh 52936285Sbrian if (arg->prompt && !arg->prompt->owner) 53036285Sbrian prompt_TtyCommandMode(arg->prompt); 53120813Sjkh 53236285Sbrian return 0; 53310528Samurai} 53410528Samurai 53531343Sbrianstatic int 53631343SbrianBgShellCommand(struct cmdargs const *arg) 53731343Sbrian{ 53836285Sbrian if (arg->argc == arg->argn) 53931343Sbrian return -1; 54031343Sbrian return ShellCommand(arg, 1); 54131343Sbrian} 54231343Sbrian 54331343Sbrianstatic int 54431343SbrianFgShellCommand(struct cmdargs const *arg) 54531343Sbrian{ 54631343Sbrian return ShellCommand(arg, 0); 54731343Sbrian} 54831343Sbrian 54950059Sbrian#ifndef NONAT 55040561Sbrianstatic struct cmdtab const AliasCommands[] = 55140561Sbrian{ 55250059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 55350059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 55440561Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 55550059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 55640561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 55740561Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 55850059Sbrian "enable NAT", "nat enable yes|no"}, 55940561Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 56050059Sbrian "log NAT link creation", "nat log yes|no", 56140561Sbrian (const void *) PKT_ALIAS_LOG}, 56250059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 56350059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 56450059Sbrian {"pptp", NULL, nat_Pptp, LOCAL_AUTH, 56550059Sbrian "Set the PPTP address", "nat pptp IP"}, 56650059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 56750059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 56840561Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 56950059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 57040561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 57140561Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 57250059Sbrian "translate unregistered (private) IP address space only", 57350059Sbrian "nat unregistered_only yes|no", 57440561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 57540561Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 57650059Sbrian "allocate host sockets", "nat use_sockets yes|no", 57740561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 57840561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 57950059Sbrian "Display this message", "nat help|? [command]", AliasCommands}, 58040561Sbrian {NULL, NULL, NULL}, 58140561Sbrian}; 58240561Sbrian#endif 58340561Sbrian 58440561Sbrianstatic struct cmdtab const AllowCommands[] = { 58540561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 58640561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 58740561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 58840561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 58940561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 59040561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 59140561Sbrian {NULL, NULL, NULL}, 59240561Sbrian}; 59340561Sbrian 59440561Sbrianstatic struct cmdtab const IfaceCommands[] = 59540561Sbrian{ 59640561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 59740561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 59840561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 59940561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 60040561Sbrian (void *)1}, 60140561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 60240561Sbrian "Clear iface address(es)", "iface clear"}, 60340561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 60440561Sbrian "Delete iface address", "iface delete addr", NULL}, 60540561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 60640561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 60740561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 60840561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 60940561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 61040561Sbrian "Show iface address(es)", "iface show"}, 61140561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 61250059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 61340561Sbrian {NULL, NULL, NULL}, 61440561Sbrian}; 61540561Sbrian 61630715Sbrianstatic struct cmdtab const Commands[] = { 61736285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61828679Sbrian "accept option request", "accept option .."}, 61928679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 62032109Sbrian "add route", "add dest mask gateway", NULL}, 62136285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 62232109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 62340561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 62440561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 62528679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 62631372Sbrian "Run a background command", "[!]bg command"}, 62736934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 62846686Sbrian "Clear throughput statistics", 62946686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 63036285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 63136285Sbrian "Clone a link", "clone newname..."}, 63236285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63336285Sbrian "Close an FSM", "close [lcp|ccp]"}, 63428679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 63532109Sbrian "delete route", "delete dest", NULL}, 63636285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 63732109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 63836285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63928679Sbrian "Deny option request", "deny option .."}, 64036285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64140797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 64236285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64328679Sbrian "Disable option", "disable option .."}, 64436285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64546686Sbrian "Generate a down event", "down [ccp|lcp]"}, 64636285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64728679Sbrian "Enable option", "enable option .."}, 64840561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 64940561Sbrian "interface control", "iface option ...", IfaceCommands}, 65036285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 65136285Sbrian "Link specific commands", "link name command ..."}, 65237008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65340797Sbrian "Load settings", "load [system ...]"}, 65450059Sbrian#ifndef NONAT 65550059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 65650059Sbrian "NAT control", "nat option yes|no", AliasCommands}, 65750059Sbrian#endif 65836285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65937955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 66036285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 66136285Sbrian "Password for manipulation", "passwd LocalPassword"}, 66236285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 66336285Sbrian "Quit PPP program", "quit|bye [all]"}, 66436285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 66536285Sbrian "Remove a link", "remove"}, 66636285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 66736285Sbrian "Rename a link", "rename name"}, 66828679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 66928679Sbrian "Save settings", "save"}, 67036285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67128679Sbrian "Set parameters", "set[up] var value"}, 67228679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 67328679Sbrian "Run a subshell", "shell|! [sh command]"}, 67436285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67531372Sbrian "Show status and stats", "show var"}, 67636285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 67731372Sbrian "Enter terminal mode", "term"}, 67828679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 67931343Sbrian "Display this message", "help|? [command]", Commands}, 68028679Sbrian {NULL, NULL, NULL}, 6816059Samurai}; 6826059Samurai 68328536Sbrianstatic int 68431343SbrianShowEscape(struct cmdargs const *arg) 6856059Samurai{ 68636285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 68736285Sbrian int code, bit; 68836285Sbrian const char *sep = ""; 6896059Samurai 69026516Sbrian for (code = 0; code < 32; code++) 69136285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 69228679Sbrian for (bit = 0; bit < 8; bit++) 69336285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 69436285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 69536285Sbrian sep = ", "; 69636285Sbrian } 69736285Sbrian prompt_Printf(arg->prompt, "\n"); 6986059Samurai } 69931077Sbrian return 0; 7006059Samurai} 7016059Samurai 70228679Sbrianstatic int 70336285SbrianShowTimerList(struct cmdargs const *arg) 7046059Samurai{ 70536285Sbrian timer_Show(0, arg->prompt); 70631077Sbrian return 0; 7076059Samurai} 7086059Samurai 70928679Sbrianstatic int 71031343SbrianShowStopped(struct cmdargs const *arg) 71128327Sbrian{ 71236285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 71336285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 71436285Sbrian prompt_Printf(arg->prompt, "Disabled"); 71528327Sbrian else 71636285Sbrian prompt_Printf(arg->prompt, "%ld secs", 71736285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 71828461Sbrian 71936285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 72036285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 72136285Sbrian prompt_Printf(arg->prompt, "Disabled"); 72228461Sbrian else 72336285Sbrian prompt_Printf(arg->prompt, "%ld secs", 72436285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 72528461Sbrian 72636285Sbrian prompt_Printf(arg->prompt, "\n"); 72728461Sbrian 72831077Sbrian return 0; 72928327Sbrian} 73028327Sbrian 73128679Sbrianstatic int 73231343SbrianShowVersion(struct cmdargs const *arg) 7336059Samurai{ 73436285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 73531077Sbrian return 0; 7366059Samurai} 7376059Samurai 73828679Sbrianstatic int 73936285SbrianShowProtocolStats(struct cmdargs const *arg) 74026326Sbrian{ 74136285Sbrian struct link *l = command_ChooseLink(arg); 74226326Sbrian 74336285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 74436285Sbrian link_ReportProtocolStatus(l, arg->prompt); 74531077Sbrian return 0; 74626326Sbrian} 74726326Sbrian 74830715Sbrianstatic struct cmdtab const ShowCommands[] = { 74936285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 75036285Sbrian "bundle details", "show bundle"}, 75136285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 75236285Sbrian "CCP status", "show cpp"}, 75336285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 75436285Sbrian "VJ compression stats", "show compress"}, 75536285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 75636285Sbrian "escape characters", "show escape"}, 75736285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 75836285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 75936285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 76036285Sbrian "HDLC errors", "show hdlc"}, 76140561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 76240561Sbrian "Interface status", "show iface"}, 76336285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 76436285Sbrian "IPCP status", "show ipcp"}, 76547211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 76647211Sbrian "Protocol layers", "show layers"}, 76736285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 76836285Sbrian "LCP status", "show lcp"}, 76936285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 77036285Sbrian "(high-level) link info", "show link"}, 77136285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 77236285Sbrian "available link names", "show links"}, 77336285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 77436285Sbrian "log levels", "show log"}, 77536285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 77636285Sbrian "mbuf allocations", "show mem"}, 77746686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 77846686Sbrian "(low-level) link info", "show physical"}, 77936285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 78036285Sbrian "multilink setup", "show mp"}, 78136285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 78236285Sbrian "protocol summary", "show proto"}, 78336285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 78436285Sbrian "routing table", "show route"}, 78536285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 78636285Sbrian "STOPPED timeout", "show stopped"}, 78736285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 78836285Sbrian "alarm timers", "show timers"}, 78928679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 79036285Sbrian "version string", "show version"}, 79136285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 79236285Sbrian "client list", "show who"}, 79328679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 79431343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 79528679Sbrian {NULL, NULL, NULL}, 7966059Samurai}; 7976059Samurai 79830715Sbrianstatic struct cmdtab const * 79931343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 8006059Samurai{ 80126516Sbrian int nmatch; 80226516Sbrian int len; 80328679Sbrian struct cmdtab const *found; 8046059Samurai 80526516Sbrian found = NULL; 80626516Sbrian len = strlen(str); 80726516Sbrian nmatch = 0; 8086059Samurai while (cmds->func) { 80925566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 81026516Sbrian if (cmds->name[len] == '\0') { 81128679Sbrian *pmatch = 1; 81228679Sbrian return cmds; 81326516Sbrian } 8146059Samurai nmatch++; 8156059Samurai found = cmds; 81628679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 81726516Sbrian if (cmds->alias[len] == '\0') { 81828679Sbrian *pmatch = 1; 81928679Sbrian return cmds; 82026516Sbrian } 8216059Samurai nmatch++; 8226059Samurai found = cmds; 8236059Samurai } 8246059Samurai cmds++; 8256059Samurai } 8266059Samurai *pmatch = nmatch; 82726516Sbrian return found; 8286059Samurai} 8296059Samurai 83036285Sbrianstatic const char * 83136285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 83236285Sbrian{ 83336285Sbrian int f, tlen, len; 83436285Sbrian 83536285Sbrian tlen = 0; 83636285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 83736285Sbrian if (f) 83836285Sbrian tgt[tlen++] = ' '; 83936285Sbrian len = strlen(argv[f]); 84036285Sbrian if (len > sz - tlen - 1) 84136285Sbrian len = sz - tlen - 1; 84236285Sbrian strncpy(tgt+tlen, argv[f], len); 84336285Sbrian tlen += len; 84436285Sbrian } 84536285Sbrian tgt[tlen] = '\0'; 84636285Sbrian return tgt; 84736285Sbrian} 84836285Sbrian 84930715Sbrianstatic int 85036285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 85136285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8526059Samurai{ 85328679Sbrian struct cmdtab const *cmd; 8546059Samurai int val = 1; 8556059Samurai int nmatch; 85631343Sbrian struct cmdargs arg; 85736285Sbrian char prefix[100]; 8586059Samurai 85936285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8606059Samurai if (nmatch > 1) 86136285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 86236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 86336285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 86436285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 86536285Sbrian /* We've got no context, but we require it */ 86636285Sbrian cx = bundle2datalink(bundle, NULL); 86736285Sbrian 86836285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 86936285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 87036285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 87136285Sbrian else { 87236285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 87336285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 87436285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 87536285Sbrian cx = NULL; 87636285Sbrian } 87736285Sbrian arg.cmdtab = cmds; 87836285Sbrian arg.cmd = cmd; 87936285Sbrian arg.argc = argc; 88036285Sbrian arg.argn = argn+1; 88136285Sbrian arg.argv = argv; 88236285Sbrian arg.bundle = bundle; 88336285Sbrian arg.cx = cx; 88436285Sbrian arg.prompt = prompt; 88536285Sbrian val = (*cmd->func) (&arg); 88636285Sbrian } 88731343Sbrian } else 88836285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 88936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 89026516Sbrian 89126516Sbrian if (val == -1) 89236285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 89328679Sbrian else if (val) 89436285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 89536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 89626516Sbrian 89726516Sbrian return val; 8986059Samurai} 8996059Samurai 90037009Sbrianint 90137009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 9026059Samurai{ 9036059Samurai char *cp; 9046059Samurai 9056059Samurai if (nb > 0) { 9066059Samurai cp = buff + strcspn(buff, "\r\n"); 9076059Samurai if (cp) 9086059Samurai *cp = '\0'; 90937009Sbrian return MakeArgs(buff, argv, MAXARGS); 91037009Sbrian } 91137009Sbrian return 0; 91231121Sbrian} 9136059Samurai 91431822Sbrianstatic int 91531822Sbrianarghidden(int argc, char const *const *argv, int n) 91631822Sbrian{ 91731822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 91831828Sbrian 91931828Sbrian /* set authkey xxxxx */ 92031828Sbrian /* set key xxxxx */ 92131822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 92231822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 92331822Sbrian return 1; 92431822Sbrian 92531828Sbrian /* passwd xxxxx */ 92631828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 92731828Sbrian return 1; 92831828Sbrian 92936285Sbrian /* set server port xxxxx .... */ 93036285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 93136285Sbrian !strncasecmp(argv[1], "se", 2)) 93236285Sbrian return 1; 93336285Sbrian 93431822Sbrian return 0; 93531822Sbrian} 93631822Sbrian 93731121Sbrianvoid 93836285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 93937008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 94031121Sbrian{ 94131156Sbrian if (argc > 0) { 94236285Sbrian if (log_IsKept(LogCOMMAND)) { 94347844Sbrian char buf[LINE_LEN]; 94431156Sbrian int f, n; 94531156Sbrian 94631156Sbrian if (label) { 94731962Sbrian strncpy(buf, label, sizeof buf - 3); 94831962Sbrian buf[sizeof buf - 3] = '\0'; 94931156Sbrian strcat(buf, ": "); 95047844Sbrian n = strlen(buf); 95147844Sbrian } else { 95247844Sbrian *buf = '\0'; 95347844Sbrian n = 0; 95431156Sbrian } 95547844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 95647844Sbrian 95731156Sbrian for (f = 0; f < argc; f++) { 95831962Sbrian if (n < sizeof buf - 1 && f) 95931156Sbrian buf[n++] = ' '; 96031822Sbrian if (arghidden(argc, argv, f)) 96136285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 96231822Sbrian else 96331962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 96431156Sbrian n += strlen(buf+n); 96531156Sbrian } 96636285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 96731156Sbrian } 96837008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 96931156Sbrian } 9706059Samurai} 9716059Samurai 97231121Sbrianvoid 97336285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 97436285Sbrian const char *label) 97531121Sbrian{ 97631121Sbrian int argc; 97737009Sbrian char *argv[MAXARGS]; 97831121Sbrian 97937009Sbrian argc = command_Interpret(buff, nb, argv); 98037008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 98131121Sbrian} 98231121Sbrian 9836059Samuraistatic int 98431343SbrianShowCommand(struct cmdargs const *arg) 9856059Samurai{ 98636285Sbrian if (!arg->prompt) 98736285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 98836285Sbrian else if (arg->argc > arg->argn) 98936285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 99036285Sbrian arg->prompt, arg->cx); 9916059Samurai else 99236285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 99326516Sbrian 99426516Sbrian return 0; 9956059Samurai} 9966059Samurai 9976059Samuraistatic int 99831343SbrianTerminalCommand(struct cmdargs const *arg) 9996059Samurai{ 100036285Sbrian if (!arg->prompt) { 100136285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 100226516Sbrian return 1; 10036059Samurai } 100436285Sbrian 100536285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 100636285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 100736285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 100836285Sbrian return 1; 10096059Samurai } 101036285Sbrian 101136285Sbrian datalink_Up(arg->cx, 0, 0); 101236285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 101336285Sbrian return 0; 10146059Samurai} 10156059Samurai 10166059Samuraistatic int 101731343SbrianQuitCommand(struct cmdargs const *arg) 10186059Samurai{ 101936285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 102036285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 102136285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 102236285Sbrian Cleanup(EX_NORMAL); 102336285Sbrian if (arg->prompt) 102436285Sbrian prompt_Destroy(arg->prompt, 1); 102526516Sbrian 102626516Sbrian return 0; 10276059Samurai} 10286059Samurai 10296059Samuraistatic int 103036285SbrianOpenCommand(struct cmdargs const *arg) 10316059Samurai{ 103237160Sbrian if (arg->argc == arg->argn) 103337993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 103437160Sbrian else if (arg->argc == arg->argn + 1) { 103537160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 103637385Sbrian struct datalink *cx = arg->cx ? 103737385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 103837385Sbrian if (cx) { 103937385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 104037385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 104137160Sbrian else 104237993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 104337160Sbrian } else 104437160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 104537160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 104637160Sbrian struct fsm *fp; 10476059Samurai 104837210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 104937160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 105037160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 105137160Sbrian else if (fp->state == ST_OPENED) 105237160Sbrian fsm_Reopen(fp); 105337160Sbrian else { 105437160Sbrian fp->open_mode = 0; /* Not passive any more */ 105537160Sbrian if (fp->state == ST_STOPPED) { 105637160Sbrian fsm_Down(fp); 105737160Sbrian fsm_Up(fp); 105837160Sbrian } else { 105937160Sbrian fsm_Up(fp); 106037160Sbrian fsm_Open(fp); 106137160Sbrian } 106236285Sbrian } 106337160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 106437160Sbrian if (arg->cx) 106537160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 106637160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 106737160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 106837160Sbrian else 106937993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 107037160Sbrian } else 107137160Sbrian return -1; 107236285Sbrian } else 107336285Sbrian return -1; 107436285Sbrian 107526516Sbrian return 0; 10766059Samurai} 10776059Samurai 107825067Sbrianstatic int 107936285SbrianCloseCommand(struct cmdargs const *arg) 10806059Samurai{ 108137007Sbrian if (arg->argc == arg->argn) 108237007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 108337007Sbrian else if (arg->argc == arg->argn + 1) { 108437007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 108537007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 108637007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 108737007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 108837007Sbrian struct fsm *fp; 10896059Samurai 109037210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 109137007Sbrian if (fp->state == ST_OPENED) { 109237007Sbrian fsm_Close(fp); 109337007Sbrian if (arg->argv[arg->argn][3] == '!') 109437007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 109537007Sbrian else 109637007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 109737007Sbrian } 109837007Sbrian } else 109936285Sbrian return -1; 110036285Sbrian } else 110136285Sbrian return -1; 110236285Sbrian 110336285Sbrian return 0; 11046059Samurai} 11056059Samurai 110625067Sbrianstatic int 110736285SbrianDownCommand(struct cmdargs const *arg) 110811336Samurai{ 110937018Sbrian if (arg->argc == arg->argn) { 111037018Sbrian if (arg->cx) 111137018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 111237018Sbrian else 111337018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 111437018Sbrian } else if (arg->argc == arg->argn + 1) { 111537018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 111637018Sbrian if (arg->cx) 111737018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 111837018Sbrian else 111937018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 112037018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 112137018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 112237018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 112337060Sbrian fsm2initial(fp); 112437018Sbrian } else 112537018Sbrian return -1; 112636285Sbrian } else 112736285Sbrian return -1; 112836285Sbrian 112936285Sbrian return 0; 113025067Sbrian} 113125067Sbrian 113225067Sbrianstatic int 113336285SbrianSetModemSpeed(struct cmdargs const *arg) 113425067Sbrian{ 113536285Sbrian long speed; 113636285Sbrian char *end; 113711336Samurai 113836285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 113936285Sbrian if (arg->argc > arg->argn+1) { 114036285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 114136285Sbrian return -1; 114211336Samurai } 114336285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 114436285Sbrian physical_SetSync(arg->cx->physical); 114536285Sbrian return 0; 114636285Sbrian } 114736285Sbrian end = NULL; 114836285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 114936285Sbrian if (*end) { 115036285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 115136285Sbrian arg->argv[arg->argn]); 115236285Sbrian return -1; 115336285Sbrian } 115436285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 115536285Sbrian return 0; 115636285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 115736285Sbrian } else 115836285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 115924939Sbrian 116026516Sbrian return -1; 116111336Samurai} 116211336Samurai 116325067Sbrianstatic int 116431343SbrianSetStoppedTimeout(struct cmdargs const *arg) 116528327Sbrian{ 116636285Sbrian struct link *l = &arg->cx->physical->link; 116736285Sbrian 116836285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 116936285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 117036285Sbrian if (arg->argc <= arg->argn+2) { 117136285Sbrian if (arg->argc > arg->argn) { 117236285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 117336285Sbrian if (arg->argc > arg->argn+1) 117436285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 117528461Sbrian } 117628327Sbrian return 0; 117728327Sbrian } 117828327Sbrian return -1; 117928327Sbrian} 118028327Sbrian 118131081Sbrian#define ismask(x) \ 118231081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 118331081Sbrian 118428327Sbrianstatic int 118531343SbrianSetServer(struct cmdargs const *arg) 118626940Sbrian{ 118726940Sbrian int res = -1; 118826940Sbrian 118936285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 119031081Sbrian const char *port, *passwd, *mask; 119131081Sbrian 119231081Sbrian /* What's what ? */ 119336285Sbrian port = arg->argv[arg->argn]; 119436285Sbrian if (arg->argc == arg->argn + 2) { 119536285Sbrian passwd = arg->argv[arg->argn+1]; 119636285Sbrian mask = NULL; 119736285Sbrian } else if (arg->argc == arg->argn + 3) { 119836285Sbrian passwd = arg->argv[arg->argn+1]; 119936285Sbrian mask = arg->argv[arg->argn+2]; 120031081Sbrian if (!ismask(mask)) 120131081Sbrian return -1; 120236285Sbrian } else if (strcasecmp(port, "none") == 0) { 120336285Sbrian if (server_Close(arg->bundle)) 120436285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 120536285Sbrian return 0; 120631081Sbrian } else 120736285Sbrian return -1; 120831081Sbrian 120936285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 121036285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 121131081Sbrian 121236285Sbrian if (*port == '/') { 121331081Sbrian mode_t imask; 121436285Sbrian char *ptr, name[LINE_LEN + 12]; 121528679Sbrian 121631081Sbrian if (mask != NULL) { 121728679Sbrian unsigned m; 121828679Sbrian 121931081Sbrian if (sscanf(mask, "%o", &m) == 1) 122031081Sbrian imask = m; 122131081Sbrian else 122231081Sbrian return -1; 122331081Sbrian } else 122431081Sbrian imask = (mode_t)-1; 122536285Sbrian 122636285Sbrian ptr = strstr(port, "%d"); 122736285Sbrian if (ptr) { 122836285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 122937210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 123036285Sbrian port = name; 123136285Sbrian } 123236285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 123327346Sbrian } else { 123436285Sbrian int iport, add = 0; 123528679Sbrian 123631081Sbrian if (mask != NULL) 123731081Sbrian return -1; 123828679Sbrian 123936285Sbrian if (*port == '+') { 124036285Sbrian port++; 124136285Sbrian add = 1; 124236285Sbrian } 124331081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 124431081Sbrian struct servent *s; 124531081Sbrian 124631081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 124731081Sbrian iport = 0; 124836285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 124928679Sbrian } else 125031081Sbrian iport = ntohs(s->s_port); 125127346Sbrian } else 125231081Sbrian iport = atoi(port); 125336285Sbrian 125436285Sbrian if (iport) { 125536285Sbrian if (add) 125636285Sbrian iport += arg->bundle->unit; 125736285Sbrian res = server_TcpOpen(arg->bundle, iport); 125836285Sbrian } else 125936285Sbrian res = -1; 126027346Sbrian } 126131081Sbrian } 126226940Sbrian 126326940Sbrian return res; 126426940Sbrian} 126526940Sbrian 126626940Sbrianstatic int 126731343SbrianSetEscape(struct cmdargs const *arg) 12686059Samurai{ 12696059Samurai int code; 127036285Sbrian int argc = arg->argc - arg->argn; 127136285Sbrian char const *const *argv = arg->argv + arg->argn; 12726059Samurai 12736059Samurai for (code = 0; code < 33; code++) 127436285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 127531343Sbrian 12766059Samurai while (argc-- > 0) { 12776059Samurai sscanf(*argv++, "%x", &code); 12786059Samurai code &= 0xff; 127936285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 128036285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 12816059Samurai } 128226516Sbrian return 0; 12836059Samurai} 12846059Samurai 12856059Samuraistatic int 128631343SbrianSetInterfaceAddr(struct cmdargs const *arg) 12876059Samurai{ 128836285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 128932267Sbrian const char *hisaddr; 129032267Sbrian 129140561Sbrian if (arg->argc > arg->argn + 4) 129240561Sbrian return -1; 129340561Sbrian 129432267Sbrian hisaddr = NULL; 129544874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 129644874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 129736285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 129836285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 129936285Sbrian iplist_reset(&ipcp->cfg.peer_list); 130028394Sbrian 130136285Sbrian if (arg->argc > arg->argn) { 130243313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 130336285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 130436285Sbrian &ipcp->cfg.my_range.width)) 130528679Sbrian return 1; 130636285Sbrian if (arg->argc > arg->argn+1) { 130736285Sbrian hisaddr = arg->argv[arg->argn+1]; 130836285Sbrian if (arg->argc > arg->argn+2) { 130944455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 131036285Sbrian if (arg->argc > arg->argn+3) { 131136285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 131236285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 13139440Samurai } 13146059Samurai } 13156059Samurai } 13166059Samurai } 131728394Sbrian 131840561Sbrian /* 0.0.0.0 means any address (0 bits) */ 131936285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 132036285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 132136285Sbrian ipcp->cfg.my_range.width = 0; 13226059Samurai } 132336285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 132447648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 132536285Sbrian 132636285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 132736928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 132832267Sbrian return 4; 132931121Sbrian 133026516Sbrian return 0; 13316059Samurai} 13326059Samurai 133318752Sjkhstatic int 133444305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 133544305Sbrian u_int *maxtrm, int def) 133644305Sbrian{ 133744305Sbrian if (argc == 0) { 133844305Sbrian *timeout = DEF_FSMRETRY; 133944305Sbrian *maxreq = def; 134044305Sbrian if (maxtrm != NULL) 134144305Sbrian *maxtrm = def; 134244305Sbrian } else { 134344305Sbrian long l = atol(argv[0]); 134444305Sbrian 134544305Sbrian if (l < MIN_FSMRETRY) { 134644305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 134744305Sbrian l, MIN_FSMRETRY); 134844305Sbrian return 1; 134944305Sbrian } else 135044305Sbrian *timeout = l; 135144305Sbrian 135244305Sbrian if (argc > 1) { 135344305Sbrian l = atol(argv[1]); 135444305Sbrian if (l < 1) { 135544305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 135644305Sbrian l = 1; 135744305Sbrian } 135844305Sbrian *maxreq = l; 135944305Sbrian 136044305Sbrian if (argc > 2 && maxtrm != NULL) { 136144305Sbrian l = atol(argv[2]); 136244305Sbrian if (l < 1) { 136344305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 136444305Sbrian l = 1; 136544305Sbrian } 136644305Sbrian *maxtrm = l; 136744305Sbrian } 136844305Sbrian } 136944305Sbrian } 137044305Sbrian 137144305Sbrian return 0; 137244305Sbrian} 137344305Sbrian 137444305Sbrianstatic int 137531343SbrianSetVariable(struct cmdargs const *arg) 13766059Samurai{ 137737210Sbrian long long_val, param = (long)arg->cmd->args; 137837210Sbrian int mode, dummyint; 137931343Sbrian const char *argp; 138036285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 138136285Sbrian const char *err = NULL; 138236285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 138336285Sbrian struct in_addr dummyaddr, *addr; 13846059Samurai 138536285Sbrian if (arg->argc > arg->argn) 138636285Sbrian argp = arg->argv[arg->argn]; 138726551Sbrian else 138831343Sbrian argp = ""; 138926551Sbrian 139036285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 139136285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 139236285Sbrian arg->cmd->name); 139336285Sbrian return 1; 139436285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 139536285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 139636285Sbrian arg->cmd->name, cx->name); 139736285Sbrian cx = NULL; 139836285Sbrian } 139936285Sbrian 140026551Sbrian switch (param) { 140128679Sbrian case VAR_AUTHKEY: 140250139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 140350139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 140450139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 140528679Sbrian break; 140637210Sbrian 140728679Sbrian case VAR_AUTHNAME: 140840622Sbrian switch (bundle_Phase(arg->bundle)) { 140940622Sbrian case PHASE_DEAD: 141040622Sbrian case PHASE_ESTABLISH: 141140622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 141240622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 141340622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 141440622Sbrian break; 141540622Sbrian default: 141640622Sbrian err = "set authname: Only available at phase DEAD/ESTABLISH\n"; 141740622Sbrian log_Printf(LogWARN, err); 141840622Sbrian break; 141936285Sbrian } 142028679Sbrian break; 142137210Sbrian 142236285Sbrian case VAR_AUTOLOAD: 142349434Sbrian if (arg->argc == arg->argn + 3) { 142449434Sbrian int v1, v2, v3; 142549434Sbrian char *end; 142649434Sbrian 142749434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 142849434Sbrian if (v1 < 0 || *end) { 142949434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 143049434Sbrian arg->argv[arg->argn]); 143149434Sbrian return 1; 143236285Sbrian } 143349434Sbrian 143449434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 143549434Sbrian if (v2 < 0 || *end) { 143649434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 143749434Sbrian arg->argv[arg->argn + 1]); 143849434Sbrian return 1; 143949434Sbrian } 144049434Sbrian if (v2 < v1) { 144149434Sbrian v3 = v1; 144249434Sbrian v1 = v2; 144349434Sbrian v2 = v3; 144449434Sbrian } 144549434Sbrian 144649434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 144749434Sbrian if (v3 <= 0 || *end) { 144849434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 144949434Sbrian arg->argv[arg->argn + 2]); 145049434Sbrian return 1; 145149434Sbrian } 145249434Sbrian 145349434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 145449434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 145549434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 145649434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 145736285Sbrian } else { 145849434Sbrian err = "Set autoload requires three arguments\n"; 145936285Sbrian log_Printf(LogWARN, err); 146036285Sbrian } 146136285Sbrian break; 146237210Sbrian 146328679Sbrian case VAR_DIAL: 146436285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 146536285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 146628679Sbrian break; 146737210Sbrian 146828679Sbrian case VAR_LOGIN: 146936285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 147036285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 147128679Sbrian break; 147237210Sbrian 147336285Sbrian case VAR_WINSIZE: 147436285Sbrian if (arg->argc > arg->argn) { 147536285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 147636285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 147736285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 147836285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 147936285Sbrian l->ccp.cfg.deflate.out.winsize); 148036285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 148136285Sbrian } 148236285Sbrian if (arg->argc > arg->argn+1) { 148336285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 148436285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 148536285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 148636285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 148736285Sbrian l->ccp.cfg.deflate.in.winsize); 148836285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 148936285Sbrian } 149036285Sbrian } else 149136285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 149236285Sbrian } else { 149336285Sbrian err = "No window size specified\n"; 149436285Sbrian log_Printf(LogWARN, err); 149536285Sbrian } 149636285Sbrian break; 149737210Sbrian 149828679Sbrian case VAR_DEVICE: 149936285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 150036285Sbrian arg->argv + arg->argn); 150136285Sbrian break; 150237210Sbrian 150336285Sbrian case VAR_ACCMAP: 150436285Sbrian if (arg->argc > arg->argn) { 150537210Sbrian u_long ulong_val; 150636285Sbrian sscanf(argp, "%lx", &ulong_val); 150737210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 150836285Sbrian } else { 150936285Sbrian err = "No accmap specified\n"; 151036285Sbrian log_Printf(LogWARN, err); 151136285Sbrian } 151236285Sbrian break; 151337210Sbrian 151436285Sbrian case VAR_MODE: 151536285Sbrian mode = Nam2mode(argp); 151636285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 151736285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 151836285Sbrian return -1; 151936285Sbrian } 152036285Sbrian bundle_SetMode(arg->bundle, cx, mode); 152136285Sbrian break; 152237210Sbrian 152336285Sbrian case VAR_MRRU: 152440622Sbrian switch (bundle_Phase(arg->bundle)) { 152540622Sbrian case PHASE_DEAD: 152640622Sbrian break; 152740622Sbrian case PHASE_ESTABLISH: 152840622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 152940622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 153040622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 153140622Sbrian return 1; 153240622Sbrian } 153340622Sbrian break; 153440622Sbrian default: 153540622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 153640622Sbrian return 1; 153729696Sbrian } 153837210Sbrian long_val = atol(argp); 153937210Sbrian if (long_val && long_val < MIN_MRU) { 154037210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 154137210Sbrian return 1; 154237210Sbrian } else if (long_val > MAX_MRU) { 154337210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 154437210Sbrian return 1; 154537210Sbrian } else 154637210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 154728679Sbrian break; 154837210Sbrian 154936285Sbrian case VAR_MRU: 155037210Sbrian long_val = atol(argp); 155137210Sbrian if (long_val == 0) 155237210Sbrian l->lcp.cfg.mru = DEF_MRU; 155337210Sbrian else if (long_val < MIN_MRU) { 155437210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 155537210Sbrian return 1; 155637210Sbrian } else if (long_val > MAX_MRU) { 155737210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 155837210Sbrian return 1; 155937210Sbrian } else 156037210Sbrian l->lcp.cfg.mru = long_val; 156128679Sbrian break; 156237210Sbrian 156336285Sbrian case VAR_MTU: 156437210Sbrian long_val = atol(argp); 156537210Sbrian if (long_val && long_val < MIN_MTU) { 156637210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 156737210Sbrian return 1; 156837210Sbrian } else if (long_val > MAX_MTU) { 156937210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 157037210Sbrian return 1; 157137210Sbrian } else 157237210Sbrian arg->bundle->cfg.mtu = long_val; 157336285Sbrian break; 157437210Sbrian 157536285Sbrian case VAR_OPENMODE: 157636285Sbrian if (strcasecmp(argp, "active") == 0) 157736285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 157836285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 157936285Sbrian else if (strcasecmp(argp, "passive") == 0) 158036285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 158136285Sbrian else { 158236285Sbrian err = "%s: Invalid openmode\n"; 158336285Sbrian log_Printf(LogWARN, err, argp); 158436285Sbrian } 158536285Sbrian break; 158637210Sbrian 158728679Sbrian case VAR_PHONE: 158836285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 158936285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 159038174Sbrian cx->phone.alt = cx->phone.next = NULL; 159128679Sbrian break; 159237210Sbrian 159328679Sbrian case VAR_HANGUP: 159436285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 159536285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 159628679Sbrian break; 159737210Sbrian 159836285Sbrian case VAR_IDLETIMEOUT: 159949978Sbrian if (arg->argc > arg->argn+2) 160036285Sbrian err = "Too many idle timeout values\n"; 160149978Sbrian else if (arg->argc == arg->argn) 160249978Sbrian err = "Too few idle timeout values\n"; 160349978Sbrian else { 160449978Sbrian int timeout, min; 160549978Sbrian 160649978Sbrian timeout = atoi(argp); 160749978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 160849978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 160949978Sbrian } 161036285Sbrian if (err) 161136285Sbrian log_Printf(LogWARN, err); 161229549Sbrian break; 161337210Sbrian 161436285Sbrian case VAR_LQRPERIOD: 161537210Sbrian long_val = atol(argp); 161637210Sbrian if (long_val < MIN_LQRPERIOD) { 161737210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 161837210Sbrian long_val, MIN_LQRPERIOD); 161937210Sbrian return 1; 162036285Sbrian } else 162137210Sbrian l->lcp.cfg.lqrperiod = long_val; 162236285Sbrian break; 162337210Sbrian 162436285Sbrian case VAR_LCPRETRY: 162544305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 162644305Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 162744305Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 162844305Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 162936285Sbrian break; 163037210Sbrian 163136285Sbrian case VAR_CHAPRETRY: 163244305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 163344305Sbrian &cx->chap.auth.cfg.fsm.timeout, 163444305Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 163536285Sbrian break; 163637210Sbrian 163736285Sbrian case VAR_PAPRETRY: 163844305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 163944305Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 164044305Sbrian NULL, DEF_FSMAUTHTRIES); 164136285Sbrian break; 164237210Sbrian 164336285Sbrian case VAR_CCPRETRY: 164444305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 164544305Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 164644305Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 164736285Sbrian break; 164837210Sbrian 164936285Sbrian case VAR_IPCPRETRY: 165044305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 165144305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 165244305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 165344305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 165436285Sbrian break; 165537210Sbrian 165636285Sbrian case VAR_NBNS: 165736285Sbrian case VAR_DNS: 165836285Sbrian if (param == VAR_DNS) 165936285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 166036285Sbrian else 166136285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 166236285Sbrian 166336285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 166436285Sbrian 166536285Sbrian if (arg->argc > arg->argn) { 166643313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 166736285Sbrian addr, &dummyaddr, &dummyint); 166836285Sbrian if (arg->argc > arg->argn+1) 166943313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 167036285Sbrian addr + 1, &dummyaddr, &dummyint); 167136285Sbrian 167236285Sbrian if (addr[1].s_addr == INADDR_ANY) 167336285Sbrian addr[1].s_addr = addr[0].s_addr; 167436285Sbrian if (addr[0].s_addr == INADDR_ANY) 167536285Sbrian addr[0].s_addr = addr[1].s_addr; 167636285Sbrian } 167736285Sbrian break; 167838174Sbrian 167938174Sbrian case VAR_CALLBACK: 168038174Sbrian cx->cfg.callback.opmask = 0; 168138174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 168238174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 168338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 168438174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 168538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 168638174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 168738174Sbrian if (dummyint == arg->argc - 1) 168838174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 168938174Sbrian else { 169038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 169138174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 169238174Sbrian sizeof cx->cfg.callback.msg - 1); 169338174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 169438174Sbrian } 169538174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 169638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 169738174Sbrian else 169838174Sbrian return -1; 169938174Sbrian } 170038174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 170138174Sbrian cx->cfg.callback.opmask = 0; 170238174Sbrian break; 170338174Sbrian 170438174Sbrian case VAR_CBCP: 170538174Sbrian cx->cfg.cbcp.delay = 0; 170638174Sbrian *cx->cfg.cbcp.phone = '\0'; 170738174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 170838174Sbrian if (arg->argc > arg->argn) { 170938174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 171038174Sbrian sizeof cx->cfg.cbcp.phone - 1); 171138174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 171238174Sbrian if (arg->argc > arg->argn + 1) { 171338174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 171438174Sbrian if (arg->argc > arg->argn + 2) { 171538174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 171638174Sbrian if (long_val < MIN_FSMRETRY) 171738174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 171838174Sbrian long_val, MIN_FSMRETRY); 171938174Sbrian else 172038174Sbrian cx->cfg.cbcp.fsmretry = long_val; 172138174Sbrian } 172238174Sbrian } 172338174Sbrian } 172438174Sbrian break; 172538544Sbrian 172638544Sbrian case VAR_CHOKED: 172738544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 172838544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 172938544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 173038544Sbrian break; 173140665Sbrian 173240665Sbrian case VAR_SENDPIPE: 173340665Sbrian long_val = atol(argp); 173440665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 173540665Sbrian break; 173640665Sbrian 173740665Sbrian case VAR_RECVPIPE: 173840665Sbrian long_val = atol(argp); 173940665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 174040665Sbrian break; 174143313Sbrian 174243313Sbrian#ifndef NORADIUS 174343313Sbrian case VAR_RADIUS: 174443313Sbrian if (!*argp) 174543313Sbrian *arg->bundle->radius.cfg.file = '\0'; 174643313Sbrian else if (access(argp, R_OK)) { 174743313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 174843313Sbrian return 1; 174943313Sbrian } else { 175043313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 175143313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 175243313Sbrian arg->bundle->radius.cfg.file 175343313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 175443313Sbrian } 175543313Sbrian break; 175643313Sbrian#endif 175744073Sbrian 175844073Sbrian case VAR_CD: 175944073Sbrian if (*argp) { 176044073Sbrian long_val = atol(argp); 176144073Sbrian if (long_val < 0) 176244073Sbrian long_val = 0; 176344073Sbrian cx->physical->cfg.cd.delay = long_val; 176444073Sbrian cx->physical->cfg.cd.required = argp[strlen(argp)-1] == '!'; 176544073Sbrian } else { 176644073Sbrian cx->physical->cfg.cd.delay = DEF_CDDELAY; 176744073Sbrian cx->physical->cfg.cd.required = 0; 176844073Sbrian } 176944073Sbrian break; 177036285Sbrian 177146686Sbrian case VAR_PARITY: 177246686Sbrian if (arg->argc == arg->argn + 1) 177346686Sbrian return physical_SetParity(arg->cx->physical, argp); 177446686Sbrian else { 177546686Sbrian err = "Parity value must be odd, even or none\n"; 177646686Sbrian log_Printf(LogWARN, err); 177746686Sbrian } 177846686Sbrian break; 17796059Samurai 178046686Sbrian case VAR_CRTSCTS: 178146686Sbrian if (strcasecmp(argp, "on") == 0) 178236285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 178346686Sbrian else if (strcasecmp(argp, "off") == 0) 178436285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 178546686Sbrian else { 178646686Sbrian err = "RTS/CTS value must be on or off\n"; 178746686Sbrian log_Printf(LogWARN, err); 178846686Sbrian } 178946686Sbrian break; 179020812Sjkh } 179146686Sbrian 179246686Sbrian return err ? 1 : 0; 179320812Sjkh} 179420812Sjkh 179530715Sbrianstatic struct cmdtab const SetCommands[] = { 179636285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 179736285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 179828679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 179936285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 180028679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 180136285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 180236285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 180336285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 180436285Sbrian (const void *)VAR_AUTOLOAD}, 180538174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 180638174Sbrian "callback control", "set callback [none|auth|cbcp|" 180738174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 180838174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 180938174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 181038174Sbrian (const void *)VAR_CBCP}, 181144305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 181244305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 181344073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 181444073Sbrian "set cd value[!]", (const void *)VAR_CD}, 181544305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 181644305Sbrian "CHAP retries", "set chapretry value [attempts]", 181744305Sbrian (const void *)VAR_CHAPRETRY}, 181838544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 181938544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 182046686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 182146686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 182246686Sbrian (const char *)VAR_CRTSCTS}, 182336285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 182436285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 182536285Sbrian (const void *) VAR_WINSIZE}, 182636285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 182746686Sbrian "physical device name", "set device|line device-name[,device-name]", 182836285Sbrian (const void *) VAR_DEVICE}, 182936285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 183036285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 183136285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 183236285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 183336285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 183436285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 183536285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 183636285Sbrian "escape characters", "set escape hex-digit ..."}, 183736285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 183836285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 183949388Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 184048142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 184136285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 184236285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 184336285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 184431343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 184544305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 184644305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 184744305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 184844305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 184936712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 185038622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 185147699Sbrian "ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 185236285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 185336285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 185436285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 185536285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 185636285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 185736285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 185836285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 185936285Sbrian "set mrru value", (const void *)VAR_MRRU}, 186036285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 186136285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 186236285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 186336285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 186436285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 186536285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 186636285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 186736285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 186844305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 186944305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 187046686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 187146686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 187236285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 187336285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 187440679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 187540679Sbrian "Process title", "set proctitle [value]"}, 187643313Sbrian#ifndef NORADIUS 187743313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 187843313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 187943313Sbrian#endif 188036285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 188136285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 188240665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 188340665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 188436285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 188544468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 188640665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 188740665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 188828679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 188936774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 189036285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 189146686Sbrian "physical speed", "set speed value|sync"}, 189236285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 189336285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 189436285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 189536285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 189636285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 189736285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 189849434Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 189949434Sbrian "datalink bandwidth", "set bandwidth value"}, 190028679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 190131343Sbrian "Display this message", "set help|? [command]", SetCommands}, 190228679Sbrian {NULL, NULL, NULL}, 19036059Samurai}; 19046059Samurai 19056059Samuraistatic int 190631343SbrianSetCommand(struct cmdargs const *arg) 19076059Samurai{ 190836285Sbrian if (arg->argc > arg->argn) 190936285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 191036285Sbrian arg->prompt, arg->cx); 191136285Sbrian else if (arg->prompt) 191236285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 191326516Sbrian " syntax help.\n"); 19146059Samurai else 191536285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 191626516Sbrian 191726516Sbrian return 0; 19186059Samurai} 19196059Samurai 19206059Samuraistatic int 192131343SbrianAddCommand(struct cmdargs const *arg) 19226059Samurai{ 19236059Samurai struct in_addr dest, gateway, netmask; 192436285Sbrian int gw, addrs; 19256059Samurai 192636285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 192731598Sbrian return -1; 192831598Sbrian 192936285Sbrian addrs = 0; 193036285Sbrian if (arg->argc == arg->argn+2) { 193136285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 193236285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 193331598Sbrian else { 193436285Sbrian int width; 193536285Sbrian 193643313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 193736285Sbrian &dest, &netmask, &width)) 193836285Sbrian return -1; 193936285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 194036285Sbrian addrs = ROUTE_DSTMYADDR; 194136285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 194236285Sbrian addrs = ROUTE_DSTHISADDR; 194331598Sbrian } 194436285Sbrian gw = 1; 194534536Sbrian } else { 194636285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 194736285Sbrian addrs = ROUTE_DSTMYADDR; 194836285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 194936285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 195036285Sbrian addrs = ROUTE_DSTHISADDR; 195136285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 195236285Sbrian } else 195336285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 195436285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 195531598Sbrian gw = 2; 19566059Samurai } 195736285Sbrian 195836285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 195936285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 196036285Sbrian addrs |= ROUTE_GWHISADDR; 196140561Sbrian } else 196236285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 196336285Sbrian 196436285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 196543313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 196643313Sbrian && addrs != ROUTE_STATIC) 196736285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 196836285Sbrian 196931598Sbrian return 0; 19706059Samurai} 19716059Samurai 19726059Samuraistatic int 197331343SbrianDeleteCommand(struct cmdargs const *arg) 19746059Samurai{ 197531598Sbrian struct in_addr dest, none; 197636285Sbrian int addrs; 19776059Samurai 197836285Sbrian if (arg->argc == arg->argn+1) { 197936285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 198036285Sbrian route_IfDelete(arg->bundle, 0); 198136285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 198236285Sbrian } else { 198336285Sbrian addrs = 0; 198436285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 198536285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 198636285Sbrian addrs = ROUTE_DSTMYADDR; 198736285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 198836285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 198936285Sbrian addrs = ROUTE_DSTHISADDR; 199036285Sbrian } else { 199144279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 199244279Sbrian if (dest.s_addr == INADDR_NONE) { 199344279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 199444279Sbrian return -1; 199544279Sbrian } 199636285Sbrian addrs = ROUTE_STATIC; 199736285Sbrian } 199831598Sbrian none.s_addr = INADDR_ANY; 199936285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 200037927Sbrian arg->cmd->args ? 1 : 0, 0); 200136285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 200231598Sbrian } 200334536Sbrian } else 200426516Sbrian return -1; 200526516Sbrian 200626516Sbrian return 0; 20076059Samurai} 20086059Samurai 200950059Sbrian#ifndef NONAT 201026031Sbrianstatic int 201131343SbrianAliasEnable(struct cmdargs const *arg) 201226031Sbrian{ 201336285Sbrian if (arg->argc == arg->argn+1) { 201436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 201550059Sbrian if (!arg->bundle->NatEnabled) { 201646686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 201746686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 201850059Sbrian arg->bundle->NatEnabled = 1; 201946686Sbrian } 202037191Sbrian return 0; 202136285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 202250059Sbrian arg->bundle->NatEnabled = 0; 202340561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 202440561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 202526516Sbrian return 0; 202626142Sbrian } 202735449Sbrian } 202836285Sbrian 202926516Sbrian return -1; 203026031Sbrian} 203126031Sbrian 203226031Sbrian 203326031Sbrianstatic int 203431343SbrianAliasOption(struct cmdargs const *arg) 203526031Sbrian{ 203638559Sbrian long param = (long)arg->cmd->args; 203738559Sbrian 203836285Sbrian if (arg->argc == arg->argn+1) { 203936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 204050059Sbrian if (arg->bundle->NatEnabled) { 204137191Sbrian PacketAliasSetMode(param, param); 204228679Sbrian return 0; 204328679Sbrian } 204450059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 204536285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 204650059Sbrian if (arg->bundle->NatEnabled) { 204737191Sbrian PacketAliasSetMode(0, param); 204828679Sbrian return 0; 204928679Sbrian } 205050059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 205128679Sbrian } 205235449Sbrian } 205328679Sbrian return -1; 205426031Sbrian} 205550059Sbrian#endif /* #ifndef NONAT */ 205631121Sbrian 205731121Sbrianstatic int 205836285SbrianLinkCommand(struct cmdargs const *arg) 205936285Sbrian{ 206036285Sbrian if (arg->argc > arg->argn+1) { 206136285Sbrian char namelist[LINE_LEN]; 206236285Sbrian struct datalink *cx; 206336285Sbrian char *name; 206436285Sbrian int result = 0; 206536285Sbrian 206636285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 206736285Sbrian struct datalink *dl; 206836285Sbrian 206936285Sbrian cx = arg->bundle->links; 207036285Sbrian while (cx) { 207136285Sbrian /* Watch it, the command could be a ``remove'' */ 207236285Sbrian dl = cx->next; 207336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 207436285Sbrian arg->prompt, cx); 207536285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 207636285Sbrian if (cx == dl) 207736285Sbrian break; /* Pointer's still valid ! */ 207836285Sbrian } 207936285Sbrian } else { 208036285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 208136285Sbrian namelist[sizeof namelist - 1] = '\0'; 208236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 208336285Sbrian if (!bundle2datalink(arg->bundle, name)) { 208436285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 208536285Sbrian return 1; 208636285Sbrian } 208736285Sbrian 208836285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 208936285Sbrian namelist[sizeof namelist - 1] = '\0'; 209036285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 209136285Sbrian cx = bundle2datalink(arg->bundle, name); 209236285Sbrian if (cx) 209336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 209436285Sbrian arg->prompt, cx); 209536285Sbrian else { 209636285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 209736285Sbrian result++; 209836285Sbrian } 209936285Sbrian } 210036285Sbrian } 210136285Sbrian return result; 210236285Sbrian } 210336285Sbrian 210436285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 210536285Sbrian return 2; 210636285Sbrian} 210736285Sbrian 210836285Sbrianstruct link * 210936285Sbriancommand_ChooseLink(struct cmdargs const *arg) 211036285Sbrian{ 211136285Sbrian if (arg->cx) 211236285Sbrian return &arg->cx->physical->link; 211337210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 211436285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 211537210Sbrian if (dl) 211637210Sbrian return &dl->physical->link; 211736285Sbrian } 211837210Sbrian return &arg->bundle->ncp.mp.link; 211936285Sbrian} 212036285Sbrian 212136285Sbrianstatic const char * 212236285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 212336285Sbrian{ 212436285Sbrian const char *result; 212536285Sbrian 212636285Sbrian switch (*cmd) { 212736285Sbrian case 'A': 212836285Sbrian case 'a': 212936285Sbrian result = "accept"; 213036285Sbrian *keep = NEG_MYMASK; 213136285Sbrian *add = NEG_ACCEPTED; 213236285Sbrian break; 213336285Sbrian case 'D': 213436285Sbrian case 'd': 213536285Sbrian switch (cmd[1]) { 213636285Sbrian case 'E': 213736285Sbrian case 'e': 213836285Sbrian result = "deny"; 213936285Sbrian *keep = NEG_MYMASK; 214036285Sbrian *add = 0; 214136285Sbrian break; 214236285Sbrian case 'I': 214336285Sbrian case 'i': 214436285Sbrian result = "disable"; 214536285Sbrian *keep = NEG_HISMASK; 214636285Sbrian *add = 0; 214736285Sbrian break; 214836285Sbrian default: 214936285Sbrian return NULL; 215036285Sbrian } 215136285Sbrian break; 215236285Sbrian case 'E': 215336285Sbrian case 'e': 215436285Sbrian result = "enable"; 215536285Sbrian *keep = NEG_HISMASK; 215636285Sbrian *add = NEG_ENABLED; 215736285Sbrian break; 215836285Sbrian default: 215936285Sbrian return NULL; 216036285Sbrian } 216136285Sbrian 216236285Sbrian return result; 216336285Sbrian} 216436285Sbrian 216536285Sbrianstatic int 216636285SbrianOptSet(struct cmdargs const *arg) 216736285Sbrian{ 216837574Sbrian int bit = (int)(long)arg->cmd->args; 216936285Sbrian const char *cmd; 217036285Sbrian unsigned keep; /* Keep these bits */ 217136285Sbrian unsigned add; /* Add these bits */ 217236285Sbrian 217336285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 217436285Sbrian return 1; 217536285Sbrian 217636285Sbrian if (add) 217736285Sbrian arg->bundle->cfg.opt |= bit; 217836285Sbrian else 217936285Sbrian arg->bundle->cfg.opt &= ~bit; 218036285Sbrian return 0; 218136285Sbrian} 218236285Sbrian 218336285Sbrianstatic int 218440561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 218540561Sbrian{ 218640561Sbrian unsigned save = arg->bundle->cfg.opt; 218740561Sbrian int result = OptSet(arg); 218840561Sbrian 218940561Sbrian if (result == 0) 219050059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 219140561Sbrian arg->bundle->cfg.opt = save; 219250059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 219340561Sbrian result = 2; 219440561Sbrian } 219540561Sbrian 219640561Sbrian return result; 219740561Sbrian} 219840561Sbrian 219940561Sbrianstatic int 220036285SbrianNegotiateSet(struct cmdargs const *arg) 220136285Sbrian{ 220237210Sbrian long param = (long)arg->cmd->args; 220336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 220436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 220536285Sbrian const char *cmd; 220636285Sbrian unsigned keep; /* Keep these bits */ 220736285Sbrian unsigned add; /* Add these bits */ 220836285Sbrian 220936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 221036285Sbrian return 1; 221136285Sbrian 221236285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 221336285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 221436285Sbrian cmd, arg->cmd->name); 221536285Sbrian return 2; 221636285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 221736285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 221836285Sbrian cmd, arg->cmd->name, cx->name); 221936285Sbrian cx = NULL; 222036285Sbrian } 222136285Sbrian 222236285Sbrian switch (param) { 222336285Sbrian case NEG_ACFCOMP: 222436285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 222536285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 222636285Sbrian break; 222744106Sbrian case NEG_CHAP05: 222844106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 222944106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 223036285Sbrian break; 223144106Sbrian#ifdef HAVE_DES 223244106Sbrian case NEG_CHAP80: 223344106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 223444106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 223544106Sbrian break; 223644106Sbrian case NEG_CHAP80LM: 223744106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 223844106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 223944106Sbrian break; 224044106Sbrian#endif 224136285Sbrian case NEG_DEFLATE: 224236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 224336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 224436285Sbrian break; 224536285Sbrian case NEG_DNS: 224636285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 224736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 224836285Sbrian break; 224947858Sbrian case NEG_ENDDISC: 225047858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 225147858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 225247858Sbrian break; 225336285Sbrian case NEG_LQR: 225436285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 225536285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 225636285Sbrian break; 225736285Sbrian case NEG_PAP: 225836285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 225936285Sbrian cx->physical->link.lcp.cfg.pap |= add; 226036285Sbrian break; 226136285Sbrian case NEG_PPPDDEFLATE: 226236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 226336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 226436285Sbrian break; 226536285Sbrian case NEG_PRED1: 226636285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 226736285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 226836285Sbrian break; 226936285Sbrian case NEG_PROTOCOMP: 227036285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 227136285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 227236285Sbrian break; 227336285Sbrian case NEG_SHORTSEQ: 227440622Sbrian switch (bundle_Phase(arg->bundle)) { 227540622Sbrian case PHASE_DEAD: 227640622Sbrian break; 227740622Sbrian case PHASE_ESTABLISH: 227840622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 227940622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 228040622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 228140622Sbrian " LCP negotiations\n"); 228240622Sbrian return 1; 228340622Sbrian } 228440622Sbrian break; 228540622Sbrian default: 228640622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 228740622Sbrian " DEAD/ESTABLISH\n"); 228840622Sbrian return 1; 228936285Sbrian } 229040622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 229140622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 229236285Sbrian break; 229336285Sbrian case NEG_VJCOMP: 229436285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 229536285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 229636285Sbrian break; 229736285Sbrian } 229836285Sbrian 229936285Sbrian return 0; 230036285Sbrian} 230136285Sbrian 230236285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 230336285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 230436285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 230540666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 230640666Sbrian "retain interface addresses", "disable|enable", 230740666Sbrian (const void *)OPT_IFACEALIAS}, 230847689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 230947689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 231036285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 231136285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 231236285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 231336285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 231440665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 231536285Sbrian "disable|enable", (const void *)OPT_PROXY}, 231640665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 231740665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 231836285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 231936285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 232036285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 232136285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 232236285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 232336285Sbrian "disable|enable", (const void *)OPT_UTMP}, 232436285Sbrian 232547689Sbrian#define OPT_MAX 10 /* accept/deny allowed below and not above */ 232636285Sbrian 232736285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 232836285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 232936285Sbrian (const void *)NEG_ACFCOMP}, 233044106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 233136285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 233244106Sbrian (const void *)NEG_CHAP05}, 233344106Sbrian#ifdef HAVE_DES 233444106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 233544106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 233644106Sbrian (const void *)NEG_CHAP80}, 233744106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 233844106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 233944106Sbrian (const void *)NEG_CHAP80LM}, 234044106Sbrian#endif 234136285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 234236285Sbrian "Deflate compression", "accept|deny|disable|enable", 234336285Sbrian (const void *)NEG_DEFLATE}, 234436285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 234536285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 234636285Sbrian (const void *)NEG_PPPDDEFLATE}, 234736285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 234836285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 234947858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 235047858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 235136285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 235236285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 235336285Sbrian (const void *)NEG_LQR}, 235436285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 235536285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 235636285Sbrian (const void *)NEG_PAP}, 235736285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 235836285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 235936285Sbrian (const void *)NEG_PRED1}, 236036285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 236136285Sbrian "Protocol field compression", "accept|deny|disable|enable", 236236285Sbrian (const void *)NEG_PROTOCOMP}, 236336285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 236436285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 236536285Sbrian (const void *)NEG_SHORTSEQ}, 236636285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 236736285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 236836285Sbrian (const void *)NEG_VJCOMP}, 236936285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 237036285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 237136285Sbrian NegotiateCommands}, 237236285Sbrian {NULL, NULL, NULL}, 237336285Sbrian}; 237436285Sbrian 237536285Sbrianstatic int 237636285SbrianNegotiateCommand(struct cmdargs const *arg) 237736285Sbrian{ 237836285Sbrian if (arg->argc > arg->argn) { 237936285Sbrian char const *argv[3]; 238036285Sbrian unsigned keep, add; 238136285Sbrian int n; 238236285Sbrian 238336285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 238436285Sbrian return -1; 238536285Sbrian argv[2] = NULL; 238636285Sbrian 238736285Sbrian for (n = arg->argn; n < arg->argc; n++) { 238836285Sbrian argv[1] = arg->argv[n]; 238936285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 239036285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 239136285Sbrian } 239236285Sbrian } else if (arg->prompt) 239336285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 239436285Sbrian arg->argv[arg->argn-1]); 239536285Sbrian else 239636285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 239736285Sbrian arg->argv[arg->argn] ); 239836285Sbrian 239936285Sbrian return 0; 240036285Sbrian} 240136285Sbrian 240236285Sbrianconst char * 240336285Sbriancommand_ShowNegval(unsigned val) 240436285Sbrian{ 240536285Sbrian switch (val&3) { 240636285Sbrian case 1: return "disabled & accepted"; 240736285Sbrian case 2: return "enabled & denied"; 240836285Sbrian case 3: return "enabled & accepted"; 240936285Sbrian } 241036285Sbrian return "disabled & denied"; 241136285Sbrian} 241236934Sbrian 241336934Sbrianstatic int 241436934SbrianClearCommand(struct cmdargs const *arg) 241536934Sbrian{ 241636934Sbrian struct pppThroughput *t; 241736934Sbrian struct datalink *cx; 241836934Sbrian int i, clear_type; 241936934Sbrian 242036934Sbrian if (arg->argc < arg->argn + 1) 242136934Sbrian return -1; 242236934Sbrian 242346686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 242436934Sbrian cx = arg->cx; 242536934Sbrian if (!cx) 242636934Sbrian cx = bundle2datalink(arg->bundle, NULL); 242736934Sbrian if (!cx) { 242846686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 242936934Sbrian return 1; 243036934Sbrian } 243136934Sbrian t = &cx->physical->link.throughput; 243236934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 243336934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 243436934Sbrian else 243536934Sbrian return -1; 243636934Sbrian 243736934Sbrian if (arg->argc > arg->argn + 1) { 243836934Sbrian clear_type = 0; 243936934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 244036934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 244136934Sbrian clear_type |= THROUGHPUT_OVERALL; 244236934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 244336934Sbrian clear_type |= THROUGHPUT_CURRENT; 244436934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 244536934Sbrian clear_type |= THROUGHPUT_PEAK; 244636934Sbrian else 244736934Sbrian return -1; 244836934Sbrian } else 244936934Sbrian clear_type = THROUGHPUT_ALL; 245036934Sbrian 245136934Sbrian throughput_clear(t, clear_type, arg->prompt); 245236934Sbrian return 0; 245336934Sbrian} 245440561Sbrian 245540561Sbrianstatic int 245640561SbrianRunListCommand(struct cmdargs const *arg) 245740561Sbrian{ 245840561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 245940561Sbrian 246040561Sbrian if (arg->argc > arg->argn) 246140561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 246240561Sbrian arg->prompt, arg->cx); 246340561Sbrian else if (arg->prompt) 246440561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 246540561Sbrian " <option>' for syntax help.\n", cmd, cmd); 246640561Sbrian else 246740561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 246840561Sbrian 246940561Sbrian return 0; 247040561Sbrian} 247140561Sbrian 247240561Sbrianstatic int 247340561SbrianIfaceAddCommand(struct cmdargs const *arg) 247440561Sbrian{ 247540561Sbrian int bits, n, how; 247640561Sbrian struct in_addr ifa, mask, brd; 247740561Sbrian 247840664Sbrian if (arg->argc == arg->argn + 1) { 247943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 248040561Sbrian return -1; 248140664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 248240664Sbrian } else { 248340664Sbrian if (arg->argc == arg->argn + 2) { 248443313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 248540664Sbrian return -1; 248640664Sbrian n = 1; 248740664Sbrian } else if (arg->argc == arg->argn + 3) { 248843313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 248940664Sbrian return -1; 249043313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 249140664Sbrian return -1; 249240664Sbrian n = 2; 249340664Sbrian } else 249440561Sbrian return -1; 249540561Sbrian 249643313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 249740664Sbrian return -1; 249840664Sbrian } 249940561Sbrian 250040561Sbrian how = IFACE_ADD_LAST; 250140561Sbrian if (arg->cmd->args) 250240561Sbrian how |= IFACE_FORCE_ADD; 250340561Sbrian 250440561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 250540561Sbrian} 250640561Sbrian 250740561Sbrianstatic int 250840561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 250940561Sbrian{ 251040561Sbrian struct in_addr ifa; 251140561Sbrian int ok; 251240561Sbrian 251340561Sbrian if (arg->argc != arg->argn + 1) 251440561Sbrian return -1; 251540561Sbrian 251643313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 251740561Sbrian return -1; 251840561Sbrian 251940561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 252040561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 252140561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 252240561Sbrian inet_ntoa(ifa)); 252340561Sbrian return 1; 252440561Sbrian } 252540561Sbrian 252640561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 252740561Sbrian if (!ok) { 252840561Sbrian if (arg->cmd->args) 252940561Sbrian ok = 1; 253040561Sbrian else if (arg->prompt) 253140561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 253240561Sbrian else 253340561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 253440561Sbrian } 253540561Sbrian 253640561Sbrian return !ok; 253740561Sbrian} 253840561Sbrian 253940561Sbrianstatic int 254040561SbrianIfaceClearCommand(struct cmdargs const *arg) 254140561Sbrian{ 254240561Sbrian int how; 254340561Sbrian 254440561Sbrian if (arg->argc != arg->argn) 254540561Sbrian return -1; 254640561Sbrian 254740941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 254840941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 254940561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 255040561Sbrian iface_Clear(arg->bundle->iface, how); 255140561Sbrian 255240561Sbrian return 0; 255340561Sbrian} 255440679Sbrian 255540679Sbrianstatic int 255640679SbrianSetProcTitle(struct cmdargs const *arg) 255740679Sbrian{ 255840679Sbrian static char title[LINE_LEN]; 255940679Sbrian char *argv[MAXARGS], *ptr; 256040679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 256140679Sbrian 256240679Sbrian if (arg->argc == arg->argn) { 256340679Sbrian arg->bundle->argv[0] = arg->bundle->argv0; 256440679Sbrian arg->bundle->argv[1] = arg->bundle->argv1; 256540679Sbrian return 0; 256640679Sbrian } 256740679Sbrian 256840679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 256940679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 257040679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 257140679Sbrian } 257247849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 257340679Sbrian 257440679Sbrian ptr = title; 257540679Sbrian remaining = sizeof title - 1; 257640679Sbrian for (f = 0; f < argc && remaining; f++) { 257740679Sbrian if (f) { 257840679Sbrian *ptr++ = ' '; 257940679Sbrian remaining--; 258040679Sbrian } 258140679Sbrian len = strlen(argv[f]); 258240679Sbrian if (len > remaining) 258340679Sbrian len = remaining; 258440679Sbrian memcpy(ptr, argv[f], len); 258540679Sbrian remaining -= len; 258640679Sbrian ptr += len; 258740679Sbrian } 258840679Sbrian *ptr = '\0'; 258940679Sbrian 259040679Sbrian arg->bundle->argv[0] = title; 259140679Sbrian arg->bundle->argv[1] = NULL; 259240679Sbrian 259340679Sbrian return 0; 259440679Sbrian} 2595