command.c revision 53733
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 53733 1999-11-26 22:44:33Z 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 5046086Sbrian#ifdef __FreeBSD__ 5146086Sbrian#include <alias.h> 5246086Sbrian#else 5339395Sbrian#include "alias.h" 5439395Sbrian#endif 5539395Sbrian#endif 5646686Sbrian#include "layer.h" 5737009Sbrian#include "defs.h" 5831343Sbrian#include "command.h" 5930715Sbrian#include "mbuf.h" 6030715Sbrian#include "log.h" 6130715Sbrian#include "timer.h" 626059Samurai#include "fsm.h" 636059Samurai#include "lcp.h" 6431690Sbrian#include "iplist.h" 6536285Sbrian#include "throughput.h" 6636285Sbrian#include "slcompress.h" 6738557Sbrian#include "lqr.h" 6838557Sbrian#include "hdlc.h" 696059Samurai#include "ipcp.h" 7050059Sbrian#ifndef NONAT 7151075Sbrian#include "nat_cmd.h" 7231343Sbrian#endif 7325630Sbrian#include "systems.h" 7436285Sbrian#include "filter.h" 7536285Sbrian#include "descriptor.h" 7630715Sbrian#include "main.h" 7730715Sbrian#include "route.h" 7830715Sbrian#include "ccp.h" 7931080Sbrian#include "auth.h" 8036285Sbrian#include "async.h" 8136285Sbrian#include "link.h" 8236285Sbrian#include "physical.h" 8336285Sbrian#include "mp.h" 8443313Sbrian#ifndef NORADIUS 8543313Sbrian#include "radius.h" 8643313Sbrian#endif 8736285Sbrian#include "bundle.h" 8836285Sbrian#include "server.h" 8936285Sbrian#include "prompt.h" 9036285Sbrian#include "chat.h" 9136285Sbrian#include "chap.h" 9238174Sbrian#include "cbcp.h" 9336285Sbrian#include "datalink.h" 9440561Sbrian#include "iface.h" 9553298Sbrian#include "id.h" 966059Samurai 9736285Sbrian/* ``set'' values */ 9836285Sbrian#define VAR_AUTHKEY 0 9936285Sbrian#define VAR_DIAL 1 10036285Sbrian#define VAR_LOGIN 2 10136285Sbrian#define VAR_AUTHNAME 3 10236285Sbrian#define VAR_AUTOLOAD 4 10336285Sbrian#define VAR_WINSIZE 5 10436285Sbrian#define VAR_DEVICE 6 10536285Sbrian#define VAR_ACCMAP 7 10636285Sbrian#define VAR_MRRU 8 10736285Sbrian#define VAR_MRU 9 10836285Sbrian#define VAR_MTU 10 10936285Sbrian#define VAR_OPENMODE 11 11036285Sbrian#define VAR_PHONE 12 11136285Sbrian#define VAR_HANGUP 13 11236285Sbrian#define VAR_IDLETIMEOUT 14 11336285Sbrian#define VAR_LQRPERIOD 15 11436285Sbrian#define VAR_LCPRETRY 16 11536285Sbrian#define VAR_CHAPRETRY 17 11636285Sbrian#define VAR_PAPRETRY 18 11736285Sbrian#define VAR_CCPRETRY 19 11836285Sbrian#define VAR_IPCPRETRY 20 11936285Sbrian#define VAR_DNS 21 12036285Sbrian#define VAR_NBNS 22 12136285Sbrian#define VAR_MODE 23 12238174Sbrian#define VAR_CALLBACK 24 12338174Sbrian#define VAR_CBCP 25 12438544Sbrian#define VAR_CHOKED 26 12540665Sbrian#define VAR_SENDPIPE 27 12640665Sbrian#define VAR_RECVPIPE 28 12743313Sbrian#define VAR_RADIUS 29 12844073Sbrian#define VAR_CD 30 12946686Sbrian#define VAR_PARITY 31 13046686Sbrian#define VAR_CRTSCTS 32 13150867Sbrian#define VAR_URGENTPORTS 33 13252488Sbrian#define VAR_LOGOUT 34 1336059Samurai 13436285Sbrian/* ``accept|deny|disable|enable'' masks */ 13536285Sbrian#define NEG_HISMASK (1) 13636285Sbrian#define NEG_MYMASK (2) 13736285Sbrian 13836285Sbrian/* ``accept|deny|disable|enable'' values */ 13936285Sbrian#define NEG_ACFCOMP 40 14044106Sbrian#define NEG_CHAP05 41 14144106Sbrian#define NEG_CHAP80 42 14244106Sbrian#define NEG_CHAP80LM 43 14344106Sbrian#define NEG_DEFLATE 44 14447858Sbrian#define NEG_DNS 45 14547858Sbrian#define NEG_ENDDISC 46 14647858Sbrian#define NEG_LQR 47 14747858Sbrian#define NEG_PAP 48 14847858Sbrian#define NEG_PPPDDEFLATE 49 14947858Sbrian#define NEG_PRED1 50 15047858Sbrian#define NEG_PROTOCOMP 51 15147858Sbrian#define NEG_SHORTSEQ 52 15247858Sbrian#define NEG_VJCOMP 53 15336285Sbrian 15453684Sbrianconst char Version[] = "2.25"; 15536285Sbrian 15636285Sbrianstatic int ShowCommand(struct cmdargs const *); 15736285Sbrianstatic int TerminalCommand(struct cmdargs const *); 15836285Sbrianstatic int QuitCommand(struct cmdargs const *); 15936285Sbrianstatic int OpenCommand(struct cmdargs const *); 16036285Sbrianstatic int CloseCommand(struct cmdargs const *); 16136285Sbrianstatic int DownCommand(struct cmdargs const *); 16236285Sbrianstatic int SetCommand(struct cmdargs const *); 16336285Sbrianstatic int LinkCommand(struct cmdargs const *); 16436285Sbrianstatic int AddCommand(struct cmdargs const *); 16536285Sbrianstatic int DeleteCommand(struct cmdargs const *); 16636285Sbrianstatic int NegotiateCommand(struct cmdargs const *); 16736934Sbrianstatic int ClearCommand(struct cmdargs const *); 16840561Sbrianstatic int RunListCommand(struct cmdargs const *); 16940561Sbrianstatic int IfaceAddCommand(struct cmdargs const *); 17040561Sbrianstatic int IfaceDeleteCommand(struct cmdargs const *); 17140561Sbrianstatic int IfaceClearCommand(struct cmdargs const *); 17240679Sbrianstatic int SetProcTitle(struct cmdargs const *); 17350059Sbrian#ifndef NONAT 17436285Sbrianstatic int AliasEnable(struct cmdargs const *); 17536285Sbrianstatic int AliasOption(struct cmdargs const *); 17631343Sbrian#endif 1776059Samurai 17836285Sbrianstatic const char * 17936285Sbrianshowcx(struct cmdtab const *cmd) 18036285Sbrian{ 18136285Sbrian if (cmd->lauth & LOCAL_CX) 18236285Sbrian return "(c)"; 18336285Sbrian else if (cmd->lauth & LOCAL_CX_OPT) 18436285Sbrian return "(o)"; 18536285Sbrian 18636285Sbrian return ""; 18736285Sbrian} 18836285Sbrian 1896059Samuraistatic int 19031343SbrianHelpCommand(struct cmdargs const *arg) 1916059Samurai{ 19228679Sbrian struct cmdtab const *cmd; 19336285Sbrian int n, cmax, dmax, cols, cxlen; 19436285Sbrian const char *cx; 1956059Samurai 19636285Sbrian if (!arg->prompt) { 19736285Sbrian log_Printf(LogWARN, "help: Cannot help without a prompt\n"); 19826516Sbrian return 0; 19936285Sbrian } 20026516Sbrian 20136285Sbrian if (arg->argc > arg->argn) { 20236285Sbrian for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++) 20336285Sbrian if ((cmd->lauth & arg->prompt->auth) && 20436285Sbrian ((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) || 20536285Sbrian (cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) { 20636285Sbrian prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd)); 20728679Sbrian return 0; 2086059Samurai } 20926516Sbrian return -1; 2106059Samurai } 21136285Sbrian 21231372Sbrian cmax = dmax = 0; 21336285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 21436285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 21536285Sbrian if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax) 21631372Sbrian cmax = n; 21731372Sbrian if ((n = strlen(cmd->helpmes)) > dmax) 21831372Sbrian dmax = n; 21931372Sbrian } 22031372Sbrian 22131372Sbrian cols = 80 / (dmax + cmax + 3); 2226059Samurai n = 0; 22336285Sbrian prompt_Printf(arg->prompt, "(o) = Optional context," 22436285Sbrian " (c) = Context required\n"); 22536285Sbrian for (cmd = arg->cmdtab; cmd->func; cmd++) 22636285Sbrian if (cmd->name && (cmd->lauth & arg->prompt->auth)) { 22736285Sbrian cx = showcx(cmd); 22836285Sbrian cxlen = cmax - strlen(cmd->name); 22940482Sbrian if (n % cols != 0) 23040482Sbrian prompt_Printf(arg->prompt, " "); 23140482Sbrian prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", 23236285Sbrian cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); 23331372Sbrian if (++n % cols == 0) 23436285Sbrian prompt_Printf(arg->prompt, "\n"); 2356059Samurai } 23631372Sbrian if (n % cols != 0) 23736285Sbrian prompt_Printf(arg->prompt, "\n"); 23826516Sbrian 23926516Sbrian return 0; 2406059Samurai} 2416059Samurai 24236285Sbrianstatic int 24336285SbrianCloneCommand(struct cmdargs const *arg) 2446059Samurai{ 24536285Sbrian char namelist[LINE_LEN]; 24636285Sbrian char *name; 24736285Sbrian int f; 2486059Samurai 24936285Sbrian if (arg->argc == arg->argn) 25036285Sbrian return -1; 25136285Sbrian 25236285Sbrian namelist[sizeof namelist - 1] = '\0'; 25336285Sbrian for (f = arg->argn; f < arg->argc; f++) { 25436285Sbrian strncpy(namelist, arg->argv[f], sizeof namelist - 1); 25536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 25636285Sbrian bundle_DatalinkClone(arg->bundle, arg->cx, name); 2576059Samurai } 25836285Sbrian 25936285Sbrian return 0; 2606059Samurai} 2616059Samurai 2626059Samuraistatic int 26336285SbrianRemoveCommand(struct cmdargs const *arg) 2646059Samurai{ 26536285Sbrian if (arg->argc != arg->argn) 26636285Sbrian return -1; 26711336Samurai 26836285Sbrian if (arg->cx->state != DATALINK_CLOSED) { 26936285Sbrian log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n"); 27036285Sbrian return 2; 2716059Samurai } 27226516Sbrian 27336285Sbrian bundle_DatalinkRemove(arg->bundle, arg->cx); 27436285Sbrian return 0; 27536285Sbrian} 27632711Sbrian 27736285Sbrianstatic int 27836285SbrianRenameCommand(struct cmdargs const *arg) 27936285Sbrian{ 28036285Sbrian if (arg->argc != arg->argn + 1) 28136285Sbrian return -1; 28231121Sbrian 28336285Sbrian if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn])) 28436285Sbrian return 0; 28536285Sbrian 28636285Sbrian log_Printf(LogWARN, "%s -> %s: target name already exists\n", 28736285Sbrian arg->cx->name, arg->argv[arg->argn]); 28836285Sbrian return 1; 28936285Sbrian} 29036285Sbrian 29136285Sbrianint 29236285SbrianLoadCommand(struct cmdargs const *arg) 29336285Sbrian{ 29440797Sbrian const char *err; 29540797Sbrian int n, mode; 29636285Sbrian 29740797Sbrian mode = arg->bundle->phys_type.all; 29836285Sbrian 29940797Sbrian if (arg->argn < arg->argc) { 30040797Sbrian for (n = arg->argn; n < arg->argc; n++) 30140797Sbrian if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) { 30240797Sbrian log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err); 30340797Sbrian return 1; 30440797Sbrian } 30540797Sbrian 30640797Sbrian for (n = arg->argn; n < arg->argc; n++) { 30740797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 30840797Sbrian system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx); 30940797Sbrian } 31040797Sbrian bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]); 31140797Sbrian } else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) { 31240797Sbrian log_Printf(LogWARN, "default: %s\n", err); 31336285Sbrian return 1; 31436285Sbrian } else { 31540797Sbrian bundle_SetLabel(arg->bundle, "default"); 31640797Sbrian system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx); 31740797Sbrian bundle_SetLabel(arg->bundle, "default"); 31836285Sbrian } 31940797Sbrian 32026516Sbrian return 0; 3216059Samurai} 3226059Samurai 32336285Sbrianint 32436285SbrianSaveCommand(struct cmdargs const *arg) 32536285Sbrian{ 32636285Sbrian log_Printf(LogWARN, "save command is not implemented (yet).\n"); 32736285Sbrian return 1; 32836285Sbrian} 32936285Sbrian 33010528Samuraistatic int 33136285SbrianDialCommand(struct cmdargs const *arg) 33228536Sbrian{ 33336285Sbrian int res; 33436285Sbrian 33536465Sbrian if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO))) 33636465Sbrian || (!arg->cx && 33736928Sbrian (arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) { 33836285Sbrian log_Printf(LogWARN, "Manual dial is only available for auto and" 33936285Sbrian " interactive links\n"); 34036285Sbrian return 1; 34134536Sbrian } 34236285Sbrian 34336285Sbrian if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0) 34436285Sbrian return res; 34536285Sbrian 34637993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 34736285Sbrian 34836285Sbrian return 0; 34928536Sbrian} 35028536Sbrian 35138628Sbrian#define isinword(ch) (isalnum(ch) || (ch) == '_') 35238628Sbrian 35338628Sbrianstatic char * 35438628Sbrianstrstrword(char *big, const char *little) 35538628Sbrian{ 35638628Sbrian /* Get the first occurance of the word ``little'' in ``big'' */ 35738628Sbrian char *pos; 35838628Sbrian int len; 35938628Sbrian 36038628Sbrian pos = big; 36138628Sbrian len = strlen(little); 36238628Sbrian 36338628Sbrian while ((pos = strstr(pos, little)) != NULL) 36447865Sbrian if ((pos != big && isinword(pos[-1])) || isinword(pos[len])) 36547865Sbrian pos++; 36647865Sbrian else if (pos != big && pos[-1] == '\\') 36747865Sbrian memmove(pos - 1, pos, strlen(pos) + 1); 36847865Sbrian else 36938628Sbrian break; 37038628Sbrian 37138628Sbrian return pos; 37238628Sbrian} 37338628Sbrian 37438628Sbrianstatic char * 37538628Sbriansubst(char *tgt, const char *oldstr, const char *newstr) 37638628Sbrian{ 37738628Sbrian /* tgt is a malloc()d area... realloc() as necessary */ 37838628Sbrian char *word, *ntgt; 37938628Sbrian int ltgt, loldstr, lnewstr, pos; 38038628Sbrian 38138628Sbrian if ((word = strstrword(tgt, oldstr)) == NULL) 38238628Sbrian return tgt; 38338628Sbrian 38438628Sbrian ltgt = strlen(tgt) + 1; 38538628Sbrian loldstr = strlen(oldstr); 38638628Sbrian lnewstr = strlen(newstr); 38738628Sbrian do { 38838628Sbrian pos = word - tgt; 38938628Sbrian if (loldstr > lnewstr) 39038628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 39138628Sbrian if (loldstr != lnewstr) { 39238628Sbrian ntgt = realloc(tgt, ltgt += lnewstr - loldstr); 39338628Sbrian if (ntgt == NULL) 39438628Sbrian break; /* Oh wonderful ! */ 39538628Sbrian word = ntgt + pos; 39638628Sbrian tgt = ntgt; 39738628Sbrian } 39838628Sbrian if (lnewstr > loldstr) 39938628Sbrian bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr); 40038628Sbrian bcopy(newstr, word, lnewstr); 40138628Sbrian } while ((word = strstrword(word, oldstr))); 40238628Sbrian 40338628Sbrian return tgt; 40438628Sbrian} 40538628Sbrian 40643888Sbrianvoid 40743888Sbriancommand_Expand(char **nargv, int argc, char const *const *oargv, 40847849Sbrian struct bundle *bundle, int inc0, pid_t pid) 40938628Sbrian{ 41038628Sbrian int arg; 41147849Sbrian char pidstr[12]; 41238628Sbrian 41341755Sbrian if (inc0) 41441755Sbrian arg = 0; /* Start at arg 0 */ 41541755Sbrian else { 41641755Sbrian nargv[0] = strdup(oargv[0]); 41741755Sbrian arg = 1; 41841755Sbrian } 41947849Sbrian snprintf(pidstr, sizeof pidstr, "%d", (int)pid); 42041755Sbrian for (; arg < argc; arg++) { 42138629Sbrian nargv[arg] = strdup(oargv[arg]); 42238629Sbrian nargv[arg] = subst(nargv[arg], "HISADDR", 42338628Sbrian inet_ntoa(bundle->ncp.ipcp.peer_ip)); 42438629Sbrian nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name); 42540561Sbrian nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name); 42638628Sbrian nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip)); 42738629Sbrian nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname); 42838629Sbrian nargv[arg] = subst(nargv[arg], "PEER_ENDDISC", 42938629Sbrian mp_Enddisc(bundle->ncp.mp.peer.enddisc.class, 43038629Sbrian bundle->ncp.mp.peer.enddisc.address, 43138629Sbrian bundle->ncp.mp.peer.enddisc.len)); 43238629Sbrian nargv[arg] = subst(nargv[arg], "ENDDISC", 43338629Sbrian mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, 43438629Sbrian bundle->ncp.mp.cfg.enddisc.address, 43538629Sbrian bundle->ncp.mp.cfg.enddisc.len)); 43647849Sbrian nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); 43738629Sbrian nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); 43838628Sbrian } 43938628Sbrian nargv[arg] = NULL; 44038628Sbrian} 44138628Sbrian 44228536Sbrianstatic int 44331343SbrianShellCommand(struct cmdargs const *arg, int bg) 44410528Samurai{ 44510528Samurai const char *shell; 44647849Sbrian pid_t shpid, pid; 44720813Sjkh 44818856Ssos#ifdef SHELL_ONLY_INTERACTIVELY 44926911Sbrian /* we're only allowed to shell when we run ppp interactively */ 45036285Sbrian if (arg->prompt && arg->prompt->owner) { 45136285Sbrian log_Printf(LogWARN, "Can't start a shell from a network connection\n"); 45226516Sbrian return 1; 45310528Samurai } 45426911Sbrian#endif 45528679Sbrian 45636285Sbrian if (arg->argc == arg->argn) { 45736285Sbrian if (!arg->prompt) { 45836285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 45936285Sbrian " a config file\n"); 46028381Sbrian return 1; 46136285Sbrian } else if (arg->prompt->owner) { 46236285Sbrian log_Printf(LogWARN, "Can't start an interactive shell from" 46336285Sbrian " a socket connection\n"); 46436285Sbrian return 1; 46528381Sbrian } else if (bg) { 46636285Sbrian log_Printf(LogWARN, "Can only start an interactive shell in" 46728679Sbrian " the foreground mode\n"); 46828381Sbrian return 1; 46928381Sbrian } 47034536Sbrian } 47134536Sbrian 47247849Sbrian pid = getpid(); 47328679Sbrian if ((shpid = fork()) == 0) { 47436285Sbrian int i, fd; 47518531Sbde 47636285Sbrian if ((shell = getenv("SHELL")) == 0) 47736285Sbrian shell = _PATH_BSHELL; 47832017Sbrian 47936285Sbrian timer_TermService(); 48036285Sbrian 48136285Sbrian if (arg->prompt) 48236285Sbrian fd = arg->prompt->fd_out; 48336285Sbrian else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 48436285Sbrian log_Printf(LogALERT, "Failed to open %s: %s\n", 48536285Sbrian _PATH_DEVNULL, strerror(errno)); 48628679Sbrian exit(1); 48728679Sbrian } 48849976Sbrian dup2(fd, STDIN_FILENO); 48949976Sbrian dup2(fd, STDOUT_FILENO); 49049976Sbrian dup2(fd, STDERR_FILENO); 49149976Sbrian for (i = getdtablesize(); i > STDERR_FILENO; i--) 49249976Sbrian fcntl(i, F_SETFD, 1); 49326516Sbrian 49431061Sbrian setuid(geteuid()); 49536285Sbrian if (arg->argc > arg->argn) { 49628679Sbrian /* substitute pseudo args */ 49738628Sbrian char *argv[MAXARGS]; 49838628Sbrian int argc = arg->argc - arg->argn; 49938628Sbrian 50038628Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 50138628Sbrian argc = sizeof argv / sizeof argv[0] - 1; 50238628Sbrian log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); 50331343Sbrian } 50447849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid); 50528679Sbrian if (bg) { 50628679Sbrian pid_t p; 50710528Samurai 50828679Sbrian p = getpid(); 50928679Sbrian if (daemon(1, 1) == -1) { 51036832Sbrian log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno)); 51128679Sbrian exit(1); 51228679Sbrian } 51336285Sbrian } else if (arg->prompt) 51436285Sbrian printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]); 51531343Sbrian execvp(argv[0], argv); 51630316Sbrian } else { 51736285Sbrian if (arg->prompt) 51832017Sbrian printf("ppp: Pausing until %s finishes\n", shell); 51936285Sbrian prompt_TtyOldMode(arg->prompt); 52031343Sbrian execl(shell, shell, NULL); 52130316Sbrian } 52220813Sjkh 52340665Sbrian log_Printf(LogWARN, "exec() of %s failed: %s\n", 52440665Sbrian arg->argc > arg->argn ? arg->argv[arg->argn] : shell, 52540665Sbrian strerror(errno)); 52649976Sbrian _exit(255); 52710528Samurai } 52836285Sbrian 52936285Sbrian if (shpid == (pid_t) - 1) 53036285Sbrian log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno)); 53136285Sbrian else { 53210528Samurai int status; 53331343Sbrian waitpid(shpid, &status, 0); 53410528Samurai } 53520813Sjkh 53636285Sbrian if (arg->prompt && !arg->prompt->owner) 53736285Sbrian prompt_TtyCommandMode(arg->prompt); 53820813Sjkh 53936285Sbrian return 0; 54010528Samurai} 54110528Samurai 54231343Sbrianstatic int 54331343SbrianBgShellCommand(struct cmdargs const *arg) 54431343Sbrian{ 54536285Sbrian if (arg->argc == arg->argn) 54631343Sbrian return -1; 54731343Sbrian return ShellCommand(arg, 1); 54831343Sbrian} 54931343Sbrian 55031343Sbrianstatic int 55131343SbrianFgShellCommand(struct cmdargs const *arg) 55231343Sbrian{ 55331343Sbrian return ShellCommand(arg, 0); 55431343Sbrian} 55531343Sbrian 55650059Sbrian#ifndef NONAT 55740561Sbrianstatic struct cmdtab const AliasCommands[] = 55840561Sbrian{ 55950059Sbrian {"addr", NULL, nat_RedirectAddr, LOCAL_AUTH, 56050059Sbrian "static address translation", "nat addr [addr_local addr_alias]"}, 56140561Sbrian {"deny_incoming", NULL, AliasOption, LOCAL_AUTH, 56250059Sbrian "stop incoming connections", "nat deny_incoming yes|no", 56340561Sbrian (const void *) PKT_ALIAS_DENY_INCOMING}, 56440561Sbrian {"enable", NULL, AliasEnable, LOCAL_AUTH, 56550059Sbrian "enable NAT", "nat enable yes|no"}, 56640561Sbrian {"log", NULL, AliasOption, LOCAL_AUTH, 56750059Sbrian "log NAT link creation", "nat log yes|no", 56840561Sbrian (const void *) PKT_ALIAS_LOG}, 56950059Sbrian {"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection", 57050059Sbrian "nat port proto localaddr:port[-port] aliasport[-aliasport]"}, 57150059Sbrian {"pptp", NULL, nat_Pptp, LOCAL_AUTH, 57250059Sbrian "Set the PPTP address", "nat pptp IP"}, 57350059Sbrian {"proxy", NULL, nat_ProxyRule, LOCAL_AUTH, 57450059Sbrian "proxy control", "nat proxy server host[:port] ..."}, 57540561Sbrian {"same_ports", NULL, AliasOption, LOCAL_AUTH, 57650059Sbrian "try to leave port numbers unchanged", "nat same_ports yes|no", 57740561Sbrian (const void *) PKT_ALIAS_SAME_PORTS}, 57840561Sbrian {"unregistered_only", NULL, AliasOption, LOCAL_AUTH, 57950059Sbrian "translate unregistered (private) IP address space only", 58050059Sbrian "nat unregistered_only yes|no", 58140561Sbrian (const void *) PKT_ALIAS_UNREGISTERED_ONLY}, 58240561Sbrian {"use_sockets", NULL, AliasOption, LOCAL_AUTH, 58350059Sbrian "allocate host sockets", "nat use_sockets yes|no", 58440561Sbrian (const void *) PKT_ALIAS_USE_SOCKETS}, 58540561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 58650059Sbrian "Display this message", "nat help|? [command]", AliasCommands}, 58740561Sbrian {NULL, NULL, NULL}, 58840561Sbrian}; 58940561Sbrian#endif 59040561Sbrian 59140561Sbrianstatic struct cmdtab const AllowCommands[] = { 59240561Sbrian {"modes", "mode", AllowModes, LOCAL_AUTH, 59340561Sbrian "Only allow certain ppp modes", "allow modes mode..."}, 59440561Sbrian {"users", "user", AllowUsers, LOCAL_AUTH, 59540561Sbrian "Only allow ppp access to certain users", "allow users logname..."}, 59640561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 59740561Sbrian "Display this message", "allow help|? [command]", AllowCommands}, 59840561Sbrian {NULL, NULL, NULL}, 59940561Sbrian}; 60040561Sbrian 60140561Sbrianstatic struct cmdtab const IfaceCommands[] = 60240561Sbrian{ 60340561Sbrian {"add", NULL, IfaceAddCommand, LOCAL_AUTH, 60440561Sbrian "Add iface address", "iface add addr[/bits| mask] peer", NULL}, 60540561Sbrian {NULL, "add!", IfaceAddCommand, LOCAL_AUTH, 60640561Sbrian "Add or change an iface address", "iface add! addr[/bits| mask] peer", 60740561Sbrian (void *)1}, 60840561Sbrian {"clear", NULL, IfaceClearCommand, LOCAL_AUTH, 60940561Sbrian "Clear iface address(es)", "iface clear"}, 61040561Sbrian {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH, 61140561Sbrian "Delete iface address", "iface delete addr", NULL}, 61240561Sbrian {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH, 61340561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 61440561Sbrian {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH, 61540561Sbrian "Delete iface address", "iface delete addr", (void *)1}, 61640561Sbrian {"show", NULL, iface_Show, LOCAL_AUTH, 61740561Sbrian "Show iface address(es)", "iface show"}, 61840561Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 61950059Sbrian "Display this message", "nat help|? [command]", IfaceCommands}, 62040561Sbrian {NULL, NULL, NULL}, 62140561Sbrian}; 62240561Sbrian 62330715Sbrianstatic struct cmdtab const Commands[] = { 62436285Sbrian {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 62528679Sbrian "accept option request", "accept option .."}, 62628679Sbrian {"add", NULL, AddCommand, LOCAL_AUTH, 62732109Sbrian "add route", "add dest mask gateway", NULL}, 62836285Sbrian {NULL, "add!", AddCommand, LOCAL_AUTH, 62932109Sbrian "add or change route", "add! dest mask gateway", (void *)1}, 63040561Sbrian {"allow", "auth", RunListCommand, LOCAL_AUTH, 63140561Sbrian "Allow ppp access", "allow users|modes ....", AllowCommands}, 63228679Sbrian {"bg", "!bg", BgShellCommand, LOCAL_AUTH, 63331372Sbrian "Run a background command", "[!]bg command"}, 63436934Sbrian {"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT, 63546686Sbrian "Clear throughput statistics", 63646686Sbrian "clear ipcp|physical [current|overall|peak]..."}, 63736285Sbrian {"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX, 63836285Sbrian "Clone a link", "clone newname..."}, 63936285Sbrian {"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64036285Sbrian "Close an FSM", "close [lcp|ccp]"}, 64128679Sbrian {"delete", NULL, DeleteCommand, LOCAL_AUTH, 64232109Sbrian "delete route", "delete dest", NULL}, 64336285Sbrian {NULL, "delete!", DeleteCommand, LOCAL_AUTH, 64432109Sbrian "delete a route if it exists", "delete! dest", (void *)1}, 64536285Sbrian {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64628679Sbrian "Deny option request", "deny option .."}, 64736285Sbrian {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT, 64840797Sbrian "Dial and login", "dial|call [system ...]", NULL}, 64936285Sbrian {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65028679Sbrian "Disable option", "disable option .."}, 65136285Sbrian {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65246686Sbrian "Generate a down event", "down [ccp|lcp]"}, 65336285Sbrian {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT, 65428679Sbrian "Enable option", "enable option .."}, 65540561Sbrian {"iface", "interface", RunListCommand, LOCAL_AUTH, 65640561Sbrian "interface control", "iface option ...", IfaceCommands}, 65736285Sbrian {"link", "datalink", LinkCommand, LOCAL_AUTH, 65836285Sbrian "Link specific commands", "link name command ..."}, 65937008Sbrian {"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66040797Sbrian "Load settings", "load [system ...]"}, 66150059Sbrian#ifndef NONAT 66250059Sbrian {"nat", "alias", RunListCommand, LOCAL_AUTH, 66350059Sbrian "NAT control", "nat option yes|no", AliasCommands}, 66450059Sbrian#endif 66536285Sbrian {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT, 66637955Sbrian "Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1}, 66736285Sbrian {"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH, 66836285Sbrian "Password for manipulation", "passwd LocalPassword"}, 66936285Sbrian {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 67036285Sbrian "Quit PPP program", "quit|bye [all]"}, 67136285Sbrian {"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX, 67236285Sbrian "Remove a link", "remove"}, 67336285Sbrian {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, 67436285Sbrian "Rename a link", "rename name"}, 67528679Sbrian {"save", NULL, SaveCommand, LOCAL_AUTH, 67628679Sbrian "Save settings", "save"}, 67736285Sbrian {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, 67828679Sbrian "Set parameters", "set[up] var value"}, 67928679Sbrian {"shell", "!", FgShellCommand, LOCAL_AUTH, 68028679Sbrian "Run a subshell", "shell|! [sh command]"}, 68136285Sbrian {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT, 68231372Sbrian "Show status and stats", "show var"}, 68336285Sbrian {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX, 68431372Sbrian "Enter terminal mode", "term"}, 68528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 68631343Sbrian "Display this message", "help|? [command]", Commands}, 68728679Sbrian {NULL, NULL, NULL}, 6886059Samurai}; 6896059Samurai 69028536Sbrianstatic int 69131343SbrianShowEscape(struct cmdargs const *arg) 6926059Samurai{ 69336285Sbrian if (arg->cx->physical->async.cfg.EscMap[32]) { 69436285Sbrian int code, bit; 69536285Sbrian const char *sep = ""; 6966059Samurai 69726516Sbrian for (code = 0; code < 32; code++) 69836285Sbrian if (arg->cx->physical->async.cfg.EscMap[code]) 69928679Sbrian for (bit = 0; bit < 8; bit++) 70036285Sbrian if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) { 70136285Sbrian prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit); 70236285Sbrian sep = ", "; 70336285Sbrian } 70436285Sbrian prompt_Printf(arg->prompt, "\n"); 7056059Samurai } 70631077Sbrian return 0; 7076059Samurai} 7086059Samurai 70928679Sbrianstatic int 71036285SbrianShowTimerList(struct cmdargs const *arg) 7116059Samurai{ 71236285Sbrian timer_Show(0, arg->prompt); 71331077Sbrian return 0; 7146059Samurai} 7156059Samurai 71628679Sbrianstatic int 71731343SbrianShowStopped(struct cmdargs const *arg) 71828327Sbrian{ 71936285Sbrian prompt_Printf(arg->prompt, " Stopped Timer: LCP: "); 72036285Sbrian if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load) 72136285Sbrian prompt_Printf(arg->prompt, "Disabled"); 72228327Sbrian else 72336285Sbrian prompt_Printf(arg->prompt, "%ld secs", 72436285Sbrian arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS); 72528461Sbrian 72636285Sbrian prompt_Printf(arg->prompt, ", CCP: "); 72736285Sbrian if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load) 72836285Sbrian prompt_Printf(arg->prompt, "Disabled"); 72928461Sbrian else 73036285Sbrian prompt_Printf(arg->prompt, "%ld secs", 73136285Sbrian arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS); 73228461Sbrian 73336285Sbrian prompt_Printf(arg->prompt, "\n"); 73428461Sbrian 73531077Sbrian return 0; 73628327Sbrian} 73728327Sbrian 73828679Sbrianstatic int 73931343SbrianShowVersion(struct cmdargs const *arg) 7406059Samurai{ 74151026Sbrian prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__); 74231077Sbrian return 0; 7436059Samurai} 7446059Samurai 74528679Sbrianstatic int 74636285SbrianShowProtocolStats(struct cmdargs const *arg) 74726326Sbrian{ 74836285Sbrian struct link *l = command_ChooseLink(arg); 74926326Sbrian 75036285Sbrian prompt_Printf(arg->prompt, "%s:\n", l->name); 75136285Sbrian link_ReportProtocolStatus(l, arg->prompt); 75231077Sbrian return 0; 75326326Sbrian} 75426326Sbrian 75530715Sbrianstatic struct cmdtab const ShowCommands[] = { 75636285Sbrian {"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH, 75736285Sbrian "bundle details", "show bundle"}, 75836285Sbrian {"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, 75936285Sbrian "CCP status", "show cpp"}, 76036285Sbrian {"compress", NULL, sl_Show, LOCAL_AUTH, 76136285Sbrian "VJ compression stats", "show compress"}, 76236285Sbrian {"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX, 76336285Sbrian "escape characters", "show escape"}, 76436285Sbrian {"filter", NULL, filter_Show, LOCAL_AUTH, 76536285Sbrian "packet filters", "show filter [in|out|dial|alive]"}, 76636285Sbrian {"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX, 76736285Sbrian "HDLC errors", "show hdlc"}, 76840561Sbrian {"iface", "interface", iface_Show, LOCAL_AUTH, 76940561Sbrian "Interface status", "show iface"}, 77036285Sbrian {"ipcp", NULL, ipcp_Show, LOCAL_AUTH, 77136285Sbrian "IPCP status", "show ipcp"}, 77247211Sbrian {"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT, 77347211Sbrian "Protocol layers", "show layers"}, 77436285Sbrian {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, 77536285Sbrian "LCP status", "show lcp"}, 77636285Sbrian {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, 77736285Sbrian "(high-level) link info", "show link"}, 77836285Sbrian {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, 77936285Sbrian "available link names", "show links"}, 78036285Sbrian {"log", NULL, log_ShowLevel, LOCAL_AUTH, 78136285Sbrian "log levels", "show log"}, 78236285Sbrian {"mem", NULL, mbuf_Show, LOCAL_AUTH, 78336285Sbrian "mbuf allocations", "show mem"}, 78446686Sbrian {"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX, 78546686Sbrian "(low-level) link info", "show physical"}, 78636285Sbrian {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, 78736285Sbrian "multilink setup", "show mp"}, 78836285Sbrian {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, 78936285Sbrian "protocol summary", "show proto"}, 79036285Sbrian {"route", NULL, route_Show, LOCAL_AUTH, 79136285Sbrian "routing table", "show route"}, 79236285Sbrian {"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX, 79336285Sbrian "STOPPED timeout", "show stopped"}, 79436285Sbrian {"timers", NULL, ShowTimerList, LOCAL_AUTH, 79536285Sbrian "alarm timers", "show timers"}, 79628679Sbrian {"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH, 79736285Sbrian "version string", "show version"}, 79836285Sbrian {"who", NULL, log_ShowWho, LOCAL_AUTH, 79936285Sbrian "client list", "show who"}, 80028679Sbrian {"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH, 80131343Sbrian "Display this message", "show help|? [command]", ShowCommands}, 80228679Sbrian {NULL, NULL, NULL}, 8036059Samurai}; 8046059Samurai 80530715Sbrianstatic struct cmdtab const * 80631343SbrianFindCommand(struct cmdtab const *cmds, const char *str, int *pmatch) 8076059Samurai{ 80826516Sbrian int nmatch; 80926516Sbrian int len; 81028679Sbrian struct cmdtab const *found; 8116059Samurai 81226516Sbrian found = NULL; 81326516Sbrian len = strlen(str); 81426516Sbrian nmatch = 0; 8156059Samurai while (cmds->func) { 81625566Sbrian if (cmds->name && strncasecmp(str, cmds->name, len) == 0) { 81726516Sbrian if (cmds->name[len] == '\0') { 81828679Sbrian *pmatch = 1; 81928679Sbrian return cmds; 82026516Sbrian } 8216059Samurai nmatch++; 8226059Samurai found = cmds; 82328679Sbrian } else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) { 82426516Sbrian if (cmds->alias[len] == '\0') { 82528679Sbrian *pmatch = 1; 82628679Sbrian return cmds; 82726516Sbrian } 8286059Samurai nmatch++; 8296059Samurai found = cmds; 8306059Samurai } 8316059Samurai cmds++; 8326059Samurai } 8336059Samurai *pmatch = nmatch; 83426516Sbrian return found; 8356059Samurai} 8366059Samurai 83736285Sbrianstatic const char * 83836285SbrianmkPrefix(int argc, char const *const *argv, char *tgt, int sz) 83936285Sbrian{ 84036285Sbrian int f, tlen, len; 84136285Sbrian 84236285Sbrian tlen = 0; 84336285Sbrian for (f = 0; f < argc && tlen < sz - 2; f++) { 84436285Sbrian if (f) 84536285Sbrian tgt[tlen++] = ' '; 84636285Sbrian len = strlen(argv[f]); 84736285Sbrian if (len > sz - tlen - 1) 84836285Sbrian len = sz - tlen - 1; 84936285Sbrian strncpy(tgt+tlen, argv[f], len); 85036285Sbrian tlen += len; 85136285Sbrian } 85236285Sbrian tgt[tlen] = '\0'; 85336285Sbrian return tgt; 85436285Sbrian} 85536285Sbrian 85630715Sbrianstatic int 85736285SbrianFindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn, 85836285Sbrian char const *const *argv, struct prompt *prompt, struct datalink *cx) 8596059Samurai{ 86028679Sbrian struct cmdtab const *cmd; 8616059Samurai int val = 1; 8626059Samurai int nmatch; 86331343Sbrian struct cmdargs arg; 86436285Sbrian char prefix[100]; 8656059Samurai 86636285Sbrian cmd = FindCommand(cmds, argv[argn], &nmatch); 8676059Samurai if (nmatch > 1) 86836285Sbrian log_Printf(LogWARN, "%s: Ambiguous command\n", 86936285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 87036285Sbrian else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) { 87136285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 87236285Sbrian /* We've got no context, but we require it */ 87336285Sbrian cx = bundle2datalink(bundle, NULL); 87436285Sbrian 87536285Sbrian if ((cmd->lauth & LOCAL_CX) && !cx) 87636285Sbrian log_Printf(LogWARN, "%s: No context (use the `link' command)\n", 87736285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 87836285Sbrian else { 87936285Sbrian if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 88036285Sbrian log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n", 88136285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name); 88236285Sbrian cx = NULL; 88336285Sbrian } 88436285Sbrian arg.cmdtab = cmds; 88536285Sbrian arg.cmd = cmd; 88636285Sbrian arg.argc = argc; 88736285Sbrian arg.argn = argn+1; 88836285Sbrian arg.argv = argv; 88936285Sbrian arg.bundle = bundle; 89036285Sbrian arg.cx = cx; 89136285Sbrian arg.prompt = prompt; 89236285Sbrian val = (*cmd->func) (&arg); 89336285Sbrian } 89431343Sbrian } else 89536285Sbrian log_Printf(LogWARN, "%s: Invalid command\n", 89636285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix)); 89726516Sbrian 89826516Sbrian if (val == -1) 89936285Sbrian log_Printf(LogWARN, "Usage: %s\n", cmd->syntax); 90028679Sbrian else if (val) 90136285Sbrian log_Printf(LogWARN, "%s: Failed %d\n", 90236285Sbrian mkPrefix(argn+1, argv, prefix, sizeof prefix), val); 90326516Sbrian 90426516Sbrian return val; 9056059Samurai} 9066059Samurai 90737009Sbrianint 90837009Sbriancommand_Interpret(char *buff, int nb, char *argv[MAXARGS]) 9096059Samurai{ 9106059Samurai char *cp; 9116059Samurai 9126059Samurai if (nb > 0) { 9136059Samurai cp = buff + strcspn(buff, "\r\n"); 9146059Samurai if (cp) 9156059Samurai *cp = '\0'; 91637009Sbrian return MakeArgs(buff, argv, MAXARGS); 91737009Sbrian } 91837009Sbrian return 0; 91931121Sbrian} 9206059Samurai 92131822Sbrianstatic int 92231822Sbrianarghidden(int argc, char const *const *argv, int n) 92331822Sbrian{ 92431822Sbrian /* Is arg n of the given command to be hidden from the log ? */ 92531828Sbrian 92631828Sbrian /* set authkey xxxxx */ 92731828Sbrian /* set key xxxxx */ 92831822Sbrian if (n == 2 && !strncasecmp(argv[0], "se", 2) && 92931822Sbrian (!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2))) 93031822Sbrian return 1; 93131822Sbrian 93231828Sbrian /* passwd xxxxx */ 93331828Sbrian if (n == 1 && !strncasecmp(argv[0], "p", 1)) 93431828Sbrian return 1; 93531828Sbrian 93636285Sbrian /* set server port xxxxx .... */ 93736285Sbrian if (n == 3 && !strncasecmp(argv[0], "se", 2) && 93836285Sbrian !strncasecmp(argv[1], "se", 2)) 93936285Sbrian return 1; 94036285Sbrian 94131822Sbrian return 0; 94231822Sbrian} 94331822Sbrian 94431121Sbrianvoid 94536285Sbriancommand_Run(struct bundle *bundle, int argc, char const *const *argv, 94637008Sbrian struct prompt *prompt, const char *label, struct datalink *cx) 94731121Sbrian{ 94831156Sbrian if (argc > 0) { 94936285Sbrian if (log_IsKept(LogCOMMAND)) { 95047844Sbrian char buf[LINE_LEN]; 95131156Sbrian int f, n; 95231156Sbrian 95331156Sbrian if (label) { 95431962Sbrian strncpy(buf, label, sizeof buf - 3); 95531962Sbrian buf[sizeof buf - 3] = '\0'; 95631156Sbrian strcat(buf, ": "); 95747844Sbrian n = strlen(buf); 95847844Sbrian } else { 95947844Sbrian *buf = '\0'; 96047844Sbrian n = 0; 96131156Sbrian } 96247844Sbrian buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */ 96347844Sbrian 96431156Sbrian for (f = 0; f < argc; f++) { 96531962Sbrian if (n < sizeof buf - 1 && f) 96631156Sbrian buf[n++] = ' '; 96731822Sbrian if (arghidden(argc, argv, f)) 96836285Sbrian strncpy(buf+n, "********", sizeof buf - n - 1); 96931822Sbrian else 97031962Sbrian strncpy(buf+n, argv[f], sizeof buf - n - 1); 97131156Sbrian n += strlen(buf+n); 97231156Sbrian } 97336285Sbrian log_Printf(LogCOMMAND, "%s\n", buf); 97431156Sbrian } 97537008Sbrian FindExec(bundle, Commands, argc, 0, argv, prompt, cx); 97631156Sbrian } 9776059Samurai} 9786059Samurai 97931121Sbrianvoid 98036285Sbriancommand_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt, 98136285Sbrian const char *label) 98231121Sbrian{ 98331121Sbrian int argc; 98437009Sbrian char *argv[MAXARGS]; 98531121Sbrian 98637009Sbrian argc = command_Interpret(buff, nb, argv); 98737008Sbrian command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL); 98831121Sbrian} 98931121Sbrian 9906059Samuraistatic int 99131343SbrianShowCommand(struct cmdargs const *arg) 9926059Samurai{ 99336285Sbrian if (!arg->prompt) 99436285Sbrian log_Printf(LogWARN, "show: Cannot show without a prompt\n"); 99536285Sbrian else if (arg->argc > arg->argn) 99636285Sbrian FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv, 99736285Sbrian arg->prompt, arg->cx); 9986059Samurai else 99936285Sbrian prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n"); 100026516Sbrian 100126516Sbrian return 0; 10026059Samurai} 10036059Samurai 10046059Samuraistatic int 100531343SbrianTerminalCommand(struct cmdargs const *arg) 10066059Samurai{ 100736285Sbrian if (!arg->prompt) { 100836285Sbrian log_Printf(LogWARN, "term: Need a prompt\n"); 100926516Sbrian return 1; 10106059Samurai } 101136285Sbrian 101236285Sbrian if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) { 101336285Sbrian prompt_Printf(arg->prompt, "LCP state is [%s]\n", 101436285Sbrian State2Nam(arg->cx->physical->link.lcp.fsm.state)); 101536285Sbrian return 1; 10166059Samurai } 101736285Sbrian 101836285Sbrian datalink_Up(arg->cx, 0, 0); 101936285Sbrian prompt_TtyTermMode(arg->prompt, arg->cx); 102036285Sbrian return 0; 10216059Samurai} 10226059Samurai 10236059Samuraistatic int 102431343SbrianQuitCommand(struct cmdargs const *arg) 10256059Samurai{ 102636285Sbrian if (!arg->prompt || prompt_IsController(arg->prompt) || 102736285Sbrian (arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") && 102836285Sbrian (arg->prompt->auth & LOCAL_AUTH))) 102936285Sbrian Cleanup(EX_NORMAL); 103036285Sbrian if (arg->prompt) 103136285Sbrian prompt_Destroy(arg->prompt, 1); 103226516Sbrian 103326516Sbrian return 0; 10346059Samurai} 10356059Samurai 10366059Samuraistatic int 103736285SbrianOpenCommand(struct cmdargs const *arg) 10386059Samurai{ 103937160Sbrian if (arg->argc == arg->argn) 104037993Sbrian bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1); 104137160Sbrian else if (arg->argc == arg->argn + 1) { 104237160Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 104337385Sbrian struct datalink *cx = arg->cx ? 104437385Sbrian arg->cx : bundle2datalink(arg->bundle, NULL); 104537385Sbrian if (cx) { 104637385Sbrian if (cx->physical->link.lcp.fsm.state == ST_OPENED) 104737385Sbrian fsm_Reopen(&cx->physical->link.lcp.fsm); 104837160Sbrian else 104937993Sbrian bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1); 105037160Sbrian } else 105137160Sbrian log_Printf(LogWARN, "open lcp: You must specify a link\n"); 105237160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 105337160Sbrian struct fsm *fp; 10546059Samurai 105537210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 105637160Sbrian if (fp->link->lcp.fsm.state != ST_OPENED) 105737160Sbrian log_Printf(LogWARN, "open: LCP must be open before opening CCP\n"); 105837160Sbrian else if (fp->state == ST_OPENED) 105937160Sbrian fsm_Reopen(fp); 106037160Sbrian else { 106137160Sbrian fp->open_mode = 0; /* Not passive any more */ 106237160Sbrian if (fp->state == ST_STOPPED) { 106337160Sbrian fsm_Down(fp); 106437160Sbrian fsm_Up(fp); 106537160Sbrian } else { 106637160Sbrian fsm_Up(fp); 106737160Sbrian fsm_Open(fp); 106837160Sbrian } 106936285Sbrian } 107037160Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) { 107137160Sbrian if (arg->cx) 107237160Sbrian log_Printf(LogWARN, "open ipcp: You need not specify a link\n"); 107337160Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 107437160Sbrian fsm_Reopen(&arg->bundle->ncp.ipcp.fsm); 107537160Sbrian else 107637993Sbrian bundle_Open(arg->bundle, NULL, PHYS_ALL, 1); 107737160Sbrian } else 107837160Sbrian return -1; 107936285Sbrian } else 108036285Sbrian return -1; 108136285Sbrian 108226516Sbrian return 0; 10836059Samurai} 10846059Samurai 108525067Sbrianstatic int 108636285SbrianCloseCommand(struct cmdargs const *arg) 10876059Samurai{ 108837007Sbrian if (arg->argc == arg->argn) 108937007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN); 109037007Sbrian else if (arg->argc == arg->argn + 1) { 109137007Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) 109237007Sbrian bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP); 109337007Sbrian else if (!strcasecmp(arg->argv[arg->argn], "ccp") || 109437007Sbrian !strcasecmp(arg->argv[arg->argn], "ccp!")) { 109537007Sbrian struct fsm *fp; 10966059Samurai 109737210Sbrian fp = &command_ChooseLink(arg)->ccp.fsm; 109837007Sbrian if (fp->state == ST_OPENED) { 109937007Sbrian fsm_Close(fp); 110037007Sbrian if (arg->argv[arg->argn][3] == '!') 110137007Sbrian fp->open_mode = 0; /* Stay ST_CLOSED */ 110237007Sbrian else 110337007Sbrian fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */ 110437007Sbrian } 110537007Sbrian } else 110636285Sbrian return -1; 110736285Sbrian } else 110836285Sbrian return -1; 110936285Sbrian 111036285Sbrian return 0; 11116059Samurai} 11126059Samurai 111325067Sbrianstatic int 111436285SbrianDownCommand(struct cmdargs const *arg) 111511336Samurai{ 111637018Sbrian if (arg->argc == arg->argn) { 111737018Sbrian if (arg->cx) 111837018Sbrian datalink_Down(arg->cx, CLOSE_STAYDOWN); 111937018Sbrian else 112037018Sbrian bundle_Down(arg->bundle, CLOSE_STAYDOWN); 112137018Sbrian } else if (arg->argc == arg->argn + 1) { 112237018Sbrian if (!strcasecmp(arg->argv[arg->argn], "lcp")) { 112337018Sbrian if (arg->cx) 112437018Sbrian datalink_Down(arg->cx, CLOSE_LCP); 112537018Sbrian else 112637018Sbrian bundle_Down(arg->bundle, CLOSE_LCP); 112737018Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "ccp")) { 112837018Sbrian struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm : 112937018Sbrian &arg->bundle->ncp.mp.link.ccp.fsm; 113037060Sbrian fsm2initial(fp); 113137018Sbrian } else 113237018Sbrian return -1; 113336285Sbrian } else 113436285Sbrian return -1; 113536285Sbrian 113636285Sbrian return 0; 113725067Sbrian} 113825067Sbrian 113925067Sbrianstatic int 114036285SbrianSetModemSpeed(struct cmdargs const *arg) 114125067Sbrian{ 114236285Sbrian long speed; 114336285Sbrian char *end; 114411336Samurai 114536285Sbrian if (arg->argc > arg->argn && *arg->argv[arg->argn]) { 114636285Sbrian if (arg->argc > arg->argn+1) { 114736285Sbrian log_Printf(LogWARN, "SetModemSpeed: Too many arguments"); 114836285Sbrian return -1; 114911336Samurai } 115036285Sbrian if (strcasecmp(arg->argv[arg->argn], "sync") == 0) { 115136285Sbrian physical_SetSync(arg->cx->physical); 115236285Sbrian return 0; 115336285Sbrian } 115436285Sbrian end = NULL; 115536285Sbrian speed = strtol(arg->argv[arg->argn], &end, 10); 115636285Sbrian if (*end) { 115736285Sbrian log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"", 115836285Sbrian arg->argv[arg->argn]); 115936285Sbrian return -1; 116036285Sbrian } 116136285Sbrian if (physical_SetSpeed(arg->cx->physical, speed)) 116236285Sbrian return 0; 116336285Sbrian log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]); 116436285Sbrian } else 116536285Sbrian log_Printf(LogWARN, "SetModemSpeed: No speed specified\n"); 116624939Sbrian 116726516Sbrian return -1; 116811336Samurai} 116911336Samurai 117025067Sbrianstatic int 117131343SbrianSetStoppedTimeout(struct cmdargs const *arg) 117228327Sbrian{ 117336285Sbrian struct link *l = &arg->cx->physical->link; 117436285Sbrian 117536285Sbrian l->lcp.fsm.StoppedTimer.load = 0; 117636285Sbrian l->ccp.fsm.StoppedTimer.load = 0; 117736285Sbrian if (arg->argc <= arg->argn+2) { 117836285Sbrian if (arg->argc > arg->argn) { 117936285Sbrian l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS; 118036285Sbrian if (arg->argc > arg->argn+1) 118136285Sbrian l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS; 118228461Sbrian } 118328327Sbrian return 0; 118428327Sbrian } 118528327Sbrian return -1; 118628327Sbrian} 118728327Sbrian 118828327Sbrianstatic int 118931343SbrianSetServer(struct cmdargs const *arg) 119026940Sbrian{ 119126940Sbrian int res = -1; 119226940Sbrian 119336285Sbrian if (arg->argc > arg->argn && arg->argc < arg->argn+4) { 119431081Sbrian const char *port, *passwd, *mask; 119553125Sbrian int mlen; 119631081Sbrian 119731081Sbrian /* What's what ? */ 119836285Sbrian port = arg->argv[arg->argn]; 119936285Sbrian if (arg->argc == arg->argn + 2) { 120036285Sbrian passwd = arg->argv[arg->argn+1]; 120136285Sbrian mask = NULL; 120236285Sbrian } else if (arg->argc == arg->argn + 3) { 120336285Sbrian passwd = arg->argv[arg->argn+1]; 120436285Sbrian mask = arg->argv[arg->argn+2]; 120553125Sbrian mlen = strlen(mask); 120653125Sbrian if (mlen == 0 || mlen > 4 || strspn(mask, "01234567") != mlen || 120753125Sbrian (mlen == 4 && *mask != '0')) { 120853125Sbrian log_Printf(LogWARN, "%s %s: %s: Invalid mask\n", 120953125Sbrian arg->argv[arg->argn - 2], arg->argv[arg->argn - 1], mask); 121031081Sbrian return -1; 121153125Sbrian } 121236285Sbrian } else if (strcasecmp(port, "none") == 0) { 121336285Sbrian if (server_Close(arg->bundle)) 121436285Sbrian log_Printf(LogPHASE, "Disabled server port.\n"); 121536285Sbrian return 0; 121631081Sbrian } else 121736285Sbrian return -1; 121831081Sbrian 121936285Sbrian strncpy(server.passwd, passwd, sizeof server.passwd - 1); 122036285Sbrian server.passwd[sizeof server.passwd - 1] = '\0'; 122131081Sbrian 122236285Sbrian if (*port == '/') { 122331081Sbrian mode_t imask; 122436285Sbrian char *ptr, name[LINE_LEN + 12]; 122528679Sbrian 122653125Sbrian if (mask == NULL) 122731081Sbrian imask = (mode_t)-1; 122853125Sbrian else for (imask = mlen = 0; mask[mlen]; mlen++) 122953125Sbrian imask = (imask * 8) + mask[mlen] - '0'; 123036285Sbrian 123136285Sbrian ptr = strstr(port, "%d"); 123236285Sbrian if (ptr) { 123336285Sbrian snprintf(name, sizeof name, "%.*s%d%s", 123437210Sbrian (int)(ptr - port), port, arg->bundle->unit, ptr + 2); 123536285Sbrian port = name; 123636285Sbrian } 123736285Sbrian res = server_LocalOpen(arg->bundle, port, imask); 123827346Sbrian } else { 123936285Sbrian int iport, add = 0; 124028679Sbrian 124131081Sbrian if (mask != NULL) 124231081Sbrian return -1; 124328679Sbrian 124436285Sbrian if (*port == '+') { 124536285Sbrian port++; 124636285Sbrian add = 1; 124736285Sbrian } 124831081Sbrian if (strspn(port, "0123456789") != strlen(port)) { 124931081Sbrian struct servent *s; 125031081Sbrian 125131081Sbrian if ((s = getservbyname(port, "tcp")) == NULL) { 125231081Sbrian iport = 0; 125336285Sbrian log_Printf(LogWARN, "%s: Invalid port or service\n", port); 125428679Sbrian } else 125531081Sbrian iport = ntohs(s->s_port); 125627346Sbrian } else 125731081Sbrian iport = atoi(port); 125836285Sbrian 125936285Sbrian if (iport) { 126036285Sbrian if (add) 126136285Sbrian iport += arg->bundle->unit; 126236285Sbrian res = server_TcpOpen(arg->bundle, iport); 126336285Sbrian } else 126436285Sbrian res = -1; 126527346Sbrian } 126631081Sbrian } 126726940Sbrian 126826940Sbrian return res; 126926940Sbrian} 127026940Sbrian 127126940Sbrianstatic int 127231343SbrianSetEscape(struct cmdargs const *arg) 12736059Samurai{ 12746059Samurai int code; 127536285Sbrian int argc = arg->argc - arg->argn; 127636285Sbrian char const *const *argv = arg->argv + arg->argn; 12776059Samurai 12786059Samurai for (code = 0; code < 33; code++) 127936285Sbrian arg->cx->physical->async.cfg.EscMap[code] = 0; 128031343Sbrian 12816059Samurai while (argc-- > 0) { 12826059Samurai sscanf(*argv++, "%x", &code); 12836059Samurai code &= 0xff; 128436285Sbrian arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7)); 128536285Sbrian arg->cx->physical->async.cfg.EscMap[32] = 1; 12866059Samurai } 128726516Sbrian return 0; 12886059Samurai} 12896059Samurai 12906059Samuraistatic int 129131343SbrianSetInterfaceAddr(struct cmdargs const *arg) 12926059Samurai{ 129336285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 129432267Sbrian const char *hisaddr; 129532267Sbrian 129640561Sbrian if (arg->argc > arg->argn + 4) 129740561Sbrian return -1; 129840561Sbrian 129932267Sbrian hisaddr = NULL; 130044874Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 130144874Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 130236285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 130336285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 130436285Sbrian iplist_reset(&ipcp->cfg.peer_list); 130528394Sbrian 130636285Sbrian if (arg->argc > arg->argn) { 130743313Sbrian if (!ParseAddr(ipcp, arg->argv[arg->argn], 130836285Sbrian &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask, 130936285Sbrian &ipcp->cfg.my_range.width)) 131028679Sbrian return 1; 131136285Sbrian if (arg->argc > arg->argn+1) { 131236285Sbrian hisaddr = arg->argv[arg->argn+1]; 131336285Sbrian if (arg->argc > arg->argn+2) { 131444455Sbrian ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]); 131536285Sbrian if (arg->argc > arg->argn+3) { 131636285Sbrian ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]); 131736285Sbrian ipcp->cfg.HaveTriggerAddress = 1; 13189440Samurai } 13196059Samurai } 13206059Samurai } 13216059Samurai } 132228394Sbrian 132340561Sbrian /* 0.0.0.0 means any address (0 bits) */ 132436285Sbrian if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) { 132536285Sbrian ipcp->cfg.my_range.mask.s_addr = INADDR_ANY; 132636285Sbrian ipcp->cfg.my_range.width = 0; 13276059Samurai } 132836285Sbrian ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr; 132947648Sbrian bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL); 133036285Sbrian 133136285Sbrian if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr, 133236928Sbrian arg->bundle->phys_type.all & PHYS_AUTO)) 133332267Sbrian return 4; 133431121Sbrian 133526516Sbrian return 0; 13366059Samurai} 13376059Samurai 133818752Sjkhstatic int 133944305SbrianSetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq, 134044305Sbrian u_int *maxtrm, int def) 134144305Sbrian{ 134244305Sbrian if (argc == 0) { 134344305Sbrian *timeout = DEF_FSMRETRY; 134444305Sbrian *maxreq = def; 134544305Sbrian if (maxtrm != NULL) 134644305Sbrian *maxtrm = def; 134744305Sbrian } else { 134844305Sbrian long l = atol(argv[0]); 134944305Sbrian 135044305Sbrian if (l < MIN_FSMRETRY) { 135144305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n", 135244305Sbrian l, MIN_FSMRETRY); 135344305Sbrian return 1; 135444305Sbrian } else 135544305Sbrian *timeout = l; 135644305Sbrian 135744305Sbrian if (argc > 1) { 135844305Sbrian l = atol(argv[1]); 135944305Sbrian if (l < 1) { 136044305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l); 136144305Sbrian l = 1; 136244305Sbrian } 136344305Sbrian *maxreq = l; 136444305Sbrian 136544305Sbrian if (argc > 2 && maxtrm != NULL) { 136644305Sbrian l = atol(argv[2]); 136744305Sbrian if (l < 1) { 136844305Sbrian log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l); 136944305Sbrian l = 1; 137044305Sbrian } 137144305Sbrian *maxtrm = l; 137244305Sbrian } 137344305Sbrian } 137444305Sbrian } 137544305Sbrian 137644305Sbrian return 0; 137744305Sbrian} 137844305Sbrian 137944305Sbrianstatic int 138031343SbrianSetVariable(struct cmdargs const *arg) 13816059Samurai{ 138237210Sbrian long long_val, param = (long)arg->cmd->args; 138351048Sbrian int mode, dummyint, f, first; 138431343Sbrian const char *argp; 138536285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 138636285Sbrian const char *err = NULL; 138736285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 138836285Sbrian struct in_addr dummyaddr, *addr; 13896059Samurai 139036285Sbrian if (arg->argc > arg->argn) 139136285Sbrian argp = arg->argv[arg->argn]; 139226551Sbrian else 139331343Sbrian argp = ""; 139426551Sbrian 139536285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 139636285Sbrian log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", 139736285Sbrian arg->cmd->name); 139836285Sbrian return 1; 139936285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 140036285Sbrian log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n", 140136285Sbrian arg->cmd->name, cx->name); 140236285Sbrian cx = NULL; 140336285Sbrian } 140436285Sbrian 140526551Sbrian switch (param) { 140628679Sbrian case VAR_AUTHKEY: 140750139Sbrian strncpy(arg->bundle->cfg.auth.key, argp, 140850139Sbrian sizeof arg->bundle->cfg.auth.key - 1); 140950139Sbrian arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; 141028679Sbrian break; 141137210Sbrian 141228679Sbrian case VAR_AUTHNAME: 141340622Sbrian switch (bundle_Phase(arg->bundle)) { 141440622Sbrian case PHASE_DEAD: 141540622Sbrian case PHASE_ESTABLISH: 141640622Sbrian strncpy(arg->bundle->cfg.auth.name, argp, 141740622Sbrian sizeof arg->bundle->cfg.auth.name - 1); 141840622Sbrian arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; 141940622Sbrian break; 142040622Sbrian default: 142140622Sbrian err = "set authname: Only available at phase DEAD/ESTABLISH\n"; 142240622Sbrian log_Printf(LogWARN, err); 142340622Sbrian break; 142436285Sbrian } 142528679Sbrian break; 142637210Sbrian 142736285Sbrian case VAR_AUTOLOAD: 142849434Sbrian if (arg->argc == arg->argn + 3) { 142949434Sbrian int v1, v2, v3; 143049434Sbrian char *end; 143149434Sbrian 143249434Sbrian v1 = strtol(arg->argv[arg->argn], &end, 0); 143349434Sbrian if (v1 < 0 || *end) { 143449434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", 143549434Sbrian arg->argv[arg->argn]); 143649434Sbrian return 1; 143736285Sbrian } 143849434Sbrian 143949434Sbrian v2 = strtol(arg->argv[arg->argn + 1], &end, 0); 144049434Sbrian if (v2 < 0 || *end) { 144149434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", 144249434Sbrian arg->argv[arg->argn + 1]); 144349434Sbrian return 1; 144449434Sbrian } 144549434Sbrian if (v2 < v1) { 144649434Sbrian v3 = v1; 144749434Sbrian v1 = v2; 144849434Sbrian v2 = v3; 144949434Sbrian } 145049434Sbrian 145149434Sbrian v3 = strtol(arg->argv[arg->argn + 2], &end, 0); 145249434Sbrian if (v3 <= 0 || *end) { 145349434Sbrian log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", 145449434Sbrian arg->argv[arg->argn + 2]); 145549434Sbrian return 1; 145649434Sbrian } 145749434Sbrian 145849434Sbrian arg->bundle->ncp.mp.cfg.autoload.min = v1; 145949434Sbrian arg->bundle->ncp.mp.cfg.autoload.max = v2; 146049434Sbrian arg->bundle->ncp.mp.cfg.autoload.period = v3; 146149434Sbrian mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); 146236285Sbrian } else { 146349434Sbrian err = "Set autoload requires three arguments\n"; 146436285Sbrian log_Printf(LogWARN, err); 146536285Sbrian } 146636285Sbrian break; 146737210Sbrian 146828679Sbrian case VAR_DIAL: 146936285Sbrian strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1); 147036285Sbrian cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0'; 147128679Sbrian break; 147237210Sbrian 147328679Sbrian case VAR_LOGIN: 147436285Sbrian strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1); 147536285Sbrian cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; 147628679Sbrian break; 147737210Sbrian 147836285Sbrian case VAR_WINSIZE: 147936285Sbrian if (arg->argc > arg->argn) { 148036285Sbrian l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]); 148136285Sbrian if (l->ccp.cfg.deflate.out.winsize < 8 || 148236285Sbrian l->ccp.cfg.deflate.out.winsize > 15) { 148336285Sbrian log_Printf(LogWARN, "%d: Invalid outgoing window size\n", 148436285Sbrian l->ccp.cfg.deflate.out.winsize); 148536285Sbrian l->ccp.cfg.deflate.out.winsize = 15; 148636285Sbrian } 148736285Sbrian if (arg->argc > arg->argn+1) { 148836285Sbrian l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]); 148936285Sbrian if (l->ccp.cfg.deflate.in.winsize < 8 || 149036285Sbrian l->ccp.cfg.deflate.in.winsize > 15) { 149136285Sbrian log_Printf(LogWARN, "%d: Invalid incoming window size\n", 149236285Sbrian l->ccp.cfg.deflate.in.winsize); 149336285Sbrian l->ccp.cfg.deflate.in.winsize = 15; 149436285Sbrian } 149536285Sbrian } else 149636285Sbrian l->ccp.cfg.deflate.in.winsize = 0; 149736285Sbrian } else { 149836285Sbrian err = "No window size specified\n"; 149936285Sbrian log_Printf(LogWARN, err); 150036285Sbrian } 150136285Sbrian break; 150237210Sbrian 150328679Sbrian case VAR_DEVICE: 150436285Sbrian physical_SetDeviceList(cx->physical, arg->argc - arg->argn, 150536285Sbrian arg->argv + arg->argn); 150636285Sbrian break; 150737210Sbrian 150836285Sbrian case VAR_ACCMAP: 150936285Sbrian if (arg->argc > arg->argn) { 151037210Sbrian u_long ulong_val; 151136285Sbrian sscanf(argp, "%lx", &ulong_val); 151237210Sbrian cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; 151336285Sbrian } else { 151436285Sbrian err = "No accmap specified\n"; 151536285Sbrian log_Printf(LogWARN, err); 151636285Sbrian } 151736285Sbrian break; 151837210Sbrian 151936285Sbrian case VAR_MODE: 152036285Sbrian mode = Nam2mode(argp); 152136285Sbrian if (mode == PHYS_NONE || mode == PHYS_ALL) { 152236285Sbrian log_Printf(LogWARN, "%s: Invalid mode\n", argp); 152336285Sbrian return -1; 152436285Sbrian } 152536285Sbrian bundle_SetMode(arg->bundle, cx, mode); 152636285Sbrian break; 152737210Sbrian 152836285Sbrian case VAR_MRRU: 152940622Sbrian switch (bundle_Phase(arg->bundle)) { 153040622Sbrian case PHASE_DEAD: 153140622Sbrian break; 153240622Sbrian case PHASE_ESTABLISH: 153340622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 153440622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 153540622Sbrian log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); 153640622Sbrian return 1; 153740622Sbrian } 153840622Sbrian break; 153940622Sbrian default: 154040622Sbrian log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); 154140622Sbrian return 1; 154229696Sbrian } 154337210Sbrian long_val = atol(argp); 154437210Sbrian if (long_val && long_val < MIN_MRU) { 154537210Sbrian log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); 154637210Sbrian return 1; 154737210Sbrian } else if (long_val > MAX_MRU) { 154837210Sbrian log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); 154937210Sbrian return 1; 155037210Sbrian } else 155137210Sbrian arg->bundle->ncp.mp.cfg.mrru = long_val; 155228679Sbrian break; 155337210Sbrian 155436285Sbrian case VAR_MRU: 155537210Sbrian long_val = atol(argp); 155637210Sbrian if (long_val == 0) 155737210Sbrian l->lcp.cfg.mru = DEF_MRU; 155837210Sbrian else if (long_val < MIN_MRU) { 155937210Sbrian log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); 156037210Sbrian return 1; 156137210Sbrian } else if (long_val > MAX_MRU) { 156237210Sbrian log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); 156337210Sbrian return 1; 156437210Sbrian } else 156537210Sbrian l->lcp.cfg.mru = long_val; 156628679Sbrian break; 156737210Sbrian 156836285Sbrian case VAR_MTU: 156937210Sbrian long_val = atol(argp); 157037210Sbrian if (long_val && long_val < MIN_MTU) { 157137210Sbrian log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); 157237210Sbrian return 1; 157337210Sbrian } else if (long_val > MAX_MTU) { 157437210Sbrian log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); 157537210Sbrian return 1; 157637210Sbrian } else 157737210Sbrian arg->bundle->cfg.mtu = long_val; 157836285Sbrian break; 157937210Sbrian 158036285Sbrian case VAR_OPENMODE: 158136285Sbrian if (strcasecmp(argp, "active") == 0) 158236285Sbrian cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ? 158336285Sbrian atoi(arg->argv[arg->argn+1]) : 1; 158436285Sbrian else if (strcasecmp(argp, "passive") == 0) 158536285Sbrian cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; 158636285Sbrian else { 158736285Sbrian err = "%s: Invalid openmode\n"; 158836285Sbrian log_Printf(LogWARN, err, argp); 158936285Sbrian } 159036285Sbrian break; 159137210Sbrian 159228679Sbrian case VAR_PHONE: 159336285Sbrian strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1); 159436285Sbrian cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0'; 159538174Sbrian cx->phone.alt = cx->phone.next = NULL; 159628679Sbrian break; 159737210Sbrian 159828679Sbrian case VAR_HANGUP: 159936285Sbrian strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1); 160036285Sbrian cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0'; 160128679Sbrian break; 160237210Sbrian 160352488Sbrian case VAR_LOGOUT: 160452488Sbrian strncpy(cx->cfg.script.logout, argp, sizeof cx->cfg.script.logout - 1); 160552488Sbrian cx->cfg.script.logout[sizeof cx->cfg.script.logout - 1] = '\0'; 160652488Sbrian break; 160752488Sbrian 160836285Sbrian case VAR_IDLETIMEOUT: 160949978Sbrian if (arg->argc > arg->argn+2) 161036285Sbrian err = "Too many idle timeout values\n"; 161149978Sbrian else if (arg->argc == arg->argn) 161249978Sbrian err = "Too few idle timeout values\n"; 161349978Sbrian else { 161449978Sbrian int timeout, min; 161549978Sbrian 161649978Sbrian timeout = atoi(argp); 161749978Sbrian min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; 161849978Sbrian bundle_SetIdleTimer(arg->bundle, timeout, min); 161949978Sbrian } 162036285Sbrian if (err) 162136285Sbrian log_Printf(LogWARN, err); 162229549Sbrian break; 162337210Sbrian 162436285Sbrian case VAR_LQRPERIOD: 162537210Sbrian long_val = atol(argp); 162637210Sbrian if (long_val < MIN_LQRPERIOD) { 162737210Sbrian log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", 162837210Sbrian long_val, MIN_LQRPERIOD); 162937210Sbrian return 1; 163036285Sbrian } else 163137210Sbrian l->lcp.cfg.lqrperiod = long_val; 163236285Sbrian break; 163337210Sbrian 163436285Sbrian case VAR_LCPRETRY: 163544305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 163644305Sbrian &cx->physical->link.lcp.cfg.fsm.timeout, 163744305Sbrian &cx->physical->link.lcp.cfg.fsm.maxreq, 163844305Sbrian &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 163936285Sbrian break; 164037210Sbrian 164136285Sbrian case VAR_CHAPRETRY: 164244305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 164344305Sbrian &cx->chap.auth.cfg.fsm.timeout, 164444305Sbrian &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); 164536285Sbrian break; 164637210Sbrian 164736285Sbrian case VAR_PAPRETRY: 164844305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 164944305Sbrian &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, 165044305Sbrian NULL, DEF_FSMAUTHTRIES); 165136285Sbrian break; 165237210Sbrian 165336285Sbrian case VAR_CCPRETRY: 165444305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 165544305Sbrian &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, 165644305Sbrian &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); 165736285Sbrian break; 165837210Sbrian 165936285Sbrian case VAR_IPCPRETRY: 166044305Sbrian return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, 166144305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.timeout, 166244305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, 166344305Sbrian &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); 166436285Sbrian break; 166537210Sbrian 166636285Sbrian case VAR_NBNS: 166736285Sbrian case VAR_DNS: 166836285Sbrian if (param == VAR_DNS) 166936285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.dns; 167036285Sbrian else 167136285Sbrian addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; 167236285Sbrian 167336285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 167436285Sbrian 167536285Sbrian if (arg->argc > arg->argn) { 167643313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 167736285Sbrian addr, &dummyaddr, &dummyint); 167836285Sbrian if (arg->argc > arg->argn+1) 167943313Sbrian ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], 168036285Sbrian addr + 1, &dummyaddr, &dummyint); 168136285Sbrian 168236285Sbrian if (addr[1].s_addr == INADDR_ANY) 168336285Sbrian addr[1].s_addr = addr[0].s_addr; 168436285Sbrian if (addr[0].s_addr == INADDR_ANY) 168536285Sbrian addr[0].s_addr = addr[1].s_addr; 168636285Sbrian } 168736285Sbrian break; 168838174Sbrian 168938174Sbrian case VAR_CALLBACK: 169038174Sbrian cx->cfg.callback.opmask = 0; 169138174Sbrian for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) { 169238174Sbrian if (!strcasecmp(arg->argv[dummyint], "auth")) 169338174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH); 169438174Sbrian else if (!strcasecmp(arg->argv[dummyint], "cbcp")) 169538174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP); 169638174Sbrian else if (!strcasecmp(arg->argv[dummyint], "e.164")) { 169738174Sbrian if (dummyint == arg->argc - 1) 169838174Sbrian log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n"); 169938174Sbrian else { 170038174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164); 170138174Sbrian strncpy(cx->cfg.callback.msg, arg->argv[++dummyint], 170238174Sbrian sizeof cx->cfg.callback.msg - 1); 170338174Sbrian cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0'; 170438174Sbrian } 170538174Sbrian } else if (!strcasecmp(arg->argv[dummyint], "none")) 170638174Sbrian cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); 170738174Sbrian else 170838174Sbrian return -1; 170938174Sbrian } 171038174Sbrian if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) 171138174Sbrian cx->cfg.callback.opmask = 0; 171238174Sbrian break; 171338174Sbrian 171438174Sbrian case VAR_CBCP: 171538174Sbrian cx->cfg.cbcp.delay = 0; 171638174Sbrian *cx->cfg.cbcp.phone = '\0'; 171738174Sbrian cx->cfg.cbcp.fsmretry = DEF_FSMRETRY; 171838174Sbrian if (arg->argc > arg->argn) { 171938174Sbrian strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn], 172038174Sbrian sizeof cx->cfg.cbcp.phone - 1); 172138174Sbrian cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0'; 172238174Sbrian if (arg->argc > arg->argn + 1) { 172338174Sbrian cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]); 172438174Sbrian if (arg->argc > arg->argn + 2) { 172538174Sbrian long_val = atol(arg->argv[arg->argn + 2]); 172638174Sbrian if (long_val < MIN_FSMRETRY) 172738174Sbrian log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n", 172838174Sbrian long_val, MIN_FSMRETRY); 172938174Sbrian else 173038174Sbrian cx->cfg.cbcp.fsmretry = long_val; 173138174Sbrian } 173238174Sbrian } 173338174Sbrian } 173438174Sbrian break; 173538544Sbrian 173638544Sbrian case VAR_CHOKED: 173738544Sbrian arg->bundle->cfg.choked.timeout = atoi(argp); 173838544Sbrian if (arg->bundle->cfg.choked.timeout <= 0) 173938544Sbrian arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; 174038544Sbrian break; 174140665Sbrian 174240665Sbrian case VAR_SENDPIPE: 174340665Sbrian long_val = atol(argp); 174440665Sbrian arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; 174540665Sbrian break; 174640665Sbrian 174740665Sbrian case VAR_RECVPIPE: 174840665Sbrian long_val = atol(argp); 174940665Sbrian arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; 175040665Sbrian break; 175143313Sbrian 175243313Sbrian#ifndef NORADIUS 175343313Sbrian case VAR_RADIUS: 175443313Sbrian if (!*argp) 175543313Sbrian *arg->bundle->radius.cfg.file = '\0'; 175643313Sbrian else if (access(argp, R_OK)) { 175743313Sbrian log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); 175843313Sbrian return 1; 175943313Sbrian } else { 176043313Sbrian strncpy(arg->bundle->radius.cfg.file, argp, 176143313Sbrian sizeof arg->bundle->radius.cfg.file - 1); 176243313Sbrian arg->bundle->radius.cfg.file 176343313Sbrian [sizeof arg->bundle->radius.cfg.file - 1] = '\0'; 176443313Sbrian } 176543313Sbrian break; 176643313Sbrian#endif 176744073Sbrian 176844073Sbrian case VAR_CD: 176944073Sbrian if (*argp) { 177051699Sbrian if (strcasecmp(argp, "off")) { 177151699Sbrian long_val = atol(argp); 177251699Sbrian if (long_val < 0) 177351699Sbrian long_val = 0; 177451699Sbrian cx->physical->cfg.cd.delay = long_val; 177551699Sbrian cx->physical->cfg.cd.necessity = argp[strlen(argp)-1] == '!' ? 177651699Sbrian CD_REQUIRED : CD_VARIABLE; 177751699Sbrian } else 177851699Sbrian cx->physical->cfg.cd.necessity = CD_NOTREQUIRED; 177944073Sbrian } else { 178053733Sbrian cx->physical->cfg.cd.delay = 0; 178153733Sbrian cx->physical->cfg.cd.necessity = CD_DEFAULT; 178244073Sbrian } 178344073Sbrian break; 178436285Sbrian 178546686Sbrian case VAR_PARITY: 178646686Sbrian if (arg->argc == arg->argn + 1) 178746686Sbrian return physical_SetParity(arg->cx->physical, argp); 178846686Sbrian else { 178946686Sbrian err = "Parity value must be odd, even or none\n"; 179046686Sbrian log_Printf(LogWARN, err); 179146686Sbrian } 179246686Sbrian break; 17936059Samurai 179446686Sbrian case VAR_CRTSCTS: 179546686Sbrian if (strcasecmp(argp, "on") == 0) 179636285Sbrian physical_SetRtsCts(arg->cx->physical, 1); 179746686Sbrian else if (strcasecmp(argp, "off") == 0) 179836285Sbrian physical_SetRtsCts(arg->cx->physical, 0); 179946686Sbrian else { 180046686Sbrian err = "RTS/CTS value must be on or off\n"; 180146686Sbrian log_Printf(LogWARN, err); 180246686Sbrian } 180346686Sbrian break; 180450867Sbrian 180550867Sbrian case VAR_URGENTPORTS: 180651048Sbrian if (arg->argn == arg->argc) { 180751048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 180851048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 180951048Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "udp")) { 181051048Sbrian if (arg->argn == arg->argc - 1) 181151048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 181251048Sbrian else for (f = arg->argn + 1; f < arg->argc; f++) 181351048Sbrian if (*arg->argv[f] == '+') 181451048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 181551048Sbrian else if (*arg->argv[f] == '-') 181651048Sbrian ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp, 181751048Sbrian atoi(arg->argv[f] + 1)); 181851048Sbrian else { 181951048Sbrian if (f == arg->argn) 182051048Sbrian ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp); 182151048Sbrian ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 182251048Sbrian } 182351048Sbrian } else { 182451048Sbrian first = arg->argn; 182551048Sbrian if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc) 182651048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 182751048Sbrian 182851048Sbrian for (f = first; f < arg->argc; f++) 182951048Sbrian if (*arg->argv[f] == '+') 183051048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1)); 183151048Sbrian else if (*arg->argv[f] == '-') 183251048Sbrian ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp, 183351048Sbrian atoi(arg->argv[f] + 1)); 183451048Sbrian else { 183551048Sbrian if (f == first) 183651048Sbrian ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp); 183751048Sbrian ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f])); 183851048Sbrian } 183951048Sbrian } 184050867Sbrian break; 184120812Sjkh } 184246686Sbrian 184346686Sbrian return err ? 1 : 0; 184420812Sjkh} 184520812Sjkh 184630715Sbrianstatic struct cmdtab const SetCommands[] = { 184736285Sbrian {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 184836285Sbrian "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP}, 184928679Sbrian {"authkey", "key", SetVariable, LOCAL_AUTH, 185036285Sbrian "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY}, 185128679Sbrian {"authname", NULL, SetVariable, LOCAL_AUTH, 185236285Sbrian "authentication name", "set authname name", (const void *)VAR_AUTHNAME}, 185336285Sbrian {"autoload", NULL, SetVariable, LOCAL_AUTH, 185436285Sbrian "auto link [de]activation", "set autoload maxtime maxload mintime minload", 185536285Sbrian (const void *)VAR_AUTOLOAD}, 185650867Sbrian {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, 185750867Sbrian "datalink bandwidth", "set bandwidth value"}, 185838174Sbrian {"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 185938174Sbrian "callback control", "set callback [none|auth|cbcp|" 186038174Sbrian "E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK}, 186138174Sbrian {"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 186238174Sbrian "CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]", 186338174Sbrian (const void *)VAR_CBCP}, 186444305Sbrian {"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 186544305Sbrian "CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY}, 186644073Sbrian {"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement", 186744073Sbrian "set cd value[!]", (const void *)VAR_CD}, 186844305Sbrian {"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX, 186944305Sbrian "CHAP retries", "set chapretry value [attempts]", 187044305Sbrian (const void *)VAR_CHAPRETRY}, 187138544Sbrian {"choked", NULL, SetVariable, LOCAL_AUTH, 187238544Sbrian "choked timeout", "set choked [secs]", (const void *)VAR_CHOKED}, 187346686Sbrian {"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX, 187446686Sbrian "Use hardware flow control", "set ctsrts [on|off]", 187546686Sbrian (const char *)VAR_CRTSCTS}, 187636285Sbrian {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 187736285Sbrian "deflate window sizes", "set deflate out-winsize in-winsize", 187836285Sbrian (const void *) VAR_WINSIZE}, 187936285Sbrian {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, 188046686Sbrian "physical device name", "set device|line device-name[,device-name]", 188136285Sbrian (const void *) VAR_DEVICE}, 188236285Sbrian {"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 188336285Sbrian "dialing script", "set dial chat-script", (const void *) VAR_DIAL}, 188436285Sbrian {"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server", 188536285Sbrian "set dns pri-addr [sec-addr]", (const void *)VAR_DNS}, 188636285Sbrian {"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH, 188736285Sbrian "Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"}, 188836285Sbrian {"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX, 188936285Sbrian "escape characters", "set escape hex-digit ..."}, 189036285Sbrian {"filter", NULL, filter_Set, LOCAL_AUTH, 189136285Sbrian "packet filters", "set filter alive|dial|in|out rule-no permit|deny " 189249388Sbrian "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp " 189348142Sbrian "[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"}, 189436285Sbrian {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 189536285Sbrian "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP}, 189636285Sbrian {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address", 189731343Sbrian "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"}, 189844305Sbrian {"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries", 189944305Sbrian "set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY}, 190044305Sbrian {"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries", 190144305Sbrian "set lcpretry value [attempts]", (const void *)VAR_LCPRETRY}, 190236712Sbrian {"log", NULL, log_SetLevel, LOCAL_AUTH, "log level", 190338622Sbrian "set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|" 190447699Sbrian "ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."}, 190536285Sbrian {"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 190636285Sbrian "login script", "set login chat-script", (const void *) VAR_LOGIN}, 190752488Sbrian {"logout", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, 190852488Sbrian "logout script", "set logout chat-script", (const void *) VAR_LOGOUT}, 190936285Sbrian {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 191036285Sbrian "LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, 191136285Sbrian {"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value", 191236285Sbrian "set mode interactive|auto|ddial|background", (const void *)VAR_MODE}, 191336285Sbrian {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", 191436285Sbrian "set mrru value", (const void *)VAR_MRRU}, 191536285Sbrian {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, 191636285Sbrian "MRU value", "set mru value", (const void *)VAR_MRU}, 191736285Sbrian {"mtu", NULL, SetVariable, LOCAL_AUTH, 191836285Sbrian "interface MTU value", "set mtu value", (const void *)VAR_MTU}, 191936285Sbrian {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", 192036285Sbrian "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, 192136285Sbrian {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", 192236285Sbrian "set openmode active|passive [secs]", (const void *)VAR_OPENMODE}, 192344305Sbrian {"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries", 192444305Sbrian "set papretry value [attempts]", (const void *)VAR_PAPRETRY}, 192546686Sbrian {"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity", 192646686Sbrian "set parity [odd|even|none]", (const void *)VAR_PARITY}, 192736285Sbrian {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", 192836285Sbrian "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, 192940679Sbrian {"proctitle", "title", SetProcTitle, LOCAL_AUTH, 193040679Sbrian "Process title", "set proctitle [value]"}, 193143313Sbrian#ifndef NORADIUS 193243313Sbrian {"radius", NULL, SetVariable, LOCAL_AUTH, 193343313Sbrian "RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS}, 193443313Sbrian#endif 193536285Sbrian {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, 193636285Sbrian "Reconnect timeout", "set reconnect value ntries"}, 193740665Sbrian {"recvpipe", NULL, SetVariable, LOCAL_AUTH, 193840665Sbrian "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, 193936285Sbrian {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, 194044468Sbrian "Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"}, 194140665Sbrian {"sendpipe", NULL, SetVariable, LOCAL_AUTH, 194240665Sbrian "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, 194328679Sbrian {"server", "socket", SetServer, LOCAL_AUTH, 194436774Sbrian "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, 194536285Sbrian {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, 194646686Sbrian "physical speed", "set speed value|sync"}, 194736285Sbrian {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX, 194836285Sbrian "STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"}, 194936285Sbrian {"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout", 195036285Sbrian "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, 195151048Sbrian {"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports", 195251048Sbrian "set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS}, 195336285Sbrian {"vj", NULL, ipcp_vjset, LOCAL_AUTH, 195436285Sbrian "vj values", "set vj slots|slotcomp [value]"}, 195528679Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 195631343Sbrian "Display this message", "set help|? [command]", SetCommands}, 195728679Sbrian {NULL, NULL, NULL}, 19586059Samurai}; 19596059Samurai 19606059Samuraistatic int 196131343SbrianSetCommand(struct cmdargs const *arg) 19626059Samurai{ 196336285Sbrian if (arg->argc > arg->argn) 196436285Sbrian FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv, 196536285Sbrian arg->prompt, arg->cx); 196636285Sbrian else if (arg->prompt) 196736285Sbrian prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" 196826516Sbrian " syntax help.\n"); 19696059Samurai else 197036285Sbrian log_Printf(LogWARN, "set command must have arguments\n"); 197126516Sbrian 197226516Sbrian return 0; 19736059Samurai} 19746059Samurai 19756059Samuraistatic int 197631343SbrianAddCommand(struct cmdargs const *arg) 19776059Samurai{ 19786059Samurai struct in_addr dest, gateway, netmask; 197936285Sbrian int gw, addrs; 19806059Samurai 198136285Sbrian if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2) 198231598Sbrian return -1; 198331598Sbrian 198436285Sbrian addrs = 0; 198536285Sbrian if (arg->argc == arg->argn+2) { 198636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "default")) 198736285Sbrian dest.s_addr = netmask.s_addr = INADDR_ANY; 198831598Sbrian else { 198936285Sbrian int width; 199036285Sbrian 199143313Sbrian if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], 199236285Sbrian &dest, &netmask, &width)) 199336285Sbrian return -1; 199436285Sbrian if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6)) 199536285Sbrian addrs = ROUTE_DSTMYADDR; 199636285Sbrian else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) 199736285Sbrian addrs = ROUTE_DSTHISADDR; 199831598Sbrian } 199936285Sbrian gw = 1; 200034536Sbrian } else { 200136285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 200236285Sbrian addrs = ROUTE_DSTMYADDR; 200336285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 200436285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 200536285Sbrian addrs = ROUTE_DSTHISADDR; 200636285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 200736285Sbrian } else 200836285Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 200936285Sbrian netmask = GetIpAddr(arg->argv[arg->argn+1]); 201031598Sbrian gw = 2; 20116059Samurai } 201236285Sbrian 201336285Sbrian if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) { 201436285Sbrian gateway = arg->bundle->ncp.ipcp.peer_ip; 201536285Sbrian addrs |= ROUTE_GWHISADDR; 201640561Sbrian } else 201736285Sbrian gateway = GetIpAddr(arg->argv[arg->argn+gw]); 201836285Sbrian 201936285Sbrian if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask, 202043313Sbrian arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0) 202143313Sbrian && addrs != ROUTE_STATIC) 202236285Sbrian route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway); 202336285Sbrian 202431598Sbrian return 0; 20256059Samurai} 20266059Samurai 20276059Samuraistatic int 202831343SbrianDeleteCommand(struct cmdargs const *arg) 20296059Samurai{ 203031598Sbrian struct in_addr dest, none; 203136285Sbrian int addrs; 20326059Samurai 203336285Sbrian if (arg->argc == arg->argn+1) { 203436285Sbrian if(strcasecmp(arg->argv[arg->argn], "all") == 0) { 203536285Sbrian route_IfDelete(arg->bundle, 0); 203636285Sbrian route_DeleteAll(&arg->bundle->ncp.ipcp.route); 203736285Sbrian } else { 203836285Sbrian addrs = 0; 203936285Sbrian if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) { 204036285Sbrian dest = arg->bundle->ncp.ipcp.my_ip; 204136285Sbrian addrs = ROUTE_DSTMYADDR; 204236285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { 204336285Sbrian dest = arg->bundle->ncp.ipcp.peer_ip; 204436285Sbrian addrs = ROUTE_DSTHISADDR; 204536285Sbrian } else { 204644279Sbrian dest = GetIpAddr(arg->argv[arg->argn]); 204744279Sbrian if (dest.s_addr == INADDR_NONE) { 204844279Sbrian log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]); 204944279Sbrian return -1; 205044279Sbrian } 205136285Sbrian addrs = ROUTE_STATIC; 205236285Sbrian } 205331598Sbrian none.s_addr = INADDR_ANY; 205436285Sbrian bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none, 205537927Sbrian arg->cmd->args ? 1 : 0, 0); 205636285Sbrian route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest); 205731598Sbrian } 205834536Sbrian } else 205926516Sbrian return -1; 206026516Sbrian 206126516Sbrian return 0; 20626059Samurai} 20636059Samurai 206450059Sbrian#ifndef NONAT 206526031Sbrianstatic int 206631343SbrianAliasEnable(struct cmdargs const *arg) 206726031Sbrian{ 206836285Sbrian if (arg->argc == arg->argn+1) { 206936285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 207050059Sbrian if (!arg->bundle->NatEnabled) { 207146686Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) 207246686Sbrian PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip); 207350059Sbrian arg->bundle->NatEnabled = 1; 207446686Sbrian } 207537191Sbrian return 0; 207636285Sbrian } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) { 207750059Sbrian arg->bundle->NatEnabled = 0; 207840561Sbrian arg->bundle->cfg.opt &= ~OPT_IFACEALIAS; 207940561Sbrian /* Don't iface_Clear() - there may be manually configured addresses */ 208026516Sbrian return 0; 208126142Sbrian } 208235449Sbrian } 208336285Sbrian 208426516Sbrian return -1; 208526031Sbrian} 208626031Sbrian 208726031Sbrian 208826031Sbrianstatic int 208931343SbrianAliasOption(struct cmdargs const *arg) 209026031Sbrian{ 209138559Sbrian long param = (long)arg->cmd->args; 209238559Sbrian 209336285Sbrian if (arg->argc == arg->argn+1) { 209436285Sbrian if (strcasecmp(arg->argv[arg->argn], "yes") == 0) { 209550059Sbrian if (arg->bundle->NatEnabled) { 209637191Sbrian PacketAliasSetMode(param, param); 209728679Sbrian return 0; 209828679Sbrian } 209950059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 210036285Sbrian } else if (strcmp(arg->argv[arg->argn], "no") == 0) { 210150059Sbrian if (arg->bundle->NatEnabled) { 210237191Sbrian PacketAliasSetMode(0, param); 210328679Sbrian return 0; 210428679Sbrian } 210550059Sbrian log_Printf(LogWARN, "nat not enabled\n"); 210628679Sbrian } 210735449Sbrian } 210828679Sbrian return -1; 210926031Sbrian} 211050059Sbrian#endif /* #ifndef NONAT */ 211131121Sbrian 211231121Sbrianstatic int 211336285SbrianLinkCommand(struct cmdargs const *arg) 211436285Sbrian{ 211536285Sbrian if (arg->argc > arg->argn+1) { 211636285Sbrian char namelist[LINE_LEN]; 211736285Sbrian struct datalink *cx; 211836285Sbrian char *name; 211936285Sbrian int result = 0; 212036285Sbrian 212136285Sbrian if (!strcmp(arg->argv[arg->argn], "*")) { 212236285Sbrian struct datalink *dl; 212336285Sbrian 212436285Sbrian cx = arg->bundle->links; 212536285Sbrian while (cx) { 212636285Sbrian /* Watch it, the command could be a ``remove'' */ 212736285Sbrian dl = cx->next; 212836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 212936285Sbrian arg->prompt, cx); 213036285Sbrian for (cx = arg->bundle->links; cx; cx = cx->next) 213136285Sbrian if (cx == dl) 213236285Sbrian break; /* Pointer's still valid ! */ 213336285Sbrian } 213436285Sbrian } else { 213536285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 213636285Sbrian namelist[sizeof namelist - 1] = '\0'; 213736285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) 213836285Sbrian if (!bundle2datalink(arg->bundle, name)) { 213936285Sbrian log_Printf(LogWARN, "link: %s: Invalid link name\n", name); 214036285Sbrian return 1; 214136285Sbrian } 214236285Sbrian 214336285Sbrian strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1); 214436285Sbrian namelist[sizeof namelist - 1] = '\0'; 214536285Sbrian for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) { 214636285Sbrian cx = bundle2datalink(arg->bundle, name); 214736285Sbrian if (cx) 214836285Sbrian FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv, 214936285Sbrian arg->prompt, cx); 215036285Sbrian else { 215136285Sbrian log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name); 215236285Sbrian result++; 215336285Sbrian } 215436285Sbrian } 215536285Sbrian } 215636285Sbrian return result; 215736285Sbrian } 215836285Sbrian 215936285Sbrian log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax); 216036285Sbrian return 2; 216136285Sbrian} 216236285Sbrian 216336285Sbrianstruct link * 216436285Sbriancommand_ChooseLink(struct cmdargs const *arg) 216536285Sbrian{ 216636285Sbrian if (arg->cx) 216736285Sbrian return &arg->cx->physical->link; 216837210Sbrian else if (!arg->bundle->ncp.mp.cfg.mrru) { 216936285Sbrian struct datalink *dl = bundle2datalink(arg->bundle, NULL); 217037210Sbrian if (dl) 217137210Sbrian return &dl->physical->link; 217236285Sbrian } 217337210Sbrian return &arg->bundle->ncp.mp.link; 217436285Sbrian} 217536285Sbrian 217636285Sbrianstatic const char * 217736285Sbrianident_cmd(const char *cmd, unsigned *keep, unsigned *add) 217836285Sbrian{ 217936285Sbrian const char *result; 218036285Sbrian 218136285Sbrian switch (*cmd) { 218236285Sbrian case 'A': 218336285Sbrian case 'a': 218436285Sbrian result = "accept"; 218536285Sbrian *keep = NEG_MYMASK; 218636285Sbrian *add = NEG_ACCEPTED; 218736285Sbrian break; 218836285Sbrian case 'D': 218936285Sbrian case 'd': 219036285Sbrian switch (cmd[1]) { 219136285Sbrian case 'E': 219236285Sbrian case 'e': 219336285Sbrian result = "deny"; 219436285Sbrian *keep = NEG_MYMASK; 219536285Sbrian *add = 0; 219636285Sbrian break; 219736285Sbrian case 'I': 219836285Sbrian case 'i': 219936285Sbrian result = "disable"; 220036285Sbrian *keep = NEG_HISMASK; 220136285Sbrian *add = 0; 220236285Sbrian break; 220336285Sbrian default: 220436285Sbrian return NULL; 220536285Sbrian } 220636285Sbrian break; 220736285Sbrian case 'E': 220836285Sbrian case 'e': 220936285Sbrian result = "enable"; 221036285Sbrian *keep = NEG_HISMASK; 221136285Sbrian *add = NEG_ENABLED; 221236285Sbrian break; 221336285Sbrian default: 221436285Sbrian return NULL; 221536285Sbrian } 221636285Sbrian 221736285Sbrian return result; 221836285Sbrian} 221936285Sbrian 222036285Sbrianstatic int 222136285SbrianOptSet(struct cmdargs const *arg) 222236285Sbrian{ 222337574Sbrian int bit = (int)(long)arg->cmd->args; 222436285Sbrian const char *cmd; 222536285Sbrian unsigned keep; /* Keep these bits */ 222636285Sbrian unsigned add; /* Add these bits */ 222736285Sbrian 222836285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 222936285Sbrian return 1; 223036285Sbrian 223136285Sbrian if (add) 223236285Sbrian arg->bundle->cfg.opt |= bit; 223336285Sbrian else 223436285Sbrian arg->bundle->cfg.opt &= ~bit; 223536285Sbrian return 0; 223636285Sbrian} 223736285Sbrian 223836285Sbrianstatic int 223940561SbrianIfaceAliasOptSet(struct cmdargs const *arg) 224040561Sbrian{ 224140561Sbrian unsigned save = arg->bundle->cfg.opt; 224240561Sbrian int result = OptSet(arg); 224340561Sbrian 224440561Sbrian if (result == 0) 224550059Sbrian if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) { 224640561Sbrian arg->bundle->cfg.opt = save; 224750059Sbrian log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n"); 224840561Sbrian result = 2; 224940561Sbrian } 225040561Sbrian 225140561Sbrian return result; 225240561Sbrian} 225340561Sbrian 225440561Sbrianstatic int 225536285SbrianNegotiateSet(struct cmdargs const *arg) 225636285Sbrian{ 225737210Sbrian long param = (long)arg->cmd->args; 225836285Sbrian struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ 225936285Sbrian struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ 226036285Sbrian const char *cmd; 226136285Sbrian unsigned keep; /* Keep these bits */ 226236285Sbrian unsigned add; /* Add these bits */ 226336285Sbrian 226436285Sbrian if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL) 226536285Sbrian return 1; 226636285Sbrian 226736285Sbrian if ((arg->cmd->lauth & LOCAL_CX) && !cx) { 226836285Sbrian log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n", 226936285Sbrian cmd, arg->cmd->name); 227036285Sbrian return 2; 227136285Sbrian } else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) { 227236285Sbrian log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n", 227336285Sbrian cmd, arg->cmd->name, cx->name); 227436285Sbrian cx = NULL; 227536285Sbrian } 227636285Sbrian 227736285Sbrian switch (param) { 227836285Sbrian case NEG_ACFCOMP: 227936285Sbrian cx->physical->link.lcp.cfg.acfcomp &= keep; 228036285Sbrian cx->physical->link.lcp.cfg.acfcomp |= add; 228136285Sbrian break; 228244106Sbrian case NEG_CHAP05: 228344106Sbrian cx->physical->link.lcp.cfg.chap05 &= keep; 228444106Sbrian cx->physical->link.lcp.cfg.chap05 |= add; 228536285Sbrian break; 228644106Sbrian#ifdef HAVE_DES 228744106Sbrian case NEG_CHAP80: 228844106Sbrian cx->physical->link.lcp.cfg.chap80nt &= keep; 228944106Sbrian cx->physical->link.lcp.cfg.chap80nt |= add; 229044106Sbrian break; 229144106Sbrian case NEG_CHAP80LM: 229244106Sbrian cx->physical->link.lcp.cfg.chap80lm &= keep; 229344106Sbrian cx->physical->link.lcp.cfg.chap80lm |= add; 229444106Sbrian break; 229544106Sbrian#endif 229636285Sbrian case NEG_DEFLATE: 229736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep; 229836285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add; 229936285Sbrian break; 230036285Sbrian case NEG_DNS: 230136285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep; 230236285Sbrian arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add; 230336285Sbrian break; 230447858Sbrian case NEG_ENDDISC: 230547858Sbrian arg->bundle->ncp.mp.cfg.negenddisc &= keep; 230647858Sbrian arg->bundle->ncp.mp.cfg.negenddisc |= add; 230747858Sbrian break; 230836285Sbrian case NEG_LQR: 230936285Sbrian cx->physical->link.lcp.cfg.lqr &= keep; 231036285Sbrian cx->physical->link.lcp.cfg.lqr |= add; 231136285Sbrian break; 231236285Sbrian case NEG_PAP: 231336285Sbrian cx->physical->link.lcp.cfg.pap &= keep; 231436285Sbrian cx->physical->link.lcp.cfg.pap |= add; 231536285Sbrian break; 231636285Sbrian case NEG_PPPDDEFLATE: 231736285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep; 231836285Sbrian l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add; 231936285Sbrian break; 232036285Sbrian case NEG_PRED1: 232136285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep; 232236285Sbrian l->ccp.cfg.neg[CCP_NEG_PRED1] |= add; 232336285Sbrian break; 232436285Sbrian case NEG_PROTOCOMP: 232536285Sbrian cx->physical->link.lcp.cfg.protocomp &= keep; 232636285Sbrian cx->physical->link.lcp.cfg.protocomp |= add; 232736285Sbrian break; 232836285Sbrian case NEG_SHORTSEQ: 232940622Sbrian switch (bundle_Phase(arg->bundle)) { 233040622Sbrian case PHASE_DEAD: 233140622Sbrian break; 233240622Sbrian case PHASE_ESTABLISH: 233340622Sbrian /* Make sure none of our links are DATALINK_LCP or greater */ 233440622Sbrian if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { 233540622Sbrian log_Printf(LogWARN, "shortseq: Only changable before" 233640622Sbrian " LCP negotiations\n"); 233740622Sbrian return 1; 233840622Sbrian } 233940622Sbrian break; 234040622Sbrian default: 234140622Sbrian log_Printf(LogWARN, "shortseq: Only changable at phase" 234240622Sbrian " DEAD/ESTABLISH\n"); 234340622Sbrian return 1; 234436285Sbrian } 234540622Sbrian arg->bundle->ncp.mp.cfg.shortseq &= keep; 234640622Sbrian arg->bundle->ncp.mp.cfg.shortseq |= add; 234736285Sbrian break; 234836285Sbrian case NEG_VJCOMP: 234936285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; 235036285Sbrian arg->bundle->ncp.ipcp.cfg.vj.neg |= add; 235136285Sbrian break; 235236285Sbrian } 235336285Sbrian 235436285Sbrian return 0; 235536285Sbrian} 235636285Sbrian 235736285Sbrianstatic struct cmdtab const NegotiateCommands[] = { 235836285Sbrian {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", 235936285Sbrian "disable|enable", (const void *)OPT_IDCHECK}, 236040666Sbrian {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, 236140666Sbrian "retain interface addresses", "disable|enable", 236240666Sbrian (const void *)OPT_IFACEALIAS}, 236347689Sbrian {"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader", 236447689Sbrian "disable|enable", (const void *)OPT_KEEPSESSION}, 236536285Sbrian {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", 236636285Sbrian "disable|enable", (const void *)OPT_LOOPBACK}, 236736285Sbrian {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", 236836285Sbrian "disable|enable", (const void *)OPT_PASSWDAUTH}, 236940665Sbrian {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", 237036285Sbrian "disable|enable", (const void *)OPT_PROXY}, 237140665Sbrian {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", 237240665Sbrian "disable|enable", (const void *)OPT_PROXYALL}, 237336285Sbrian {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", 237436285Sbrian "disable|enable", (const void *)OPT_SROUTES}, 237536285Sbrian {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", 237636285Sbrian "disable|enable", (const void *)OPT_THROUGHPUT}, 237736285Sbrian {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", 237836285Sbrian "disable|enable", (const void *)OPT_UTMP}, 237936285Sbrian 238047689Sbrian#define OPT_MAX 10 /* accept/deny allowed below and not above */ 238136285Sbrian 238236285Sbrian {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 238336285Sbrian "Address & Control field compression", "accept|deny|disable|enable", 238436285Sbrian (const void *)NEG_ACFCOMP}, 238544106Sbrian {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 238636285Sbrian "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", 238744106Sbrian (const void *)NEG_CHAP05}, 238844106Sbrian#ifdef HAVE_DES 238944106Sbrian {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 239044106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 239144106Sbrian (const void *)NEG_CHAP80}, 239244106Sbrian {"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX, 239344106Sbrian "Microsoft (NT) CHAP", "accept|deny|disable|enable", 239444106Sbrian (const void *)NEG_CHAP80LM}, 239544106Sbrian#endif 239636285Sbrian {"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 239736285Sbrian "Deflate compression", "accept|deny|disable|enable", 239836285Sbrian (const void *)NEG_DEFLATE}, 239936285Sbrian {"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 240036285Sbrian "Deflate (type 24) compression", "accept|deny|disable|enable", 240136285Sbrian (const void *)NEG_PPPDDEFLATE}, 240236285Sbrian {"dns", NULL, NegotiateSet, LOCAL_AUTH, 240336285Sbrian "DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS}, 240447858Sbrian {"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation", 240547858Sbrian "accept|deny|disable|enable", (const void *)NEG_ENDDISC}, 240636285Sbrian {"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 240736285Sbrian "Link Quality Reports", "accept|deny|disable|enable", 240836285Sbrian (const void *)NEG_LQR}, 240936285Sbrian {"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 241036285Sbrian "Password Authentication protocol", "accept|deny|disable|enable", 241136285Sbrian (const void *)NEG_PAP}, 241236285Sbrian {"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT, 241336285Sbrian "Predictor 1 compression", "accept|deny|disable|enable", 241436285Sbrian (const void *)NEG_PRED1}, 241536285Sbrian {"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, 241636285Sbrian "Protocol field compression", "accept|deny|disable|enable", 241736285Sbrian (const void *)NEG_PROTOCOMP}, 241836285Sbrian {"shortseq", NULL, NegotiateSet, LOCAL_AUTH, 241936285Sbrian "MP Short Sequence Numbers", "accept|deny|disable|enable", 242036285Sbrian (const void *)NEG_SHORTSEQ}, 242136285Sbrian {"vjcomp", NULL, NegotiateSet, LOCAL_AUTH, 242236285Sbrian "Van Jacobson header compression", "accept|deny|disable|enable", 242336285Sbrian (const void *)NEG_VJCOMP}, 242436285Sbrian {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, 242536285Sbrian "Display this message", "accept|deny|disable|enable help|? [value]", 242636285Sbrian NegotiateCommands}, 242736285Sbrian {NULL, NULL, NULL}, 242836285Sbrian}; 242936285Sbrian 243036285Sbrianstatic int 243136285SbrianNegotiateCommand(struct cmdargs const *arg) 243236285Sbrian{ 243336285Sbrian if (arg->argc > arg->argn) { 243436285Sbrian char const *argv[3]; 243536285Sbrian unsigned keep, add; 243636285Sbrian int n; 243736285Sbrian 243836285Sbrian if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL) 243936285Sbrian return -1; 244036285Sbrian argv[2] = NULL; 244136285Sbrian 244236285Sbrian for (n = arg->argn; n < arg->argc; n++) { 244336285Sbrian argv[1] = arg->argv[n]; 244436285Sbrian FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ? 244536285Sbrian 0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx); 244636285Sbrian } 244736285Sbrian } else if (arg->prompt) 244836285Sbrian prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n", 244936285Sbrian arg->argv[arg->argn-1]); 245036285Sbrian else 245136285Sbrian log_Printf(LogWARN, "%s command must have arguments\n", 245236285Sbrian arg->argv[arg->argn] ); 245336285Sbrian 245436285Sbrian return 0; 245536285Sbrian} 245636285Sbrian 245736285Sbrianconst char * 245836285Sbriancommand_ShowNegval(unsigned val) 245936285Sbrian{ 246036285Sbrian switch (val&3) { 246136285Sbrian case 1: return "disabled & accepted"; 246236285Sbrian case 2: return "enabled & denied"; 246336285Sbrian case 3: return "enabled & accepted"; 246436285Sbrian } 246536285Sbrian return "disabled & denied"; 246636285Sbrian} 246736934Sbrian 246836934Sbrianstatic int 246936934SbrianClearCommand(struct cmdargs const *arg) 247036934Sbrian{ 247136934Sbrian struct pppThroughput *t; 247236934Sbrian struct datalink *cx; 247336934Sbrian int i, clear_type; 247436934Sbrian 247536934Sbrian if (arg->argc < arg->argn + 1) 247636934Sbrian return -1; 247736934Sbrian 247846686Sbrian if (strcasecmp(arg->argv[arg->argn], "physical") == 0) { 247936934Sbrian cx = arg->cx; 248036934Sbrian if (!cx) 248136934Sbrian cx = bundle2datalink(arg->bundle, NULL); 248236934Sbrian if (!cx) { 248346686Sbrian log_Printf(LogWARN, "A link must be specified for ``clear physical''\n"); 248436934Sbrian return 1; 248536934Sbrian } 248636934Sbrian t = &cx->physical->link.throughput; 248736934Sbrian } else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0) 248836934Sbrian t = &arg->bundle->ncp.ipcp.throughput; 248936934Sbrian else 249036934Sbrian return -1; 249136934Sbrian 249236934Sbrian if (arg->argc > arg->argn + 1) { 249336934Sbrian clear_type = 0; 249436934Sbrian for (i = arg->argn + 1; i < arg->argc; i++) 249536934Sbrian if (strcasecmp(arg->argv[i], "overall") == 0) 249636934Sbrian clear_type |= THROUGHPUT_OVERALL; 249736934Sbrian else if (strcasecmp(arg->argv[i], "current") == 0) 249836934Sbrian clear_type |= THROUGHPUT_CURRENT; 249936934Sbrian else if (strcasecmp(arg->argv[i], "peak") == 0) 250036934Sbrian clear_type |= THROUGHPUT_PEAK; 250136934Sbrian else 250236934Sbrian return -1; 250336934Sbrian } else 250436934Sbrian clear_type = THROUGHPUT_ALL; 250536934Sbrian 250636934Sbrian throughput_clear(t, clear_type, arg->prompt); 250736934Sbrian return 0; 250836934Sbrian} 250940561Sbrian 251040561Sbrianstatic int 251140561SbrianRunListCommand(struct cmdargs const *arg) 251240561Sbrian{ 251340561Sbrian const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???"; 251440561Sbrian 251540561Sbrian if (arg->argc > arg->argn) 251640561Sbrian FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv, 251740561Sbrian arg->prompt, arg->cx); 251840561Sbrian else if (arg->prompt) 251940561Sbrian prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help" 252040561Sbrian " <option>' for syntax help.\n", cmd, cmd); 252140561Sbrian else 252240561Sbrian log_Printf(LogWARN, "%s command must have arguments\n", cmd); 252340561Sbrian 252440561Sbrian return 0; 252540561Sbrian} 252640561Sbrian 252740561Sbrianstatic int 252840561SbrianIfaceAddCommand(struct cmdargs const *arg) 252940561Sbrian{ 253040561Sbrian int bits, n, how; 253140561Sbrian struct in_addr ifa, mask, brd; 253240561Sbrian 253340664Sbrian if (arg->argc == arg->argn + 1) { 253443313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 253540561Sbrian return -1; 253640664Sbrian mask.s_addr = brd.s_addr = INADDR_BROADCAST; 253740664Sbrian } else { 253840664Sbrian if (arg->argc == arg->argn + 2) { 253943313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits)) 254040664Sbrian return -1; 254140664Sbrian n = 1; 254240664Sbrian } else if (arg->argc == arg->argn + 3) { 254343313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 254440664Sbrian return -1; 254543313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL)) 254640664Sbrian return -1; 254740664Sbrian n = 2; 254840664Sbrian } else 254940561Sbrian return -1; 255040561Sbrian 255143313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL)) 255240664Sbrian return -1; 255340664Sbrian } 255440561Sbrian 255540561Sbrian how = IFACE_ADD_LAST; 255640561Sbrian if (arg->cmd->args) 255740561Sbrian how |= IFACE_FORCE_ADD; 255840561Sbrian 255940561Sbrian return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how); 256040561Sbrian} 256140561Sbrian 256240561Sbrianstatic int 256340561SbrianIfaceDeleteCommand(struct cmdargs const *arg) 256440561Sbrian{ 256540561Sbrian struct in_addr ifa; 256640561Sbrian int ok; 256740561Sbrian 256840561Sbrian if (arg->argc != arg->argn + 1) 256940561Sbrian return -1; 257040561Sbrian 257143313Sbrian if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL)) 257240561Sbrian return -1; 257340561Sbrian 257440561Sbrian if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED && 257540561Sbrian arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) { 257640561Sbrian log_Printf(LogWARN, "%s: Cannot remove active interface address\n", 257740561Sbrian inet_ntoa(ifa)); 257840561Sbrian return 1; 257940561Sbrian } 258040561Sbrian 258140561Sbrian ok = iface_inDelete(arg->bundle->iface, ifa); 258240561Sbrian if (!ok) { 258340561Sbrian if (arg->cmd->args) 258440561Sbrian ok = 1; 258540561Sbrian else if (arg->prompt) 258640561Sbrian prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa)); 258740561Sbrian else 258840561Sbrian log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa)); 258940561Sbrian } 259040561Sbrian 259140561Sbrian return !ok; 259240561Sbrian} 259340561Sbrian 259440561Sbrianstatic int 259540561SbrianIfaceClearCommand(struct cmdargs const *arg) 259640561Sbrian{ 259740561Sbrian int how; 259840561Sbrian 259940561Sbrian if (arg->argc != arg->argn) 260040561Sbrian return -1; 260140561Sbrian 260240941Sbrian how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED || 260340941Sbrian arg->bundle->phys_type.all & PHYS_AUTO ? 260440561Sbrian IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL; 260540561Sbrian iface_Clear(arg->bundle->iface, how); 260640561Sbrian 260740561Sbrian return 0; 260840561Sbrian} 260940679Sbrian 261040679Sbrianstatic int 261140679SbrianSetProcTitle(struct cmdargs const *arg) 261240679Sbrian{ 261340679Sbrian static char title[LINE_LEN]; 261440679Sbrian char *argv[MAXARGS], *ptr; 261540679Sbrian int len, remaining, f, argc = arg->argc - arg->argn; 261640679Sbrian 261740679Sbrian if (arg->argc == arg->argn) { 261853298Sbrian ID0setproctitle(NULL); 261940679Sbrian return 0; 262040679Sbrian } 262140679Sbrian 262240679Sbrian if (argc >= sizeof argv / sizeof argv[0]) { 262340679Sbrian argc = sizeof argv / sizeof argv[0] - 1; 262440679Sbrian log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); 262540679Sbrian } 262647849Sbrian command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid()); 262740679Sbrian 262840679Sbrian ptr = title; 262940679Sbrian remaining = sizeof title - 1; 263040679Sbrian for (f = 0; f < argc && remaining; f++) { 263140679Sbrian if (f) { 263240679Sbrian *ptr++ = ' '; 263340679Sbrian remaining--; 263440679Sbrian } 263540679Sbrian len = strlen(argv[f]); 263640679Sbrian if (len > remaining) 263740679Sbrian len = remaining; 263840679Sbrian memcpy(ptr, argv[f], len); 263940679Sbrian remaining -= len; 264040679Sbrian ptr += len; 264140679Sbrian } 264240679Sbrian *ptr = '\0'; 264340679Sbrian 264453298Sbrian ID0setproctitle(title); 264540679Sbrian 264640679Sbrian return 0; 264740679Sbrian} 2648