command.c revision 43888
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 * 2043888Sbrian * $Id: command.c,v 1.179 1999/01/28 09:40:15 brian Exp $ 218857Srgrimes * 226059Samurai */ 2343313Sbrian#include <sys/param.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3338628Sbrian#include <ctype.h> 3430715Sbrian#include <errno.h> 3526516Sbrian#include <fcntl.h> 3630715Sbrian#include <paths.h> 3730715Sbrian#include <stdio.h> 3830715Sbrian#include <stdlib.h> 3930715Sbrian#include <string.h> 4030715Sbrian#include <sys/wait.h> 4130715Sbrian#include <termios.h> 4230715Sbrian#include <unistd.h> 4330715Sbrian 4439395Sbrian#ifndef NOALIAS 4539395Sbrian#ifdef __OpenBSD__ 4639395Sbrian#include "alias.h" 4739395Sbrian#else 4839395Sbrian#include <alias.h> 4939395Sbrian#endif 5039395Sbrian#endif 5137009Sbrian#include "defs.h" 5231343Sbrian#include "command.h" 5330715Sbrian#include "mbuf.h" 5430715Sbrian#include "log.h" 5530715Sbrian#include "timer.h" 566059Samurai#include "fsm.h" 576059Samurai#include "lcp.h" 5831690Sbrian#include "iplist.h" 5936285Sbrian#include "throughput.h" 6036285Sbrian#include "slcompress.h" 6138557Sbrian#include "lqr.h" 6238557Sbrian#include "hdlc.h" 636059Samurai#include "ipcp.h" 646059Samurai#include "modem.h" 6531343Sbrian#ifndef NOALIAS 6626031Sbrian#include "alias_cmd.h" 6731343Sbrian#endif 6825630Sbrian#include "systems.h" 6936285Sbrian#include "filter.h" 7036285Sbrian#include "descriptor.h" 7130715Sbrian#include "main.h" 7230715Sbrian#include "route.h" 7330715Sbrian#include "ccp.h" 7431080Sbrian#include "auth.h" 7536285Sbrian#include "async.h" 7636285Sbrian#include "link.h" 7736285Sbrian#include "physical.h" 7836285Sbrian#include "mp.h" 7943313Sbrian#ifndef NORADIUS 8043313Sbrian#include "radius.h" 8143313Sbrian#endif 8236285Sbrian#include "bundle.h" 8336285Sbrian#include "server.h" 8436285Sbrian#include "prompt.h" 8536285Sbrian#include "chat.h" 8636285Sbrian#include "chap.h" 8738174Sbrian#include "cbcp.h" 8836285Sbrian#include "datalink.h" 8940561Sbrian#include "iface.h" 906059Samurai 9136285Sbrian/* ``set'' values */ 9236285Sbrian#define VAR_AUTHKEY 0 9336285Sbrian#define VAR_DIAL 1 9436285Sbrian#define VAR_LOGIN 2 9536285Sbrian#define VAR_AUTHNAME 3 9636285Sbrian#define VAR_AUTOLOAD 4 9736285Sbrian#define VAR_WINSIZE 5 9836285Sbrian#define VAR_DEVICE 6 9936285Sbrian#define VAR_ACCMAP 7 10036285Sbrian#define VAR_MRRU 8 10136285Sbrian#define VAR_MRU 9 10236285Sbrian#define VAR_MTU 10 10336285Sbrian#define VAR_OPENMODE 11 10436285Sbrian#define VAR_PHONE 12 10536285Sbrian#define VAR_HANGUP 13 10636285Sbrian#define VAR_IDLETIMEOUT 14 10736285Sbrian#define VAR_LQRPERIOD 15 10836285Sbrian#define VAR_LCPRETRY 16 10936285Sbrian#define VAR_CHAPRETRY 17 11036285Sbrian#define VAR_PAPRETRY 18 11136285Sbrian#define VAR_CCPRETRY 19 11236285Sbrian#define VAR_IPCPRETRY 20 11336285Sbrian#define VAR_DNS 21 11436285Sbrian#define VAR_NBNS 22 11536285Sbrian#define VAR_MODE 23 11638174Sbrian#define VAR_CALLBACK 24 11738174Sbrian#define VAR_CBCP 25 11838544Sbrian#define VAR_CHOKED 26 11940665Sbrian#define VAR_SENDPIPE 27 12040665Sbrian#define VAR_RECVPIPE 28 12143313Sbrian#define VAR_RADIUS 29 1226059Samurai 12336285Sbrian/* ``accept|deny|disable|enable'' masks */ 12436285Sbrian#define NEG_HISMASK (1) 12536285Sbrian#define NEG_MYMASK (2) 12636285Sbrian 12736285Sbrian/* ``accept|deny|disable|enable'' values */ 12836285Sbrian#define NEG_ACFCOMP 40 12936285Sbrian#define NEG_CHAP 41 13036285Sbrian#define NEG_DEFLATE 42 13136285Sbrian#define NEG_LQR 43 13236285Sbrian#define NEG_PAP 44 13336285Sbrian#define NEG_PPPDDEFLATE 45 13436285Sbrian#define NEG_PRED1 46 13536285Sbrian#define NEG_PROTOCOMP 47 13636285Sbrian#define NEG_SHORTSEQ 48 13736285Sbrian#define NEG_VJCOMP 49 13836285Sbrian#define NEG_DNS 50 13936285Sbrian 14043333Sbrianconst char Version[] = "2.1"; 14143888Sbrianconst char VersionDate[] = "$Date: 1999/01/28 09:40:15 $"; 14236285Sbrian 14336285Sbrianstatic int ShowCommand(struct cmdargs const *); 14436285Sbrianstatic int TerminalCommand(struct cmdargs const *); 14536285Sbrianstatic int QuitCommand(struct cmdargs const *); 14636285Sbrianstatic int OpenCommand(struct cmdargs const *); 14736285Sbrianstatic int CloseCommand(struct cmdargs const *); 14836285Sbrianstatic int DownCommand(struct cmdargs const *); 14936285Sbrianstatic int SetCommand(struct cmdargs const *); 15036285Sbrianstatic int LinkCommand(struct cmdargs const *); 15136285Sbrianstatic int AddCommand(struct cmdargs const *); 15236285Sbrianstatic int DeleteCommand(struct cmdargs const *); 15336285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 15436934Sbrianstatic int ClearCommand(struct cmdargs const *); 15540561Sbrianstatic int RunListCommand(struct cmdargs const *); 15640561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 15740561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 15840561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 15940679Sbrianstatic int SetProcTitle(struct cmdargs const *); 16031343Sbrian#ifndef NOALIAS 16136285Sbrianstatic int AliasEnable(struct cmdargs const *); 16236285Sbrianstatic int AliasOption(struct cmdargs const *); 16331343Sbrian#endif 1646059Samurai 16536285Sbrianstatic const char * 16636285Sbrianshowcx(struct cmdtab const *cmd) 16736285Sbrian{ 16836285Sbrian if (cmd->lauth & LOCAL_CX) 16936285Sbrian return "(c)"; 17036285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 17136285Sbrian return "(o)"; 17236285Sbrian 17336285Sbrian return ""; 17436285Sbrian} 17536285Sbrian 1766059Samuraistatic int 17731343SbrianHelpCommand(struct cmdargs const *arg) 1786059Samurai{ 17928679Sbrian struct cmdtab const *cmd; 18036285Sbrian int n, cmax, dmax, cols, cxlen; 18136285Sbrian const char *cx; 1826059Samurai 18336285Sbrian if (!arg->prompt) { 18436285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 18526516Sbrian return 0; 18636285Sbrian } 18726516Sbrian 18836285Sbrian if (arg->argc > arg->argn) { 18936285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 19036285Sbrian if ((cmd->lauth & arg->prompt->auth) && 19136285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 19236285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 19336285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 19428679Sbrian return 0; 1956059Samurai } 19626516Sbrian return -1; 1976059Samurai } 19836285Sbrian 19931372Sbrian cmax = dmax = 0; 20036285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 20136285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 20236285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 20331372Sbrian cmax = n; 20431372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 20531372Sbrian dmax = n; 20631372Sbrian } 20731372Sbrian 20831372Sbrian cols = 80 / (dmax + cmax + 3); 2096059Samurai n = 0; 21036285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 21136285Sbrian " (c) = Context required\n"); 21236285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 21336285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 21436285Sbrian cx = showcx(cmd); 21536285Sbrian cxlen = cmax - strlen(cmd->name); 21640482Sbrian if (n % cols != 0) 21740482Sbrian prompt_Printf(arg->prompt, " "); 21840482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 21936285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 22031372Sbrian if (++n % cols == 0) 22136285Sbrian prompt_Printf(arg->prompt, "\n"); 2226059Samurai } 22331372Sbrian if (n % cols != 0) 22436285Sbrian prompt_Printf(arg->prompt, "\n"); 22526516Sbrian 22626516Sbrian return 0; 2276059Samurai} 2286059Samurai 22936285Sbrianstatic int 23036285SbrianCloneCommand(struct cmdargs const *arg) 2316059Samurai{ 23236285Sbrian char namelist[LINE_LEN]; 23336285Sbrian char *name; 23436285Sbrian int f; 2356059Samurai 23636285Sbrian if (arg->argc == arg->argn) 23736285Sbrian return -1; 23836285Sbrian 23936285Sbrian namelist[sizeof namelist - 1] = '\0'; 24036285Sbrian for (f = arg->argn; f < arg->argc; f++) { 24136285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 24236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 24336285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2446059Samurai } 24536285Sbrian 24636285Sbrian return 0; 2476059Samurai} 2486059Samurai 2496059Samuraistatic int 25036285SbrianRemoveCommand(struct cmdargs const *arg) 2516059Samurai{ 25236285Sbrian if (arg->argc != arg->argn) 25336285Sbrian return -1; 25411336Samurai 25536285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 25636285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 25736285Sbrian return 2; 2586059Samurai } 25926516Sbrian 26036285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 26136285Sbrian return 0; 26236285Sbrian} 26332711Sbrian 26436285Sbrianstatic int 26536285SbrianRenameCommand(struct cmdargs const *arg) 26636285Sbrian{ 26736285Sbrian if (arg->argc != arg->argn + 1) 26836285Sbrian return -1; 26931121Sbrian 27036285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 27136285Sbrian return 0; 27236285Sbrian 27336285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 27436285Sbrian arg->cx->name, arg->argv[arg->argn]); 27536285Sbrian return 1; 27636285Sbrian} 27736285Sbrian 27836285Sbrianint 27936285SbrianLoadCommand(struct cmdargs const *arg) 28036285Sbrian{ 28140797Sbrian const char *err; 28240797Sbrian int n, mode; 28336285Sbrian 28440797Sbrian mode = arg->bundle->phys_type.all; 28536285Sbrian 28640797Sbrian if (arg->argn < arg->argc) { 28740797Sbrian for (n = arg->argn; n < arg->argc; n++) 28840797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 28940797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 29040797Sbrian return 1; 29140797Sbrian } 29240797Sbrian 29340797Sbrian for (n = arg->argn; n < arg->argc; n++) { 29440797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 29540797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 29640797Sbrian } 29740797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 29840797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 29940797Sbrian log_Printf(LogWARN, "default: %s\n", err); 30036285Sbrian return 1; 30136285Sbrian } else { 30240797Sbrian bundle_SetLabel(arg->bundle, "default"); 30340797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 30440797Sbrian bundle_SetLabel(arg->bundle, "default"); 30536285Sbrian } 30640797Sbrian 30726516Sbrian return 0; 3086059Samurai} 3096059Samurai 31036285Sbrianint 31136285SbrianSaveCommand(struct cmdargs const *arg) 31236285Sbrian{ 31336285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 31436285Sbrian return 1; 31536285Sbrian} 31636285Sbrian 31710528Samuraistatic int 31836285SbrianDialCommand(struct cmdargs const *arg) 31928536Sbrian{ 32036285Sbrian int res; 32136285Sbrian 32236465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 32336465Sbrian || (!arg->cx && 32436928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 32536285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 32636285Sbrian " interactive links\n"); 32736285Sbrian return 1; 32834536Sbrian } 32936285Sbrian 33036285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 33136285Sbrian return res; 33236285Sbrian 33337993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 33436285Sbrian 33536285Sbrian return 0; 33628536Sbrian} 33728536Sbrian 33838628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 33938628Sbrian 34038628Sbrianstatic char * 34138628Sbrianstrstrword(char *big, const char *little) 34238628Sbrian{ 34338628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 34438628Sbrian char *pos; 34538628Sbrian int len; 34638628Sbrian 34738628Sbrian pos = big; 34838628Sbrian len = strlen(little); 34938628Sbrian 35038628Sbrian while ((pos = strstr(pos, little)) != NULL) 35138628Sbrian if ((pos == big || !isinword(pos[-1])) && !isinword(pos[len])) 35238628Sbrian break; 35338628Sbrian else 35438628Sbrian pos++; 35538628Sbrian 35638628Sbrian return pos; 35738628Sbrian} 35838628Sbrian 35938628Sbrianstatic char * 36038628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 36138628Sbrian{ 36238628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 36338628Sbrian char *word, *ntgt; 36438628Sbrian int ltgt, loldstr, lnewstr, pos; 36538628Sbrian 36638628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 36738628Sbrian return tgt; 36838628Sbrian 36938628Sbrian ltgt = strlen(tgt) + 1; 37038628Sbrian loldstr = strlen(oldstr); 37138628Sbrian lnewstr = strlen(newstr); 37238628Sbrian do { 37338628Sbrian pos = word - tgt; 37438628Sbrian if (loldstr > lnewstr) 37538628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 37638628Sbrian if (loldstr != lnewstr) { 37738628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 37838628Sbrian if (ntgt == NULL) 37938628Sbrian break; /* Oh wonderful ! */ 38038628Sbrian word = ntgt + pos; 38138628Sbrian tgt = ntgt; 38238628Sbrian } 38338628Sbrian if (lnewstr > loldstr) 38438628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 38538628Sbrian bcopy(newstr, word, lnewstr); 38638628Sbrian } while ((word = strstrword(word, oldstr))); 38738628Sbrian 38838628Sbrian return tgt; 38938628Sbrian} 39038628Sbrian 39143888Sbrianvoid 39243888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 39343888Sbrian struct bundle *bundle, int inc0) 39438628Sbrian{ 39538628Sbrian int arg; 39640678Sbrian char pid[12]; 39738628Sbrian 39841755Sbrian if (inc0) 39941755Sbrian arg = 0; /* Start at arg 0 */ 40041755Sbrian else { 40141755Sbrian nargv[0] = strdup(oargv[0]); 40241755Sbrian arg = 1; 40341755Sbrian } 40440678Sbrian snprintf(pid, sizeof pid, "%d", getpid()); 40541755Sbrian for (; arg < argc; arg++) { 40638629Sbrian nargv[arg] = strdup(oargv[arg]); 40738629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 40838628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 40938629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 41040561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 41138628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 41238629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 41338629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 41438629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 41538629Sbrian bundle->ncp.mp.peer.enddisc.address, 41638629Sbrian bundle->ncp.mp.peer.enddisc.len)); 41738629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 41838629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 41938629Sbrian bundle->ncp.mp.cfg.enddisc.address, 42038629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 42140678Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pid); 42238629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 42338628Sbrian } 42438628Sbrian nargv[arg] = NULL; 42538628Sbrian} 42638628Sbrian 42728536Sbrianstatic int 42831343SbrianShellCommand(struct cmdargs const *arg, int bg) 42910528Samurai{ 43010528Samurai const char *shell; 43110528Samurai pid_t shpid; 43220813Sjkh 43318856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 43426911Sbrian /* we're only allowed to shell when we run ppp interactively */ 43536285Sbrian if (arg->prompt && arg->prompt->owner) { 43636285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 43726516Sbrian return 1; 43810528Samurai } 43926911Sbrian#endif 44028679Sbrian 44136285Sbrian if (arg->argc == arg->argn) { 44236285Sbrian if (!arg->prompt) { 44336285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 44436285Sbrian " a config file\n"); 44528381Sbrian return 1; 44636285Sbrian } else if (arg->prompt->owner) { 44736285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 44836285Sbrian " a socket connection\n"); 44936285Sbrian return 1; 45028381Sbrian } else if (bg) { 45136285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 45228679Sbrian " the foreground mode\n"); 45328381Sbrian return 1; 45428381Sbrian } 45534536Sbrian } 45634536Sbrian 45728679Sbrian if ((shpid = fork()) == 0) { 45836285Sbrian int i, fd; 45918531Sbde 46036285Sbrian if ((shell = getenv("SHELL")) == 0) 46136285Sbrian shell = _PATH_BSHELL; 46232017Sbrian 46336285Sbrian timer_TermService(); 46436285Sbrian 46536285Sbrian if (arg->prompt) 46636285Sbrian fd = arg->prompt->fd_out; 46736285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 46836285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 46936285Sbrian _PATH_DEVNULL, strerror(errno)); 47028679Sbrian exit(1); 47128679Sbrian } 47228679Sbrian for (i = 0; i < 3; i++) 47328679Sbrian dup2(fd, i); 47426516Sbrian 47536285Sbrian fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ 47626516Sbrian 47731061Sbrian setuid(geteuid()); 47836285Sbrian if (arg->argc > arg->argn) { 47928679Sbrian /* substitute pseudo args */ 48038628Sbrian char *argv[MAXARGS]; 48138628Sbrian int argc = arg->argc - arg->argn; 48238628Sbrian 48338628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 48438628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 48538628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 48631343Sbrian } 48743888Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0); 48828679Sbrian if (bg) { 48928679Sbrian pid_t p; 49010528Samurai 49128679Sbrian p = getpid(); 49228679Sbrian if (daemon(1, 1) == -1) { 49336832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 49428679Sbrian exit(1); 49528679Sbrian } 49636285Sbrian } else if (arg->prompt) 49736285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 49831343Sbrian execvp(argv[0], argv); 49930316Sbrian } else { 50036285Sbrian if (arg->prompt) 50132017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 50236285Sbrian prompt_TtyOldMode(arg->prompt); 50331343Sbrian execl(shell, shell, NULL); 50430316Sbrian } 50520813Sjkh 50640665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 50740665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 50840665Sbrian strerror(errno)); 50928679Sbrian exit(255); 51010528Samurai } 51136285Sbrian 51236285Sbrian if (shpid == (pid_t) - 1) 51336285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 51436285Sbrian else { 51510528Samurai int status; 51631343Sbrian waitpid(shpid, &status, 0); 51710528Samurai } 51820813Sjkh 51936285Sbrian if (arg->prompt && !arg->prompt->owner) 52036285Sbrian prompt_TtyCommandMode(arg->prompt); 52120813Sjkh 52236285Sbrian return 0; 52310528Samurai} 52410528Samurai 52531343Sbrianstatic int 52631343SbrianBgShellCommand(struct cmdargs const *arg) 52731343Sbrian{ 52836285Sbrian if (arg->argc == arg->argn) 52931343Sbrian return -1; 53031343Sbrian return ShellCommand(arg, 1); 53131343Sbrian} 53231343Sbrian 53331343Sbrianstatic int 53431343SbrianFgShellCommand(struct cmdargs const *arg) 53531343Sbrian{ 53631343Sbrian return ShellCommand(arg, 0); 53731343Sbrian} 53831343Sbrian 53940561Sbrian#ifndef NOALIAS 54040561Sbrianstatic struct cmdtab const AliasCommands[] = 54140561Sbrian{ 54240561Sbrian {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH, 54340561Sbrian "static address translation", "alias addr [addr_local addr_alias]"}, 54440561Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 54540561Sbrian "stop incoming connections", "alias deny_incoming [yes|no]", 54640561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 54740561Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 54840561Sbrian "enable IP aliasing", "alias enable [yes|no]"}, 54940561Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 55040561Sbrian "log aliasing link creation", "alias log [yes|no]", 55140561Sbrian (const void *) PKT_ALIAS_LOG}, 55240561Sbrian {"port", NULL, alias_RedirectPort, LOCAL_AUTH, 55340561Sbrian "port redirection", "alias port [proto addr_local:port_local port_alias]"}, 55440561Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 55540561Sbrian "try to leave port numbers unchanged", "alias same_ports [yes|no]", 55640561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 55740561Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 55840561Sbrian "alias unregistered (private) IP address space only", 55940561Sbrian "alias unregistered_only [yes|no]", 56040561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 56140561Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 56240561Sbrian "allocate host sockets", "alias use_sockets [yes|no]", 56340561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 56440561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 56540561Sbrian "Display this message", "alias help|? [command]", AliasCommands}, 56640561Sbrian {NULL, NULL, NULL}, 56740561Sbrian}; 56840561Sbrian#endif 56940561Sbrian 57040561Sbrianstatic struct cmdtab const AllowCommands[] = { 57140561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 57240561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 57340561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 57440561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 57540561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 57640561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 57740561Sbrian {NULL, NULL, NULL}, 57840561Sbrian}; 57940561Sbrian 58040561Sbrianstatic struct cmdtab const IfaceCommands[] = 58140561Sbrian{ 58240561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 58340561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 58440561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 58540561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 58640561Sbrian (void *)1}, 58740561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 58840561Sbrian "Clear iface address(es)", "iface clear"}, 58940561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 59040561Sbrian "Delete iface address", "iface delete addr", NULL}, 59140561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 59240561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 59340561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 59440561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 59540561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 59640561Sbrian "Show iface address(es)", "iface show"}, 59740561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 59840561Sbrian "Display this message", "alias help|? [command]", IfaceCommands}, 59940561Sbrian {NULL, NULL, NULL}, 60040561Sbrian}; 60140561Sbrian 60230715Sbrianstatic struct cmdtab const Commands[] = { 60336285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 60428679Sbrian "accept option request", "accept option .."}, 60528679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 60632109Sbrian "add route", "add dest mask gateway", NULL}, 60736285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 60832109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 60936285Sbrian#ifndef NOALIAS 61040561Sbrian {"alias", NULL, RunListCommand, LOCAL_AUTH, 61140561Sbrian "alias control", "alias option [yes|no]", AliasCommands}, 61236285Sbrian#endif 61340561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 61440561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 61528679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 61631372Sbrian "Run a background command", "[!]bg command"}, 61736934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 61836934Sbrian "Clear throughput statistics", "clear ipcp|modem [current|overall|peak]..."}, 61936285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 62036285Sbrian "Clone a link", "clone newname..."}, 62136285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 62236285Sbrian "Close an FSM", "close [lcp|ccp]"}, 62328679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 62432109Sbrian "delete route", "delete dest", NULL}, 62536285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 62632109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 62736285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 62828679Sbrian "Deny option request", "deny option .."}, 62936285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63040797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 63136285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63228679Sbrian "Disable option", "disable option .."}, 63336285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63436285Sbrian "Generate a down event", "down"}, 63536285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63628679Sbrian "Enable option", "enable option .."}, 63740561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 63840561Sbrian "interface control", "iface option ...", IfaceCommands}, 63936285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 64036285Sbrian "Link specific commands", "link name command ..."}, 64137008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64240797Sbrian "Load settings", "load [system ...]"}, 64336285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64437955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 64536285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 64636285Sbrian "Password for manipulation", "passwd LocalPassword"}, 64736285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 64836285Sbrian "Quit PPP program", "quit|bye [all]"}, 64936285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 65036285Sbrian "Remove a link", "remove"}, 65136285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 65236285Sbrian "Rename a link", "rename name"}, 65328679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 65428679Sbrian "Save settings", "save"}, 65536285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65628679Sbrian "Set parameters", "set[up] var value"}, 65728679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 65828679Sbrian "Run a subshell", "shell|! [sh command]"}, 65936285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66031372Sbrian "Show status and stats", "show var"}, 66136285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 66231372Sbrian "Enter terminal mode", "term"}, 66328679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 66431343Sbrian "Display this message", "help|? [command]", Commands}, 66528679Sbrian {NULL, NULL, NULL}, 6666059Samurai}; 6676059Samurai 66828536Sbrianstatic int 66931343SbrianShowEscape(struct cmdargs const *arg) 6706059Samurai{ 67136285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 67236285Sbrian int code, bit; 67336285Sbrian const char *sep = ""; 6746059Samurai 67526516Sbrian for (code = 0; code < 32; code++) 67636285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 67728679Sbrian for (bit = 0; bit < 8; bit++) 67836285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 67936285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 68036285Sbrian sep = ", "; 68136285Sbrian } 68236285Sbrian prompt_Printf(arg->prompt, "\n"); 6836059Samurai } 68431077Sbrian return 0; 6856059Samurai} 6866059Samurai 68728679Sbrianstatic int 68836285SbrianShowTimerList(struct cmdargs const *arg) 6896059Samurai{ 69036285Sbrian timer_Show(0, arg->prompt); 69131077Sbrian return 0; 6926059Samurai} 6936059Samurai 69428679Sbrianstatic int 69531343SbrianShowStopped(struct cmdargs const *arg) 69628327Sbrian{ 69736285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 69836285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 69936285Sbrian prompt_Printf(arg->prompt, "Disabled"); 70028327Sbrian else 70136285Sbrian prompt_Printf(arg->prompt, "%ld secs", 70236285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 70328461Sbrian 70436285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 70536285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 70636285Sbrian prompt_Printf(arg->prompt, "Disabled"); 70728461Sbrian else 70836285Sbrian prompt_Printf(arg->prompt, "%ld secs", 70936285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 71028461Sbrian 71136285Sbrian prompt_Printf(arg->prompt, "\n"); 71228461Sbrian 71331077Sbrian return 0; 71428327Sbrian} 71528327Sbrian 71628679Sbrianstatic int 71731343SbrianShowVersion(struct cmdargs const *arg) 7186059Samurai{ 71936285Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate); 72031077Sbrian return 0; 7216059Samurai} 7226059Samurai 72328679Sbrianstatic int 72436285SbrianShowProtocolStats(struct cmdargs const *arg) 72526326Sbrian{ 72636285Sbrian struct link *l = command_ChooseLink(arg); 72726326Sbrian 72836285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 72936285Sbrian link_ReportProtocolStatus(l, arg->prompt); 73031077Sbrian return 0; 73126326Sbrian} 73226326Sbrian 73330715Sbrianstatic struct cmdtab const ShowCommands[] = { 73436285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 73536285Sbrian "bundle details", "show bundle"}, 73636285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 73736285Sbrian "CCP status", "show cpp"}, 73836285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 73936285Sbrian "VJ compression stats", "show compress"}, 74036285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 74136285Sbrian "escape characters", "show escape"}, 74236285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 74336285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 74436285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 74536285Sbrian "HDLC errors", "show hdlc"}, 74640561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 74740561Sbrian "Interface status", "show iface"}, 74836285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 74936285Sbrian "IPCP status", "show ipcp"}, 75036285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 75136285Sbrian "LCP status", "show lcp"}, 75236285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 75336285Sbrian "(high-level) link info", "show link"}, 75436285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 75536285Sbrian "available link names", "show links"}, 75636285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 75736285Sbrian "log levels", "show log"}, 75836285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 75936285Sbrian "mbuf allocations", "show mem"}, 76036285Sbrian {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, 76136285Sbrian "(low-level) link info", "show modem"}, 76236285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 76336285Sbrian "multilink setup", "show mp"}, 76436285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 76536285Sbrian "protocol summary", "show proto"}, 76636285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 76736285Sbrian "routing table", "show route"}, 76836285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 76936285Sbrian "STOPPED timeout", "show stopped"}, 77036285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 77136285Sbrian "alarm timers", "show timers"}, 77228679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 77336285Sbrian "version string", "show version"}, 77436285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 77536285Sbrian "client list", "show who"}, 77628679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 77731343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 77828679Sbrian {NULL, NULL, NULL}, 7796059Samurai}; 7806059Samurai 78130715Sbrianstatic struct cmdtab const * 78231343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 7836059Samurai{ 78426516Sbrian int nmatch; 78526516Sbrian int len; 78628679Sbrian struct cmdtab const *found; 7876059Samurai 78826516Sbrian found = NULL; 78926516Sbrian len = strlen(str); 79026516Sbrian nmatch = 0; 7916059Samurai while (cmds->func) { 79225566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 79326516Sbrian if (cmds->name[len] == '\0') { 79428679Sbrian *pmatch = 1; 79528679Sbrian return cmds; 79626516Sbrian } 7976059Samurai nmatch++; 7986059Samurai found = cmds; 79928679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 80026516Sbrian if (cmds->alias[len] == '\0') { 80128679Sbrian *pmatch = 1; 80228679Sbrian return cmds; 80326516Sbrian } 8046059Samurai nmatch++; 8056059Samurai found = cmds; 8066059Samurai } 8076059Samurai cmds++; 8086059Samurai } 8096059Samurai *pmatch = nmatch; 81026516Sbrian return found; 8116059Samurai} 8126059Samurai 81336285Sbrianstatic const char * 81436285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 81536285Sbrian{ 81636285Sbrian int f, tlen, len; 81736285Sbrian 81836285Sbrian tlen = 0; 81936285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 82036285Sbrian if (f) 82136285Sbrian tgt[tlen++] = ' '; 82236285Sbrian len = strlen(argv[f]); 82336285Sbrian if (len > sz - tlen - 1) 82436285Sbrian len = sz - tlen - 1; 82536285Sbrian strncpy(tgt+tlen, argv[f], len); 82636285Sbrian tlen += len; 82736285Sbrian } 82836285Sbrian tgt[tlen] = '\0'; 82936285Sbrian return tgt; 83036285Sbrian} 83136285Sbrian 83230715Sbrianstatic int 83336285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 83436285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8356059Samurai{ 83628679Sbrian struct cmdtab const *cmd; 8376059Samurai int val = 1; 8386059Samurai int nmatch; 83931343Sbrian struct cmdargs arg; 84036285Sbrian char prefix[100]; 8416059Samurai 84236285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8436059Samurai if (nmatch > 1) 84436285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 84536285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 84636285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 84736285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 84836285Sbrian /* We've got no context, but we require it */ 84936285Sbrian cx = bundle2datalink(bundle, NULL); 85036285Sbrian 85136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 85236285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 85336285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 85436285Sbrian else { 85536285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 85636285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 85736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 85836285Sbrian cx = NULL; 85936285Sbrian } 86036285Sbrian arg.cmdtab = cmds; 86136285Sbrian arg.cmd = cmd; 86236285Sbrian arg.argc = argc; 86336285Sbrian arg.argn = argn+1; 86436285Sbrian arg.argv = argv; 86536285Sbrian arg.bundle = bundle; 86636285Sbrian arg.cx = cx; 86736285Sbrian arg.prompt = prompt; 86836285Sbrian val = (*cmd->func) (&arg); 86936285Sbrian } 87031343Sbrian } else 87136285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 87236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 87326516Sbrian 87426516Sbrian if (val == -1) 87536285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 87628679Sbrian else if (val) 87736285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 87836285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 87926516Sbrian 88026516Sbrian return val; 8816059Samurai} 8826059Samurai 88337009Sbrianint 88437009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 8856059Samurai{ 8866059Samurai char *cp; 8876059Samurai 8886059Samurai if (nb > 0) { 8896059Samurai cp = buff + strcspn(buff, "\r\n"); 8906059Samurai if (cp) 8916059Samurai *cp = '\0'; 89237009Sbrian return MakeArgs(buff, argv, MAXARGS); 89337009Sbrian } 89437009Sbrian return 0; 89531121Sbrian} 8966059Samurai 89731822Sbrianstatic int 89831822Sbrianarghidden(int argc, char const *const *argv, int n) 89931822Sbrian{ 90031822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 90131828Sbrian 90231828Sbrian /* set authkey xxxxx */ 90331828Sbrian /* set key xxxxx */ 90431822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 90531822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 90631822Sbrian return 1; 90731822Sbrian 90831828Sbrian /* passwd xxxxx */ 90931828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 91031828Sbrian return 1; 91131828Sbrian 91236285Sbrian /* set server port xxxxx .... */ 91336285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 91436285Sbrian !strncasecmp(argv[1], "se", 2)) 91536285Sbrian return 1; 91636285Sbrian 91731822Sbrian return 0; 91831822Sbrian} 91931822Sbrian 92031121Sbrianvoid 92136285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 92237008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 92331121Sbrian{ 92431156Sbrian if (argc > 0) { 92536285Sbrian if (log_IsKept(LogCOMMAND)) { 92631156Sbrian static char buf[LINE_LEN]; 92731156Sbrian int f, n; 92831156Sbrian 92931156Sbrian *buf = '\0'; 93031156Sbrian if (label) { 93131962Sbrian strncpy(buf, label, sizeof buf - 3); 93231962Sbrian buf[sizeof buf - 3] = '\0'; 93331156Sbrian strcat(buf, ": "); 93431156Sbrian } 93531156Sbrian n = strlen(buf); 93631156Sbrian for (f = 0; f < argc; f++) { 93731962Sbrian if (n < sizeof buf - 1 && f) 93831156Sbrian buf[n++] = ' '; 93931822Sbrian if (arghidden(argc, argv, f)) 94036285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 94131822Sbrian else 94231962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 94331156Sbrian n += strlen(buf+n); 94431156Sbrian } 94536285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 94631156Sbrian } 94737008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 94831156Sbrian } 9496059Samurai} 9506059Samurai 95131121Sbrianvoid 95236285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 95336285Sbrian const char *label) 95431121Sbrian{ 95531121Sbrian int argc; 95637009Sbrian char *argv[MAXARGS]; 95731121Sbrian 95837009Sbrian argc = command_Interpret(buff, nb, argv); 95937008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 96031121Sbrian} 96131121Sbrian 9626059Samuraistatic int 96331343SbrianShowCommand(struct cmdargs const *arg) 9646059Samurai{ 96536285Sbrian if (!arg->prompt) 96636285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 96736285Sbrian else if (arg->argc > arg->argn) 96836285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 96936285Sbrian arg->prompt, arg->cx); 9706059Samurai else 97136285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 97226516Sbrian 97326516Sbrian return 0; 9746059Samurai} 9756059Samurai 9766059Samuraistatic int 97731343SbrianTerminalCommand(struct cmdargs const *arg) 9786059Samurai{ 97936285Sbrian if (!arg->prompt) { 98036285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 98126516Sbrian return 1; 9826059Samurai } 98336285Sbrian 98436285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 98536285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 98636285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 98736285Sbrian return 1; 9886059Samurai } 98936285Sbrian 99036285Sbrian datalink_Up(arg->cx, 0, 0); 99136285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 99236285Sbrian return 0; 9936059Samurai} 9946059Samurai 9956059Samuraistatic int 99631343SbrianQuitCommand(struct cmdargs const *arg) 9976059Samurai{ 99836285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 99936285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 100036285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 100136285Sbrian Cleanup(EX_NORMAL); 100236285Sbrian if (arg->prompt) 100336285Sbrian prompt_Destroy(arg->prompt, 1); 100426516Sbrian 100526516Sbrian return 0; 10066059Samurai} 10076059Samurai 10086059Samuraistatic int 100936285SbrianOpenCommand(struct cmdargs const *arg) 10106059Samurai{ 101137160Sbrian if (arg->argc == arg->argn) 101237993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 101337160Sbrian else if (arg->argc == arg->argn + 1) { 101437160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 101537385Sbrian struct datalink *cx = arg->cx ? 101637385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 101737385Sbrian if (cx) { 101837385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 101937385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 102037160Sbrian else 102137993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 102237160Sbrian } else 102337160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 102437160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 102537160Sbrian struct fsm *fp; 10266059Samurai 102737210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 102837160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 102937160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 103037160Sbrian else if (fp->state == ST_OPENED) 103137160Sbrian fsm_Reopen(fp); 103237160Sbrian else { 103337160Sbrian fp->open_mode = 0; /* Not passive any more */ 103437160Sbrian if (fp->state == ST_STOPPED) { 103537160Sbrian fsm_Down(fp); 103637160Sbrian fsm_Up(fp); 103737160Sbrian } else { 103837160Sbrian fsm_Up(fp); 103937160Sbrian fsm_Open(fp); 104037160Sbrian } 104136285Sbrian } 104237160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 104337160Sbrian if (arg->cx) 104437160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 104537160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 104637160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 104737160Sbrian else 104837993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 104937160Sbrian } else 105037160Sbrian return -1; 105136285Sbrian } else 105236285Sbrian return -1; 105336285Sbrian 105426516Sbrian return 0; 10556059Samurai} 10566059Samurai 105725067Sbrianstatic int 105836285SbrianCloseCommand(struct cmdargs const *arg) 10596059Samurai{ 106037007Sbrian if (arg->argc == arg->argn) 106137007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 106237007Sbrian else if (arg->argc == arg->argn + 1) { 106337007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 106437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 106537007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 106637007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 106737007Sbrian struct fsm *fp; 10686059Samurai 106937210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 107037007Sbrian if (fp->state == ST_OPENED) { 107137007Sbrian fsm_Close(fp); 107237007Sbrian if (arg->argv[arg->argn][3] == '!') 107337007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 107437007Sbrian else 107537007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 107637007Sbrian } 107737007Sbrian } else 107836285Sbrian return -1; 107936285Sbrian } else 108036285Sbrian return -1; 108136285Sbrian 108236285Sbrian return 0; 10836059Samurai} 10846059Samurai 108525067Sbrianstatic int 108636285SbrianDownCommand(struct cmdargs const *arg) 108711336Samurai{ 108837018Sbrian if (arg->argc == arg->argn) { 108937018Sbrian if (arg->cx) 109037018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 109137018Sbrian else 109237018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 109337018Sbrian } else if (arg->argc == arg->argn + 1) { 109437018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 109537018Sbrian if (arg->cx) 109637018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 109737018Sbrian else 109837018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 109937018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 110037018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 110137018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 110237060Sbrian fsm2initial(fp); 110337018Sbrian } else 110437018Sbrian return -1; 110536285Sbrian } else 110636285Sbrian return -1; 110736285Sbrian 110836285Sbrian return 0; 110925067Sbrian} 111025067Sbrian 111125067Sbrianstatic int 111236285SbrianSetModemSpeed(struct cmdargs const *arg) 111325067Sbrian{ 111436285Sbrian long speed; 111536285Sbrian char *end; 111611336Samurai 111736285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 111836285Sbrian if (arg->argc > arg->argn+1) { 111936285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 112036285Sbrian return -1; 112111336Samurai } 112236285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 112336285Sbrian physical_SetSync(arg->cx->physical); 112436285Sbrian return 0; 112536285Sbrian } 112636285Sbrian end = NULL; 112736285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 112836285Sbrian if (*end) { 112936285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 113036285Sbrian arg->argv[arg->argn]); 113136285Sbrian return -1; 113236285Sbrian } 113336285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 113436285Sbrian return 0; 113536285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 113636285Sbrian } else 113736285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 113824939Sbrian 113926516Sbrian return -1; 114011336Samurai} 114111336Samurai 114225067Sbrianstatic int 114331343SbrianSetStoppedTimeout(struct cmdargs const *arg) 114428327Sbrian{ 114536285Sbrian struct link *l = &arg->cx->physical->link; 114636285Sbrian 114736285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 114836285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 114936285Sbrian if (arg->argc <= arg->argn+2) { 115036285Sbrian if (arg->argc > arg->argn) { 115136285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 115236285Sbrian if (arg->argc > arg->argn+1) 115336285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 115428461Sbrian } 115528327Sbrian return 0; 115628327Sbrian } 115728327Sbrian return -1; 115828327Sbrian} 115928327Sbrian 116031081Sbrian#define ismask(x) \ 116131081Sbrian (*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3) 116231081Sbrian 116328327Sbrianstatic int 116431343SbrianSetServer(struct cmdargs const *arg) 116526940Sbrian{ 116626940Sbrian int res = -1; 116726940Sbrian 116836285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 116931081Sbrian const char *port, *passwd, *mask; 117031081Sbrian 117131081Sbrian /* What's what ? */ 117236285Sbrian port = arg->argv[arg->argn]; 117336285Sbrian if (arg->argc == arg->argn + 2) { 117436285Sbrian passwd = arg->argv[arg->argn+1]; 117536285Sbrian mask = NULL; 117636285Sbrian } else if (arg->argc == arg->argn + 3) { 117736285Sbrian passwd = arg->argv[arg->argn+1]; 117836285Sbrian mask = arg->argv[arg->argn+2]; 117931081Sbrian if (!ismask(mask)) 118031081Sbrian return -1; 118136285Sbrian } else if (strcasecmp(port, "none") == 0) { 118236285Sbrian if (server_Close(arg->bundle)) 118336285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 118436285Sbrian return 0; 118531081Sbrian } else 118636285Sbrian return -1; 118731081Sbrian 118836285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 118936285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 119031081Sbrian 119136285Sbrian if (*port == '/') { 119231081Sbrian mode_t imask; 119336285Sbrian char *ptr, name[LINE_LEN + 12]; 119428679Sbrian 119531081Sbrian if (mask != NULL) { 119628679Sbrian unsigned m; 119728679Sbrian 119831081Sbrian if (sscanf(mask, "%o", &m) == 1) 119931081Sbrian imask = m; 120031081Sbrian else 120131081Sbrian return -1; 120231081Sbrian } else 120331081Sbrian imask = (mode_t)-1; 120436285Sbrian 120536285Sbrian ptr = strstr(port, "%d"); 120636285Sbrian if (ptr) { 120736285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 120837210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 120936285Sbrian port = name; 121036285Sbrian } 121136285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 121227346Sbrian } else { 121336285Sbrian int iport, add = 0; 121428679Sbrian 121531081Sbrian if (mask != NULL) 121631081Sbrian return -1; 121728679Sbrian 121836285Sbrian if (*port == '+') { 121936285Sbrian port++; 122036285Sbrian add = 1; 122136285Sbrian } 122231081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 122331081Sbrian struct servent *s; 122431081Sbrian 122531081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 122631081Sbrian iport = 0; 122736285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 122828679Sbrian } else 122931081Sbrian iport = ntohs(s->s_port); 123027346Sbrian } else 123131081Sbrian iport = atoi(port); 123236285Sbrian 123336285Sbrian if (iport) { 123436285Sbrian if (add) 123536285Sbrian iport += arg->bundle->unit; 123636285Sbrian res = server_TcpOpen(arg->bundle, iport); 123736285Sbrian } else 123836285Sbrian res = -1; 123927346Sbrian } 124031081Sbrian } 124126940Sbrian 124226940Sbrian return res; 124326940Sbrian} 124426940Sbrian 124526940Sbrianstatic int 124631343SbrianSetModemParity(struct cmdargs const *arg) 12476059Samurai{ 124836285Sbrian return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical, 124936285Sbrian arg->argv[arg->argn]) : -1; 12506059Samurai} 12516059Samurai 12526059Samuraistatic int 125331343SbrianSetEscape(struct cmdargs const *arg) 12546059Samurai{ 12556059Samurai int code; 125636285Sbrian int argc = arg->argc - arg->argn; 125736285Sbrian char const *const *argv = arg->argv + arg->argn; 12586059Samurai 12596059Samurai for (code = 0; code < 33; code++) 126036285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 126131343Sbrian 12626059Samurai while (argc-- > 0) { 12636059Samurai sscanf(*argv++, "%x", &code); 12646059Samurai code &= 0xff; 126536285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 126636285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 12676059Samurai } 126826516Sbrian return 0; 12696059Samurai} 12706059Samurai 127130715Sbrianstatic struct in_addr 127231343SbrianGetIpAddr(const char *cp) 12736059Samurai{ 12746059Samurai struct hostent *hp; 12756059Samurai struct in_addr ipaddr; 12766059Samurai 127732124Sbrian if (inet_aton(cp, &ipaddr) == 0) { 127832124Sbrian hp = gethostbyname(cp); 127932124Sbrian if (hp && hp->h_addrtype == AF_INET) 128032124Sbrian memcpy(&ipaddr, hp->h_addr, hp->h_length); 128132124Sbrian else 128232124Sbrian ipaddr.s_addr = 0; 128332124Sbrian } 128428679Sbrian return (ipaddr); 12856059Samurai} 12866059Samurai 12876059Samuraistatic int 128831343SbrianSetInterfaceAddr(struct cmdargs const *arg) 12896059Samurai{ 129036285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 129132267Sbrian const char *hisaddr; 129232267Sbrian 129340561Sbrian if (arg->argc > arg->argn + 4) 129440561Sbrian return -1; 129540561Sbrian 129632267Sbrian hisaddr = NULL; 129736285Sbrian ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 129836285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 129936285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 130036285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 130136285Sbrian iplist_reset(&ipcp->cfg.peer_list); 130228394Sbrian 130336285Sbrian if (arg->argc > arg->argn) { 130443313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 130536285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 130636285Sbrian &ipcp->cfg.my_range.width)) 130728679Sbrian return 1; 130836285Sbrian if (arg->argc > arg->argn+1) { 130936285Sbrian hisaddr = arg->argv[arg->argn+1]; 131036285Sbrian if (arg->argc > arg->argn+2) { 131136285Sbrian ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 131236285Sbrian if (arg->argc > arg->argn+3) { 131336285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 131436285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 13159440Samurai } 13166059Samurai } 13176059Samurai } 13186059Samurai } 131928394Sbrian 132040561Sbrian /* 0.0.0.0 means any address (0 bits) */ 132136285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 132236285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 132336285Sbrian ipcp->cfg.my_range.width = 0; 13246059Samurai } 132536285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 132636285Sbrian 132736285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 132836928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 132932267Sbrian return 4; 133031121Sbrian 133126516Sbrian return 0; 13326059Samurai} 13336059Samurai 133418752Sjkhstatic int 133531343SbrianSetVariable(struct cmdargs const *arg) 13366059Samurai{ 133737210Sbrian long long_val, param = (long)arg->cmd->args; 133837210Sbrian int mode, dummyint; 133931343Sbrian const char *argp; 134036285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 134136285Sbrian const char *err = NULL; 134236285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 134336285Sbrian struct in_addr dummyaddr, *addr; 13446059Samurai 134536285Sbrian if (arg->argc > arg->argn) 134636285Sbrian argp = arg->argv[arg->argn]; 134726551Sbrian else 134831343Sbrian argp = ""; 134926551Sbrian 135036285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 135136285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 135236285Sbrian arg->cmd->name); 135336285Sbrian return 1; 135436285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 135536285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 135636285Sbrian arg->cmd->name, cx->name); 135736285Sbrian cx = NULL; 135836285Sbrian } 135936285Sbrian 136026551Sbrian switch (param) { 136128679Sbrian case VAR_AUTHKEY: 136240622Sbrian switch (bundle_Phase(arg->bundle)) { 136340622Sbrian case PHASE_DEAD: 136440622Sbrian case PHASE_ESTABLISH: 136540622Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 136640622Sbrian sizeof arg->bundle->cfg.auth.key - 1); 136740622Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 136840622Sbrian break; 136940622Sbrian default: 137040622Sbrian err = "set authkey: Only available at phase DEAD/ESTABLISH\n"; 137140622Sbrian log_Printf(LogWARN, err); 137240622Sbrian break; 137336285Sbrian } 137428679Sbrian break; 137537210Sbrian 137628679Sbrian case VAR_AUTHNAME: 137740622Sbrian switch (bundle_Phase(arg->bundle)) { 137840622Sbrian case PHASE_DEAD: 137940622Sbrian case PHASE_ESTABLISH: 138040622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 138140622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 138240622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 138340622Sbrian break; 138440622Sbrian default: 138540622Sbrian err = "set authname: Only available at phase DEAD/ESTABLISH\n"; 138640622Sbrian log_Printf(LogWARN, err); 138740622Sbrian break; 138836285Sbrian } 138928679Sbrian break; 139037210Sbrian 139136285Sbrian case VAR_AUTOLOAD: 139236285Sbrian if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { 139336285Sbrian arg->bundle->autoload.running = 1; 139436285Sbrian arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); 139536285Sbrian arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); 139636285Sbrian if (arg->argc == arg->argn + 4) { 139736285Sbrian arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); 139836285Sbrian arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); 139936285Sbrian } else { 140036285Sbrian arg->bundle->cfg.autoload.min.timeout = 0; 140136285Sbrian arg->bundle->cfg.autoload.min.packets = 0; 140236285Sbrian } 140336285Sbrian } else { 140436285Sbrian err = "Set autoload requires two or four arguments\n"; 140536285Sbrian log_Printf(LogWARN, err); 140636285Sbrian } 140736285Sbrian break; 140837210Sbrian 140928679Sbrian case VAR_DIAL: 141036285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 141136285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 141228679Sbrian break; 141337210Sbrian 141428679Sbrian case VAR_LOGIN: 141536285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 141636285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 141728679Sbrian break; 141837210Sbrian 141936285Sbrian case VAR_WINSIZE: 142036285Sbrian if (arg->argc > arg->argn) { 142136285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 142236285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 142336285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 142436285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 142536285Sbrian l->ccp.cfg.deflate.out.winsize); 142636285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 142736285Sbrian } 142836285Sbrian if (arg->argc > arg->argn+1) { 142936285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 143036285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 143136285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 143236285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 143336285Sbrian l->ccp.cfg.deflate.in.winsize); 143436285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 143536285Sbrian } 143636285Sbrian } else 143736285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 143836285Sbrian } else { 143936285Sbrian err = "No window size specified\n"; 144036285Sbrian log_Printf(LogWARN, err); 144136285Sbrian } 144236285Sbrian break; 144337210Sbrian 144428679Sbrian case VAR_DEVICE: 144536285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 144636285Sbrian arg->argv + arg->argn); 144736285Sbrian break; 144837210Sbrian 144936285Sbrian case VAR_ACCMAP: 145036285Sbrian if (arg->argc > arg->argn) { 145137210Sbrian u_long ulong_val; 145236285Sbrian sscanf(argp, "%lx", &ulong_val); 145337210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 145436285Sbrian } else { 145536285Sbrian err = "No accmap specified\n"; 145636285Sbrian log_Printf(LogWARN, err); 145736285Sbrian } 145836285Sbrian break; 145937210Sbrian 146036285Sbrian case VAR_MODE: 146136285Sbrian mode = Nam2mode(argp); 146236285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 146336285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 146436285Sbrian return -1; 146536285Sbrian } 146636285Sbrian bundle_SetMode(arg->bundle, cx, mode); 146736285Sbrian break; 146837210Sbrian 146936285Sbrian case VAR_MRRU: 147040622Sbrian switch (bundle_Phase(arg->bundle)) { 147140622Sbrian case PHASE_DEAD: 147240622Sbrian break; 147340622Sbrian case PHASE_ESTABLISH: 147440622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 147540622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 147640622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 147740622Sbrian return 1; 147840622Sbrian } 147940622Sbrian break; 148040622Sbrian default: 148140622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 148240622Sbrian return 1; 148329696Sbrian } 148437210Sbrian long_val = atol(argp); 148537210Sbrian if (long_val && long_val < MIN_MRU) { 148637210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 148737210Sbrian return 1; 148837210Sbrian } else if (long_val > MAX_MRU) { 148937210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 149037210Sbrian return 1; 149137210Sbrian } else 149237210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 149328679Sbrian break; 149437210Sbrian 149536285Sbrian case VAR_MRU: 149637210Sbrian long_val = atol(argp); 149737210Sbrian if (long_val == 0) 149837210Sbrian l->lcp.cfg.mru = DEF_MRU; 149937210Sbrian else if (long_val < MIN_MRU) { 150037210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 150137210Sbrian return 1; 150237210Sbrian } else if (long_val > MAX_MRU) { 150337210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 150437210Sbrian return 1; 150537210Sbrian } else 150637210Sbrian l->lcp.cfg.mru = long_val; 150728679Sbrian break; 150837210Sbrian 150936285Sbrian case VAR_MTU: 151037210Sbrian long_val = atol(argp); 151137210Sbrian if (long_val && long_val < MIN_MTU) { 151237210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 151337210Sbrian return 1; 151437210Sbrian } else if (long_val > MAX_MTU) { 151537210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 151637210Sbrian return 1; 151737210Sbrian } else 151837210Sbrian arg->bundle->cfg.mtu = long_val; 151936285Sbrian break; 152037210Sbrian 152136285Sbrian case VAR_OPENMODE: 152236285Sbrian if (strcasecmp(argp, "active") == 0) 152336285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 152436285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 152536285Sbrian else if (strcasecmp(argp, "passive") == 0) 152636285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 152736285Sbrian else { 152836285Sbrian err = "%s: Invalid openmode\n"; 152936285Sbrian log_Printf(LogWARN, err, argp); 153036285Sbrian } 153136285Sbrian break; 153237210Sbrian 153328679Sbrian case VAR_PHONE: 153436285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 153536285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 153638174Sbrian cx->phone.alt = cx->phone.next = NULL; 153728679Sbrian break; 153837210Sbrian 153928679Sbrian case VAR_HANGUP: 154036285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 154136285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 154228679Sbrian break; 154337210Sbrian 154436285Sbrian case VAR_IDLETIMEOUT: 154536285Sbrian if (arg->argc > arg->argn+1) 154636285Sbrian err = "Too many idle timeout values\n"; 154736285Sbrian else if (arg->argc == arg->argn+1) 154836285Sbrian bundle_SetIdleTimer(arg->bundle, atoi(argp)); 154936285Sbrian if (err) 155036285Sbrian log_Printf(LogWARN, err); 155129549Sbrian break; 155237210Sbrian 155336285Sbrian case VAR_LQRPERIOD: 155437210Sbrian long_val = atol(argp); 155537210Sbrian if (long_val < MIN_LQRPERIOD) { 155637210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 155737210Sbrian long_val, MIN_LQRPERIOD); 155837210Sbrian return 1; 155936285Sbrian } else 156037210Sbrian l->lcp.cfg.lqrperiod = long_val; 156136285Sbrian break; 156237210Sbrian 156336285Sbrian case VAR_LCPRETRY: 156437210Sbrian long_val = atol(argp); 156537210Sbrian if (long_val < MIN_FSMRETRY) { 156637210Sbrian log_Printf(LogWARN, "%ld: Invalid LCP FSM retry period - min %d\n", 156737210Sbrian long_val, MIN_FSMRETRY); 156837210Sbrian return 1; 156936285Sbrian } else 157037210Sbrian cx->physical->link.lcp.cfg.fsmretry = long_val; 157136285Sbrian break; 157237210Sbrian 157336285Sbrian case VAR_CHAPRETRY: 157437210Sbrian long_val = atol(argp); 157537210Sbrian if (long_val < MIN_FSMRETRY) { 157637210Sbrian log_Printf(LogWARN, "%ld: Invalid CHAP FSM retry period - min %d\n", 157737210Sbrian long_val, MIN_FSMRETRY); 157837210Sbrian return 1; 157936285Sbrian } else 158037210Sbrian cx->chap.auth.cfg.fsmretry = long_val; 158136285Sbrian break; 158237210Sbrian 158336285Sbrian case VAR_PAPRETRY: 158437210Sbrian long_val = atol(argp); 158537210Sbrian if (long_val < MIN_FSMRETRY) { 158637210Sbrian log_Printf(LogWARN, "%ld: Invalid PAP FSM retry period - min %d\n", 158737210Sbrian long_val, MIN_FSMRETRY); 158837210Sbrian return 1; 158936285Sbrian } else 159037210Sbrian cx->pap.cfg.fsmretry = long_val; 159136285Sbrian break; 159237210Sbrian 159336285Sbrian case VAR_CCPRETRY: 159437210Sbrian long_val = atol(argp); 159537210Sbrian if (long_val < MIN_FSMRETRY) { 159637210Sbrian log_Printf(LogWARN, "%ld: Invalid CCP FSM retry period - min %d\n", 159737210Sbrian long_val, MIN_FSMRETRY); 159837210Sbrian return 1; 159936285Sbrian } else 160037210Sbrian l->ccp.cfg.fsmretry = long_val; 160136285Sbrian break; 160237210Sbrian 160336285Sbrian case VAR_IPCPRETRY: 160437210Sbrian long_val = atol(argp); 160537210Sbrian if (long_val < MIN_FSMRETRY) { 160637210Sbrian log_Printf(LogWARN, "%ld: Invalid IPCP FSM retry period - min %d\n", 160737210Sbrian long_val, MIN_FSMRETRY); 160837210Sbrian return 1; 160936285Sbrian } else 161037210Sbrian arg->bundle->ncp.ipcp.cfg.fsmretry = long_val; 161136285Sbrian break; 161237210Sbrian 161336285Sbrian case VAR_NBNS: 161436285Sbrian case VAR_DNS: 161536285Sbrian if (param == VAR_DNS) 161636285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 161736285Sbrian else 161836285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 161936285Sbrian 162036285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 162136285Sbrian 162236285Sbrian if (arg->argc > arg->argn) { 162343313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 162436285Sbrian addr, &dummyaddr, &dummyint); 162536285Sbrian if (arg->argc > arg->argn+1) 162643313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 162736285Sbrian addr + 1, &dummyaddr, &dummyint); 162836285Sbrian 162936285Sbrian if (addr[1].s_addr == INADDR_ANY) 163036285Sbrian addr[1].s_addr = addr[0].s_addr; 163136285Sbrian if (addr[0].s_addr == INADDR_ANY) 163236285Sbrian addr[0].s_addr = addr[1].s_addr; 163336285Sbrian } 163436285Sbrian break; 163538174Sbrian 163638174Sbrian case VAR_CALLBACK: 163738174Sbrian cx->cfg.callback.opmask = 0; 163838174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 163938174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 164038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 164138174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 164238174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 164338174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 164438174Sbrian if (dummyint == arg->argc - 1) 164538174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 164638174Sbrian else { 164738174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 164838174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 164938174Sbrian sizeof cx->cfg.callback.msg - 1); 165038174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 165138174Sbrian } 165238174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 165338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 165438174Sbrian else 165538174Sbrian return -1; 165638174Sbrian } 165738174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 165838174Sbrian cx->cfg.callback.opmask = 0; 165938174Sbrian break; 166038174Sbrian 166138174Sbrian case VAR_CBCP: 166238174Sbrian cx->cfg.cbcp.delay = 0; 166338174Sbrian *cx->cfg.cbcp.phone = '\0'; 166438174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 166538174Sbrian if (arg->argc > arg->argn) { 166638174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 166738174Sbrian sizeof cx->cfg.cbcp.phone - 1); 166838174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 166938174Sbrian if (arg->argc > arg->argn + 1) { 167038174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 167138174Sbrian if (arg->argc > arg->argn + 2) { 167238174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 167338174Sbrian if (long_val < MIN_FSMRETRY) 167438174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 167538174Sbrian long_val, MIN_FSMRETRY); 167638174Sbrian else 167738174Sbrian cx->cfg.cbcp.fsmretry = long_val; 167838174Sbrian } 167938174Sbrian } 168038174Sbrian } 168138174Sbrian break; 168238544Sbrian 168338544Sbrian case VAR_CHOKED: 168438544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 168538544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 168638544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 168738544Sbrian break; 168840665Sbrian 168940665Sbrian case VAR_SENDPIPE: 169040665Sbrian long_val = atol(argp); 169140665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 169240665Sbrian break; 169340665Sbrian 169440665Sbrian case VAR_RECVPIPE: 169540665Sbrian long_val = atol(argp); 169640665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 169740665Sbrian break; 169843313Sbrian 169943313Sbrian#ifndef NORADIUS 170043313Sbrian case VAR_RADIUS: 170143313Sbrian if (!*argp) 170243313Sbrian *arg->bundle->radius.cfg.file = '\0'; 170343313Sbrian else if (access(argp, R_OK)) { 170443313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 170543313Sbrian return 1; 170643313Sbrian } else { 170743313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 170843313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 170943313Sbrian arg->bundle->radius.cfg.file 171043313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 171143313Sbrian } 171243313Sbrian break; 171343313Sbrian#endif 17146059Samurai } 171536285Sbrian 171636285Sbrian return err ? 1 : 0; 17176059Samurai} 17186059Samurai 171928679Sbrianstatic int 172031343SbrianSetCtsRts(struct cmdargs const *arg) 172120812Sjkh{ 172236285Sbrian if (arg->argc == arg->argn+1) { 172336285Sbrian if (strcmp(arg->argv[arg->argn], "on") == 0) 172436285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 172536285Sbrian else if (strcmp(arg->argv[arg->argn], "off") == 0) 172636285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 172720812Sjkh else 172826516Sbrian return -1; 172926516Sbrian return 0; 173020812Sjkh } 173126516Sbrian return -1; 173220812Sjkh} 173320812Sjkh 173430715Sbrianstatic struct cmdtab const SetCommands[] = { 173536285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 173636285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 173728679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 173836285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 173928679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 174036285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 174136285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 174236285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 174336285Sbrian (const void *)VAR_AUTOLOAD}, 174438174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 174538174Sbrian "callback control", "set callback [none|auth|cbcp|" 174638174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 174738174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 174838174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 174938174Sbrian (const void *)VAR_CBCP}, 175036285Sbrian {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 175136285Sbrian "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY}, 175236285Sbrian {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 175336285Sbrian "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY}, 175438544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 175538544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 175636285Sbrian {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX, 175736285Sbrian "Use hardware flow control", "set ctsrts [on|off]"}, 175836285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 175936285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 176036285Sbrian (const void *) VAR_WINSIZE}, 176136285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 176236285Sbrian "modem device name", "set device|line device-name[,device-name]", 176336285Sbrian (const void *) VAR_DEVICE}, 176436285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 176536285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 176636285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 176736285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 176836285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 176936285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 177036285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 177136285Sbrian "escape characters", "set escape hex-digit ..."}, 177236285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 177336285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 177436285Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] " 177536285Sbrian "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 177636285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 177736285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 177836285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 177931343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 178036285Sbrian {"ipcpretry", NULL, SetVariable, LOCAL_AUTH, 178136285Sbrian "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY}, 178236285Sbrian {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 178336285Sbrian "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY}, 178436712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 178538622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 178638622Sbrian "ipcp|lcp|lqm|phase|tcp/ip|timer|tun..."}, 178736285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 178836285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 178936285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 179036285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 179136285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 179236285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 179336285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 179436285Sbrian "set mrru value", (const void *)VAR_MRRU}, 179536285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 179636285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 179736285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 179836285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 179936285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 180036285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 180136285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 180236285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 180336285Sbrian {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 180436285Sbrian "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY}, 180536285Sbrian {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX, 180636285Sbrian "modem parity", "set parity [odd|even|none]"}, 180736285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 180836285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 180940679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 181040679Sbrian "Process title", "set proctitle [value]"}, 181143313Sbrian#ifndef NORADIUS 181243313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 181343313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 181443313Sbrian#endif 181536285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 181636285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 181740665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 181840665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 181936285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 182036285Sbrian "Redial timeout", "set redial value|random[.value|random] [attempts]"}, 182140665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 182240665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 182328679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 182436774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 182536285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 182636285Sbrian "modem speed", "set speed value"}, 182736285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 182836285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 182936285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 183036285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 183136285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 183236285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 183336285Sbrian {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, 183436285Sbrian "datalink weighting", "set weight n"}, 183528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 183631343Sbrian "Display this message", "set help|? [command]", SetCommands}, 183728679Sbrian {NULL, NULL, NULL}, 18386059Samurai}; 18396059Samurai 18406059Samuraistatic int 184131343SbrianSetCommand(struct cmdargs const *arg) 18426059Samurai{ 184336285Sbrian if (arg->argc > arg->argn) 184436285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 184536285Sbrian arg->prompt, arg->cx); 184636285Sbrian else if (arg->prompt) 184736285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 184826516Sbrian " syntax help.\n"); 18496059Samurai else 185036285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 185126516Sbrian 185226516Sbrian return 0; 18536059Samurai} 18546059Samurai 18556059Samuraistatic int 185631343SbrianAddCommand(struct cmdargs const *arg) 18576059Samurai{ 18586059Samurai struct in_addr dest, gateway, netmask; 185936285Sbrian int gw, addrs; 18606059Samurai 186136285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 186231598Sbrian return -1; 186331598Sbrian 186436285Sbrian addrs = 0; 186536285Sbrian if (arg->argc == arg->argn+2) { 186636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 186736285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 186831598Sbrian else { 186936285Sbrian int width; 187036285Sbrian 187143313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 187236285Sbrian &dest, &netmask, &width)) 187336285Sbrian return -1; 187436285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 187536285Sbrian addrs = ROUTE_DSTMYADDR; 187636285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 187736285Sbrian addrs = ROUTE_DSTHISADDR; 187831598Sbrian } 187936285Sbrian gw = 1; 188034536Sbrian } else { 188136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 188236285Sbrian addrs = ROUTE_DSTMYADDR; 188336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 188436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 188536285Sbrian addrs = ROUTE_DSTHISADDR; 188636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 188736285Sbrian } else 188836285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 188936285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 189031598Sbrian gw = 2; 18916059Samurai } 189236285Sbrian 189336285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 189436285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 189536285Sbrian addrs |= ROUTE_GWHISADDR; 189640561Sbrian } else 189736285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 189836285Sbrian 189936285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 190043313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 190143313Sbrian && addrs != ROUTE_STATIC) 190236285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 190336285Sbrian 190431598Sbrian return 0; 19056059Samurai} 19066059Samurai 19076059Samuraistatic int 190831343SbrianDeleteCommand(struct cmdargs const *arg) 19096059Samurai{ 191031598Sbrian struct in_addr dest, none; 191136285Sbrian int addrs; 19126059Samurai 191336285Sbrian if (arg->argc == arg->argn+1) { 191436285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 191536285Sbrian route_IfDelete(arg->bundle, 0); 191636285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 191736285Sbrian } else { 191836285Sbrian addrs = 0; 191936285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 192036285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 192136285Sbrian addrs = ROUTE_DSTMYADDR; 192236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 192336285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 192436285Sbrian addrs = ROUTE_DSTHISADDR; 192536285Sbrian } else { 192636285Sbrian if (strcasecmp(arg->argv[arg->argn], "default") == 0) 192736285Sbrian dest.s_addr = INADDR_ANY; 192836285Sbrian else 192936285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 193036285Sbrian addrs = ROUTE_STATIC; 193136285Sbrian } 193231598Sbrian none.s_addr = INADDR_ANY; 193336285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 193437927Sbrian arg->cmd->args ? 1 : 0, 0); 193536285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 193631598Sbrian } 193734536Sbrian } else 193826516Sbrian return -1; 193926516Sbrian 194026516Sbrian return 0; 19416059Samurai} 19426059Samurai 194331343Sbrian#ifndef NOALIAS 194426031Sbrianstatic int 194531343SbrianAliasEnable(struct cmdargs const *arg) 194626031Sbrian{ 194736285Sbrian if (arg->argc == arg->argn+1) { 194836285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 194937191Sbrian arg->bundle->AliasEnabled = 1; 195037191Sbrian return 0; 195136285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 195237191Sbrian arg->bundle->AliasEnabled = 0; 195340561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 195440561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 195526516Sbrian return 0; 195626142Sbrian } 195735449Sbrian } 195836285Sbrian 195926516Sbrian return -1; 196026031Sbrian} 196126031Sbrian 196226031Sbrian 196326031Sbrianstatic int 196431343SbrianAliasOption(struct cmdargs const *arg) 196526031Sbrian{ 196638559Sbrian long param = (long)arg->cmd->args; 196738559Sbrian 196836285Sbrian if (arg->argc == arg->argn+1) { 196936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 197037191Sbrian if (arg->bundle->AliasEnabled) { 197137191Sbrian PacketAliasSetMode(param, param); 197228679Sbrian return 0; 197328679Sbrian } 197436285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 197536285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 197637191Sbrian if (arg->bundle->AliasEnabled) { 197737191Sbrian PacketAliasSetMode(0, param); 197828679Sbrian return 0; 197928679Sbrian } 198036285Sbrian log_Printf(LogWARN, "alias not enabled\n"); 198128679Sbrian } 198235449Sbrian } 198328679Sbrian return -1; 198426031Sbrian} 198531343Sbrian#endif /* #ifndef NOALIAS */ 198631121Sbrian 198731121Sbrianstatic int 198836285SbrianLinkCommand(struct cmdargs const *arg) 198936285Sbrian{ 199036285Sbrian if (arg->argc > arg->argn+1) { 199136285Sbrian char namelist[LINE_LEN]; 199236285Sbrian struct datalink *cx; 199336285Sbrian char *name; 199436285Sbrian int result = 0; 199536285Sbrian 199636285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 199736285Sbrian struct datalink *dl; 199836285Sbrian 199936285Sbrian cx = arg->bundle->links; 200036285Sbrian while (cx) { 200136285Sbrian /* Watch it, the command could be a ``remove'' */ 200236285Sbrian dl = cx->next; 200336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 200436285Sbrian arg->prompt, cx); 200536285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 200636285Sbrian if (cx == dl) 200736285Sbrian break; /* Pointer's still valid ! */ 200836285Sbrian } 200936285Sbrian } else { 201036285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 201136285Sbrian namelist[sizeof namelist - 1] = '\0'; 201236285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 201336285Sbrian if (!bundle2datalink(arg->bundle, name)) { 201436285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 201536285Sbrian return 1; 201636285Sbrian } 201736285Sbrian 201836285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 201936285Sbrian namelist[sizeof namelist - 1] = '\0'; 202036285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 202136285Sbrian cx = bundle2datalink(arg->bundle, name); 202236285Sbrian if (cx) 202336285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 202436285Sbrian arg->prompt, cx); 202536285Sbrian else { 202636285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 202736285Sbrian result++; 202836285Sbrian } 202936285Sbrian } 203036285Sbrian } 203136285Sbrian return result; 203236285Sbrian } 203336285Sbrian 203436285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 203536285Sbrian return 2; 203636285Sbrian} 203736285Sbrian 203836285Sbrianstruct link * 203936285Sbriancommand_ChooseLink(struct cmdargs const *arg) 204036285Sbrian{ 204136285Sbrian if (arg->cx) 204236285Sbrian return &arg->cx->physical->link; 204337210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 204436285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 204537210Sbrian if (dl) 204637210Sbrian return &dl->physical->link; 204736285Sbrian } 204837210Sbrian return &arg->bundle->ncp.mp.link; 204936285Sbrian} 205036285Sbrian 205136285Sbrianstatic const char * 205236285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 205336285Sbrian{ 205436285Sbrian const char *result; 205536285Sbrian 205636285Sbrian switch (*cmd) { 205736285Sbrian case 'A': 205836285Sbrian case 'a': 205936285Sbrian result = "accept"; 206036285Sbrian *keep = NEG_MYMASK; 206136285Sbrian *add = NEG_ACCEPTED; 206236285Sbrian break; 206336285Sbrian case 'D': 206436285Sbrian case 'd': 206536285Sbrian switch (cmd[1]) { 206636285Sbrian case 'E': 206736285Sbrian case 'e': 206836285Sbrian result = "deny"; 206936285Sbrian *keep = NEG_MYMASK; 207036285Sbrian *add = 0; 207136285Sbrian break; 207236285Sbrian case 'I': 207336285Sbrian case 'i': 207436285Sbrian result = "disable"; 207536285Sbrian *keep = NEG_HISMASK; 207636285Sbrian *add = 0; 207736285Sbrian break; 207836285Sbrian default: 207936285Sbrian return NULL; 208036285Sbrian } 208136285Sbrian break; 208236285Sbrian case 'E': 208336285Sbrian case 'e': 208436285Sbrian result = "enable"; 208536285Sbrian *keep = NEG_HISMASK; 208636285Sbrian *add = NEG_ENABLED; 208736285Sbrian break; 208836285Sbrian default: 208936285Sbrian return NULL; 209036285Sbrian } 209136285Sbrian 209236285Sbrian return result; 209336285Sbrian} 209436285Sbrian 209536285Sbrianstatic int 209636285SbrianOptSet(struct cmdargs const *arg) 209736285Sbrian{ 209837574Sbrian int bit = (int)(long)arg->cmd->args; 209936285Sbrian const char *cmd; 210036285Sbrian unsigned keep; /* Keep these bits */ 210136285Sbrian unsigned add; /* Add these bits */ 210236285Sbrian 210336285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 210436285Sbrian return 1; 210536285Sbrian 210636285Sbrian if (add) 210736285Sbrian arg->bundle->cfg.opt |= bit; 210836285Sbrian else 210936285Sbrian arg->bundle->cfg.opt &= ~bit; 211036285Sbrian return 0; 211136285Sbrian} 211236285Sbrian 211336285Sbrianstatic int 211440561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 211540561Sbrian{ 211640561Sbrian unsigned save = arg->bundle->cfg.opt; 211740561Sbrian int result = OptSet(arg); 211840561Sbrian 211940561Sbrian if (result == 0) 212040561Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->AliasEnabled) { 212140561Sbrian arg->bundle->cfg.opt = save; 212240561Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without IP aliasing\n"); 212340561Sbrian result = 2; 212440561Sbrian } 212540561Sbrian 212640561Sbrian return result; 212740561Sbrian} 212840561Sbrian 212940561Sbrianstatic int 213036285SbrianNegotiateSet(struct cmdargs const *arg) 213136285Sbrian{ 213237210Sbrian long param = (long)arg->cmd->args; 213336285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 213436285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 213536285Sbrian const char *cmd; 213636285Sbrian unsigned keep; /* Keep these bits */ 213736285Sbrian unsigned add; /* Add these bits */ 213836285Sbrian 213936285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 214036285Sbrian return 1; 214136285Sbrian 214236285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 214336285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 214436285Sbrian cmd, arg->cmd->name); 214536285Sbrian return 2; 214636285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 214736285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 214836285Sbrian cmd, arg->cmd->name, cx->name); 214936285Sbrian cx = NULL; 215036285Sbrian } 215136285Sbrian 215236285Sbrian switch (param) { 215336285Sbrian case NEG_ACFCOMP: 215436285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 215536285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 215636285Sbrian break; 215736285Sbrian case NEG_CHAP: 215836285Sbrian cx->physical->link.lcp.cfg.chap &= keep; 215936285Sbrian cx->physical->link.lcp.cfg.chap |= add; 216036285Sbrian break; 216136285Sbrian case NEG_DEFLATE: 216236285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 216336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 216436285Sbrian break; 216536285Sbrian case NEG_DNS: 216636285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 216736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 216836285Sbrian break; 216936285Sbrian case NEG_LQR: 217036285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 217136285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 217236285Sbrian break; 217336285Sbrian case NEG_PAP: 217436285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 217536285Sbrian cx->physical->link.lcp.cfg.pap |= add; 217636285Sbrian break; 217736285Sbrian case NEG_PPPDDEFLATE: 217836285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 217936285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 218036285Sbrian break; 218136285Sbrian case NEG_PRED1: 218236285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 218336285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 218436285Sbrian break; 218536285Sbrian case NEG_PROTOCOMP: 218636285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 218736285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 218836285Sbrian break; 218936285Sbrian case NEG_SHORTSEQ: 219040622Sbrian switch (bundle_Phase(arg->bundle)) { 219140622Sbrian case PHASE_DEAD: 219240622Sbrian break; 219340622Sbrian case PHASE_ESTABLISH: 219440622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 219540622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 219640622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 219740622Sbrian " LCP negotiations\n"); 219840622Sbrian return 1; 219940622Sbrian } 220040622Sbrian break; 220140622Sbrian default: 220240622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 220340622Sbrian " DEAD/ESTABLISH\n"); 220440622Sbrian return 1; 220536285Sbrian } 220640622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 220740622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 220836285Sbrian break; 220936285Sbrian case NEG_VJCOMP: 221036285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 221136285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 221236285Sbrian break; 221336285Sbrian } 221436285Sbrian 221536285Sbrian return 0; 221636285Sbrian} 221736285Sbrian 221836285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 221936285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 222036285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 222140666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 222240666Sbrian "retain interface addresses", "disable|enable", 222340666Sbrian (const void *)OPT_IFACEALIAS}, 222436285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 222536285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 222636285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 222736285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 222840665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 222936285Sbrian "disable|enable", (const void *)OPT_PROXY}, 223040665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 223140665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 223236285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 223336285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 223436285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 223536285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 223636285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 223736285Sbrian "disable|enable", (const void *)OPT_UTMP}, 223836285Sbrian 223940665Sbrian#define OPT_MAX 9 /* accept/deny allowed below and not above */ 224036285Sbrian 224136285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 224236285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 224336285Sbrian (const void *)NEG_ACFCOMP}, 224436285Sbrian {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 224536285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 224636285Sbrian (const void *)NEG_CHAP}, 224736285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 224836285Sbrian "Deflate compression", "accept|deny|disable|enable", 224936285Sbrian (const void *)NEG_DEFLATE}, 225036285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 225136285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 225236285Sbrian (const void *)NEG_PPPDDEFLATE}, 225336285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 225436285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 225536285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 225636285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 225736285Sbrian (const void *)NEG_LQR}, 225836285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 225936285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 226036285Sbrian (const void *)NEG_PAP}, 226136285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 226236285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 226336285Sbrian (const void *)NEG_PRED1}, 226436285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 226536285Sbrian "Protocol field compression", "accept|deny|disable|enable", 226636285Sbrian (const void *)NEG_PROTOCOMP}, 226736285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 226836285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 226936285Sbrian (const void *)NEG_SHORTSEQ}, 227036285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 227136285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 227236285Sbrian (const void *)NEG_VJCOMP}, 227336285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 227436285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 227536285Sbrian NegotiateCommands}, 227636285Sbrian {NULL, NULL, NULL}, 227736285Sbrian}; 227836285Sbrian 227936285Sbrianstatic int 228036285SbrianNegotiateCommand(struct cmdargs const *arg) 228136285Sbrian{ 228236285Sbrian if (arg->argc > arg->argn) { 228336285Sbrian char const *argv[3]; 228436285Sbrian unsigned keep, add; 228536285Sbrian int n; 228636285Sbrian 228736285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 228836285Sbrian return -1; 228936285Sbrian argv[2] = NULL; 229036285Sbrian 229136285Sbrian for (n = arg->argn; n < arg->argc; n++) { 229236285Sbrian argv[1] = arg->argv[n]; 229336285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 229436285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 229536285Sbrian } 229636285Sbrian } else if (arg->prompt) 229736285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 229836285Sbrian arg->argv[arg->argn-1]); 229936285Sbrian else 230036285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 230136285Sbrian arg->argv[arg->argn] ); 230236285Sbrian 230336285Sbrian return 0; 230436285Sbrian} 230536285Sbrian 230636285Sbrianconst char * 230736285Sbriancommand_ShowNegval(unsigned val) 230836285Sbrian{ 230936285Sbrian switch (val&3) { 231036285Sbrian case 1: return "disabled & accepted"; 231136285Sbrian case 2: return "enabled & denied"; 231236285Sbrian case 3: return "enabled & accepted"; 231336285Sbrian } 231436285Sbrian return "disabled & denied"; 231536285Sbrian} 231636934Sbrian 231736934Sbrianstatic int 231836934SbrianClearCommand(struct cmdargs const *arg) 231936934Sbrian{ 232036934Sbrian struct pppThroughput *t; 232136934Sbrian struct datalink *cx; 232236934Sbrian int i, clear_type; 232336934Sbrian 232436934Sbrian if (arg->argc < arg->argn + 1) 232536934Sbrian return -1; 232636934Sbrian 232736934Sbrian if (strcasecmp(arg->argv[arg->argn], "modem") == 0) { 232836934Sbrian cx = arg->cx; 232936934Sbrian if (!cx) 233036934Sbrian cx = bundle2datalink(arg->bundle, NULL); 233136934Sbrian if (!cx) { 233236934Sbrian log_Printf(LogWARN, "A link must be specified for ``clear modem''\n"); 233336934Sbrian return 1; 233436934Sbrian } 233536934Sbrian t = &cx->physical->link.throughput; 233636934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 233736934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 233836934Sbrian else 233936934Sbrian return -1; 234036934Sbrian 234136934Sbrian if (arg->argc > arg->argn + 1) { 234236934Sbrian clear_type = 0; 234336934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 234436934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 234536934Sbrian clear_type |= THROUGHPUT_OVERALL; 234636934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 234736934Sbrian clear_type |= THROUGHPUT_CURRENT; 234836934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 234936934Sbrian clear_type |= THROUGHPUT_PEAK; 235036934Sbrian else 235136934Sbrian return -1; 235236934Sbrian } else 235336934Sbrian clear_type = THROUGHPUT_ALL; 235436934Sbrian 235536934Sbrian throughput_clear(t, clear_type, arg->prompt); 235636934Sbrian return 0; 235736934Sbrian} 235840561Sbrian 235940561Sbrianstatic int 236040561SbrianRunListCommand(struct cmdargs const *arg) 236140561Sbrian{ 236240561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 236340561Sbrian 236440561Sbrian if (arg->argc > arg->argn) 236540561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 236640561Sbrian arg->prompt, arg->cx); 236740561Sbrian else if (arg->prompt) 236840561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 236940561Sbrian " <option>' for syntax help.\n", cmd, cmd); 237040561Sbrian else 237140561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 237240561Sbrian 237340561Sbrian return 0; 237440561Sbrian} 237540561Sbrian 237640561Sbrianstatic int 237740561SbrianIfaceAddCommand(struct cmdargs const *arg) 237840561Sbrian{ 237940561Sbrian int bits, n, how; 238040561Sbrian struct in_addr ifa, mask, brd; 238140561Sbrian 238240664Sbrian if (arg->argc == arg->argn + 1) { 238343313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 238440561Sbrian return -1; 238540664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 238640664Sbrian } else { 238740664Sbrian if (arg->argc == arg->argn + 2) { 238843313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 238940664Sbrian return -1; 239040664Sbrian n = 1; 239140664Sbrian } else if (arg->argc == arg->argn + 3) { 239243313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 239340664Sbrian return -1; 239443313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 239540664Sbrian return -1; 239640664Sbrian n = 2; 239740664Sbrian } else 239840561Sbrian return -1; 239940561Sbrian 240043313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 240140664Sbrian return -1; 240240664Sbrian } 240340561Sbrian 240440561Sbrian how = IFACE_ADD_LAST; 240540561Sbrian if (arg->cmd->args) 240640561Sbrian how |= IFACE_FORCE_ADD; 240740561Sbrian 240840561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 240940561Sbrian} 241040561Sbrian 241140561Sbrianstatic int 241240561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 241340561Sbrian{ 241440561Sbrian struct in_addr ifa; 241540561Sbrian int ok; 241640561Sbrian 241740561Sbrian if (arg->argc != arg->argn + 1) 241840561Sbrian return -1; 241940561Sbrian 242043313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 242140561Sbrian return -1; 242240561Sbrian 242340561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 242440561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 242540561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 242640561Sbrian inet_ntoa(ifa)); 242740561Sbrian return 1; 242840561Sbrian } 242940561Sbrian 243040561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 243140561Sbrian if (!ok) { 243240561Sbrian if (arg->cmd->args) 243340561Sbrian ok = 1; 243440561Sbrian else if (arg->prompt) 243540561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 243640561Sbrian else 243740561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 243840561Sbrian } 243940561Sbrian 244040561Sbrian return !ok; 244140561Sbrian} 244240561Sbrian 244340561Sbrianstatic int 244440561SbrianIfaceClearCommand(struct cmdargs const *arg) 244540561Sbrian{ 244640561Sbrian int how; 244740561Sbrian 244840561Sbrian if (arg->argc != arg->argn) 244940561Sbrian return -1; 245040561Sbrian 245140941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 245240941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 245340561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 245440561Sbrian iface_Clear(arg->bundle->iface, how); 245540561Sbrian 245640561Sbrian return 0; 245740561Sbrian} 245840679Sbrian 245940679Sbrianstatic int 246040679SbrianSetProcTitle(struct cmdargs const *arg) 246140679Sbrian{ 246240679Sbrian static char title[LINE_LEN]; 246340679Sbrian char *argv[MAXARGS], *ptr; 246440679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 246540679Sbrian 246640679Sbrian if (arg->argc == arg->argn) { 246740679Sbrian arg->bundle->argv[0] = arg->bundle->argv0; 246840679Sbrian arg->bundle->argv[1] = arg->bundle->argv1; 246940679Sbrian return 0; 247040679Sbrian } 247140679Sbrian 247240679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 247340679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 247440679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 247540679Sbrian } 247643888Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1); 247740679Sbrian 247840679Sbrian ptr = title; 247940679Sbrian remaining = sizeof title - 1; 248040679Sbrian for (f = 0; f < argc && remaining; f++) { 248140679Sbrian if (f) { 248240679Sbrian *ptr++ = ' '; 248340679Sbrian remaining--; 248440679Sbrian } 248540679Sbrian len = strlen(argv[f]); 248640679Sbrian if (len > remaining) 248740679Sbrian len = remaining; 248840679Sbrian memcpy(ptr, argv[f], len); 248940679Sbrian remaining -= len; 249040679Sbrian ptr += len; 249140679Sbrian } 249240679Sbrian *ptr = '\0'; 249340679Sbrian 249440679Sbrian arg->bundle->argv[0] = title; 249540679Sbrian arg->bundle->argv[1] = NULL; 249640679Sbrian 249740679Sbrian return 0; 249840679Sbrian} 2499