command.c revision 58045
16059Samurai/* 26059Samurai * PPP User command processing module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2050479Speter * $FreeBSD: head/usr.sbin/ppp/command.c 58045 2000-03-14 01:47:31Z brian $ 218857Srgrimes * 226059Samurai */ 2343313Sbrian#include <sys/param.h> 2430715Sbrian#include <netinet/in_systm.h> 2526031Sbrian#include <netinet/in.h> 2630715Sbrian#include <netinet/ip.h> 2726031Sbrian#include <arpa/inet.h> 2830715Sbrian#include <sys/socket.h> 2926031Sbrian#include <net/route.h> 3030715Sbrian#include <netdb.h> 3136285Sbrian#include <sys/un.h> 3230715Sbrian 3338628Sbrian#include <ctype.h> 3430715Sbrian#include <errno.h> 3526516Sbrian#include <fcntl.h> 3653298Sbrian#ifdef __OpenBSD__ 3753298Sbrian#include <util.h> 3853298Sbrian#else 3953298Sbrian#include <libutil.h> 4053298Sbrian#endif 4130715Sbrian#include <paths.h> 4230715Sbrian#include <stdio.h> 4330715Sbrian#include <stdlib.h> 4430715Sbrian#include <string.h> 4530715Sbrian#include <sys/wait.h> 4630715Sbrian#include <termios.h> 4730715Sbrian#include <unistd.h> 4830715Sbrian 4950059Sbrian#ifndef NONAT 5058037Sbrian#ifdef LOCALNAT 5158037Sbrian#include "alias.h" 5258037Sbrian#else 5346086Sbrian#include <alias.h> 5439395Sbrian#endif 5539395Sbrian#endif 5658037Sbrian 5746686Sbrian#include "layer.h" 5837009Sbrian#include "defs.h" 5931343Sbrian#include "command.h" 6030715Sbrian#include "mbuf.h" 6130715Sbrian#include "log.h" 6230715Sbrian#include "timer.h" 636059Samurai#include "fsm.h" 646059Samurai#include "lcp.h" 6531690Sbrian#include "iplist.h" 6636285Sbrian#include "throughput.h" 6736285Sbrian#include "slcompress.h" 6838557Sbrian#include "lqr.h" 6938557Sbrian#include "hdlc.h" 706059Samurai#include "ipcp.h" 7150059Sbrian#ifndef NONAT 7251075Sbrian#include "nat_cmd.h" 7331343Sbrian#endif 7425630Sbrian#include "systems.h" 7536285Sbrian#include "filter.h" 7636285Sbrian#include "descriptor.h" 7730715Sbrian#include "main.h" 7830715Sbrian#include "route.h" 7930715Sbrian#include "ccp.h" 8031080Sbrian#include "auth.h" 8136285Sbrian#include "async.h" 8236285Sbrian#include "link.h" 8336285Sbrian#include "physical.h" 8436285Sbrian#include "mp.h" 8543313Sbrian#ifndef NORADIUS 8643313Sbrian#include "radius.h" 8743313Sbrian#endif 8836285Sbrian#include "bundle.h" 8936285Sbrian#include "server.h" 9036285Sbrian#include "prompt.h" 9136285Sbrian#include "chat.h" 9236285Sbrian#include "chap.h" 9338174Sbrian#include "cbcp.h" 9436285Sbrian#include "datalink.h" 9540561Sbrian#include "iface.h" 9653298Sbrian#include "id.h" 976059Samurai 9836285Sbrian/* ``set'' values */ 9936285Sbrian#define VAR_AUTHKEY 0 10036285Sbrian#define VAR_DIAL 1 10136285Sbrian#define VAR_LOGIN 2 10236285Sbrian#define VAR_AUTHNAME 3 10336285Sbrian#define VAR_AUTOLOAD 4 10436285Sbrian#define VAR_WINSIZE 5 10536285Sbrian#define VAR_DEVICE 6 10636285Sbrian#define VAR_ACCMAP 7 10736285Sbrian#define VAR_MRRU 8 10836285Sbrian#define VAR_MRU 9 10936285Sbrian#define VAR_MTU 10 11036285Sbrian#define VAR_OPENMODE 11 11136285Sbrian#define VAR_PHONE 12 11236285Sbrian#define VAR_HANGUP 13 11336285Sbrian#define VAR_IDLETIMEOUT 14 11436285Sbrian#define VAR_LQRPERIOD 15 11536285Sbrian#define VAR_LCPRETRY 16 11636285Sbrian#define VAR_CHAPRETRY 17 11736285Sbrian#define VAR_PAPRETRY 18 11836285Sbrian#define VAR_CCPRETRY 19 11936285Sbrian#define VAR_IPCPRETRY 20 12036285Sbrian#define VAR_DNS 21 12136285Sbrian#define VAR_NBNS 22 12236285Sbrian#define VAR_MODE 23 12338174Sbrian#define VAR_CALLBACK 24 12438174Sbrian#define VAR_CBCP 25 12538544Sbrian#define VAR_CHOKED 26 12640665Sbrian#define VAR_SENDPIPE 27 12740665Sbrian#define VAR_RECVPIPE 28 12843313Sbrian#define VAR_RADIUS 29 12944073Sbrian#define VAR_CD 30 13046686Sbrian#define VAR_PARITY 31 13146686Sbrian#define VAR_CRTSCTS 32 13250867Sbrian#define VAR_URGENTPORTS 33 13352488Sbrian#define VAR_LOGOUT 34 1346059Samurai 13536285Sbrian/* ``accept|deny|disable|enable'' masks */ 13636285Sbrian#define NEG_HISMASK (1) 13736285Sbrian#define NEG_MYMASK (2) 13836285Sbrian 13936285Sbrian/* ``accept|deny|disable|enable'' values */ 14036285Sbrian#define NEG_ACFCOMP 40 14144106Sbrian#define NEG_CHAP05 41 14244106Sbrian#define NEG_CHAP80 42 14344106Sbrian#define NEG_CHAP80LM 43 14444106Sbrian#define NEG_DEFLATE 44 14547858Sbrian#define NEG_DNS 45 14647858Sbrian#define NEG_ENDDISC 46 14747858Sbrian#define NEG_LQR 47 14847858Sbrian#define NEG_PAP 48 14947858Sbrian#define NEG_PPPDDEFLATE 49 15047858Sbrian#define NEG_PRED1 50 15147858Sbrian#define NEG_PROTOCOMP 51 15247858Sbrian#define NEG_SHORTSEQ 52 15347858Sbrian#define NEG_VJCOMP 53 15436285Sbrian 15553970Sbrianconst char Version[] = "2.26"; 15636285Sbrian 15736285Sbrianstatic int ShowCommand(struct cmdargs const *); 15836285Sbrianstatic int TerminalCommand(struct cmdargs const *); 15936285Sbrianstatic int QuitCommand(struct cmdargs const *); 16036285Sbrianstatic int OpenCommand(struct cmdargs const *); 16136285Sbrianstatic int CloseCommand(struct cmdargs const *); 16236285Sbrianstatic int DownCommand(struct cmdargs const *); 16336285Sbrianstatic int SetCommand(struct cmdargs const *); 16436285Sbrianstatic int LinkCommand(struct cmdargs const *); 16536285Sbrianstatic int AddCommand(struct cmdargs const *); 16636285Sbrianstatic int DeleteCommand(struct cmdargs const *); 16736285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 16836934Sbrianstatic int ClearCommand(struct cmdargs const *); 16940561Sbrianstatic int RunListCommand(struct cmdargs const *); 17040561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 17140561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 17240561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 17340679Sbrianstatic int SetProcTitle(struct cmdargs const *); 17450059Sbrian#ifndef NONAT 17536285Sbrianstatic int AliasEnable(struct cmdargs const *); 17636285Sbrianstatic int AliasOption(struct cmdargs const *); 17731343Sbrian#endif 1786059Samurai 17936285Sbrianstatic const char * 18036285Sbrianshowcx(struct cmdtab const *cmd) 18136285Sbrian{ 18236285Sbrian if (cmd->lauth & LOCAL_CX) 18336285Sbrian return "(c)"; 18436285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 18536285Sbrian return "(o)"; 18636285Sbrian 18736285Sbrian return ""; 18836285Sbrian} 18936285Sbrian 1906059Samuraistatic int 19131343SbrianHelpCommand(struct cmdargs const *arg) 1926059Samurai{ 19328679Sbrian struct cmdtab const *cmd; 19436285Sbrian int n, cmax, dmax, cols, cxlen; 19536285Sbrian const char *cx; 1966059Samurai 19736285Sbrian if (!arg->prompt) { 19836285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 19926516Sbrian return 0; 20036285Sbrian } 20126516Sbrian 20236285Sbrian if (arg->argc > arg->argn) { 20336285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 20436285Sbrian if ((cmd->lauth & arg->prompt->auth) && 20536285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 20636285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 20736285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 20828679Sbrian return 0; 2096059Samurai } 21026516Sbrian return -1; 2116059Samurai } 21236285Sbrian 21331372Sbrian cmax = dmax = 0; 21436285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 21536285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 21636285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 21731372Sbrian cmax = n; 21831372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 21931372Sbrian dmax = n; 22031372Sbrian } 22131372Sbrian 22231372Sbrian cols = 80 / (dmax + cmax + 3); 2236059Samurai n = 0; 22436285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 22536285Sbrian " (c) = Context required\n"); 22636285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22736285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22836285Sbrian cx = showcx(cmd); 22936285Sbrian cxlen = cmax - strlen(cmd->name); 23040482Sbrian if (n % cols != 0) 23140482Sbrian prompt_Printf(arg->prompt, " "); 23240482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 23336285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 23431372Sbrian if (++n % cols == 0) 23536285Sbrian prompt_Printf(arg->prompt, "\n"); 2366059Samurai } 23731372Sbrian if (n % cols != 0) 23836285Sbrian prompt_Printf(arg->prompt, "\n"); 23926516Sbrian 24026516Sbrian return 0; 2416059Samurai} 2426059Samurai 24336285Sbrianstatic int 24436285SbrianCloneCommand(struct cmdargs const *arg) 2456059Samurai{ 24636285Sbrian char namelist[LINE_LEN]; 24736285Sbrian char *name; 24836285Sbrian int f; 2496059Samurai 25036285Sbrian if (arg->argc == arg->argn) 25136285Sbrian return -1; 25236285Sbrian 25336285Sbrian namelist[sizeof namelist - 1] = '\0'; 25436285Sbrian for (f = arg->argn; f < arg->argc; f++) { 25536285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 25636285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 25736285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2586059Samurai } 25936285Sbrian 26036285Sbrian return 0; 2616059Samurai} 2626059Samurai 2636059Samuraistatic int 26436285SbrianRemoveCommand(struct cmdargs const *arg) 2656059Samurai{ 26636285Sbrian if (arg->argc != arg->argn) 26736285Sbrian return -1; 26811336Samurai 26936285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 27036285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 27136285Sbrian return 2; 2726059Samurai } 27326516Sbrian 27436285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 27536285Sbrian return 0; 27636285Sbrian} 27732711Sbrian 27836285Sbrianstatic int 27936285SbrianRenameCommand(struct cmdargs const *arg) 28036285Sbrian{ 28136285Sbrian if (arg->argc != arg->argn + 1) 28236285Sbrian return -1; 28331121Sbrian 28436285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 28536285Sbrian return 0; 28636285Sbrian 28736285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 28836285Sbrian arg->cx->name, arg->argv[arg->argn]); 28936285Sbrian return 1; 29036285Sbrian} 29136285Sbrian 29236285Sbrianint 29336285SbrianLoadCommand(struct cmdargs const *arg) 29436285Sbrian{ 29540797Sbrian const char *err; 29640797Sbrian int n, mode; 29736285Sbrian 29840797Sbrian mode = arg->bundle->phys_type.all; 29936285Sbrian 30040797Sbrian if (arg->argn < arg->argc) { 30140797Sbrian for (n = arg->argn; n < arg->argc; n++) 30240797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 30340797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 30440797Sbrian return 1; 30540797Sbrian } 30640797Sbrian 30740797Sbrian for (n = arg->argn; n < arg->argc; n++) { 30840797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 30940797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 31040797Sbrian } 31140797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 31240797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 31340797Sbrian log_Printf(LogWARN, "default: %s\n", err); 31436285Sbrian return 1; 31536285Sbrian } else { 31640797Sbrian bundle_SetLabel(arg->bundle, "default"); 31740797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 31840797Sbrian bundle_SetLabel(arg->bundle, "default"); 31936285Sbrian } 32040797Sbrian 32126516Sbrian return 0; 3226059Samurai} 3236059Samurai 32436285Sbrianint 32536285SbrianSaveCommand(struct cmdargs const *arg) 32636285Sbrian{ 32736285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 32836285Sbrian return 1; 32936285Sbrian} 33036285Sbrian 33110528Samuraistatic int 33236285SbrianDialCommand(struct cmdargs const *arg) 33328536Sbrian{ 33436285Sbrian int res; 33536285Sbrian 33636465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 33736465Sbrian || (!arg->cx && 33836928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 33936285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 34036285Sbrian " interactive links\n"); 34136285Sbrian return 1; 34234536Sbrian } 34336285Sbrian 34436285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 34536285Sbrian return res; 34636285Sbrian 34737993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 34836285Sbrian 34936285Sbrian return 0; 35028536Sbrian} 35128536Sbrian 35238628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 35338628Sbrian 35438628Sbrianstatic char * 35538628Sbrianstrstrword(char *big, const char *little) 35638628Sbrian{ 35738628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 35838628Sbrian char *pos; 35938628Sbrian int len; 36038628Sbrian 36138628Sbrian pos = big; 36238628Sbrian len = strlen(little); 36338628Sbrian 36438628Sbrian while ((pos = strstr(pos, little)) != NULL) 36547865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 36647865Sbrian pos++; 36747865Sbrian else if (pos != big && pos[-1] == '\\') 36847865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 36947865Sbrian else 37038628Sbrian break; 37138628Sbrian 37238628Sbrian return pos; 37338628Sbrian} 37438628Sbrian 37538628Sbrianstatic char * 37638628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 37738628Sbrian{ 37838628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 37938628Sbrian char *word, *ntgt; 38038628Sbrian int ltgt, loldstr, lnewstr, pos; 38138628Sbrian 38238628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 38338628Sbrian return tgt; 38438628Sbrian 38538628Sbrian ltgt = strlen(tgt) + 1; 38638628Sbrian loldstr = strlen(oldstr); 38738628Sbrian lnewstr = strlen(newstr); 38838628Sbrian do { 38938628Sbrian pos = word - tgt; 39038628Sbrian if (loldstr > lnewstr) 39138628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 39238628Sbrian if (loldstr != lnewstr) { 39338628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 39438628Sbrian if (ntgt == NULL) 39538628Sbrian break; /* Oh wonderful ! */ 39638628Sbrian word = ntgt + pos; 39738628Sbrian tgt = ntgt; 39838628Sbrian } 39938628Sbrian if (lnewstr > loldstr) 40038628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 40138628Sbrian bcopy(newstr, word, lnewstr); 40238628Sbrian } while ((word = strstrword(word, oldstr))); 40338628Sbrian 40438628Sbrian return tgt; 40538628Sbrian} 40638628Sbrian 40743888Sbrianvoid 40843888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 40947849Sbrian struct bundle *bundle, int inc0, pid_t pid) 41038628Sbrian{ 41138628Sbrian int arg; 41247849Sbrian char pidstr[12]; 41338628Sbrian 41441755Sbrian if (inc0) 41541755Sbrian arg = 0; /* Start at arg 0 */ 41641755Sbrian else { 41741755Sbrian nargv[0] = strdup(oargv[0]); 41841755Sbrian arg = 1; 41941755Sbrian } 42047849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 42141755Sbrian for (; arg < argc; arg++) { 42238629Sbrian nargv[arg] = strdup(oargv[arg]); 42338629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 42438628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 42538629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 42640561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 42738628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 42838629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 42938629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 43038629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 43138629Sbrian bundle->ncp.mp.peer.enddisc.address, 43238629Sbrian bundle->ncp.mp.peer.enddisc.len)); 43338629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 43438629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 43538629Sbrian bundle->ncp.mp.cfg.enddisc.address, 43638629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 43747849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 43838629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 43958044Sbrian nargv[arg] = subst(nargv[arg], "DNS0", 44058044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); 44158044Sbrian nargv[arg] = subst(nargv[arg], "DNS1", 44258044Sbrian inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); 44338628Sbrian } 44438628Sbrian nargv[arg] = NULL; 44538628Sbrian} 44638628Sbrian 44728536Sbrianstatic int 44831343SbrianShellCommand(struct cmdargs const *arg, int bg) 44910528Samurai{ 45010528Samurai const char *shell; 45147849Sbrian pid_t shpid, pid; 45220813Sjkh 45318856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 45426911Sbrian /* we're only allowed to shell when we run ppp interactively */ 45536285Sbrian if (arg->prompt && arg->prompt->owner) { 45636285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 45726516Sbrian return 1; 45810528Samurai } 45926911Sbrian#endif 46028679Sbrian 46136285Sbrian if (arg->argc == arg->argn) { 46236285Sbrian if (!arg->prompt) { 46336285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 46436285Sbrian " a config file\n"); 46528381Sbrian return 1; 46636285Sbrian } else if (arg->prompt->owner) { 46736285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 46836285Sbrian " a socket connection\n"); 46936285Sbrian return 1; 47028381Sbrian } else if (bg) { 47136285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 47228679Sbrian " the foreground mode\n"); 47328381Sbrian return 1; 47428381Sbrian } 47534536Sbrian } 47634536Sbrian 47747849Sbrian pid = getpid(); 47828679Sbrian if ((shpid = fork()) == 0) { 47936285Sbrian int i, fd; 48018531Sbde 48136285Sbrian if ((shell = getenv("SHELL")) == 0) 48236285Sbrian shell = _PATH_BSHELL; 48332017Sbrian 48436285Sbrian timer_TermService(); 48536285Sbrian 48636285Sbrian if (arg->prompt) 48736285Sbrian fd = arg->prompt->fd_out; 48836285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 48936285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 49036285Sbrian _PATH_DEVNULL, strerror(errno)); 49128679Sbrian exit(1); 49228679Sbrian } 49349976Sbrian dup2(fd, STDIN_FILENO); 49449976Sbrian dup2(fd, STDOUT_FILENO); 49549976Sbrian dup2(fd, STDERR_FILENO); 49649976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 49749976Sbrian fcntl(i, F_SETFD, 1); 49826516Sbrian 49955252Sbrian setuid(ID0realuid()); 50036285Sbrian if (arg->argc > arg->argn) { 50128679Sbrian /* substitute pseudo args */ 50238628Sbrian char *argv[MAXARGS]; 50338628Sbrian int argc = arg->argc - arg->argn; 50438628Sbrian 50538628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 50638628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 50738628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 50831343Sbrian } 50947849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 51028679Sbrian if (bg) { 51128679Sbrian pid_t p; 51210528Samurai 51328679Sbrian p = getpid(); 51428679Sbrian if (daemon(1, 1) == -1) { 51536832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 51628679Sbrian exit(1); 51728679Sbrian } 51836285Sbrian } else if (arg->prompt) 51936285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 52031343Sbrian execvp(argv[0], argv); 52130316Sbrian } else { 52236285Sbrian if (arg->prompt) 52332017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 52436285Sbrian prompt_TtyOldMode(arg->prompt); 52531343Sbrian execl(shell, shell, NULL); 52630316Sbrian } 52720813Sjkh 52840665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 52940665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 53040665Sbrian strerror(errno)); 53149976Sbrian _exit(255); 53210528Samurai } 53336285Sbrian 53436285Sbrian if (shpid == (pid_t) - 1) 53536285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 53636285Sbrian else { 53710528Samurai int status; 53831343Sbrian waitpid(shpid, &status, 0); 53910528Samurai } 54020813Sjkh 54136285Sbrian if (arg->prompt && !arg->prompt->owner) 54236285Sbrian prompt_TtyCommandMode(arg->prompt); 54320813Sjkh 54436285Sbrian return 0; 54510528Samurai} 54610528Samurai 54731343Sbrianstatic int 54831343SbrianBgShellCommand(struct cmdargs const *arg) 54931343Sbrian{ 55036285Sbrian if (arg->argc == arg->argn) 55131343Sbrian return -1; 55231343Sbrian return ShellCommand(arg, 1); 55331343Sbrian} 55431343Sbrian 55531343Sbrianstatic int 55631343SbrianFgShellCommand(struct cmdargs const *arg) 55731343Sbrian{ 55831343Sbrian return ShellCommand(arg, 0); 55931343Sbrian} 56031343Sbrian 56158044Sbrianstatic int 56258044SbrianResolvCommand(struct cmdargs const *arg) 56358044Sbrian{ 56458044Sbrian if (arg->argc == arg->argn + 1) { 56558044Sbrian if (!strcasecmp(arg->argv[arg->argn], "reload")) 56658044Sbrian ipcp_LoadDNS(&arg->bundle->ncp.ipcp); 56758044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "restore")) 56858044Sbrian ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); 56958044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) 57058044Sbrian ipcp_WriteDNS(&arg->bundle->ncp.ipcp); 57158044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "readonly")) 57258044Sbrian arg->bundle->ncp.ipcp.ns.writable = 0; 57358044Sbrian else if (!strcasecmp(arg->argv[arg->argn], "writable")) 57458044Sbrian arg->bundle->ncp.ipcp.ns.writable = 1; 57558044Sbrian else 57658044Sbrian return -1; 57758044Sbrian 57858044Sbrian return 0; 57958044Sbrian } 58058044Sbrian 58158044Sbrian return -1; 58258044Sbrian} 58358044Sbrian 58450059Sbrian#ifndef NONAT 58540561Sbrianstatic struct cmdtab const AliasCommands[] = 58640561Sbrian{ 58750059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 58850059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 58940561Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 59050059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 59140561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 59240561Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 59350059Sbrian "enable NAT", "nat enable yes|no"}, 59440561Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 59550059Sbrian "log NAT link creation", "nat log yes|no", 59640561Sbrian (const void *) PKT_ALIAS_LOG}, 59750059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 59850059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 59950059Sbrian {"pptp", NULL, nat_Pptp, LOCAL_AUTH, 60050059Sbrian "Set the PPTP address", "nat pptp IP"}, 60150059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 60250059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 60340561Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 60450059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 60540561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 60640561Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 60750059Sbrian "translate unregistered (private) IP address space only", 60850059Sbrian "nat unregistered_only yes|no", 60940561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 61040561Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 61150059Sbrian "allocate host sockets", "nat use_sockets yes|no", 61240561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 61340561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 61450059Sbrian "Display this message", "nat help|? [command]", AliasCommands}, 61540561Sbrian {NULL, NULL, NULL}, 61640561Sbrian}; 61740561Sbrian#endif 61840561Sbrian 61940561Sbrianstatic struct cmdtab const AllowCommands[] = { 62040561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 62140561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 62240561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 62340561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 62440561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 62540561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 62640561Sbrian {NULL, NULL, NULL}, 62740561Sbrian}; 62840561Sbrian 62940561Sbrianstatic struct cmdtab const IfaceCommands[] = 63040561Sbrian{ 63140561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 63240561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 63340561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 63440561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 63540561Sbrian (void *)1}, 63640561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 63740561Sbrian "Clear iface address(es)", "iface clear"}, 63840561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 63940561Sbrian "Delete iface address", "iface delete addr", NULL}, 64040561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 64140561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 64240561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 64340561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 64440561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 64540561Sbrian "Show iface address(es)", "iface show"}, 64640561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 64750059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 64840561Sbrian {NULL, NULL, NULL}, 64940561Sbrian}; 65040561Sbrian 65130715Sbrianstatic struct cmdtab const Commands[] = { 65236285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65328679Sbrian "accept option request", "accept option .."}, 65428679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 65532109Sbrian "add route", "add dest mask gateway", NULL}, 65636285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 65732109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 65840561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 65940561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 66028679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 66131372Sbrian "Run a background command", "[!]bg command"}, 66236934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66346686Sbrian "Clear throughput statistics", 66446686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 66536285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 66636285Sbrian "Clone a link", "clone newname..."}, 66736285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66836285Sbrian "Close an FSM", "close [lcp|ccp]"}, 66928679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 67032109Sbrian "delete route", "delete dest", NULL}, 67136285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 67232109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 67336285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67428679Sbrian "Deny option request", "deny option .."}, 67536285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67640797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 67736285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67828679Sbrian "Disable option", "disable option .."}, 67936285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68046686Sbrian "Generate a down event", "down [ccp|lcp]"}, 68136285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68228679Sbrian "Enable option", "enable option .."}, 68340561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 68440561Sbrian "interface control", "iface option ...", IfaceCommands}, 68536285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 68636285Sbrian "Link specific commands", "link name command ..."}, 68737008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68840797Sbrian "Load settings", "load [system ...]"}, 68950059Sbrian#ifndef NONAT 69050059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 69150059Sbrian "NAT control", "nat option yes|no", AliasCommands}, 69250059Sbrian#endif 69336285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 69437955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 69536285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 69636285Sbrian "Password for manipulation", "passwd LocalPassword"}, 69736285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 69836285Sbrian "Quit PPP program", "quit|bye [all]"}, 69936285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 70036285Sbrian "Remove a link", "remove"}, 70136285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 70236285Sbrian "Rename a link", "rename name"}, 70358044Sbrian {"resolv", NULL, ResolvCommand, LOCAL_AUTH, 70458044Sbrian "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, 70528679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 70628679Sbrian "Save settings", "save"}, 70736285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 70828679Sbrian "Set parameters", "set[up] var value"}, 70928679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 71028679Sbrian "Run a subshell", "shell|! [sh command]"}, 71136285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 71231372Sbrian "Show status and stats", "show var"}, 71336285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 71431372Sbrian "Enter terminal mode", "term"}, 71528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 71631343Sbrian "Display this message", "help|? [command]", Commands}, 71728679Sbrian {NULL, NULL, NULL}, 7186059Samurai}; 7196059Samurai 72028536Sbrianstatic int 72131343SbrianShowEscape(struct cmdargs const *arg) 7226059Samurai{ 72336285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 72436285Sbrian int code, bit; 72536285Sbrian const char *sep = ""; 7266059Samurai 72726516Sbrian for (code = 0; code < 32; code++) 72836285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 72928679Sbrian for (bit = 0; bit < 8; bit++) 73036285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 73136285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 73236285Sbrian sep = ", "; 73336285Sbrian } 73436285Sbrian prompt_Printf(arg->prompt, "\n"); 7356059Samurai } 73631077Sbrian return 0; 7376059Samurai} 7386059Samurai 73928679Sbrianstatic int 74036285SbrianShowTimerList(struct cmdargs const *arg) 7416059Samurai{ 74236285Sbrian timer_Show(0, arg->prompt); 74331077Sbrian return 0; 7446059Samurai} 7456059Samurai 74628679Sbrianstatic int 74731343SbrianShowStopped(struct cmdargs const *arg) 74828327Sbrian{ 74936285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 75036285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 75136285Sbrian prompt_Printf(arg->prompt, "Disabled"); 75228327Sbrian else 75336285Sbrian prompt_Printf(arg->prompt, "%ld secs", 75436285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 75528461Sbrian 75636285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 75736285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 75836285Sbrian prompt_Printf(arg->prompt, "Disabled"); 75928461Sbrian else 76036285Sbrian prompt_Printf(arg->prompt, "%ld secs", 76136285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 76228461Sbrian 76336285Sbrian prompt_Printf(arg->prompt, "\n"); 76428461Sbrian 76531077Sbrian return 0; 76628327Sbrian} 76728327Sbrian 76828679Sbrianstatic int 76931343SbrianShowVersion(struct cmdargs const *arg) 7706059Samurai{ 77151026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 77231077Sbrian return 0; 7736059Samurai} 7746059Samurai 77528679Sbrianstatic int 77636285SbrianShowProtocolStats(struct cmdargs const *arg) 77726326Sbrian{ 77836285Sbrian struct link *l = command_ChooseLink(arg); 77926326Sbrian 78036285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 78136285Sbrian link_ReportProtocolStatus(l, arg->prompt); 78231077Sbrian return 0; 78326326Sbrian} 78426326Sbrian 78530715Sbrianstatic struct cmdtab const ShowCommands[] = { 78636285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 78736285Sbrian "bundle details", "show bundle"}, 78836285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 78936285Sbrian "CCP status", "show cpp"}, 79036285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 79136285Sbrian "VJ compression stats", "show compress"}, 79236285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 79336285Sbrian "escape characters", "show escape"}, 79436285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 79536285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 79636285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 79736285Sbrian "HDLC errors", "show hdlc"}, 79840561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 79940561Sbrian "Interface status", "show iface"}, 80036285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 80136285Sbrian "IPCP status", "show ipcp"}, 80247211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 80347211Sbrian "Protocol layers", "show layers"}, 80436285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 80536285Sbrian "LCP status", "show lcp"}, 80636285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 80736285Sbrian "(high-level) link info", "show link"}, 80836285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 80936285Sbrian "available link names", "show links"}, 81036285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 81136285Sbrian "log levels", "show log"}, 81236285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 81336285Sbrian "mbuf allocations", "show mem"}, 81446686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 81546686Sbrian "(low-level) link info", "show physical"}, 81636285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 81736285Sbrian "multilink setup", "show mp"}, 81836285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 81936285Sbrian "protocol summary", "show proto"}, 82036285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 82136285Sbrian "routing table", "show route"}, 82236285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 82336285Sbrian "STOPPED timeout", "show stopped"}, 82436285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 82536285Sbrian "alarm timers", "show timers"}, 82628679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 82736285Sbrian "version string", "show version"}, 82836285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 82936285Sbrian "client list", "show who"}, 83028679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 83131343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 83228679Sbrian {NULL, NULL, NULL}, 8336059Samurai}; 8346059Samurai 83530715Sbrianstatic struct cmdtab const * 83631343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 8376059Samurai{ 83826516Sbrian int nmatch; 83926516Sbrian int len; 84028679Sbrian struct cmdtab const *found; 8416059Samurai 84226516Sbrian found = NULL; 84326516Sbrian len = strlen(str); 84426516Sbrian nmatch = 0; 8456059Samurai while (cmds->func) { 84625566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 84726516Sbrian if (cmds->name[len] == '\0') { 84828679Sbrian *pmatch = 1; 84928679Sbrian return cmds; 85026516Sbrian } 8516059Samurai nmatch++; 8526059Samurai found = cmds; 85328679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 85426516Sbrian if (cmds->alias[len] == '\0') { 85528679Sbrian *pmatch = 1; 85628679Sbrian return cmds; 85726516Sbrian } 8586059Samurai nmatch++; 8596059Samurai found = cmds; 8606059Samurai } 8616059Samurai cmds++; 8626059Samurai } 8636059Samurai *pmatch = nmatch; 86426516Sbrian return found; 8656059Samurai} 8666059Samurai 86736285Sbrianstatic const char * 86836285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 86936285Sbrian{ 87036285Sbrian int f, tlen, len; 87136285Sbrian 87236285Sbrian tlen = 0; 87336285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 87436285Sbrian if (f) 87536285Sbrian tgt[tlen++] = ' '; 87636285Sbrian len = strlen(argv[f]); 87736285Sbrian if (len > sz - tlen - 1) 87836285Sbrian len = sz - tlen - 1; 87936285Sbrian strncpy(tgt+tlen, argv[f], len); 88036285Sbrian tlen += len; 88136285Sbrian } 88236285Sbrian tgt[tlen] = '\0'; 88336285Sbrian return tgt; 88436285Sbrian} 88536285Sbrian 88630715Sbrianstatic int 88736285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 88836285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8896059Samurai{ 89028679Sbrian struct cmdtab const *cmd; 8916059Samurai int val = 1; 8926059Samurai int nmatch; 89331343Sbrian struct cmdargs arg; 89436285Sbrian char prefix[100]; 8956059Samurai 89636285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8976059Samurai if (nmatch > 1) 89836285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 89936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 90036285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 90136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 90236285Sbrian /* We've got no context, but we require it */ 90336285Sbrian cx = bundle2datalink(bundle, NULL); 90436285Sbrian 90536285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 90636285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 90736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 90836285Sbrian else { 90936285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 91036285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 91136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 91236285Sbrian cx = NULL; 91336285Sbrian } 91436285Sbrian arg.cmdtab = cmds; 91536285Sbrian arg.cmd = cmd; 91636285Sbrian arg.argc = argc; 91736285Sbrian arg.argn = argn+1; 91836285Sbrian arg.argv = argv; 91936285Sbrian arg.bundle = bundle; 92036285Sbrian arg.cx = cx; 92136285Sbrian arg.prompt = prompt; 92236285Sbrian val = (*cmd->func) (&arg); 92336285Sbrian } 92431343Sbrian } else 92536285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 92636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 92726516Sbrian 92826516Sbrian if (val == -1) 92936285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 93028679Sbrian else if (val) 93136285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 93236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 93326516Sbrian 93426516Sbrian return val; 9356059Samurai} 9366059Samurai 93737009Sbrianint 93858045Sbriancommand_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset) 93958045Sbrian{ 94058045Sbrian char buff2[LINE_LEN-offset]; 94158045Sbrian 94258045Sbrian InterpretArg(buff, buff2); 94358045Sbrian strncpy(buff, buff2, LINE_LEN - offset - 1); 94458045Sbrian buff[LINE_LEN - offset - 1] = '\0'; 94558045Sbrian 94658045Sbrian return command_Interpret(buff, nb, argv); 94758045Sbrian} 94858045Sbrian 94958045Sbrianint 95037009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 9516059Samurai{ 9526059Samurai char *cp; 9536059Samurai 9546059Samurai if (nb > 0) { 9556059Samurai cp = buff + strcspn(buff, "\r\n"); 9566059Samurai if (cp) 9576059Samurai *cp = '\0'; 95855145Sbrian return MakeArgs(buff, argv, MAXARGS, PARSE_REDUCE); 95937009Sbrian } 96037009Sbrian return 0; 96131121Sbrian} 9626059Samurai 96331822Sbrianstatic int 96431822Sbrianarghidden(int argc, char const *const *argv, int n) 96531822Sbrian{ 96631822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 96731828Sbrian 96831828Sbrian /* set authkey xxxxx */ 96931828Sbrian /* set key xxxxx */ 97031822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 97131822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 97231822Sbrian return 1; 97331822Sbrian 97431828Sbrian /* passwd xxxxx */ 97531828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 97631828Sbrian return 1; 97731828Sbrian 97836285Sbrian /* set server port xxxxx .... */ 97936285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 98036285Sbrian !strncasecmp(argv[1], "se", 2)) 98136285Sbrian return 1; 98236285Sbrian 98331822Sbrian return 0; 98431822Sbrian} 98531822Sbrian 98631121Sbrianvoid 98736285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 98837008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 98931121Sbrian{ 99031156Sbrian if (argc > 0) { 99136285Sbrian if (log_IsKept(LogCOMMAND)) { 99247844Sbrian char buf[LINE_LEN]; 99331156Sbrian int f, n; 99431156Sbrian 99531156Sbrian if (label) { 99631962Sbrian strncpy(buf, label, sizeof buf - 3); 99731962Sbrian buf[sizeof buf - 3] = '\0'; 99831156Sbrian strcat(buf, ": "); 99947844Sbrian n = strlen(buf); 100047844Sbrian } else { 100147844Sbrian *buf = '\0'; 100247844Sbrian n = 0; 100331156Sbrian } 100447844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 100547844Sbrian 100631156Sbrian for (f = 0; f < argc; f++) { 100731962Sbrian if (n < sizeof buf - 1 && f) 100831156Sbrian buf[n++] = ' '; 100931822Sbrian if (arghidden(argc, argv, f)) 101036285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 101131822Sbrian else 101231962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 101331156Sbrian n += strlen(buf+n); 101431156Sbrian } 101536285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 101631156Sbrian } 101737008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 101831156Sbrian } 10196059Samurai} 10206059Samurai 102154914Sbrianint 102236285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 102336285Sbrian const char *label) 102431121Sbrian{ 102531121Sbrian int argc; 102637009Sbrian char *argv[MAXARGS]; 102731121Sbrian 102858045Sbrian if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0) 102954914Sbrian return 0; 103054914Sbrian 103137008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 103254914Sbrian return 1; 103331121Sbrian} 103431121Sbrian 10356059Samuraistatic int 103631343SbrianShowCommand(struct cmdargs const *arg) 10376059Samurai{ 103836285Sbrian if (!arg->prompt) 103936285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 104036285Sbrian else if (arg->argc > arg->argn) 104136285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 104236285Sbrian arg->prompt, arg->cx); 10436059Samurai else 104436285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 104526516Sbrian 104626516Sbrian return 0; 10476059Samurai} 10486059Samurai 10496059Samuraistatic int 105031343SbrianTerminalCommand(struct cmdargs const *arg) 10516059Samurai{ 105236285Sbrian if (!arg->prompt) { 105336285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 105426516Sbrian return 1; 10556059Samurai } 105636285Sbrian 105736285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 105836285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 105936285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 106036285Sbrian return 1; 10616059Samurai } 106236285Sbrian 106336285Sbrian datalink_Up(arg->cx, 0, 0); 106436285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 106536285Sbrian return 0; 10666059Samurai} 10676059Samurai 10686059Samuraistatic int 106931343SbrianQuitCommand(struct cmdargs const *arg) 10706059Samurai{ 107136285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 107236285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 107336285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 107436285Sbrian Cleanup(EX_NORMAL); 107536285Sbrian if (arg->prompt) 107636285Sbrian prompt_Destroy(arg->prompt, 1); 107726516Sbrian 107826516Sbrian return 0; 10796059Samurai} 10806059Samurai 10816059Samuraistatic int 108236285SbrianOpenCommand(struct cmdargs const *arg) 10836059Samurai{ 108437160Sbrian if (arg->argc == arg->argn) 108537993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 108637160Sbrian else if (arg->argc == arg->argn + 1) { 108737160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 108837385Sbrian struct datalink *cx = arg->cx ? 108937385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 109037385Sbrian if (cx) { 109137385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 109237385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 109337160Sbrian else 109437993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 109537160Sbrian } else 109637160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 109737160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 109837160Sbrian struct fsm *fp; 10996059Samurai 110037210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 110137160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 110237160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 110337160Sbrian else if (fp->state == ST_OPENED) 110437160Sbrian fsm_Reopen(fp); 110537160Sbrian else { 110637160Sbrian fp->open_mode = 0; /* Not passive any more */ 110737160Sbrian if (fp->state == ST_STOPPED) { 110837160Sbrian fsm_Down(fp); 110937160Sbrian fsm_Up(fp); 111037160Sbrian } else { 111137160Sbrian fsm_Up(fp); 111237160Sbrian fsm_Open(fp); 111337160Sbrian } 111436285Sbrian } 111537160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 111637160Sbrian if (arg->cx) 111737160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 111837160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 111937160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 112037160Sbrian else 112137993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 112237160Sbrian } else 112337160Sbrian return -1; 112436285Sbrian } else 112536285Sbrian return -1; 112636285Sbrian 112726516Sbrian return 0; 11286059Samurai} 11296059Samurai 113025067Sbrianstatic int 113136285SbrianCloseCommand(struct cmdargs const *arg) 11326059Samurai{ 113337007Sbrian if (arg->argc == arg->argn) 113437007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 113537007Sbrian else if (arg->argc == arg->argn + 1) { 113637007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 113737007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 113837007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 113937007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 114037007Sbrian struct fsm *fp; 11416059Samurai 114237210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 114337007Sbrian if (fp->state == ST_OPENED) { 114437007Sbrian fsm_Close(fp); 114537007Sbrian if (arg->argv[arg->argn][3] == '!') 114637007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 114737007Sbrian else 114837007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 114937007Sbrian } 115037007Sbrian } else 115136285Sbrian return -1; 115236285Sbrian } else 115336285Sbrian return -1; 115436285Sbrian 115536285Sbrian return 0; 11566059Samurai} 11576059Samurai 115825067Sbrianstatic int 115936285SbrianDownCommand(struct cmdargs const *arg) 116011336Samurai{ 116137018Sbrian if (arg->argc == arg->argn) { 116237018Sbrian if (arg->cx) 116337018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 116437018Sbrian else 116537018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 116637018Sbrian } else if (arg->argc == arg->argn + 1) { 116737018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 116837018Sbrian if (arg->cx) 116937018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 117037018Sbrian else 117137018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 117237018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 117337018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 117437018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 117537060Sbrian fsm2initial(fp); 117637018Sbrian } else 117737018Sbrian return -1; 117836285Sbrian } else 117936285Sbrian return -1; 118036285Sbrian 118136285Sbrian return 0; 118225067Sbrian} 118325067Sbrian 118425067Sbrianstatic int 118536285SbrianSetModemSpeed(struct cmdargs const *arg) 118625067Sbrian{ 118736285Sbrian long speed; 118836285Sbrian char *end; 118911336Samurai 119036285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 119136285Sbrian if (arg->argc > arg->argn+1) { 119254917Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments\n"); 119336285Sbrian return -1; 119411336Samurai } 119536285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 119636285Sbrian physical_SetSync(arg->cx->physical); 119736285Sbrian return 0; 119836285Sbrian } 119936285Sbrian end = NULL; 120036285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 120136285Sbrian if (*end) { 120236285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 120336285Sbrian arg->argv[arg->argn]); 120436285Sbrian return -1; 120536285Sbrian } 120636285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 120736285Sbrian return 0; 120836285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 120936285Sbrian } else 121036285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 121124939Sbrian 121226516Sbrian return -1; 121311336Samurai} 121411336Samurai 121525067Sbrianstatic int 121631343SbrianSetStoppedTimeout(struct cmdargs const *arg) 121728327Sbrian{ 121836285Sbrian struct link *l = &arg->cx->physical->link; 121936285Sbrian 122036285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 122136285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 122236285Sbrian if (arg->argc <= arg->argn+2) { 122336285Sbrian if (arg->argc > arg->argn) { 122436285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 122536285Sbrian if (arg->argc > arg->argn+1) 122636285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 122728461Sbrian } 122828327Sbrian return 0; 122928327Sbrian } 123028327Sbrian return -1; 123128327Sbrian} 123228327Sbrian 123328327Sbrianstatic int 123431343SbrianSetServer(struct cmdargs const *arg) 123526940Sbrian{ 123626940Sbrian int res = -1; 123726940Sbrian 123836285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 123931081Sbrian const char *port, *passwd, *mask; 124053125Sbrian int mlen; 124131081Sbrian 124231081Sbrian /* What's what ? */ 124336285Sbrian port = arg->argv[arg->argn]; 124436285Sbrian if (arg->argc == arg->argn + 2) { 124536285Sbrian passwd = arg->argv[arg->argn+1]; 124636285Sbrian mask = NULL; 124736285Sbrian } else if (arg->argc == arg->argn + 3) { 124836285Sbrian passwd = arg->argv[arg->argn+1]; 124936285Sbrian mask = arg->argv[arg->argn+2]; 125053125Sbrian mlen = strlen(mask); 125153125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 125253125Sbrian (mlen == 4 && *mask != '0')) { 125353125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 125453125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 125531081Sbrian return -1; 125653125Sbrian } 125736285Sbrian } else if (strcasecmp(port, "none") == 0) { 125836285Sbrian if (server_Close(arg->bundle)) 125936285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 126036285Sbrian return 0; 126131081Sbrian } else 126236285Sbrian return -1; 126331081Sbrian 126436285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 126536285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 126631081Sbrian 126736285Sbrian if (*port == '/') { 126831081Sbrian mode_t imask; 126936285Sbrian char *ptr, name[LINE_LEN + 12]; 127028679Sbrian 127153125Sbrian if (mask == NULL) 127231081Sbrian imask = (mode_t)-1; 127353125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 127453125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 127536285Sbrian 127636285Sbrian ptr = strstr(port, "%d"); 127736285Sbrian if (ptr) { 127836285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 127937210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 128036285Sbrian port = name; 128136285Sbrian } 128236285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 128327346Sbrian } else { 128436285Sbrian int iport, add = 0; 128528679Sbrian 128631081Sbrian if (mask != NULL) 128731081Sbrian return -1; 128828679Sbrian 128936285Sbrian if (*port == '+') { 129036285Sbrian port++; 129136285Sbrian add = 1; 129236285Sbrian } 129331081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 129431081Sbrian struct servent *s; 129531081Sbrian 129631081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 129731081Sbrian iport = 0; 129836285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 129928679Sbrian } else 130031081Sbrian iport = ntohs(s->s_port); 130127346Sbrian } else 130231081Sbrian iport = atoi(port); 130336285Sbrian 130436285Sbrian if (iport) { 130536285Sbrian if (add) 130636285Sbrian iport += arg->bundle->unit; 130736285Sbrian res = server_TcpOpen(arg->bundle, iport); 130836285Sbrian } else 130936285Sbrian res = -1; 131027346Sbrian } 131131081Sbrian } 131226940Sbrian 131326940Sbrian return res; 131426940Sbrian} 131526940Sbrian 131626940Sbrianstatic int 131731343SbrianSetEscape(struct cmdargs const *arg) 13186059Samurai{ 13196059Samurai int code; 132036285Sbrian int argc = arg->argc - arg->argn; 132136285Sbrian char const *const *argv = arg->argv + arg->argn; 13226059Samurai 13236059Samurai for (code = 0; code < 33; code++) 132436285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 132531343Sbrian 13266059Samurai while (argc-- > 0) { 13276059Samurai sscanf(*argv++, "%x", &code); 13286059Samurai code &= 0xff; 132936285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 133036285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 13316059Samurai } 133226516Sbrian return 0; 13336059Samurai} 13346059Samurai 13356059Samuraistatic int 133631343SbrianSetInterfaceAddr(struct cmdargs const *arg) 13376059Samurai{ 133836285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 133932267Sbrian const char *hisaddr; 134032267Sbrian 134140561Sbrian if (arg->argc > arg->argn + 4) 134240561Sbrian return -1; 134340561Sbrian 134432267Sbrian hisaddr = NULL; 134544874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 134644874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 134736285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 134836285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 134936285Sbrian iplist_reset(&ipcp->cfg.peer_list); 135028394Sbrian 135136285Sbrian if (arg->argc > arg->argn) { 135243313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 135336285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 135436285Sbrian &ipcp->cfg.my_range.width)) 135528679Sbrian return 1; 135636285Sbrian if (arg->argc > arg->argn+1) { 135736285Sbrian hisaddr = arg->argv[arg->argn+1]; 135836285Sbrian if (arg->argc > arg->argn+2) { 135944455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 136036285Sbrian if (arg->argc > arg->argn+3) { 136136285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 136236285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 13639440Samurai } 13646059Samurai } 13656059Samurai } 13666059Samurai } 136728394Sbrian 136840561Sbrian /* 0.0.0.0 means any address (0 bits) */ 136936285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 137036285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 137136285Sbrian ipcp->cfg.my_range.width = 0; 13726059Samurai } 137336285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 137447648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 137536285Sbrian 137636285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 137736928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 137832267Sbrian return 4; 137931121Sbrian 138026516Sbrian return 0; 13816059Samurai} 13826059Samurai 138318752Sjkhstatic int 138444305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 138544305Sbrian u_int *maxtrm, int def) 138644305Sbrian{ 138744305Sbrian if (argc == 0) { 138844305Sbrian *timeout = DEF_FSMRETRY; 138944305Sbrian *maxreq = def; 139044305Sbrian if (maxtrm != NULL) 139144305Sbrian *maxtrm = def; 139244305Sbrian } else { 139344305Sbrian long l = atol(argv[0]); 139444305Sbrian 139544305Sbrian if (l < MIN_FSMRETRY) { 139644305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 139744305Sbrian l, MIN_FSMRETRY); 139844305Sbrian return 1; 139944305Sbrian } else 140044305Sbrian *timeout = l; 140144305Sbrian 140244305Sbrian if (argc > 1) { 140344305Sbrian l = atol(argv[1]); 140444305Sbrian if (l < 1) { 140544305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 140644305Sbrian l = 1; 140744305Sbrian } 140844305Sbrian *maxreq = l; 140944305Sbrian 141044305Sbrian if (argc > 2 && maxtrm != NULL) { 141144305Sbrian l = atol(argv[2]); 141244305Sbrian if (l < 1) { 141344305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 141444305Sbrian l = 1; 141544305Sbrian } 141644305Sbrian *maxtrm = l; 141744305Sbrian } 141844305Sbrian } 141944305Sbrian } 142044305Sbrian 142144305Sbrian return 0; 142244305Sbrian} 142344305Sbrian 142444305Sbrianstatic int 142531343SbrianSetVariable(struct cmdargs const *arg) 14266059Samurai{ 142737210Sbrian long long_val, param = (long)arg->cmd->args; 142851048Sbrian int mode, dummyint, f, first; 142931343Sbrian const char *argp; 143036285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 143136285Sbrian const char *err = NULL; 143236285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 143336285Sbrian struct in_addr dummyaddr, *addr; 14346059Samurai 143536285Sbrian if (arg->argc > arg->argn) 143636285Sbrian argp = arg->argv[arg->argn]; 143726551Sbrian else 143831343Sbrian argp = ""; 143926551Sbrian 144036285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 144136285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 144236285Sbrian arg->cmd->name); 144336285Sbrian return 1; 144436285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 144536285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 144636285Sbrian arg->cmd->name, cx->name); 144736285Sbrian cx = NULL; 144836285Sbrian } 144936285Sbrian 145026551Sbrian switch (param) { 145128679Sbrian case VAR_AUTHKEY: 145250139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 145350139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 145450139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 145528679Sbrian break; 145637210Sbrian 145728679Sbrian case VAR_AUTHNAME: 145840622Sbrian switch (bundle_Phase(arg->bundle)) { 145940622Sbrian case PHASE_DEAD: 146040622Sbrian case PHASE_ESTABLISH: 146140622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 146240622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 146340622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 146440622Sbrian break; 146540622Sbrian default: 146640622Sbrian err = "set authname: Only available at phase DEAD/ESTABLISH\n"; 146740622Sbrian log_Printf(LogWARN, err); 146840622Sbrian break; 146936285Sbrian } 147028679Sbrian break; 147137210Sbrian 147236285Sbrian case VAR_AUTOLOAD: 147349434Sbrian if (arg->argc == arg->argn + 3) { 147449434Sbrian int v1, v2, v3; 147549434Sbrian char *end; 147649434Sbrian 147749434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 147849434Sbrian if (v1 < 0 || *end) { 147949434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 148049434Sbrian arg->argv[arg->argn]); 148149434Sbrian return 1; 148236285Sbrian } 148349434Sbrian 148449434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 148549434Sbrian if (v2 < 0 || *end) { 148649434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 148749434Sbrian arg->argv[arg->argn + 1]); 148849434Sbrian return 1; 148949434Sbrian } 149049434Sbrian if (v2 < v1) { 149149434Sbrian v3 = v1; 149249434Sbrian v1 = v2; 149349434Sbrian v2 = v3; 149449434Sbrian } 149549434Sbrian 149649434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 149749434Sbrian if (v3 <= 0 || *end) { 149849434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 149949434Sbrian arg->argv[arg->argn + 2]); 150049434Sbrian return 1; 150149434Sbrian } 150249434Sbrian 150349434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 150449434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 150549434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 150649434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 150736285Sbrian } else { 150849434Sbrian err = "Set autoload requires three arguments\n"; 150936285Sbrian log_Printf(LogWARN, err); 151036285Sbrian } 151136285Sbrian break; 151237210Sbrian 151328679Sbrian case VAR_DIAL: 151436285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 151536285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 151628679Sbrian break; 151737210Sbrian 151828679Sbrian case VAR_LOGIN: 151936285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 152036285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 152128679Sbrian break; 152237210Sbrian 152336285Sbrian case VAR_WINSIZE: 152436285Sbrian if (arg->argc > arg->argn) { 152536285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 152636285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 152736285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 152836285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 152936285Sbrian l->ccp.cfg.deflate.out.winsize); 153036285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 153136285Sbrian } 153236285Sbrian if (arg->argc > arg->argn+1) { 153336285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 153436285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 153536285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 153636285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 153736285Sbrian l->ccp.cfg.deflate.in.winsize); 153836285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 153936285Sbrian } 154036285Sbrian } else 154136285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 154236285Sbrian } else { 154336285Sbrian err = "No window size specified\n"; 154436285Sbrian log_Printf(LogWARN, err); 154536285Sbrian } 154636285Sbrian break; 154737210Sbrian 154828679Sbrian case VAR_DEVICE: 154936285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 155036285Sbrian arg->argv + arg->argn); 155136285Sbrian break; 155237210Sbrian 155336285Sbrian case VAR_ACCMAP: 155436285Sbrian if (arg->argc > arg->argn) { 155537210Sbrian u_long ulong_val; 155636285Sbrian sscanf(argp, "%lx", &ulong_val); 155737210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 155836285Sbrian } else { 155936285Sbrian err = "No accmap specified\n"; 156036285Sbrian log_Printf(LogWARN, err); 156136285Sbrian } 156236285Sbrian break; 156337210Sbrian 156436285Sbrian case VAR_MODE: 156536285Sbrian mode = Nam2mode(argp); 156636285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 156736285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 156836285Sbrian return -1; 156936285Sbrian } 157036285Sbrian bundle_SetMode(arg->bundle, cx, mode); 157136285Sbrian break; 157237210Sbrian 157336285Sbrian case VAR_MRRU: 157440622Sbrian switch (bundle_Phase(arg->bundle)) { 157540622Sbrian case PHASE_DEAD: 157640622Sbrian break; 157740622Sbrian case PHASE_ESTABLISH: 157840622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 157940622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 158040622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 158140622Sbrian return 1; 158240622Sbrian } 158340622Sbrian break; 158440622Sbrian default: 158540622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 158640622Sbrian return 1; 158729696Sbrian } 158837210Sbrian long_val = atol(argp); 158937210Sbrian if (long_val && long_val < MIN_MRU) { 159037210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 159137210Sbrian return 1; 159237210Sbrian } else if (long_val > MAX_MRU) { 159337210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 159437210Sbrian return 1; 159537210Sbrian } else 159637210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 159728679Sbrian break; 159837210Sbrian 159936285Sbrian case VAR_MRU: 160037210Sbrian long_val = atol(argp); 160137210Sbrian if (long_val == 0) 160237210Sbrian l->lcp.cfg.mru = DEF_MRU; 160337210Sbrian else if (long_val < MIN_MRU) { 160437210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 160537210Sbrian return 1; 160637210Sbrian } else if (long_val > MAX_MRU) { 160737210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 160837210Sbrian return 1; 160937210Sbrian } else 161037210Sbrian l->lcp.cfg.mru = long_val; 161128679Sbrian break; 161237210Sbrian 161336285Sbrian case VAR_MTU: 161437210Sbrian long_val = atol(argp); 161537210Sbrian if (long_val && long_val < MIN_MTU) { 161637210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 161737210Sbrian return 1; 161837210Sbrian } else if (long_val > MAX_MTU) { 161937210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 162037210Sbrian return 1; 162137210Sbrian } else 162237210Sbrian arg->bundle->cfg.mtu = long_val; 162336285Sbrian break; 162437210Sbrian 162536285Sbrian case VAR_OPENMODE: 162636285Sbrian if (strcasecmp(argp, "active") == 0) 162736285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 162836285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 162936285Sbrian else if (strcasecmp(argp, "passive") == 0) 163036285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 163136285Sbrian else { 163236285Sbrian err = "%s: Invalid openmode\n"; 163336285Sbrian log_Printf(LogWARN, err, argp); 163436285Sbrian } 163536285Sbrian break; 163637210Sbrian 163728679Sbrian case VAR_PHONE: 163836285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 163936285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 164038174Sbrian cx->phone.alt = cx->phone.next = NULL; 164128679Sbrian break; 164237210Sbrian 164328679Sbrian case VAR_HANGUP: 164436285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 164536285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 164628679Sbrian break; 164737210Sbrian 164852488Sbrian case VAR_LOGOUT: 164952488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 165052488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 165152488Sbrian break; 165252488Sbrian 165336285Sbrian case VAR_IDLETIMEOUT: 165449978Sbrian if (arg->argc > arg->argn+2) 165536285Sbrian err = "Too many idle timeout values\n"; 165649978Sbrian else if (arg->argc == arg->argn) 165749978Sbrian err = "Too few idle timeout values\n"; 165849978Sbrian else { 165949978Sbrian int timeout, min; 166049978Sbrian 166149978Sbrian timeout = atoi(argp); 166249978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 166349978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 166449978Sbrian } 166536285Sbrian if (err) 166636285Sbrian log_Printf(LogWARN, err); 166729549Sbrian break; 166837210Sbrian 166936285Sbrian case VAR_LQRPERIOD: 167037210Sbrian long_val = atol(argp); 167137210Sbrian if (long_val < MIN_LQRPERIOD) { 167237210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 167337210Sbrian long_val, MIN_LQRPERIOD); 167437210Sbrian return 1; 167536285Sbrian } else 167637210Sbrian l->lcp.cfg.lqrperiod = long_val; 167736285Sbrian break; 167837210Sbrian 167936285Sbrian case VAR_LCPRETRY: 168044305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 168144305Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 168244305Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 168344305Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 168436285Sbrian break; 168537210Sbrian 168636285Sbrian case VAR_CHAPRETRY: 168744305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 168844305Sbrian &cx->chap.auth.cfg.fsm.timeout, 168944305Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 169036285Sbrian break; 169137210Sbrian 169236285Sbrian case VAR_PAPRETRY: 169344305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 169444305Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 169544305Sbrian NULL, DEF_FSMAUTHTRIES); 169636285Sbrian break; 169737210Sbrian 169836285Sbrian case VAR_CCPRETRY: 169944305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 170044305Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 170144305Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 170236285Sbrian break; 170337210Sbrian 170436285Sbrian case VAR_IPCPRETRY: 170544305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 170644305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 170744305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 170844305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 170936285Sbrian break; 171037210Sbrian 171136285Sbrian case VAR_NBNS: 171236285Sbrian case VAR_DNS: 171358044Sbrian if (param == VAR_DNS) { 171436285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 171558044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_NONE; 171658044Sbrian } else { 171736285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 171858044Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 171958044Sbrian } 172036285Sbrian 172136285Sbrian if (arg->argc > arg->argn) { 172243313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 172336285Sbrian addr, &dummyaddr, &dummyint); 172436285Sbrian if (arg->argc > arg->argn+1) 172543313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 172636285Sbrian addr + 1, &dummyaddr, &dummyint); 172736285Sbrian 172858044Sbrian if (addr[0].s_addr == INADDR_ANY) { 172936285Sbrian addr[0].s_addr = addr[1].s_addr; 173058044Sbrian addr[1].s_addr = INADDR_ANY; 173158044Sbrian } 173258044Sbrian if (addr[0].s_addr == INADDR_NONE) { 173358044Sbrian addr[0].s_addr = addr[1].s_addr; 173458044Sbrian addr[1].s_addr = INADDR_NONE; 173558044Sbrian } 173636285Sbrian } 173736285Sbrian break; 173838174Sbrian 173938174Sbrian case VAR_CALLBACK: 174038174Sbrian cx->cfg.callback.opmask = 0; 174138174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 174238174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 174338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 174438174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 174538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 174638174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 174738174Sbrian if (dummyint == arg->argc - 1) 174838174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 174938174Sbrian else { 175038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 175138174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 175238174Sbrian sizeof cx->cfg.callback.msg - 1); 175338174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 175438174Sbrian } 175538174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 175638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 175738174Sbrian else 175838174Sbrian return -1; 175938174Sbrian } 176038174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 176138174Sbrian cx->cfg.callback.opmask = 0; 176238174Sbrian break; 176338174Sbrian 176438174Sbrian case VAR_CBCP: 176538174Sbrian cx->cfg.cbcp.delay = 0; 176638174Sbrian *cx->cfg.cbcp.phone = '\0'; 176738174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 176838174Sbrian if (arg->argc > arg->argn) { 176938174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 177038174Sbrian sizeof cx->cfg.cbcp.phone - 1); 177138174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 177238174Sbrian if (arg->argc > arg->argn + 1) { 177338174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 177438174Sbrian if (arg->argc > arg->argn + 2) { 177538174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 177638174Sbrian if (long_val < MIN_FSMRETRY) 177738174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 177838174Sbrian long_val, MIN_FSMRETRY); 177938174Sbrian else 178038174Sbrian cx->cfg.cbcp.fsmretry = long_val; 178138174Sbrian } 178238174Sbrian } 178338174Sbrian } 178438174Sbrian break; 178538544Sbrian 178638544Sbrian case VAR_CHOKED: 178738544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 178838544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 178938544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 179038544Sbrian break; 179140665Sbrian 179240665Sbrian case VAR_SENDPIPE: 179340665Sbrian long_val = atol(argp); 179440665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 179540665Sbrian break; 179640665Sbrian 179740665Sbrian case VAR_RECVPIPE: 179840665Sbrian long_val = atol(argp); 179940665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 180040665Sbrian break; 180143313Sbrian 180243313Sbrian#ifndef NORADIUS 180343313Sbrian case VAR_RADIUS: 180443313Sbrian if (!*argp) 180543313Sbrian *arg->bundle->radius.cfg.file = '\0'; 180643313Sbrian else if (access(argp, R_OK)) { 180743313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 180843313Sbrian return 1; 180943313Sbrian } else { 181043313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 181143313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 181243313Sbrian arg->bundle->radius.cfg.file 181343313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 181443313Sbrian } 181543313Sbrian break; 181643313Sbrian#endif 181744073Sbrian 181844073Sbrian case VAR_CD: 181944073Sbrian if (*argp) { 182051699Sbrian if (strcasecmp(argp, "off")) { 182151699Sbrian long_val = atol(argp); 182251699Sbrian if (long_val < 0) 182351699Sbrian long_val = 0; 182451699Sbrian cx->physical->cfg.cd.delay = long_val; 182551699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 182651699Sbrian CD_REQUIRED : CD_VARIABLE; 182751699Sbrian } else 182851699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 182944073Sbrian } else { 183053733Sbrian cx->physical->cfg.cd.delay = 0; 183153733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 183244073Sbrian } 183344073Sbrian break; 183436285Sbrian 183546686Sbrian case VAR_PARITY: 183646686Sbrian if (arg->argc == arg->argn + 1) 183746686Sbrian return physical_SetParity(arg->cx->physical, argp); 183846686Sbrian else { 183946686Sbrian err = "Parity value must be odd, even or none\n"; 184046686Sbrian log_Printf(LogWARN, err); 184146686Sbrian } 184246686Sbrian break; 18436059Samurai 184446686Sbrian case VAR_CRTSCTS: 184546686Sbrian if (strcasecmp(argp, "on") == 0) 184636285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 184746686Sbrian else if (strcasecmp(argp, "off") == 0) 184836285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 184946686Sbrian else { 185046686Sbrian err = "RTS/CTS value must be on or off\n"; 185146686Sbrian log_Printf(LogWARN, err); 185246686Sbrian } 185346686Sbrian break; 185450867Sbrian 185550867Sbrian case VAR_URGENTPORTS: 185651048Sbrian if (arg->argn == arg->argc) { 185751048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 185851048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 185951048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 186051048Sbrian if (arg->argn == arg->argc - 1) 186151048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 186251048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 186351048Sbrian if (*arg->argv[f] == '+') 186451048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 186551048Sbrian else if (*arg->argv[f] == '-') 186651048Sbrian ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp, 186751048Sbrian atoi(arg->argv[f] + 1)); 186851048Sbrian else { 186951048Sbrian if (f == arg->argn) 187051048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 187151048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 187251048Sbrian } 187351048Sbrian } else { 187451048Sbrian first = arg->argn; 187551048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 187651048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 187751048Sbrian 187851048Sbrian for (f = first; f < arg->argc; f++) 187951048Sbrian if (*arg->argv[f] == '+') 188051048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 188151048Sbrian else if (*arg->argv[f] == '-') 188251048Sbrian ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp, 188351048Sbrian atoi(arg->argv[f] + 1)); 188451048Sbrian else { 188551048Sbrian if (f == first) 188651048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 188751048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 188851048Sbrian } 188951048Sbrian } 189050867Sbrian break; 189120812Sjkh } 189246686Sbrian 189346686Sbrian return err ? 1 : 0; 189420812Sjkh} 189520812Sjkh 189630715Sbrianstatic struct cmdtab const SetCommands[] = { 189736285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 189836285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 189928679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 190036285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 190128679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 190236285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 190336285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 190436285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 190536285Sbrian (const void *)VAR_AUTOLOAD}, 190650867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 190750867Sbrian "datalink bandwidth", "set bandwidth value"}, 190838174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 190938174Sbrian "callback control", "set callback [none|auth|cbcp|" 191038174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 191138174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 191238174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 191338174Sbrian (const void *)VAR_CBCP}, 191444305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 191544305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 191644073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 191744073Sbrian "set cd value[!]", (const void *)VAR_CD}, 191844305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 191944305Sbrian "CHAP retries", "set chapretry value [attempts]", 192044305Sbrian (const void *)VAR_CHAPRETRY}, 192138544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 192238544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 192346686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 192446686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 192546686Sbrian (const char *)VAR_CRTSCTS}, 192636285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 192736285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 192836285Sbrian (const void *) VAR_WINSIZE}, 192936285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 193046686Sbrian "physical device name", "set device|line device-name[,device-name]", 193136285Sbrian (const void *) VAR_DEVICE}, 193236285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 193336285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 193436285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 193536285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 193636285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 193736285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 193836285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 193936285Sbrian "escape characters", "set escape hex-digit ..."}, 194036285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 194136285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 194249388Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 194348142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 194436285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 194536285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 194636285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 194731343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 194844305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 194944305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 195044305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 195144305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 195236712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 195358033Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|dns|hdlc|" 195458033Sbrian "id0|ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 195536285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 195636285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 195752488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 195852488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 195936285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 196036285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 196136285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 196236285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 196336285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 196436285Sbrian "set mrru value", (const void *)VAR_MRRU}, 196536285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 196636285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 196736285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 196836285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 196936285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 197036285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 197136285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 197236285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 197344305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 197444305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 197546686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 197646686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 197736285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 197836285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 197940679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 198040679Sbrian "Process title", "set proctitle [value]"}, 198143313Sbrian#ifndef NORADIUS 198243313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 198343313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 198443313Sbrian#endif 198536285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 198636285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 198740665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 198840665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 198936285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 199044468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 199140665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 199240665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 199328679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 199436774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 199536285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 199646686Sbrian "physical speed", "set speed value|sync"}, 199736285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 199836285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 199936285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 200036285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 200151048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 200251048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 200336285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 200436285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 200528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 200631343Sbrian "Display this message", "set help|? [command]", SetCommands}, 200728679Sbrian {NULL, NULL, NULL}, 20086059Samurai}; 20096059Samurai 20106059Samuraistatic int 201131343SbrianSetCommand(struct cmdargs const *arg) 20126059Samurai{ 201336285Sbrian if (arg->argc > arg->argn) 201436285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 201536285Sbrian arg->prompt, arg->cx); 201636285Sbrian else if (arg->prompt) 201736285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 201858044Sbrian " syntax help.\n"); 20196059Samurai else 202036285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 202126516Sbrian 202226516Sbrian return 0; 20236059Samurai} 20246059Samurai 20256059Samuraistatic int 202631343SbrianAddCommand(struct cmdargs const *arg) 20276059Samurai{ 20286059Samurai struct in_addr dest, gateway, netmask; 202936285Sbrian int gw, addrs; 20306059Samurai 203136285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 203231598Sbrian return -1; 203331598Sbrian 203436285Sbrian addrs = 0; 203536285Sbrian if (arg->argc == arg->argn+2) { 203636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 203736285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 203831598Sbrian else { 203936285Sbrian int width; 204036285Sbrian 204143313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 204236285Sbrian &dest, &netmask, &width)) 204336285Sbrian return -1; 204436285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 204536285Sbrian addrs = ROUTE_DSTMYADDR; 204636285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 204736285Sbrian addrs = ROUTE_DSTHISADDR; 204858044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) 204958044Sbrian addrs = ROUTE_DSTDNS0; 205058044Sbrian else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) 205158044Sbrian addrs = ROUTE_DSTDNS1; 205231598Sbrian } 205336285Sbrian gw = 1; 205434536Sbrian } else { 205536285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 205636285Sbrian addrs = ROUTE_DSTMYADDR; 205736285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 205836285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 205936285Sbrian addrs = ROUTE_DSTHISADDR; 206036285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 206158044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 206258044Sbrian addrs = ROUTE_DSTDNS0; 206358044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 206458044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 206558044Sbrian addrs = ROUTE_DSTDNS1; 206658044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 206736285Sbrian } else 206836285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 206936285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 207031598Sbrian gw = 2; 20716059Samurai } 207236285Sbrian 207336285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 207436285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 207536285Sbrian addrs |= ROUTE_GWHISADDR; 207640561Sbrian } else 207736285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 207836285Sbrian 207936285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 208043313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 208143313Sbrian && addrs != ROUTE_STATIC) 208236285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 208336285Sbrian 208431598Sbrian return 0; 20856059Samurai} 20866059Samurai 20876059Samuraistatic int 208831343SbrianDeleteCommand(struct cmdargs const *arg) 20896059Samurai{ 209031598Sbrian struct in_addr dest, none; 209136285Sbrian int addrs; 20926059Samurai 209336285Sbrian if (arg->argc == arg->argn+1) { 209436285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 209536285Sbrian route_IfDelete(arg->bundle, 0); 209636285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 209736285Sbrian } else { 209836285Sbrian addrs = 0; 209936285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 210036285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 210136285Sbrian addrs = ROUTE_DSTMYADDR; 210236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 210336285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 210436285Sbrian addrs = ROUTE_DSTHISADDR; 210558044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { 210658044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[0]; 210758044Sbrian addrs = ROUTE_DSTDNS0; 210858044Sbrian } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { 210958044Sbrian dest = arg->bundle->ncp.ipcp.ns.dns[1]; 211058044Sbrian addrs = ROUTE_DSTDNS1; 211136285Sbrian } else { 211244279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 211344279Sbrian if (dest.s_addr == INADDR_NONE) { 211444279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 211544279Sbrian return -1; 211644279Sbrian } 211736285Sbrian addrs = ROUTE_STATIC; 211836285Sbrian } 211931598Sbrian none.s_addr = INADDR_ANY; 212036285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 212137927Sbrian arg->cmd->args ? 1 : 0, 0); 212236285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 212331598Sbrian } 212434536Sbrian } else 212526516Sbrian return -1; 212626516Sbrian 212726516Sbrian return 0; 21286059Samurai} 21296059Samurai 213050059Sbrian#ifndef NONAT 213126031Sbrianstatic int 213231343SbrianAliasEnable(struct cmdargs const *arg) 213326031Sbrian{ 213436285Sbrian if (arg->argc == arg->argn+1) { 213536285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 213650059Sbrian if (!arg->bundle->NatEnabled) { 213746686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 213846686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 213950059Sbrian arg->bundle->NatEnabled = 1; 214046686Sbrian } 214137191Sbrian return 0; 214236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 214350059Sbrian arg->bundle->NatEnabled = 0; 214440561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 214540561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 214626516Sbrian return 0; 214726142Sbrian } 214835449Sbrian } 214936285Sbrian 215026516Sbrian return -1; 215126031Sbrian} 215226031Sbrian 215326031Sbrian 215426031Sbrianstatic int 215531343SbrianAliasOption(struct cmdargs const *arg) 215626031Sbrian{ 215738559Sbrian long param = (long)arg->cmd->args; 215838559Sbrian 215936285Sbrian if (arg->argc == arg->argn+1) { 216036285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 216150059Sbrian if (arg->bundle->NatEnabled) { 216237191Sbrian PacketAliasSetMode(param, param); 216328679Sbrian return 0; 216428679Sbrian } 216550059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 216636285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 216750059Sbrian if (arg->bundle->NatEnabled) { 216837191Sbrian PacketAliasSetMode(0, param); 216928679Sbrian return 0; 217028679Sbrian } 217150059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 217228679Sbrian } 217335449Sbrian } 217428679Sbrian return -1; 217526031Sbrian} 217650059Sbrian#endif /* #ifndef NONAT */ 217731121Sbrian 217831121Sbrianstatic int 217936285SbrianLinkCommand(struct cmdargs const *arg) 218036285Sbrian{ 218136285Sbrian if (arg->argc > arg->argn+1) { 218236285Sbrian char namelist[LINE_LEN]; 218336285Sbrian struct datalink *cx; 218436285Sbrian char *name; 218536285Sbrian int result = 0; 218636285Sbrian 218736285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 218836285Sbrian struct datalink *dl; 218936285Sbrian 219036285Sbrian cx = arg->bundle->links; 219136285Sbrian while (cx) { 219236285Sbrian /* Watch it, the command could be a ``remove'' */ 219336285Sbrian dl = cx->next; 219436285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 219536285Sbrian arg->prompt, cx); 219636285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 219736285Sbrian if (cx == dl) 219836285Sbrian break; /* Pointer's still valid ! */ 219936285Sbrian } 220036285Sbrian } else { 220136285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 220236285Sbrian namelist[sizeof namelist - 1] = '\0'; 220336285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 220436285Sbrian if (!bundle2datalink(arg->bundle, name)) { 220536285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 220636285Sbrian return 1; 220736285Sbrian } 220836285Sbrian 220936285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 221036285Sbrian namelist[sizeof namelist - 1] = '\0'; 221136285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 221236285Sbrian cx = bundle2datalink(arg->bundle, name); 221336285Sbrian if (cx) 221436285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 221536285Sbrian arg->prompt, cx); 221636285Sbrian else { 221736285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 221836285Sbrian result++; 221936285Sbrian } 222036285Sbrian } 222136285Sbrian } 222236285Sbrian return result; 222336285Sbrian } 222436285Sbrian 222536285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 222636285Sbrian return 2; 222736285Sbrian} 222836285Sbrian 222936285Sbrianstruct link * 223036285Sbriancommand_ChooseLink(struct cmdargs const *arg) 223136285Sbrian{ 223236285Sbrian if (arg->cx) 223336285Sbrian return &arg->cx->physical->link; 223437210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 223536285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 223637210Sbrian if (dl) 223737210Sbrian return &dl->physical->link; 223836285Sbrian } 223937210Sbrian return &arg->bundle->ncp.mp.link; 224036285Sbrian} 224136285Sbrian 224236285Sbrianstatic const char * 224336285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 224436285Sbrian{ 224536285Sbrian const char *result; 224636285Sbrian 224736285Sbrian switch (*cmd) { 224836285Sbrian case 'A': 224936285Sbrian case 'a': 225036285Sbrian result = "accept"; 225136285Sbrian *keep = NEG_MYMASK; 225236285Sbrian *add = NEG_ACCEPTED; 225336285Sbrian break; 225436285Sbrian case 'D': 225536285Sbrian case 'd': 225636285Sbrian switch (cmd[1]) { 225736285Sbrian case 'E': 225836285Sbrian case 'e': 225936285Sbrian result = "deny"; 226036285Sbrian *keep = NEG_MYMASK; 226136285Sbrian *add = 0; 226236285Sbrian break; 226336285Sbrian case 'I': 226436285Sbrian case 'i': 226536285Sbrian result = "disable"; 226636285Sbrian *keep = NEG_HISMASK; 226736285Sbrian *add = 0; 226836285Sbrian break; 226936285Sbrian default: 227036285Sbrian return NULL; 227136285Sbrian } 227236285Sbrian break; 227336285Sbrian case 'E': 227436285Sbrian case 'e': 227536285Sbrian result = "enable"; 227636285Sbrian *keep = NEG_HISMASK; 227736285Sbrian *add = NEG_ENABLED; 227836285Sbrian break; 227936285Sbrian default: 228036285Sbrian return NULL; 228136285Sbrian } 228236285Sbrian 228336285Sbrian return result; 228436285Sbrian} 228536285Sbrian 228636285Sbrianstatic int 228736285SbrianOptSet(struct cmdargs const *arg) 228836285Sbrian{ 228937574Sbrian int bit = (int)(long)arg->cmd->args; 229036285Sbrian const char *cmd; 229136285Sbrian unsigned keep; /* Keep these bits */ 229236285Sbrian unsigned add; /* Add these bits */ 229336285Sbrian 229436285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 229536285Sbrian return 1; 229636285Sbrian 229736285Sbrian if (add) 229836285Sbrian arg->bundle->cfg.opt |= bit; 229936285Sbrian else 230036285Sbrian arg->bundle->cfg.opt &= ~bit; 230136285Sbrian return 0; 230236285Sbrian} 230336285Sbrian 230436285Sbrianstatic int 230540561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 230640561Sbrian{ 230740561Sbrian unsigned save = arg->bundle->cfg.opt; 230840561Sbrian int result = OptSet(arg); 230940561Sbrian 231040561Sbrian if (result == 0) 231150059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 231240561Sbrian arg->bundle->cfg.opt = save; 231350059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 231440561Sbrian result = 2; 231540561Sbrian } 231640561Sbrian 231740561Sbrian return result; 231840561Sbrian} 231940561Sbrian 232040561Sbrianstatic int 232136285SbrianNegotiateSet(struct cmdargs const *arg) 232236285Sbrian{ 232337210Sbrian long param = (long)arg->cmd->args; 232436285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 232536285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 232636285Sbrian const char *cmd; 232736285Sbrian unsigned keep; /* Keep these bits */ 232836285Sbrian unsigned add; /* Add these bits */ 232936285Sbrian 233036285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 233136285Sbrian return 1; 233236285Sbrian 233336285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 233436285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 233536285Sbrian cmd, arg->cmd->name); 233636285Sbrian return 2; 233736285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 233836285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 233936285Sbrian cmd, arg->cmd->name, cx->name); 234036285Sbrian cx = NULL; 234136285Sbrian } 234236285Sbrian 234336285Sbrian switch (param) { 234436285Sbrian case NEG_ACFCOMP: 234536285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 234636285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 234736285Sbrian break; 234844106Sbrian case NEG_CHAP05: 234944106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 235044106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 235136285Sbrian break; 235244106Sbrian#ifdef HAVE_DES 235344106Sbrian case NEG_CHAP80: 235444106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 235544106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 235644106Sbrian break; 235744106Sbrian case NEG_CHAP80LM: 235844106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 235944106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 236044106Sbrian break; 236144106Sbrian#endif 236236285Sbrian case NEG_DEFLATE: 236336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 236436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 236536285Sbrian break; 236636285Sbrian case NEG_DNS: 236736285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 236836285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 236936285Sbrian break; 237047858Sbrian case NEG_ENDDISC: 237147858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 237247858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 237347858Sbrian break; 237436285Sbrian case NEG_LQR: 237536285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 237636285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 237736285Sbrian break; 237836285Sbrian case NEG_PAP: 237936285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 238036285Sbrian cx->physical->link.lcp.cfg.pap |= add; 238136285Sbrian break; 238236285Sbrian case NEG_PPPDDEFLATE: 238336285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 238436285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 238536285Sbrian break; 238636285Sbrian case NEG_PRED1: 238736285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 238836285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 238936285Sbrian break; 239036285Sbrian case NEG_PROTOCOMP: 239136285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 239236285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 239336285Sbrian break; 239436285Sbrian case NEG_SHORTSEQ: 239540622Sbrian switch (bundle_Phase(arg->bundle)) { 239640622Sbrian case PHASE_DEAD: 239740622Sbrian break; 239840622Sbrian case PHASE_ESTABLISH: 239940622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 240040622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 240140622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 240240622Sbrian " LCP negotiations\n"); 240340622Sbrian return 1; 240440622Sbrian } 240540622Sbrian break; 240640622Sbrian default: 240740622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 240840622Sbrian " DEAD/ESTABLISH\n"); 240940622Sbrian return 1; 241036285Sbrian } 241140622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 241240622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 241336285Sbrian break; 241436285Sbrian case NEG_VJCOMP: 241536285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 241636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 241736285Sbrian break; 241836285Sbrian } 241936285Sbrian 242036285Sbrian return 0; 242136285Sbrian} 242236285Sbrian 242336285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 242436285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 242536285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 242640666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 242740666Sbrian "retain interface addresses", "disable|enable", 242840666Sbrian (const void *)OPT_IFACEALIAS}, 242947689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 243047689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 243136285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 243236285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 243336285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 243436285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 243540665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 243636285Sbrian "disable|enable", (const void *)OPT_PROXY}, 243740665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 243840665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 243936285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 244036285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 244136285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 244236285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 244336285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 244436285Sbrian "disable|enable", (const void *)OPT_UTMP}, 244536285Sbrian 244647689Sbrian#define OPT_MAX 10 /* accept/deny allowed below and not above */ 244736285Sbrian 244836285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 244936285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 245036285Sbrian (const void *)NEG_ACFCOMP}, 245144106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 245236285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 245344106Sbrian (const void *)NEG_CHAP05}, 245444106Sbrian#ifdef HAVE_DES 245544106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 245644106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 245744106Sbrian (const void *)NEG_CHAP80}, 245844106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 245944106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 246044106Sbrian (const void *)NEG_CHAP80LM}, 246144106Sbrian#endif 246236285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 246336285Sbrian "Deflate compression", "accept|deny|disable|enable", 246436285Sbrian (const void *)NEG_DEFLATE}, 246536285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 246636285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 246736285Sbrian (const void *)NEG_PPPDDEFLATE}, 246836285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 246936285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 247047858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 247147858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 247236285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 247336285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 247436285Sbrian (const void *)NEG_LQR}, 247536285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 247636285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 247736285Sbrian (const void *)NEG_PAP}, 247836285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 247936285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 248036285Sbrian (const void *)NEG_PRED1}, 248136285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 248236285Sbrian "Protocol field compression", "accept|deny|disable|enable", 248336285Sbrian (const void *)NEG_PROTOCOMP}, 248436285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 248536285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 248636285Sbrian (const void *)NEG_SHORTSEQ}, 248736285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 248836285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 248936285Sbrian (const void *)NEG_VJCOMP}, 249036285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 249136285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 249236285Sbrian NegotiateCommands}, 249336285Sbrian {NULL, NULL, NULL}, 249436285Sbrian}; 249536285Sbrian 249636285Sbrianstatic int 249736285SbrianNegotiateCommand(struct cmdargs const *arg) 249836285Sbrian{ 249936285Sbrian if (arg->argc > arg->argn) { 250036285Sbrian char const *argv[3]; 250136285Sbrian unsigned keep, add; 250236285Sbrian int n; 250336285Sbrian 250436285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 250536285Sbrian return -1; 250636285Sbrian argv[2] = NULL; 250736285Sbrian 250836285Sbrian for (n = arg->argn; n < arg->argc; n++) { 250936285Sbrian argv[1] = arg->argv[n]; 251036285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 251136285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 251236285Sbrian } 251336285Sbrian } else if (arg->prompt) 251436285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 251536285Sbrian arg->argv[arg->argn-1]); 251636285Sbrian else 251736285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 251836285Sbrian arg->argv[arg->argn] ); 251936285Sbrian 252036285Sbrian return 0; 252136285Sbrian} 252236285Sbrian 252336285Sbrianconst char * 252436285Sbriancommand_ShowNegval(unsigned val) 252536285Sbrian{ 252636285Sbrian switch (val&3) { 252736285Sbrian case 1: return "disabled & accepted"; 252836285Sbrian case 2: return "enabled & denied"; 252936285Sbrian case 3: return "enabled & accepted"; 253036285Sbrian } 253136285Sbrian return "disabled & denied"; 253236285Sbrian} 253336934Sbrian 253436934Sbrianstatic int 253536934SbrianClearCommand(struct cmdargs const *arg) 253636934Sbrian{ 253736934Sbrian struct pppThroughput *t; 253836934Sbrian struct datalink *cx; 253936934Sbrian int i, clear_type; 254036934Sbrian 254136934Sbrian if (arg->argc < arg->argn + 1) 254236934Sbrian return -1; 254336934Sbrian 254446686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 254536934Sbrian cx = arg->cx; 254636934Sbrian if (!cx) 254736934Sbrian cx = bundle2datalink(arg->bundle, NULL); 254836934Sbrian if (!cx) { 254946686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 255036934Sbrian return 1; 255136934Sbrian } 255236934Sbrian t = &cx->physical->link.throughput; 255336934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 255436934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 255536934Sbrian else 255636934Sbrian return -1; 255736934Sbrian 255836934Sbrian if (arg->argc > arg->argn + 1) { 255936934Sbrian clear_type = 0; 256036934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 256136934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 256236934Sbrian clear_type |= THROUGHPUT_OVERALL; 256336934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 256436934Sbrian clear_type |= THROUGHPUT_CURRENT; 256536934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 256636934Sbrian clear_type |= THROUGHPUT_PEAK; 256736934Sbrian else 256836934Sbrian return -1; 256936934Sbrian } else 257036934Sbrian clear_type = THROUGHPUT_ALL; 257136934Sbrian 257236934Sbrian throughput_clear(t, clear_type, arg->prompt); 257336934Sbrian return 0; 257436934Sbrian} 257540561Sbrian 257640561Sbrianstatic int 257740561SbrianRunListCommand(struct cmdargs const *arg) 257840561Sbrian{ 257940561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 258040561Sbrian 258140561Sbrian if (arg->argc > arg->argn) 258240561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 258340561Sbrian arg->prompt, arg->cx); 258440561Sbrian else if (arg->prompt) 258540561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 258640561Sbrian " <option>' for syntax help.\n", cmd, cmd); 258740561Sbrian else 258840561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 258940561Sbrian 259040561Sbrian return 0; 259140561Sbrian} 259240561Sbrian 259340561Sbrianstatic int 259440561SbrianIfaceAddCommand(struct cmdargs const *arg) 259540561Sbrian{ 259640561Sbrian int bits, n, how; 259740561Sbrian struct in_addr ifa, mask, brd; 259840561Sbrian 259940664Sbrian if (arg->argc == arg->argn + 1) { 260043313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 260140561Sbrian return -1; 260240664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 260340664Sbrian } else { 260440664Sbrian if (arg->argc == arg->argn + 2) { 260543313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 260640664Sbrian return -1; 260740664Sbrian n = 1; 260840664Sbrian } else if (arg->argc == arg->argn + 3) { 260943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 261040664Sbrian return -1; 261143313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 261240664Sbrian return -1; 261340664Sbrian n = 2; 261440664Sbrian } else 261540561Sbrian return -1; 261640561Sbrian 261743313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 261840664Sbrian return -1; 261940664Sbrian } 262040561Sbrian 262140561Sbrian how = IFACE_ADD_LAST; 262240561Sbrian if (arg->cmd->args) 262340561Sbrian how |= IFACE_FORCE_ADD; 262440561Sbrian 262540561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 262640561Sbrian} 262740561Sbrian 262840561Sbrianstatic int 262940561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 263040561Sbrian{ 263140561Sbrian struct in_addr ifa; 263240561Sbrian int ok; 263340561Sbrian 263440561Sbrian if (arg->argc != arg->argn + 1) 263540561Sbrian return -1; 263640561Sbrian 263743313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 263840561Sbrian return -1; 263940561Sbrian 264040561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 264140561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 264240561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 264340561Sbrian inet_ntoa(ifa)); 264440561Sbrian return 1; 264540561Sbrian } 264640561Sbrian 264740561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 264840561Sbrian if (!ok) { 264940561Sbrian if (arg->cmd->args) 265040561Sbrian ok = 1; 265140561Sbrian else if (arg->prompt) 265240561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 265340561Sbrian else 265440561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 265540561Sbrian } 265640561Sbrian 265740561Sbrian return !ok; 265840561Sbrian} 265940561Sbrian 266040561Sbrianstatic int 266140561SbrianIfaceClearCommand(struct cmdargs const *arg) 266240561Sbrian{ 266340561Sbrian int how; 266440561Sbrian 266540561Sbrian if (arg->argc != arg->argn) 266640561Sbrian return -1; 266740561Sbrian 266840941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 266940941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 267040561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 267140561Sbrian iface_Clear(arg->bundle->iface, how); 267240561Sbrian 267340561Sbrian return 0; 267440561Sbrian} 267540679Sbrian 267640679Sbrianstatic int 267740679SbrianSetProcTitle(struct cmdargs const *arg) 267840679Sbrian{ 267940679Sbrian static char title[LINE_LEN]; 268040679Sbrian char *argv[MAXARGS], *ptr; 268140679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 268240679Sbrian 268340679Sbrian if (arg->argc == arg->argn) { 268453298Sbrian ID0setproctitle(NULL); 268540679Sbrian return 0; 268640679Sbrian } 268740679Sbrian 268840679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 268940679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 269040679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 269140679Sbrian } 269247849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 269340679Sbrian 269440679Sbrian ptr = title; 269540679Sbrian remaining = sizeof title - 1; 269640679Sbrian for (f = 0; f < argc && remaining; f++) { 269740679Sbrian if (f) { 269840679Sbrian *ptr++ = ' '; 269940679Sbrian remaining--; 270040679Sbrian } 270140679Sbrian len = strlen(argv[f]); 270240679Sbrian if (len > remaining) 270340679Sbrian len = remaining; 270440679Sbrian memcpy(ptr, argv[f], len); 270540679Sbrian remaining -= len; 270640679Sbrian ptr += len; 270740679Sbrian } 270840679Sbrian *ptr = '\0'; 270940679Sbrian 271053298Sbrian ID0setproctitle(title); 271140679Sbrian 271240679Sbrian return 0; 271340679Sbrian} 2714