1995-01-31 06:29:58 +00:00
|
|
|
/*
|
|
|
|
* PPP User command processing module
|
|
|
|
*
|
|
|
|
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
|
|
|
|
*
|
|
|
|
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* provided that the above copyright notice and this paragraph are
|
|
|
|
* duplicated in all such forms and that any documentation,
|
|
|
|
* advertising materials, and other materials related to such
|
|
|
|
* distribution and use acknowledge that the software was developed
|
|
|
|
* by the Internet Initiative Japan, Inc. The name of the
|
|
|
|
* IIJ may not be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
1995-05-30 03:57:47 +00:00
|
|
|
*
|
1999-08-28 01:35:59 +00:00
|
|
|
* $FreeBSD$
|
1995-05-30 03:57:47 +00:00
|
|
|
*
|
1995-01-31 06:29:58 +00:00
|
|
|
*/
|
1999-01-28 01:56:34 +00:00
|
|
|
#include <sys/param.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <netinet/in_systm.h>
|
1997-05-23 04:54:03 +00:00
|
|
|
#include <netinet/in.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <netinet/ip.h>
|
1997-05-23 04:54:03 +00:00
|
|
|
#include <arpa/inet.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <sys/socket.h>
|
1997-05-23 04:54:03 +00:00
|
|
|
#include <net/route.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <netdb.h>
|
1998-05-21 21:49:08 +00:00
|
|
|
#include <sys/un.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
|
1998-08-29 23:02:39 +00:00
|
|
|
#include <ctype.h>
|
1997-06-09 03:27:43 +00:00
|
|
|
#include <errno.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <paths.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
1999-08-19 18:15:52 +00:00
|
|
|
#ifndef NONAT
|
1999-04-26 08:54:34 +00:00
|
|
|
#ifdef __FreeBSD__
|
1998-09-17 00:45:27 +00:00
|
|
|
#include <alias.h>
|
1999-04-26 08:54:34 +00:00
|
|
|
#else
|
|
|
|
#include "alias.h"
|
1998-09-17 00:45:27 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
1999-05-08 11:07:56 +00:00
|
|
|
#include "layer.h"
|
1998-06-15 19:06:25 +00:00
|
|
|
#include "defs.h"
|
1997-11-22 03:37:54 +00:00
|
|
|
#include "command.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
#include "mbuf.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "timer.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "fsm.h"
|
|
|
|
#include "lcp.h"
|
1997-12-13 02:37:33 +00:00
|
|
|
#include "iplist.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "throughput.h"
|
|
|
|
#include "slcompress.h"
|
1998-08-26 17:39:37 +00:00
|
|
|
#include "lqr.h"
|
|
|
|
#include "hdlc.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "ipcp.h"
|
1999-08-19 18:15:52 +00:00
|
|
|
#ifndef NONAT
|
1997-05-23 04:54:03 +00:00
|
|
|
#include "alias_cmd.h"
|
1997-11-22 03:37:54 +00:00
|
|
|
#endif
|
1997-05-10 01:22:19 +00:00
|
|
|
#include "systems.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "filter.h"
|
|
|
|
#include "descriptor.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
#include "main.h"
|
|
|
|
#include "route.h"
|
|
|
|
#include "ccp.h"
|
1997-11-09 18:51:23 +00:00
|
|
|
#include "auth.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "async.h"
|
|
|
|
#include "link.h"
|
|
|
|
#include "physical.h"
|
|
|
|
#include "mp.h"
|
1999-01-28 01:56:34 +00:00
|
|
|
#ifndef NORADIUS
|
|
|
|
#include "radius.h"
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "bundle.h"
|
|
|
|
#include "server.h"
|
|
|
|
#include "prompt.h"
|
|
|
|
#include "chat.h"
|
|
|
|
#include "chap.h"
|
1998-08-07 18:42:51 +00:00
|
|
|
#include "cbcp.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "datalink.h"
|
1998-10-22 02:32:50 +00:00
|
|
|
#include "iface.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
/* ``set'' values */
|
|
|
|
#define VAR_AUTHKEY 0
|
|
|
|
#define VAR_DIAL 1
|
|
|
|
#define VAR_LOGIN 2
|
|
|
|
#define VAR_AUTHNAME 3
|
|
|
|
#define VAR_AUTOLOAD 4
|
|
|
|
#define VAR_WINSIZE 5
|
|
|
|
#define VAR_DEVICE 6
|
|
|
|
#define VAR_ACCMAP 7
|
|
|
|
#define VAR_MRRU 8
|
|
|
|
#define VAR_MRU 9
|
|
|
|
#define VAR_MTU 10
|
|
|
|
#define VAR_OPENMODE 11
|
|
|
|
#define VAR_PHONE 12
|
|
|
|
#define VAR_HANGUP 13
|
|
|
|
#define VAR_IDLETIMEOUT 14
|
|
|
|
#define VAR_LQRPERIOD 15
|
|
|
|
#define VAR_LCPRETRY 16
|
|
|
|
#define VAR_CHAPRETRY 17
|
|
|
|
#define VAR_PAPRETRY 18
|
|
|
|
#define VAR_CCPRETRY 19
|
|
|
|
#define VAR_IPCPRETRY 20
|
|
|
|
#define VAR_DNS 21
|
|
|
|
#define VAR_NBNS 22
|
|
|
|
#define VAR_MODE 23
|
1998-08-07 18:42:51 +00:00
|
|
|
#define VAR_CALLBACK 24
|
|
|
|
#define VAR_CBCP 25
|
1998-08-25 17:48:43 +00:00
|
|
|
#define VAR_CHOKED 26
|
1998-10-26 19:07:39 +00:00
|
|
|
#define VAR_SENDPIPE 27
|
|
|
|
#define VAR_RECVPIPE 28
|
1999-01-28 01:56:34 +00:00
|
|
|
#define VAR_RADIUS 29
|
1999-02-16 00:16:56 +00:00
|
|
|
#define VAR_CD 30
|
1999-05-08 11:07:56 +00:00
|
|
|
#define VAR_PARITY 31
|
|
|
|
#define VAR_CRTSCTS 32
|
1999-09-04 00:00:21 +00:00
|
|
|
#define VAR_URGENTPORTS 33
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
/* ``accept|deny|disable|enable'' masks */
|
|
|
|
#define NEG_HISMASK (1)
|
|
|
|
#define NEG_MYMASK (2)
|
|
|
|
|
|
|
|
/* ``accept|deny|disable|enable'' values */
|
|
|
|
#define NEG_ACFCOMP 40
|
1999-02-18 00:52:15 +00:00
|
|
|
#define NEG_CHAP05 41
|
|
|
|
#define NEG_CHAP80 42
|
|
|
|
#define NEG_CHAP80LM 43
|
|
|
|
#define NEG_DEFLATE 44
|
1999-06-09 16:54:04 +00:00
|
|
|
#define NEG_DNS 45
|
|
|
|
#define NEG_ENDDISC 46
|
|
|
|
#define NEG_LQR 47
|
|
|
|
#define NEG_PAP 48
|
|
|
|
#define NEG_PPPDDEFLATE 49
|
|
|
|
#define NEG_PRED1 50
|
|
|
|
#define NEG_PROTOCOMP 51
|
|
|
|
#define NEG_SHORTSEQ 52
|
|
|
|
#define NEG_VJCOMP 53
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1999-08-05 10:32:16 +00:00
|
|
|
const char Version[] = "2.23";
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
static int ShowCommand(struct cmdargs const *);
|
|
|
|
static int TerminalCommand(struct cmdargs const *);
|
|
|
|
static int QuitCommand(struct cmdargs const *);
|
|
|
|
static int OpenCommand(struct cmdargs const *);
|
|
|
|
static int CloseCommand(struct cmdargs const *);
|
|
|
|
static int DownCommand(struct cmdargs const *);
|
|
|
|
static int SetCommand(struct cmdargs const *);
|
|
|
|
static int LinkCommand(struct cmdargs const *);
|
|
|
|
static int AddCommand(struct cmdargs const *);
|
|
|
|
static int DeleteCommand(struct cmdargs const *);
|
|
|
|
static int NegotiateCommand(struct cmdargs const *);
|
1998-06-12 20:12:26 +00:00
|
|
|
static int ClearCommand(struct cmdargs const *);
|
1998-10-22 02:32:50 +00:00
|
|
|
static int RunListCommand(struct cmdargs const *);
|
|
|
|
static int IfaceAddCommand(struct cmdargs const *);
|
|
|
|
static int IfaceDeleteCommand(struct cmdargs const *);
|
|
|
|
static int IfaceClearCommand(struct cmdargs const *);
|
1998-10-27 22:53:22 +00:00
|
|
|
static int SetProcTitle(struct cmdargs const *);
|
1999-08-19 18:15:52 +00:00
|
|
|
#ifndef NONAT
|
1998-05-21 21:49:08 +00:00
|
|
|
static int AliasEnable(struct cmdargs const *);
|
|
|
|
static int AliasOption(struct cmdargs const *);
|
1997-11-22 03:37:54 +00:00
|
|
|
#endif
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static const char *
|
|
|
|
showcx(struct cmdtab const *cmd)
|
|
|
|
{
|
|
|
|
if (cmd->lauth & LOCAL_CX)
|
|
|
|
return "(c)";
|
|
|
|
else if (cmd->lauth & LOCAL_CX_OPT)
|
|
|
|
return "(o)";
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
HelpCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1997-08-25 00:29:32 +00:00
|
|
|
struct cmdtab const *cmd;
|
1998-05-21 21:49:08 +00:00
|
|
|
int n, cmax, dmax, cols, cxlen;
|
|
|
|
const char *cx;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (!arg->prompt) {
|
|
|
|
log_Printf(LogWARN, "help: Cannot help without a prompt\n");
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1997-06-09 03:27:43 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn) {
|
|
|
|
for (cmd = arg->cmdtab; cmd->name || cmd->alias; cmd++)
|
|
|
|
if ((cmd->lauth & arg->prompt->auth) &&
|
|
|
|
((cmd->name && !strcasecmp(cmd->name, arg->argv[arg->argn])) ||
|
|
|
|
(cmd->alias && !strcasecmp(cmd->alias, arg->argv[arg->argn])))) {
|
|
|
|
prompt_Printf(arg->prompt, "%s %s\n", cmd->syntax, showcx(cmd));
|
1997-08-25 00:29:32 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-06-09 03:27:43 +00:00
|
|
|
return -1;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1997-11-23 20:05:18 +00:00
|
|
|
cmax = dmax = 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
for (cmd = arg->cmdtab; cmd->func; cmd++)
|
|
|
|
if (cmd->name && (cmd->lauth & arg->prompt->auth)) {
|
|
|
|
if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax)
|
1997-11-23 20:05:18 +00:00
|
|
|
cmax = n;
|
|
|
|
if ((n = strlen(cmd->helpmes)) > dmax)
|
|
|
|
dmax = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
cols = 80 / (dmax + cmax + 3);
|
1995-01-31 06:29:58 +00:00
|
|
|
n = 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "(o) = Optional context,"
|
|
|
|
" (c) = Context required\n");
|
|
|
|
for (cmd = arg->cmdtab; cmd->func; cmd++)
|
|
|
|
if (cmd->name && (cmd->lauth & arg->prompt->auth)) {
|
|
|
|
cx = showcx(cmd);
|
|
|
|
cxlen = cmax - strlen(cmd->name);
|
1998-10-17 12:28:05 +00:00
|
|
|
if (n % cols != 0)
|
|
|
|
prompt_Printf(arg->prompt, " ");
|
|
|
|
prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s",
|
1998-05-21 21:49:08 +00:00
|
|
|
cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes);
|
1997-11-23 20:05:18 +00:00
|
|
|
if (++n % cols == 0)
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "\n");
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-11-23 20:05:18 +00:00
|
|
|
if (n % cols != 0)
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "\n");
|
1997-06-09 03:27:43 +00:00
|
|
|
|
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static int
|
|
|
|
CloneCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
char namelist[LINE_LEN];
|
|
|
|
char *name;
|
|
|
|
int f;
|
|
|
|
|
|
|
|
if (arg->argc == arg->argn)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
namelist[sizeof namelist - 1] = '\0';
|
|
|
|
for (f = arg->argn; f < arg->argc; f++) {
|
|
|
|
strncpy(namelist, arg->argv[f], sizeof namelist - 1);
|
|
|
|
for(name = strtok(namelist, ", "); name; name = strtok(NULL,", "))
|
|
|
|
bundle_DatalinkClone(arg->bundle, arg->cx, name);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
RemoveCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc != arg->argn)
|
|
|
|
return -1;
|
1995-10-08 14:57:32 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->cx->state != DATALINK_CLOSED) {
|
|
|
|
log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n");
|
|
|
|
return 2;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-06-09 03:27:43 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
bundle_DatalinkRemove(arg->bundle, arg->cx);
|
|
|
|
return 0;
|
|
|
|
}
|
1998-01-23 04:36:42 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static int
|
|
|
|
RenameCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
if (arg->argc != arg->argn + 1)
|
|
|
|
return -1;
|
1997-11-11 22:58:14 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn]))
|
|
|
|
return 0;
|
1997-06-09 03:27:43 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "%s -> %s: target name already exists\n",
|
|
|
|
arg->cx->name, arg->argv[arg->argn]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
LoadCommand(struct cmdargs const *arg)
|
|
|
|
{
|
1998-10-31 17:38:47 +00:00
|
|
|
const char *err;
|
|
|
|
int n, mode;
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1998-10-31 17:38:47 +00:00
|
|
|
mode = arg->bundle->phys_type.all;
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1998-10-31 17:38:47 +00:00
|
|
|
if (arg->argn < arg->argc) {
|
|
|
|
for (n = arg->argn; n < arg->argc; n++)
|
|
|
|
if ((err = system_IsValid(arg->argv[n], arg->prompt, mode)) != NULL) {
|
|
|
|
log_Printf(LogWARN, "%s: %s\n", arg->argv[n], err);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (n = arg->argn; n < arg->argc; n++) {
|
|
|
|
bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]);
|
|
|
|
system_Select(arg->bundle, arg->argv[n], CONFFILE, arg->prompt, arg->cx);
|
|
|
|
}
|
|
|
|
bundle_SetLabel(arg->bundle, arg->argv[arg->argc - 1]);
|
|
|
|
} else if ((err = system_IsValid("default", arg->prompt, mode)) != NULL) {
|
|
|
|
log_Printf(LogWARN, "default: %s\n", err);
|
1998-05-21 21:49:08 +00:00
|
|
|
return 1;
|
|
|
|
} else {
|
1998-10-31 17:38:47 +00:00
|
|
|
bundle_SetLabel(arg->bundle, "default");
|
|
|
|
system_Select(arg->bundle, "default", CONFFILE, arg->prompt, arg->cx);
|
|
|
|
bundle_SetLabel(arg->bundle, "default");
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1998-10-31 17:38:47 +00:00
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
int
|
|
|
|
SaveCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
log_Printf(LogWARN, "save command is not implemented (yet).\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1997-08-21 16:21:39 +00:00
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
DialCommand(struct cmdargs const *arg)
|
1997-08-21 16:21:39 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
int res;
|
|
|
|
|
1998-05-29 18:32:11 +00:00
|
|
|
if ((arg->cx && !(arg->cx->physical->type & (PHYS_INTERACTIVE|PHYS_AUTO)))
|
|
|
|
|| (!arg->cx &&
|
1998-06-12 17:45:10 +00:00
|
|
|
(arg->bundle->phys_type.all & ~(PHYS_INTERACTIVE|PHYS_AUTO)))) {
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "Manual dial is only available for auto and"
|
|
|
|
" interactive links\n");
|
|
|
|
return 1;
|
1998-03-13 01:36:10 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0)
|
|
|
|
return res;
|
|
|
|
|
1998-07-31 19:50:24 +00:00
|
|
|
bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1);
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
return 0;
|
1997-08-21 16:21:39 +00:00
|
|
|
}
|
|
|
|
|
1998-08-29 23:02:39 +00:00
|
|
|
#define isinword(ch) (isalnum(ch) || (ch) == '_')
|
|
|
|
|
|
|
|
static char *
|
|
|
|
strstrword(char *big, const char *little)
|
|
|
|
{
|
|
|
|
/* Get the first occurance of the word ``little'' in ``big'' */
|
|
|
|
char *pos;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
pos = big;
|
|
|
|
len = strlen(little);
|
|
|
|
|
|
|
|
while ((pos = strstr(pos, little)) != NULL)
|
1999-06-10 09:34:57 +00:00
|
|
|
if ((pos != big && isinword(pos[-1])) || isinword(pos[len]))
|
1998-08-29 23:02:39 +00:00
|
|
|
pos++;
|
1999-06-10 09:34:57 +00:00
|
|
|
else if (pos != big && pos[-1] == '\\')
|
|
|
|
memmove(pos - 1, pos, strlen(pos) + 1);
|
|
|
|
else
|
|
|
|
break;
|
1998-08-29 23:02:39 +00:00
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
subst(char *tgt, const char *oldstr, const char *newstr)
|
|
|
|
{
|
|
|
|
/* tgt is a malloc()d area... realloc() as necessary */
|
|
|
|
char *word, *ntgt;
|
|
|
|
int ltgt, loldstr, lnewstr, pos;
|
|
|
|
|
|
|
|
if ((word = strstrword(tgt, oldstr)) == NULL)
|
|
|
|
return tgt;
|
|
|
|
|
|
|
|
ltgt = strlen(tgt) + 1;
|
|
|
|
loldstr = strlen(oldstr);
|
|
|
|
lnewstr = strlen(newstr);
|
|
|
|
do {
|
|
|
|
pos = word - tgt;
|
|
|
|
if (loldstr > lnewstr)
|
|
|
|
bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr);
|
|
|
|
if (loldstr != lnewstr) {
|
|
|
|
ntgt = realloc(tgt, ltgt += lnewstr - loldstr);
|
|
|
|
if (ntgt == NULL)
|
|
|
|
break; /* Oh wonderful ! */
|
|
|
|
word = ntgt + pos;
|
|
|
|
tgt = ntgt;
|
|
|
|
}
|
|
|
|
if (lnewstr > loldstr)
|
|
|
|
bcopy(word + loldstr, word + lnewstr, ltgt - pos - loldstr);
|
|
|
|
bcopy(newstr, word, lnewstr);
|
|
|
|
} while ((word = strstrword(word, oldstr)));
|
|
|
|
|
|
|
|
return tgt;
|
|
|
|
}
|
|
|
|
|
1999-02-11 10:14:08 +00:00
|
|
|
void
|
|
|
|
command_Expand(char **nargv, int argc, char const *const *oargv,
|
1999-06-09 08:47:36 +00:00
|
|
|
struct bundle *bundle, int inc0, pid_t pid)
|
1998-08-29 23:02:39 +00:00
|
|
|
{
|
|
|
|
int arg;
|
1999-06-09 08:47:36 +00:00
|
|
|
char pidstr[12];
|
1998-08-29 23:02:39 +00:00
|
|
|
|
1998-12-14 01:15:34 +00:00
|
|
|
if (inc0)
|
|
|
|
arg = 0; /* Start at arg 0 */
|
|
|
|
else {
|
|
|
|
nargv[0] = strdup(oargv[0]);
|
|
|
|
arg = 1;
|
|
|
|
}
|
1999-06-09 08:47:36 +00:00
|
|
|
snprintf(pidstr, sizeof pidstr, "%d", (int)pid);
|
1998-12-14 01:15:34 +00:00
|
|
|
for (; arg < argc; arg++) {
|
1998-08-29 23:02:42 +00:00
|
|
|
nargv[arg] = strdup(oargv[arg]);
|
|
|
|
nargv[arg] = subst(nargv[arg], "HISADDR",
|
1998-08-29 23:02:39 +00:00
|
|
|
inet_ntoa(bundle->ncp.ipcp.peer_ip));
|
1998-08-29 23:02:42 +00:00
|
|
|
nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name);
|
1998-10-22 02:32:50 +00:00
|
|
|
nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name);
|
1998-08-29 23:02:39 +00:00
|
|
|
nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip));
|
1998-08-29 23:02:42 +00:00
|
|
|
nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname);
|
|
|
|
nargv[arg] = subst(nargv[arg], "PEER_ENDDISC",
|
|
|
|
mp_Enddisc(bundle->ncp.mp.peer.enddisc.class,
|
|
|
|
bundle->ncp.mp.peer.enddisc.address,
|
|
|
|
bundle->ncp.mp.peer.enddisc.len));
|
|
|
|
nargv[arg] = subst(nargv[arg], "ENDDISC",
|
|
|
|
mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class,
|
|
|
|
bundle->ncp.mp.cfg.enddisc.address,
|
|
|
|
bundle->ncp.mp.cfg.enddisc.len));
|
1999-06-09 08:47:36 +00:00
|
|
|
nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr);
|
1998-08-29 23:02:42 +00:00
|
|
|
nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle));
|
1998-08-29 23:02:39 +00:00
|
|
|
}
|
|
|
|
nargv[arg] = NULL;
|
|
|
|
}
|
|
|
|
|
1995-09-02 17:20:54 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
ShellCommand(struct cmdargs const *arg, int bg)
|
1995-09-02 17:20:54 +00:00
|
|
|
{
|
|
|
|
const char *shell;
|
1999-06-09 08:47:36 +00:00
|
|
|
pid_t shpid, pid;
|
1996-12-22 17:29:33 +00:00
|
|
|
|
1996-10-10 11:27:35 +00:00
|
|
|
#ifdef SHELL_ONLY_INTERACTIVELY
|
1997-06-25 02:04:35 +00:00
|
|
|
/* we're only allowed to shell when we run ppp interactively */
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->prompt && arg->prompt->owner) {
|
|
|
|
log_Printf(LogWARN, "Can't start a shell from a network connection\n");
|
1997-06-09 03:27:43 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc == arg->argn) {
|
|
|
|
if (!arg->prompt) {
|
|
|
|
log_Printf(LogWARN, "Can't start an interactive shell from"
|
|
|
|
" a config file\n");
|
|
|
|
return 1;
|
|
|
|
} else if (arg->prompt->owner) {
|
|
|
|
log_Printf(LogWARN, "Can't start an interactive shell from"
|
|
|
|
" a socket connection\n");
|
1997-08-18 20:15:10 +00:00
|
|
|
return 1;
|
|
|
|
} else if (bg) {
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "Can only start an interactive shell in"
|
1997-08-25 00:29:32 +00:00
|
|
|
" the foreground mode\n");
|
1997-08-18 20:15:10 +00:00
|
|
|
return 1;
|
|
|
|
}
|
1998-03-13 01:36:10 +00:00
|
|
|
}
|
|
|
|
|
1999-06-09 08:47:36 +00:00
|
|
|
pid = getpid();
|
1997-08-25 00:29:32 +00:00
|
|
|
if ((shpid = fork()) == 0) {
|
1998-05-21 21:49:08 +00:00
|
|
|
int i, fd;
|
|
|
|
|
|
|
|
if ((shell = getenv("SHELL")) == 0)
|
|
|
|
shell = _PATH_BSHELL;
|
|
|
|
|
|
|
|
timer_TermService();
|
|
|
|
|
|
|
|
if (arg->prompt)
|
|
|
|
fd = arg->prompt->fd_out;
|
|
|
|
else if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
|
|
|
log_Printf(LogALERT, "Failed to open %s: %s\n",
|
|
|
|
_PATH_DEVNULL, strerror(errno));
|
1997-08-25 00:29:32 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
1999-08-17 14:59:05 +00:00
|
|
|
dup2(fd, STDIN_FILENO);
|
|
|
|
dup2(fd, STDOUT_FILENO);
|
|
|
|
dup2(fd, STDERR_FILENO);
|
|
|
|
for (i = getdtablesize(); i > STDERR_FILENO; i--)
|
|
|
|
fcntl(i, F_SETFD, 1);
|
1997-08-25 00:29:32 +00:00
|
|
|
|
1997-11-09 06:22:49 +00:00
|
|
|
setuid(geteuid());
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn) {
|
1997-08-25 00:29:32 +00:00
|
|
|
/* substitute pseudo args */
|
1998-08-29 23:02:39 +00:00
|
|
|
char *argv[MAXARGS];
|
|
|
|
int argc = arg->argc - arg->argn;
|
|
|
|
|
|
|
|
if (argc >= sizeof argv / sizeof argv[0]) {
|
|
|
|
argc = sizeof argv / sizeof argv[0] - 1;
|
|
|
|
log_Printf(LogWARN, "Truncating shell command to %d args\n", argc);
|
1997-11-22 03:37:54 +00:00
|
|
|
}
|
1999-06-09 08:47:36 +00:00
|
|
|
command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0, pid);
|
1997-08-25 00:29:32 +00:00
|
|
|
if (bg) {
|
|
|
|
pid_t p;
|
|
|
|
|
|
|
|
p = getpid();
|
|
|
|
if (daemon(1, 1) == -1) {
|
1998-06-10 00:16:07 +00:00
|
|
|
log_Printf(LogERROR, "%d: daemon: %s\n", (int)p, strerror(errno));
|
1997-08-25 00:29:32 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
} else if (arg->prompt)
|
|
|
|
printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]);
|
1997-11-22 03:37:54 +00:00
|
|
|
execvp(argv[0], argv);
|
1997-10-12 01:49:37 +00:00
|
|
|
} else {
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->prompt)
|
1997-12-27 07:22:12 +00:00
|
|
|
printf("ppp: Pausing until %s finishes\n", shell);
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_TtyOldMode(arg->prompt);
|
1997-11-22 03:37:54 +00:00
|
|
|
execl(shell, shell, NULL);
|
1997-10-12 01:49:37 +00:00
|
|
|
}
|
1997-08-25 00:29:32 +00:00
|
|
|
|
1998-10-26 19:07:39 +00:00
|
|
|
log_Printf(LogWARN, "exec() of %s failed: %s\n",
|
|
|
|
arg->argc > arg->argn ? arg->argv[arg->argn] : shell,
|
|
|
|
strerror(errno));
|
1999-08-17 14:59:05 +00:00
|
|
|
_exit(255);
|
1997-08-25 00:29:32 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (shpid == (pid_t) - 1)
|
|
|
|
log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno));
|
|
|
|
else {
|
|
|
|
int status;
|
1997-11-22 03:37:54 +00:00
|
|
|
waitpid(shpid, &status, 0);
|
1995-09-02 17:20:54 +00:00
|
|
|
}
|
1996-12-22 17:29:33 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->prompt && !arg->prompt->owner)
|
|
|
|
prompt_TtyCommandMode(arg->prompt);
|
1996-12-22 17:29:33 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
return 0;
|
1995-09-02 17:20:54 +00:00
|
|
|
}
|
|
|
|
|
1997-11-22 03:37:54 +00:00
|
|
|
static int
|
|
|
|
BgShellCommand(struct cmdargs const *arg)
|
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc == arg->argn)
|
1997-11-22 03:37:54 +00:00
|
|
|
return -1;
|
|
|
|
return ShellCommand(arg, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
FgShellCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
return ShellCommand(arg, 0);
|
|
|
|
}
|
|
|
|
|
1999-08-19 18:15:52 +00:00
|
|
|
#ifndef NONAT
|
1998-10-22 02:32:50 +00:00
|
|
|
static struct cmdtab const AliasCommands[] =
|
|
|
|
{
|
1999-08-19 18:15:52 +00:00
|
|
|
{"addr", NULL, nat_RedirectAddr, LOCAL_AUTH,
|
|
|
|
"static address translation", "nat addr [addr_local addr_alias]"},
|
1998-10-22 02:32:50 +00:00
|
|
|
{"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"stop incoming connections", "nat deny_incoming yes|no",
|
1998-10-22 02:32:50 +00:00
|
|
|
(const void *) PKT_ALIAS_DENY_INCOMING},
|
|
|
|
{"enable", NULL, AliasEnable, LOCAL_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"enable NAT", "nat enable yes|no"},
|
1998-10-22 02:32:50 +00:00
|
|
|
{"log", NULL, AliasOption, LOCAL_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"log NAT link creation", "nat log yes|no",
|
1998-10-22 02:32:50 +00:00
|
|
|
(const void *) PKT_ALIAS_LOG},
|
1999-08-19 18:15:52 +00:00
|
|
|
{"port", NULL, nat_RedirectPort, LOCAL_AUTH, "port redirection",
|
|
|
|
"nat port proto localaddr:port[-port] aliasport[-aliasport]"},
|
|
|
|
{"pptp", NULL, nat_Pptp, LOCAL_AUTH,
|
|
|
|
"Set the PPTP address", "nat pptp IP"},
|
|
|
|
{"proxy", NULL, nat_ProxyRule, LOCAL_AUTH,
|
|
|
|
"proxy control", "nat proxy server host[:port] ..."},
|
1998-10-22 02:32:50 +00:00
|
|
|
{"same_ports", NULL, AliasOption, LOCAL_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"try to leave port numbers unchanged", "nat same_ports yes|no",
|
1998-10-22 02:32:50 +00:00
|
|
|
(const void *) PKT_ALIAS_SAME_PORTS},
|
|
|
|
{"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"translate unregistered (private) IP address space only",
|
|
|
|
"nat unregistered_only yes|no",
|
1998-10-22 02:32:50 +00:00
|
|
|
(const void *) PKT_ALIAS_UNREGISTERED_ONLY},
|
|
|
|
{"use_sockets", NULL, AliasOption, LOCAL_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"allocate host sockets", "nat use_sockets yes|no",
|
1998-10-22 02:32:50 +00:00
|
|
|
(const void *) PKT_ALIAS_USE_SOCKETS},
|
|
|
|
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"Display this message", "nat help|? [command]", AliasCommands},
|
1998-10-22 02:32:50 +00:00
|
|
|
{NULL, NULL, NULL},
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct cmdtab const AllowCommands[] = {
|
|
|
|
{"modes", "mode", AllowModes, LOCAL_AUTH,
|
|
|
|
"Only allow certain ppp modes", "allow modes mode..."},
|
|
|
|
{"users", "user", AllowUsers, LOCAL_AUTH,
|
|
|
|
"Only allow ppp access to certain users", "allow users logname..."},
|
|
|
|
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
|
|
|
|
"Display this message", "allow help|? [command]", AllowCommands},
|
|
|
|
{NULL, NULL, NULL},
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct cmdtab const IfaceCommands[] =
|
|
|
|
{
|
|
|
|
{"add", NULL, IfaceAddCommand, LOCAL_AUTH,
|
|
|
|
"Add iface address", "iface add addr[/bits| mask] peer", NULL},
|
|
|
|
{NULL, "add!", IfaceAddCommand, LOCAL_AUTH,
|
|
|
|
"Add or change an iface address", "iface add! addr[/bits| mask] peer",
|
|
|
|
(void *)1},
|
|
|
|
{"clear", NULL, IfaceClearCommand, LOCAL_AUTH,
|
|
|
|
"Clear iface address(es)", "iface clear"},
|
|
|
|
{"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH,
|
|
|
|
"Delete iface address", "iface delete addr", NULL},
|
|
|
|
{NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH,
|
|
|
|
"Delete iface address", "iface delete addr", (void *)1},
|
|
|
|
{NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH,
|
|
|
|
"Delete iface address", "iface delete addr", (void *)1},
|
|
|
|
{"show", NULL, iface_Show, LOCAL_AUTH,
|
|
|
|
"Show iface address(es)", "iface show"},
|
|
|
|
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
|
1999-08-19 18:15:52 +00:00
|
|
|
"Display this message", "nat help|? [command]", IfaceCommands},
|
1998-10-22 02:32:50 +00:00
|
|
|
{NULL, NULL, NULL},
|
|
|
|
};
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static struct cmdtab const Commands[] = {
|
1998-05-21 21:49:08 +00:00
|
|
|
{"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1997-08-25 00:29:32 +00:00
|
|
|
"accept option request", "accept option .."},
|
|
|
|
{"add", NULL, AddCommand, LOCAL_AUTH,
|
1997-12-30 02:45:48 +00:00
|
|
|
"add route", "add dest mask gateway", NULL},
|
1998-05-21 21:49:08 +00:00
|
|
|
{NULL, "add!", AddCommand, LOCAL_AUTH,
|
1997-12-30 02:45:48 +00:00
|
|
|
"add or change route", "add! dest mask gateway", (void *)1},
|
1998-10-22 02:32:50 +00:00
|
|
|
{"allow", "auth", RunListCommand, LOCAL_AUTH,
|
|
|
|
"Allow ppp access", "allow users|modes ....", AllowCommands},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"bg", "!bg", BgShellCommand, LOCAL_AUTH,
|
1997-11-23 20:05:18 +00:00
|
|
|
"Run a background command", "[!]bg command"},
|
1998-06-12 20:12:26 +00:00
|
|
|
{"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1999-05-08 11:07:56 +00:00
|
|
|
"Clear throughput statistics",
|
|
|
|
"clear ipcp|physical [current|overall|peak]..."},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Clone a link", "clone newname..."},
|
|
|
|
{"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"Close an FSM", "close [lcp|ccp]"},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"delete", NULL, DeleteCommand, LOCAL_AUTH,
|
1997-12-30 02:45:48 +00:00
|
|
|
"delete route", "delete dest", NULL},
|
1998-05-21 21:49:08 +00:00
|
|
|
{NULL, "delete!", DeleteCommand, LOCAL_AUTH,
|
1997-12-30 02:45:48 +00:00
|
|
|
"delete a route if it exists", "delete! dest", (void *)1},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1997-08-25 00:29:32 +00:00
|
|
|
"Deny option request", "deny option .."},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1998-10-31 17:38:47 +00:00
|
|
|
"Dial and login", "dial|call [system ...]", NULL},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1997-08-25 00:29:32 +00:00
|
|
|
"Disable option", "disable option .."},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1999-05-08 11:07:56 +00:00
|
|
|
"Generate a down event", "down [ccp|lcp]"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1997-08-25 00:29:32 +00:00
|
|
|
"Enable option", "enable option .."},
|
1998-10-22 02:32:50 +00:00
|
|
|
{"iface", "interface", RunListCommand, LOCAL_AUTH,
|
|
|
|
"interface control", "iface option ...", IfaceCommands},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"link", "datalink", LinkCommand, LOCAL_AUTH,
|
|
|
|
"Link specific commands", "link name command ..."},
|
1998-06-15 19:05:51 +00:00
|
|
|
{"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1998-10-31 17:38:47 +00:00
|
|
|
"Load settings", "load [system ...]"},
|
1999-08-19 18:15:52 +00:00
|
|
|
#ifndef NONAT
|
|
|
|
{"nat", "alias", RunListCommand, LOCAL_AUTH,
|
|
|
|
"NAT control", "nat option yes|no", AliasCommands},
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
{"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1998-07-29 18:21:17 +00:00
|
|
|
"Open an FSM", "open! [lcp|ccp|ipcp]", (void *)1},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"passwd", NULL, PasswdCommand, LOCAL_NO_AUTH,
|
|
|
|
"Password for manipulation", "passwd LocalPassword"},
|
|
|
|
{"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
|
|
|
|
"Quit PPP program", "quit|bye [all]"},
|
|
|
|
{"remove", "rm", RemoveCommand, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Remove a link", "remove"},
|
|
|
|
{"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Rename a link", "rename name"},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"save", NULL, SaveCommand, LOCAL_AUTH,
|
|
|
|
"Save settings", "save"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1997-08-25 00:29:32 +00:00
|
|
|
"Set parameters", "set[up] var value"},
|
|
|
|
{"shell", "!", FgShellCommand, LOCAL_AUTH,
|
|
|
|
"Run a subshell", "shell|! [sh command]"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
1997-11-23 20:05:18 +00:00
|
|
|
"Show status and stats", "show var"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX,
|
1997-11-23 20:05:18 +00:00
|
|
|
"Enter terminal mode", "term"},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
|
1997-11-22 03:37:54 +00:00
|
|
|
"Display this message", "help|? [command]", Commands},
|
1997-08-25 00:29:32 +00:00
|
|
|
{NULL, NULL, NULL},
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
ShowEscape(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->cx->physical->async.cfg.EscMap[32]) {
|
|
|
|
int code, bit;
|
|
|
|
const char *sep = "";
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
for (code = 0; code < 32; code++)
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->cx->physical->async.cfg.EscMap[code])
|
1997-08-25 00:29:32 +00:00
|
|
|
for (bit = 0; bit < 8; bit++)
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->cx->physical->async.cfg.EscMap[code] & (1 << bit)) {
|
|
|
|
prompt_Printf(arg->prompt, "%s0x%02x", sep, (code << 3) + bit);
|
|
|
|
sep = ", ";
|
|
|
|
}
|
|
|
|
prompt_Printf(arg->prompt, "\n");
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-11-09 17:51:27 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
ShowTimerList(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Show(0, arg->prompt);
|
1997-11-09 17:51:27 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
ShowStopped(struct cmdargs const *arg)
|
1997-08-17 20:45:50 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, " Stopped Timer: LCP: ");
|
|
|
|
if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load)
|
|
|
|
prompt_Printf(arg->prompt, "Disabled");
|
1997-08-20 23:47:53 +00:00
|
|
|
else
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "%ld secs",
|
|
|
|
arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS);
|
1997-08-20 23:47:53 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, ", CCP: ");
|
|
|
|
if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load)
|
|
|
|
prompt_Printf(arg->prompt, "Disabled");
|
1997-08-20 23:47:53 +00:00
|
|
|
else
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "%ld secs",
|
|
|
|
arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS);
|
1997-08-20 23:47:53 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "\n");
|
1997-08-20 23:47:53 +00:00
|
|
|
|
1997-11-09 17:51:27 +00:00
|
|
|
return 0;
|
1997-08-17 20:45:50 +00:00
|
|
|
}
|
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
ShowVersion(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1999-09-06 18:11:50 +00:00
|
|
|
prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, __DATE__);
|
1997-11-09 17:51:27 +00:00
|
|
|
return 0;
|
1997-04-21 01:02:02 +00:00
|
|
|
}
|
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
ShowProtocolStats(struct cmdargs const *arg)
|
1995-10-08 14:57:32 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct link *l = command_ChooseLink(arg);
|
1995-10-08 14:57:32 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "%s:\n", l->name);
|
|
|
|
link_ReportProtocolStatus(l, arg->prompt);
|
1997-11-09 17:51:27 +00:00
|
|
|
return 0;
|
1995-10-08 14:57:32 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static struct cmdtab const ShowCommands[] = {
|
1998-05-21 21:49:08 +00:00
|
|
|
{"bundle", NULL, bundle_ShowStatus, LOCAL_AUTH,
|
|
|
|
"bundle details", "show bundle"},
|
|
|
|
{"ccp", NULL, ccp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"CCP status", "show cpp"},
|
|
|
|
{"compress", NULL, sl_Show, LOCAL_AUTH,
|
|
|
|
"VJ compression stats", "show compress"},
|
|
|
|
{"escape", NULL, ShowEscape, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"escape characters", "show escape"},
|
|
|
|
{"filter", NULL, filter_Show, LOCAL_AUTH,
|
|
|
|
"packet filters", "show filter [in|out|dial|alive]"},
|
|
|
|
{"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"HDLC errors", "show hdlc"},
|
1998-10-22 02:32:50 +00:00
|
|
|
{"iface", "interface", iface_Show, LOCAL_AUTH,
|
|
|
|
"Interface status", "show iface"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"ipcp", NULL, ipcp_Show, LOCAL_AUTH,
|
|
|
|
"IPCP status", "show ipcp"},
|
1999-05-15 02:24:18 +00:00
|
|
|
{"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"Protocol layers", "show layers"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"LCP status", "show lcp"},
|
|
|
|
{"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"(high-level) link info", "show link"},
|
|
|
|
{"links", NULL, bundle_ShowLinks, LOCAL_AUTH,
|
|
|
|
"available link names", "show links"},
|
|
|
|
{"log", NULL, log_ShowLevel, LOCAL_AUTH,
|
|
|
|
"log levels", "show log"},
|
|
|
|
{"mem", NULL, mbuf_Show, LOCAL_AUTH,
|
|
|
|
"mbuf allocations", "show mem"},
|
1999-05-08 11:07:56 +00:00
|
|
|
{"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"(low-level) link info", "show physical"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"mp", "multilink", mp_ShowStatus, LOCAL_AUTH,
|
|
|
|
"multilink setup", "show mp"},
|
|
|
|
{"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"protocol summary", "show proto"},
|
|
|
|
{"route", NULL, route_Show, LOCAL_AUTH,
|
|
|
|
"routing table", "show route"},
|
|
|
|
{"stopped", NULL, ShowStopped, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"STOPPED timeout", "show stopped"},
|
|
|
|
{"timers", NULL, ShowTimerList, LOCAL_AUTH,
|
|
|
|
"alarm timers", "show timers"},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
|
1998-05-21 21:49:08 +00:00
|
|
|
"version string", "show version"},
|
|
|
|
{"who", NULL, log_ShowWho, LOCAL_AUTH,
|
|
|
|
"client list", "show who"},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
|
1997-11-22 03:37:54 +00:00
|
|
|
"Display this message", "show help|? [command]", ShowCommands},
|
1997-08-25 00:29:32 +00:00
|
|
|
{NULL, NULL, NULL},
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static struct cmdtab const *
|
1997-11-22 03:37:54 +00:00
|
|
|
FindCommand(struct cmdtab const *cmds, const char *str, int *pmatch)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1997-06-09 03:27:43 +00:00
|
|
|
int nmatch;
|
|
|
|
int len;
|
1997-08-25 00:29:32 +00:00
|
|
|
struct cmdtab const *found;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
found = NULL;
|
|
|
|
len = strlen(str);
|
|
|
|
nmatch = 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
while (cmds->func) {
|
1997-05-08 01:26:31 +00:00
|
|
|
if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
|
1997-06-09 03:27:43 +00:00
|
|
|
if (cmds->name[len] == '\0') {
|
1997-08-25 00:29:32 +00:00
|
|
|
*pmatch = 1;
|
|
|
|
return cmds;
|
1997-06-09 03:27:43 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
nmatch++;
|
|
|
|
found = cmds;
|
1997-08-25 00:29:32 +00:00
|
|
|
} else if (cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
|
1997-06-09 03:27:43 +00:00
|
|
|
if (cmds->alias[len] == '\0') {
|
1997-08-25 00:29:32 +00:00
|
|
|
*pmatch = 1;
|
|
|
|
return cmds;
|
1997-06-09 03:27:43 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
nmatch++;
|
|
|
|
found = cmds;
|
|
|
|
}
|
|
|
|
cmds++;
|
|
|
|
}
|
|
|
|
*pmatch = nmatch;
|
1997-06-09 03:27:43 +00:00
|
|
|
return found;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static const char *
|
|
|
|
mkPrefix(int argc, char const *const *argv, char *tgt, int sz)
|
|
|
|
{
|
|
|
|
int f, tlen, len;
|
|
|
|
|
|
|
|
tlen = 0;
|
|
|
|
for (f = 0; f < argc && tlen < sz - 2; f++) {
|
|
|
|
if (f)
|
|
|
|
tgt[tlen++] = ' ';
|
|
|
|
len = strlen(argv[f]);
|
|
|
|
if (len > sz - tlen - 1)
|
|
|
|
len = sz - tlen - 1;
|
|
|
|
strncpy(tgt+tlen, argv[f], len);
|
|
|
|
tlen += len;
|
|
|
|
}
|
|
|
|
tgt[tlen] = '\0';
|
|
|
|
return tgt;
|
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
FindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn,
|
|
|
|
char const *const *argv, struct prompt *prompt, struct datalink *cx)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1997-08-25 00:29:32 +00:00
|
|
|
struct cmdtab const *cmd;
|
1995-01-31 06:29:58 +00:00
|
|
|
int val = 1;
|
|
|
|
int nmatch;
|
1997-11-22 03:37:54 +00:00
|
|
|
struct cmdargs arg;
|
1998-05-21 21:49:08 +00:00
|
|
|
char prefix[100];
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
cmd = FindCommand(cmds, argv[argn], &nmatch);
|
1995-01-31 06:29:58 +00:00
|
|
|
if (nmatch > 1)
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "%s: Ambiguous command\n",
|
|
|
|
mkPrefix(argn+1, argv, prefix, sizeof prefix));
|
|
|
|
else if (cmd && (!prompt || (cmd->lauth & prompt->auth))) {
|
|
|
|
if ((cmd->lauth & LOCAL_CX) && !cx)
|
|
|
|
/* We've got no context, but we require it */
|
|
|
|
cx = bundle2datalink(bundle, NULL);
|
|
|
|
|
|
|
|
if ((cmd->lauth & LOCAL_CX) && !cx)
|
|
|
|
log_Printf(LogWARN, "%s: No context (use the `link' command)\n",
|
|
|
|
mkPrefix(argn+1, argv, prefix, sizeof prefix));
|
|
|
|
else {
|
|
|
|
if (cx && !(cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) {
|
|
|
|
log_Printf(LogWARN, "%s: Redundant context (%s) ignored\n",
|
|
|
|
mkPrefix(argn+1, argv, prefix, sizeof prefix), cx->name);
|
|
|
|
cx = NULL;
|
|
|
|
}
|
|
|
|
arg.cmdtab = cmds;
|
|
|
|
arg.cmd = cmd;
|
|
|
|
arg.argc = argc;
|
|
|
|
arg.argn = argn+1;
|
|
|
|
arg.argv = argv;
|
|
|
|
arg.bundle = bundle;
|
|
|
|
arg.cx = cx;
|
|
|
|
arg.prompt = prompt;
|
|
|
|
val = (*cmd->func) (&arg);
|
|
|
|
}
|
1997-11-22 03:37:54 +00:00
|
|
|
} else
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "%s: Invalid command\n",
|
|
|
|
mkPrefix(argn+1, argv, prefix, sizeof prefix));
|
1997-06-09 03:27:43 +00:00
|
|
|
|
|
|
|
if (val == -1)
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "Usage: %s\n", cmd->syntax);
|
1997-08-25 00:29:32 +00:00
|
|
|
else if (val)
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "%s: Failed %d\n",
|
|
|
|
mkPrefix(argn+1, argv, prefix, sizeof prefix), val);
|
1997-06-09 03:27:43 +00:00
|
|
|
|
|
|
|
return val;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-06-15 19:06:25 +00:00
|
|
|
int
|
|
|
|
command_Interpret(char *buff, int nb, char *argv[MAXARGS])
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
if (nb > 0) {
|
|
|
|
cp = buff + strcspn(buff, "\r\n");
|
|
|
|
if (cp)
|
|
|
|
*cp = '\0';
|
1998-06-15 19:06:25 +00:00
|
|
|
return MakeArgs(buff, argv, MAXARGS);
|
|
|
|
}
|
|
|
|
return 0;
|
1997-11-11 22:58:14 +00:00
|
|
|
}
|
|
|
|
|
1997-12-17 21:21:42 +00:00
|
|
|
static int
|
|
|
|
arghidden(int argc, char const *const *argv, int n)
|
|
|
|
{
|
|
|
|
/* Is arg n of the given command to be hidden from the log ? */
|
1997-12-18 00:28:36 +00:00
|
|
|
|
|
|
|
/* set authkey xxxxx */
|
|
|
|
/* set key xxxxx */
|
1997-12-17 21:21:42 +00:00
|
|
|
if (n == 2 && !strncasecmp(argv[0], "se", 2) &&
|
|
|
|
(!strncasecmp(argv[1], "authk", 5) || !strncasecmp(argv[1], "ke", 2)))
|
|
|
|
return 1;
|
|
|
|
|
1997-12-18 00:28:36 +00:00
|
|
|
/* passwd xxxxx */
|
|
|
|
if (n == 1 && !strncasecmp(argv[0], "p", 1))
|
|
|
|
return 1;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
/* set server port xxxxx .... */
|
|
|
|
if (n == 3 && !strncasecmp(argv[0], "se", 2) &&
|
|
|
|
!strncasecmp(argv[1], "se", 2))
|
|
|
|
return 1;
|
|
|
|
|
1997-12-17 21:21:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-11-11 22:58:14 +00:00
|
|
|
void
|
1998-05-21 21:49:08 +00:00
|
|
|
command_Run(struct bundle *bundle, int argc, char const *const *argv,
|
1998-06-15 19:05:51 +00:00
|
|
|
struct prompt *prompt, const char *label, struct datalink *cx)
|
1997-11-11 22:58:14 +00:00
|
|
|
{
|
1997-11-13 14:43:20 +00:00
|
|
|
if (argc > 0) {
|
1998-05-21 21:49:08 +00:00
|
|
|
if (log_IsKept(LogCOMMAND)) {
|
1999-06-08 20:12:06 +00:00
|
|
|
char buf[LINE_LEN];
|
1997-11-13 14:43:20 +00:00
|
|
|
int f, n;
|
|
|
|
|
|
|
|
if (label) {
|
1997-12-24 09:29:17 +00:00
|
|
|
strncpy(buf, label, sizeof buf - 3);
|
|
|
|
buf[sizeof buf - 3] = '\0';
|
1997-11-13 14:43:20 +00:00
|
|
|
strcat(buf, ": ");
|
1999-06-08 20:12:06 +00:00
|
|
|
n = strlen(buf);
|
|
|
|
} else {
|
|
|
|
*buf = '\0';
|
|
|
|
n = 0;
|
1997-11-13 14:43:20 +00:00
|
|
|
}
|
1999-06-08 20:12:06 +00:00
|
|
|
buf[sizeof buf - 1] = '\0'; /* In case we run out of room in buf */
|
|
|
|
|
1997-11-13 14:43:20 +00:00
|
|
|
for (f = 0; f < argc; f++) {
|
1997-12-24 09:29:17 +00:00
|
|
|
if (n < sizeof buf - 1 && f)
|
1997-11-13 14:43:20 +00:00
|
|
|
buf[n++] = ' ';
|
1997-12-17 21:21:42 +00:00
|
|
|
if (arghidden(argc, argv, f))
|
1998-05-21 21:49:08 +00:00
|
|
|
strncpy(buf+n, "********", sizeof buf - n - 1);
|
1997-12-17 21:21:42 +00:00
|
|
|
else
|
1997-12-24 09:29:17 +00:00
|
|
|
strncpy(buf+n, argv[f], sizeof buf - n - 1);
|
1997-11-13 14:43:20 +00:00
|
|
|
n += strlen(buf+n);
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogCOMMAND, "%s\n", buf);
|
1997-11-13 14:43:20 +00:00
|
|
|
}
|
1998-06-15 19:05:51 +00:00
|
|
|
FindExec(bundle, Commands, argc, 0, argv, prompt, cx);
|
1997-11-13 14:43:20 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-11-11 22:58:14 +00:00
|
|
|
void
|
1998-05-21 21:49:08 +00:00
|
|
|
command_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt,
|
|
|
|
const char *label)
|
1997-11-11 22:58:14 +00:00
|
|
|
{
|
|
|
|
int argc;
|
1998-06-15 19:06:25 +00:00
|
|
|
char *argv[MAXARGS];
|
1997-11-11 22:58:14 +00:00
|
|
|
|
1998-06-15 19:06:25 +00:00
|
|
|
argc = command_Interpret(buff, nb, argv);
|
1998-06-15 19:05:51 +00:00
|
|
|
command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL);
|
1997-11-11 22:58:14 +00:00
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
ShowCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (!arg->prompt)
|
|
|
|
log_Printf(LogWARN, "show: Cannot show without a prompt\n");
|
|
|
|
else if (arg->argc > arg->argn)
|
|
|
|
FindExec(arg->bundle, ShowCommands, arg->argc, arg->argn, arg->argv,
|
|
|
|
arg->prompt, arg->cx);
|
1995-01-31 06:29:58 +00:00
|
|
|
else
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n");
|
1997-06-09 03:27:43 +00:00
|
|
|
|
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
TerminalCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (!arg->prompt) {
|
|
|
|
log_Printf(LogWARN, "term: Need a prompt\n");
|
1997-06-09 03:27:43 +00:00
|
|
|
return 1;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->cx->physical->link.lcp.fsm.state > ST_CLOSED) {
|
|
|
|
prompt_Printf(arg->prompt, "LCP state is [%s]\n",
|
|
|
|
State2Nam(arg->cx->physical->link.lcp.fsm.state));
|
|
|
|
return 1;
|
1997-11-11 22:58:14 +00:00
|
|
|
}
|
1997-06-09 03:27:43 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
datalink_Up(arg->cx, 0, 0);
|
|
|
|
prompt_TtyTermMode(arg->prompt, arg->cx);
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
QuitCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (!arg->prompt || prompt_IsController(arg->prompt) ||
|
|
|
|
(arg->argc > arg->argn && !strcasecmp(arg->argv[arg->argn], "all") &&
|
|
|
|
(arg->prompt->auth & LOCAL_AUTH)))
|
|
|
|
Cleanup(EX_NORMAL);
|
|
|
|
if (arg->prompt)
|
|
|
|
prompt_Destroy(arg->prompt, 1);
|
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
OpenCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-06-25 22:33:31 +00:00
|
|
|
if (arg->argc == arg->argn)
|
1998-07-31 19:50:24 +00:00
|
|
|
bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL, 1);
|
1998-06-25 22:33:31 +00:00
|
|
|
else if (arg->argc == arg->argn + 1) {
|
|
|
|
if (!strcasecmp(arg->argv[arg->argn], "lcp")) {
|
1998-07-04 22:03:56 +00:00
|
|
|
struct datalink *cx = arg->cx ?
|
|
|
|
arg->cx : bundle2datalink(arg->bundle, NULL);
|
|
|
|
if (cx) {
|
|
|
|
if (cx->physical->link.lcp.fsm.state == ST_OPENED)
|
|
|
|
fsm_Reopen(&cx->physical->link.lcp.fsm);
|
1998-06-25 22:33:31 +00:00
|
|
|
else
|
1998-07-31 19:50:24 +00:00
|
|
|
bundle_Open(arg->bundle, cx->name, PHYS_ALL, 1);
|
1998-06-25 22:33:31 +00:00
|
|
|
} else
|
|
|
|
log_Printf(LogWARN, "open lcp: You must specify a link\n");
|
|
|
|
} else if (!strcasecmp(arg->argv[arg->argn], "ccp")) {
|
|
|
|
struct fsm *fp;
|
|
|
|
|
1998-06-27 23:48:54 +00:00
|
|
|
fp = &command_ChooseLink(arg)->ccp.fsm;
|
1998-06-25 22:33:31 +00:00
|
|
|
if (fp->link->lcp.fsm.state != ST_OPENED)
|
|
|
|
log_Printf(LogWARN, "open: LCP must be open before opening CCP\n");
|
|
|
|
else if (fp->state == ST_OPENED)
|
|
|
|
fsm_Reopen(fp);
|
|
|
|
else {
|
|
|
|
fp->open_mode = 0; /* Not passive any more */
|
|
|
|
if (fp->state == ST_STOPPED) {
|
|
|
|
fsm_Down(fp);
|
|
|
|
fsm_Up(fp);
|
|
|
|
} else {
|
|
|
|
fsm_Up(fp);
|
|
|
|
fsm_Open(fp);
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1998-06-25 22:33:31 +00:00
|
|
|
} else if (!strcasecmp(arg->argv[arg->argn], "ipcp")) {
|
|
|
|
if (arg->cx)
|
|
|
|
log_Printf(LogWARN, "open ipcp: You need not specify a link\n");
|
|
|
|
if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED)
|
|
|
|
fsm_Reopen(&arg->bundle->ncp.ipcp.fsm);
|
|
|
|
else
|
1998-07-31 19:50:24 +00:00
|
|
|
bundle_Open(arg->bundle, NULL, PHYS_ALL, 1);
|
1998-06-25 22:33:31 +00:00
|
|
|
} else
|
|
|
|
return -1;
|
1998-05-21 21:49:08 +00:00
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-04-21 01:02:02 +00:00
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
CloseCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-06-15 19:05:27 +00:00
|
|
|
if (arg->argc == arg->argn)
|
|
|
|
bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_STAYDOWN);
|
|
|
|
else if (arg->argc == arg->argn + 1) {
|
|
|
|
if (!strcasecmp(arg->argv[arg->argn], "lcp"))
|
|
|
|
bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, CLOSE_LCP);
|
|
|
|
else if (!strcasecmp(arg->argv[arg->argn], "ccp") ||
|
|
|
|
!strcasecmp(arg->argv[arg->argn], "ccp!")) {
|
|
|
|
struct fsm *fp;
|
|
|
|
|
1998-06-27 23:48:54 +00:00
|
|
|
fp = &command_ChooseLink(arg)->ccp.fsm;
|
1998-06-15 19:05:27 +00:00
|
|
|
if (fp->state == ST_OPENED) {
|
|
|
|
fsm_Close(fp);
|
|
|
|
if (arg->argv[arg->argn][3] == '!')
|
|
|
|
fp->open_mode = 0; /* Stay ST_CLOSED */
|
|
|
|
else
|
|
|
|
fp->open_mode = OPEN_PASSIVE; /* Wait for the peer to start */
|
|
|
|
}
|
|
|
|
} else
|
1998-05-21 21:49:08 +00:00
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-04-21 01:02:02 +00:00
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
DownCommand(struct cmdargs const *arg)
|
1997-04-21 01:02:02 +00:00
|
|
|
{
|
1998-06-16 19:40:28 +00:00
|
|
|
if (arg->argc == arg->argn) {
|
|
|
|
if (arg->cx)
|
|
|
|
datalink_Down(arg->cx, CLOSE_STAYDOWN);
|
|
|
|
else
|
|
|
|
bundle_Down(arg->bundle, CLOSE_STAYDOWN);
|
|
|
|
} else if (arg->argc == arg->argn + 1) {
|
|
|
|
if (!strcasecmp(arg->argv[arg->argn], "lcp")) {
|
|
|
|
if (arg->cx)
|
|
|
|
datalink_Down(arg->cx, CLOSE_LCP);
|
|
|
|
else
|
|
|
|
bundle_Down(arg->bundle, CLOSE_LCP);
|
|
|
|
} else if (!strcasecmp(arg->argv[arg->argn], "ccp")) {
|
|
|
|
struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm :
|
|
|
|
&arg->bundle->ncp.mp.link.ccp.fsm;
|
1998-06-20 00:19:42 +00:00
|
|
|
fsm2initial(fp);
|
1998-06-16 19:40:28 +00:00
|
|
|
} else
|
|
|
|
return -1;
|
1998-05-21 21:49:08 +00:00
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
1997-04-21 01:02:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1998-05-21 21:49:08 +00:00
|
|
|
SetModemSpeed(struct cmdargs const *arg)
|
1995-10-08 14:57:32 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
long speed;
|
|
|
|
char *end;
|
1995-10-08 14:57:32 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn && *arg->argv[arg->argn]) {
|
|
|
|
if (arg->argc > arg->argn+1) {
|
|
|
|
log_Printf(LogWARN, "SetModemSpeed: Too many arguments");
|
|
|
|
return -1;
|
1995-10-08 14:57:32 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
if (strcasecmp(arg->argv[arg->argn], "sync") == 0) {
|
|
|
|
physical_SetSync(arg->cx->physical);
|
|
|
|
return 0;
|
1995-10-08 14:57:32 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
end = NULL;
|
|
|
|
speed = strtol(arg->argv[arg->argn], &end, 10);
|
|
|
|
if (*end) {
|
|
|
|
log_Printf(LogWARN, "SetModemSpeed: Bad argument \"%s\"",
|
|
|
|
arg->argv[arg->argn]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (physical_SetSpeed(arg->cx->physical, speed))
|
|
|
|
return 0;
|
|
|
|
log_Printf(LogWARN, "%s: Invalid speed\n", arg->argv[arg->argn]);
|
|
|
|
} else
|
|
|
|
log_Printf(LogWARN, "SetModemSpeed: No speed specified\n");
|
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return -1;
|
1995-10-08 14:57:32 +00:00
|
|
|
}
|
|
|
|
|
1997-08-17 20:45:50 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
SetStoppedTimeout(struct cmdargs const *arg)
|
1997-08-17 20:45:50 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct link *l = &arg->cx->physical->link;
|
|
|
|
|
|
|
|
l->lcp.fsm.StoppedTimer.load = 0;
|
|
|
|
l->ccp.fsm.StoppedTimer.load = 0;
|
|
|
|
if (arg->argc <= arg->argn+2) {
|
|
|
|
if (arg->argc > arg->argn) {
|
|
|
|
l->lcp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn]) * SECTICKS;
|
|
|
|
if (arg->argc > arg->argn+1)
|
|
|
|
l->ccp.fsm.StoppedTimer.load = atoi(arg->argv[arg->argn+1]) * SECTICKS;
|
1997-08-20 23:47:53 +00:00
|
|
|
}
|
1997-08-17 20:45:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1997-11-09 22:07:29 +00:00
|
|
|
#define ismask(x) \
|
|
|
|
(*x == '0' && strlen(x) == 4 && strspn(x+1, "0123456789.") == 3)
|
|
|
|
|
1997-06-25 19:30:05 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
SetServer(struct cmdargs const *arg)
|
1997-06-25 19:30:05 +00:00
|
|
|
{
|
|
|
|
int res = -1;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn && arg->argc < arg->argn+4) {
|
1997-11-09 22:07:29 +00:00
|
|
|
const char *port, *passwd, *mask;
|
|
|
|
|
|
|
|
/* What's what ? */
|
1998-05-21 21:49:08 +00:00
|
|
|
port = arg->argv[arg->argn];
|
|
|
|
if (arg->argc == arg->argn + 2) {
|
|
|
|
passwd = arg->argv[arg->argn+1];
|
|
|
|
mask = NULL;
|
|
|
|
} else if (arg->argc == arg->argn + 3) {
|
|
|
|
passwd = arg->argv[arg->argn+1];
|
|
|
|
mask = arg->argv[arg->argn+2];
|
1997-11-09 22:07:29 +00:00
|
|
|
if (!ismask(mask))
|
|
|
|
return -1;
|
1998-05-21 21:49:08 +00:00
|
|
|
} else if (strcasecmp(port, "none") == 0) {
|
|
|
|
if (server_Close(arg->bundle))
|
|
|
|
log_Printf(LogPHASE, "Disabled server port.\n");
|
|
|
|
return 0;
|
1997-11-09 22:07:29 +00:00
|
|
|
} else
|
1998-05-21 21:49:08 +00:00
|
|
|
return -1;
|
1997-11-09 22:07:29 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
strncpy(server.passwd, passwd, sizeof server.passwd - 1);
|
|
|
|
server.passwd[sizeof server.passwd - 1] = '\0';
|
1997-11-09 22:07:29 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (*port == '/') {
|
1997-11-09 22:07:29 +00:00
|
|
|
mode_t imask;
|
1998-05-21 21:49:08 +00:00
|
|
|
char *ptr, name[LINE_LEN + 12];
|
1997-08-25 00:29:32 +00:00
|
|
|
|
1997-11-09 22:07:29 +00:00
|
|
|
if (mask != NULL) {
|
1997-08-25 00:29:32 +00:00
|
|
|
unsigned m;
|
|
|
|
|
1997-11-09 22:07:29 +00:00
|
|
|
if (sscanf(mask, "%o", &m) == 1)
|
|
|
|
imask = m;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
imask = (mode_t)-1;
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
ptr = strstr(port, "%d");
|
|
|
|
if (ptr) {
|
|
|
|
snprintf(name, sizeof name, "%.*s%d%s",
|
1998-06-27 23:48:54 +00:00
|
|
|
(int)(ptr - port), port, arg->bundle->unit, ptr + 2);
|
1998-05-21 21:49:08 +00:00
|
|
|
port = name;
|
|
|
|
}
|
|
|
|
res = server_LocalOpen(arg->bundle, port, imask);
|
1997-07-12 19:22:34 +00:00
|
|
|
} else {
|
1998-05-21 21:49:08 +00:00
|
|
|
int iport, add = 0;
|
1997-11-09 22:07:29 +00:00
|
|
|
|
|
|
|
if (mask != NULL)
|
|
|
|
return -1;
|
1997-08-25 00:29:32 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (*port == '+') {
|
|
|
|
port++;
|
|
|
|
add = 1;
|
|
|
|
}
|
1997-11-09 22:07:29 +00:00
|
|
|
if (strspn(port, "0123456789") != strlen(port)) {
|
|
|
|
struct servent *s;
|
1997-08-25 00:29:32 +00:00
|
|
|
|
1997-11-09 22:07:29 +00:00
|
|
|
if ((s = getservbyname(port, "tcp")) == NULL) {
|
|
|
|
iport = 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "%s: Invalid port or service\n", port);
|
1997-08-25 00:29:32 +00:00
|
|
|
} else
|
1997-11-09 22:07:29 +00:00
|
|
|
iport = ntohs(s->s_port);
|
1997-07-12 19:22:34 +00:00
|
|
|
} else
|
1997-11-09 22:07:29 +00:00
|
|
|
iport = atoi(port);
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
if (iport) {
|
|
|
|
if (add)
|
|
|
|
iport += arg->bundle->unit;
|
|
|
|
res = server_TcpOpen(arg->bundle, iport);
|
|
|
|
} else
|
|
|
|
res = -1;
|
1997-07-12 19:22:34 +00:00
|
|
|
}
|
1997-11-09 22:07:29 +00:00
|
|
|
}
|
1997-06-25 19:30:05 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
SetEscape(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
int code;
|
1998-05-21 21:49:08 +00:00
|
|
|
int argc = arg->argc - arg->argn;
|
|
|
|
char const *const *argv = arg->argv + arg->argn;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
for (code = 0; code < 33; code++)
|
1998-05-21 21:49:08 +00:00
|
|
|
arg->cx->physical->async.cfg.EscMap[code] = 0;
|
1997-11-22 03:37:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
while (argc-- > 0) {
|
|
|
|
sscanf(*argv++, "%x", &code);
|
|
|
|
code &= 0xff;
|
1998-05-21 21:49:08 +00:00
|
|
|
arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7));
|
|
|
|
arg->cx->physical->async.cfg.EscMap[32] = 1;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
SetInterfaceAddr(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
|
1998-01-05 01:35:20 +00:00
|
|
|
const char *hisaddr;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn + 4)
|
1997-08-25 00:29:32 +00:00
|
|
|
return -1;
|
1997-06-09 03:27:43 +00:00
|
|
|
|
1998-10-22 02:32:50 +00:00
|
|
|
hisaddr = NULL;
|
1999-03-19 00:05:32 +00:00
|
|
|
memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
|
|
|
|
memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
|
1998-05-21 21:49:08 +00:00
|
|
|
ipcp->cfg.HaveTriggerAddress = 0;
|
|
|
|
ipcp->cfg.netmask.s_addr = INADDR_ANY;
|
|
|
|
iplist_reset(&ipcp->cfg.peer_list);
|
1997-08-19 01:10:24 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn) {
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(ipcp, arg->argv[arg->argn],
|
1998-05-21 21:49:08 +00:00
|
|
|
&ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask,
|
|
|
|
&ipcp->cfg.my_range.width))
|
1997-08-25 00:29:32 +00:00
|
|
|
return 1;
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn+1) {
|
|
|
|
hisaddr = arg->argv[arg->argn+1];
|
|
|
|
if (arg->argc > arg->argn+2) {
|
1999-03-03 23:00:41 +00:00
|
|
|
ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]);
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn+3) {
|
|
|
|
ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]);
|
|
|
|
ipcp->cfg.HaveTriggerAddress = 1;
|
1995-07-08 08:28:10 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1997-08-19 01:10:24 +00:00
|
|
|
|
1998-10-22 02:32:50 +00:00
|
|
|
/* 0.0.0.0 means any address (0 bits) */
|
1998-05-21 21:49:08 +00:00
|
|
|
if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) {
|
|
|
|
ipcp->cfg.my_range.mask.s_addr = INADDR_ANY;
|
|
|
|
ipcp->cfg.my_range.width = 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr;
|
1999-05-31 23:57:40 +00:00
|
|
|
bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL);
|
1997-08-21 17:07:30 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr,
|
1998-06-12 17:45:10 +00:00
|
|
|
arg->bundle->phys_type.all & PHYS_AUTO))
|
1998-05-21 21:49:08 +00:00
|
|
|
return 4;
|
1996-10-06 13:32:37 +00:00
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1996-10-06 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
static int
|
|
|
|
SetRetry(int argc, char const *const *argv, u_int *timeout, u_int *maxreq,
|
|
|
|
u_int *maxtrm, int def)
|
|
|
|
{
|
|
|
|
if (argc == 0) {
|
|
|
|
*timeout = DEF_FSMRETRY;
|
|
|
|
*maxreq = def;
|
|
|
|
if (maxtrm != NULL)
|
|
|
|
*maxtrm = def;
|
|
|
|
} else {
|
|
|
|
long l = atol(argv[0]);
|
|
|
|
|
|
|
|
if (l < MIN_FSMRETRY) {
|
|
|
|
log_Printf(LogWARN, "%ld: Invalid FSM retry period - min %d\n",
|
|
|
|
l, MIN_FSMRETRY);
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
*timeout = l;
|
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
l = atol(argv[1]);
|
|
|
|
if (l < 1) {
|
|
|
|
log_Printf(LogWARN, "%ld: Invalid FSM REQ tries - changed to 1\n", l);
|
|
|
|
l = 1;
|
|
|
|
}
|
|
|
|
*maxreq = l;
|
|
|
|
|
|
|
|
if (argc > 2 && maxtrm != NULL) {
|
|
|
|
l = atol(argv[2]);
|
|
|
|
if (l < 1) {
|
|
|
|
log_Printf(LogWARN, "%ld: Invalid FSM TRM tries - changed to 1\n", l);
|
|
|
|
l = 1;
|
|
|
|
}
|
|
|
|
*maxtrm = l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-10-06 13:32:37 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
SetVariable(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-06-27 23:48:54 +00:00
|
|
|
long long_val, param = (long)arg->cmd->args;
|
1999-09-07 07:51:11 +00:00
|
|
|
int mode, dummyint, f, first;
|
1997-11-22 03:37:54 +00:00
|
|
|
const char *argp;
|
1998-05-21 21:49:08 +00:00
|
|
|
struct datalink *cx = arg->cx; /* LOCAL_CX uses this */
|
|
|
|
const char *err = NULL;
|
|
|
|
struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */
|
|
|
|
struct in_addr dummyaddr, *addr;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn)
|
|
|
|
argp = arg->argv[arg->argn];
|
1997-06-11 03:57:51 +00:00
|
|
|
else
|
1997-11-22 03:37:54 +00:00
|
|
|
argp = "";
|
1997-06-11 03:57:51 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if ((arg->cmd->lauth & LOCAL_CX) && !cx) {
|
|
|
|
log_Printf(LogWARN, "set %s: No context (use the `link' command)\n",
|
|
|
|
arg->cmd->name);
|
|
|
|
return 1;
|
|
|
|
} else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) {
|
|
|
|
log_Printf(LogWARN, "set %s: Redundant context (%s) ignored\n",
|
|
|
|
arg->cmd->name, cx->name);
|
|
|
|
cx = NULL;
|
|
|
|
}
|
|
|
|
|
1997-06-11 03:57:51 +00:00
|
|
|
switch (param) {
|
1997-08-25 00:29:32 +00:00
|
|
|
case VAR_AUTHKEY:
|
1999-08-22 01:29:53 +00:00
|
|
|
strncpy(arg->bundle->cfg.auth.key, argp,
|
|
|
|
sizeof arg->bundle->cfg.auth.key - 1);
|
|
|
|
arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0';
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
case VAR_AUTHNAME:
|
1998-10-24 01:08:45 +00:00
|
|
|
switch (bundle_Phase(arg->bundle)) {
|
|
|
|
case PHASE_DEAD:
|
|
|
|
case PHASE_ESTABLISH:
|
|
|
|
strncpy(arg->bundle->cfg.auth.name, argp,
|
|
|
|
sizeof arg->bundle->cfg.auth.name - 1);
|
|
|
|
arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = "set authname: Only available at phase DEAD/ESTABLISH\n";
|
|
|
|
log_Printf(LogWARN, err);
|
|
|
|
break;
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_AUTOLOAD:
|
1999-08-05 10:32:16 +00:00
|
|
|
if (arg->argc == arg->argn + 3) {
|
|
|
|
int v1, v2, v3;
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
v1 = strtol(arg->argv[arg->argn], &end, 0);
|
|
|
|
if (v1 < 0 || *end) {
|
|
|
|
log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n",
|
|
|
|
arg->argv[arg->argn]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
v2 = strtol(arg->argv[arg->argn + 1], &end, 0);
|
|
|
|
if (v2 < 0 || *end) {
|
|
|
|
log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n",
|
|
|
|
arg->argv[arg->argn + 1]);
|
|
|
|
return 1;
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1999-08-05 10:32:16 +00:00
|
|
|
if (v2 < v1) {
|
|
|
|
v3 = v1;
|
|
|
|
v1 = v2;
|
|
|
|
v2 = v3;
|
|
|
|
}
|
|
|
|
|
|
|
|
v3 = strtol(arg->argv[arg->argn + 2], &end, 0);
|
|
|
|
if (v3 <= 0 || *end) {
|
|
|
|
log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n",
|
|
|
|
arg->argv[arg->argn + 2]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg->bundle->ncp.mp.cfg.autoload.min = v1;
|
|
|
|
arg->bundle->ncp.mp.cfg.autoload.max = v2;
|
|
|
|
arg->bundle->ncp.mp.cfg.autoload.period = v3;
|
|
|
|
mp_RestartAutoloadTimer(&arg->bundle->ncp.mp);
|
1998-05-21 21:49:08 +00:00
|
|
|
} else {
|
1999-08-05 10:32:16 +00:00
|
|
|
err = "Set autoload requires three arguments\n";
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, err);
|
|
|
|
}
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
case VAR_DIAL:
|
1998-05-21 21:49:08 +00:00
|
|
|
strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1);
|
|
|
|
cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0';
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
case VAR_LOGIN:
|
1998-05-21 21:49:08 +00:00
|
|
|
strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1);
|
|
|
|
cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0';
|
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_WINSIZE:
|
|
|
|
if (arg->argc > arg->argn) {
|
|
|
|
l->ccp.cfg.deflate.out.winsize = atoi(arg->argv[arg->argn]);
|
|
|
|
if (l->ccp.cfg.deflate.out.winsize < 8 ||
|
|
|
|
l->ccp.cfg.deflate.out.winsize > 15) {
|
|
|
|
log_Printf(LogWARN, "%d: Invalid outgoing window size\n",
|
|
|
|
l->ccp.cfg.deflate.out.winsize);
|
|
|
|
l->ccp.cfg.deflate.out.winsize = 15;
|
|
|
|
}
|
|
|
|
if (arg->argc > arg->argn+1) {
|
|
|
|
l->ccp.cfg.deflate.in.winsize = atoi(arg->argv[arg->argn+1]);
|
|
|
|
if (l->ccp.cfg.deflate.in.winsize < 8 ||
|
|
|
|
l->ccp.cfg.deflate.in.winsize > 15) {
|
|
|
|
log_Printf(LogWARN, "%d: Invalid incoming window size\n",
|
|
|
|
l->ccp.cfg.deflate.in.winsize);
|
|
|
|
l->ccp.cfg.deflate.in.winsize = 15;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
l->ccp.cfg.deflate.in.winsize = 0;
|
|
|
|
} else {
|
|
|
|
err = "No window size specified\n";
|
|
|
|
log_Printf(LogWARN, err);
|
|
|
|
}
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
case VAR_DEVICE:
|
1998-05-21 21:49:08 +00:00
|
|
|
physical_SetDeviceList(cx->physical, arg->argc - arg->argn,
|
|
|
|
arg->argv + arg->argn);
|
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_ACCMAP:
|
|
|
|
if (arg->argc > arg->argn) {
|
1998-06-27 23:48:54 +00:00
|
|
|
u_long ulong_val;
|
1998-05-21 21:49:08 +00:00
|
|
|
sscanf(argp, "%lx", &ulong_val);
|
1998-06-27 23:48:54 +00:00
|
|
|
cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val;
|
1998-05-21 21:49:08 +00:00
|
|
|
} else {
|
|
|
|
err = "No accmap specified\n";
|
|
|
|
log_Printf(LogWARN, err);
|
|
|
|
}
|
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_MODE:
|
|
|
|
mode = Nam2mode(argp);
|
|
|
|
if (mode == PHYS_NONE || mode == PHYS_ALL) {
|
|
|
|
log_Printf(LogWARN, "%s: Invalid mode\n", argp);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
bundle_SetMode(arg->bundle, cx, mode);
|
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_MRRU:
|
1998-10-24 01:08:45 +00:00
|
|
|
switch (bundle_Phase(arg->bundle)) {
|
|
|
|
case PHASE_DEAD:
|
|
|
|
break;
|
|
|
|
case PHASE_ESTABLISH:
|
|
|
|
/* Make sure none of our links are DATALINK_LCP or greater */
|
|
|
|
if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) {
|
|
|
|
log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n");
|
|
|
|
return 1;
|
1997-09-22 00:46:56 +00:00
|
|
|
}
|
1998-06-27 23:48:54 +00:00
|
|
|
long_val = atol(argp);
|
|
|
|
if (long_val && long_val < MIN_MRU) {
|
|
|
|
log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU);
|
|
|
|
return 1;
|
|
|
|
} else if (long_val > MAX_MRU) {
|
|
|
|
log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU);
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
arg->bundle->ncp.mp.cfg.mrru = long_val;
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_MRU:
|
1998-06-27 23:48:54 +00:00
|
|
|
long_val = atol(argp);
|
|
|
|
if (long_val == 0)
|
|
|
|
l->lcp.cfg.mru = DEF_MRU;
|
|
|
|
else if (long_val < MIN_MRU) {
|
|
|
|
log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU);
|
|
|
|
return 1;
|
|
|
|
} else if (long_val > MAX_MRU) {
|
|
|
|
log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU);
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
l->lcp.cfg.mru = long_val;
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_MTU:
|
1998-06-27 23:48:54 +00:00
|
|
|
long_val = atol(argp);
|
|
|
|
if (long_val && long_val < MIN_MTU) {
|
|
|
|
log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU);
|
|
|
|
return 1;
|
|
|
|
} else if (long_val > MAX_MTU) {
|
|
|
|
log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU);
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
arg->bundle->cfg.mtu = long_val;
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_OPENMODE:
|
|
|
|
if (strcasecmp(argp, "active") == 0)
|
|
|
|
cx->physical->link.lcp.cfg.openmode = arg->argc > arg->argn+1 ?
|
|
|
|
atoi(arg->argv[arg->argn+1]) : 1;
|
|
|
|
else if (strcasecmp(argp, "passive") == 0)
|
|
|
|
cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE;
|
|
|
|
else {
|
|
|
|
err = "%s: Invalid openmode\n";
|
|
|
|
log_Printf(LogWARN, err, argp);
|
|
|
|
}
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
case VAR_PHONE:
|
1998-05-21 21:49:08 +00:00
|
|
|
strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1);
|
|
|
|
cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0';
|
1998-08-07 18:42:51 +00:00
|
|
|
cx->phone.alt = cx->phone.next = NULL;
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
case VAR_HANGUP:
|
1998-05-21 21:49:08 +00:00
|
|
|
strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1);
|
|
|
|
cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0';
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_IDLETIMEOUT:
|
1999-08-17 17:22:46 +00:00
|
|
|
if (arg->argc > arg->argn+2)
|
1998-05-21 21:49:08 +00:00
|
|
|
err = "Too many idle timeout values\n";
|
1999-08-17 17:22:46 +00:00
|
|
|
else if (arg->argc == arg->argn)
|
|
|
|
err = "Too few idle timeout values\n";
|
|
|
|
else {
|
|
|
|
int timeout, min;
|
|
|
|
|
|
|
|
timeout = atoi(argp);
|
|
|
|
min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1;
|
|
|
|
bundle_SetIdleTimer(arg->bundle, timeout, min);
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
if (err)
|
|
|
|
log_Printf(LogWARN, err);
|
1997-09-17 23:17:57 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_LQRPERIOD:
|
1998-06-27 23:48:54 +00:00
|
|
|
long_val = atol(argp);
|
|
|
|
if (long_val < MIN_LQRPERIOD) {
|
|
|
|
log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n",
|
|
|
|
long_val, MIN_LQRPERIOD);
|
|
|
|
return 1;
|
1998-05-21 21:49:08 +00:00
|
|
|
} else
|
1998-06-27 23:48:54 +00:00
|
|
|
l->lcp.cfg.lqrperiod = long_val;
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_LCPRETRY:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
|
|
|
|
&cx->physical->link.lcp.cfg.fsm.timeout,
|
|
|
|
&cx->physical->link.lcp.cfg.fsm.maxreq,
|
|
|
|
&cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES);
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_CHAPRETRY:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
|
|
|
|
&cx->chap.auth.cfg.fsm.timeout,
|
|
|
|
&cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES);
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_PAPRETRY:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
|
|
|
|
&cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq,
|
|
|
|
NULL, DEF_FSMAUTHTRIES);
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_CCPRETRY:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
|
|
|
|
&l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq,
|
|
|
|
&l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES);
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_IPCPRETRY:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn,
|
|
|
|
&arg->bundle->ncp.ipcp.cfg.fsm.timeout,
|
|
|
|
&arg->bundle->ncp.ipcp.cfg.fsm.maxreq,
|
|
|
|
&arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES);
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1998-06-27 23:48:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case VAR_NBNS:
|
|
|
|
case VAR_DNS:
|
|
|
|
if (param == VAR_DNS)
|
|
|
|
addr = arg->bundle->ncp.ipcp.cfg.ns.dns;
|
1996-12-22 17:09:17 +00:00
|
|
|
else
|
1998-05-21 21:49:08 +00:00
|
|
|
addr = arg->bundle->ncp.ipcp.cfg.ns.nbns;
|
|
|
|
|
|
|
|
addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
|
|
|
|
|
|
|
|
if (arg->argc > arg->argn) {
|
1999-01-28 01:56:34 +00:00
|
|
|
ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn],
|
1998-05-21 21:49:08 +00:00
|
|
|
addr, &dummyaddr, &dummyint);
|
|
|
|
if (arg->argc > arg->argn+1)
|
1999-01-28 01:56:34 +00:00
|
|
|
ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1],
|
1998-05-21 21:49:08 +00:00
|
|
|
addr + 1, &dummyaddr, &dummyint);
|
|
|
|
|
|
|
|
if (addr[1].s_addr == INADDR_ANY)
|
|
|
|
addr[1].s_addr = addr[0].s_addr;
|
|
|
|
if (addr[0].s_addr == INADDR_ANY)
|
|
|
|
addr[0].s_addr = addr[1].s_addr;
|
|
|
|
}
|
|
|
|
break;
|
1998-08-07 18:42:51 +00:00
|
|
|
|
|
|
|
case VAR_CALLBACK:
|
|
|
|
cx->cfg.callback.opmask = 0;
|
|
|
|
for (dummyint = arg->argn; dummyint < arg->argc; dummyint++) {
|
|
|
|
if (!strcasecmp(arg->argv[dummyint], "auth"))
|
|
|
|
cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_AUTH);
|
|
|
|
else if (!strcasecmp(arg->argv[dummyint], "cbcp"))
|
|
|
|
cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_CBCP);
|
|
|
|
else if (!strcasecmp(arg->argv[dummyint], "e.164")) {
|
|
|
|
if (dummyint == arg->argc - 1)
|
|
|
|
log_Printf(LogWARN, "No E.164 arg (E.164 ignored) !\n");
|
|
|
|
else {
|
|
|
|
cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_E164);
|
|
|
|
strncpy(cx->cfg.callback.msg, arg->argv[++dummyint],
|
|
|
|
sizeof cx->cfg.callback.msg - 1);
|
|
|
|
cx->cfg.callback.msg[sizeof cx->cfg.callback.msg - 1] = '\0';
|
|
|
|
}
|
|
|
|
} else if (!strcasecmp(arg->argv[dummyint], "none"))
|
|
|
|
cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE);
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE))
|
|
|
|
cx->cfg.callback.opmask = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VAR_CBCP:
|
|
|
|
cx->cfg.cbcp.delay = 0;
|
|
|
|
*cx->cfg.cbcp.phone = '\0';
|
|
|
|
cx->cfg.cbcp.fsmretry = DEF_FSMRETRY;
|
|
|
|
if (arg->argc > arg->argn) {
|
|
|
|
strncpy(cx->cfg.cbcp.phone, arg->argv[arg->argn],
|
|
|
|
sizeof cx->cfg.cbcp.phone - 1);
|
|
|
|
cx->cfg.cbcp.phone[sizeof cx->cfg.cbcp.phone - 1] = '\0';
|
|
|
|
if (arg->argc > arg->argn + 1) {
|
|
|
|
cx->cfg.cbcp.delay = atoi(arg->argv[arg->argn + 1]);
|
|
|
|
if (arg->argc > arg->argn + 2) {
|
|
|
|
long_val = atol(arg->argv[arg->argn + 2]);
|
|
|
|
if (long_val < MIN_FSMRETRY)
|
|
|
|
log_Printf(LogWARN, "%ld: Invalid CBCP FSM retry period - min %d\n",
|
|
|
|
long_val, MIN_FSMRETRY);
|
|
|
|
else
|
|
|
|
cx->cfg.cbcp.fsmretry = long_val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
1998-08-25 17:48:43 +00:00
|
|
|
|
|
|
|
case VAR_CHOKED:
|
|
|
|
arg->bundle->cfg.choked.timeout = atoi(argp);
|
|
|
|
if (arg->bundle->cfg.choked.timeout <= 0)
|
|
|
|
arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT;
|
|
|
|
break;
|
1998-10-26 19:07:39 +00:00
|
|
|
|
|
|
|
case VAR_SENDPIPE:
|
|
|
|
long_val = atol(argp);
|
|
|
|
arg->bundle->ncp.ipcp.cfg.sendpipe = long_val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VAR_RECVPIPE:
|
|
|
|
long_val = atol(argp);
|
|
|
|
arg->bundle->ncp.ipcp.cfg.recvpipe = long_val;
|
|
|
|
break;
|
1999-01-28 01:56:34 +00:00
|
|
|
|
|
|
|
#ifndef NORADIUS
|
|
|
|
case VAR_RADIUS:
|
|
|
|
if (!*argp)
|
|
|
|
*arg->bundle->radius.cfg.file = '\0';
|
|
|
|
else if (access(argp, R_OK)) {
|
|
|
|
log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno));
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
strncpy(arg->bundle->radius.cfg.file, argp,
|
|
|
|
sizeof arg->bundle->radius.cfg.file - 1);
|
|
|
|
arg->bundle->radius.cfg.file
|
|
|
|
[sizeof arg->bundle->radius.cfg.file - 1] = '\0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
1999-02-16 00:16:56 +00:00
|
|
|
|
|
|
|
case VAR_CD:
|
|
|
|
if (*argp) {
|
|
|
|
long_val = atol(argp);
|
|
|
|
if (long_val < 0)
|
|
|
|
long_val = 0;
|
|
|
|
cx->physical->cfg.cd.delay = long_val;
|
|
|
|
cx->physical->cfg.cd.required = argp[strlen(argp)-1] == '!';
|
|
|
|
} else {
|
|
|
|
cx->physical->cfg.cd.delay = DEF_CDDELAY;
|
|
|
|
cx->physical->cfg.cd.required = 0;
|
|
|
|
}
|
|
|
|
break;
|
1996-12-22 17:09:17 +00:00
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
case VAR_PARITY:
|
|
|
|
if (arg->argc == arg->argn + 1)
|
|
|
|
return physical_SetParity(arg->cx->physical, argp);
|
|
|
|
else {
|
|
|
|
err = "Parity value must be odd, even or none\n";
|
|
|
|
log_Printf(LogWARN, err);
|
|
|
|
}
|
|
|
|
break;
|
1996-12-22 17:09:17 +00:00
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
case VAR_CRTSCTS:
|
|
|
|
if (strcasecmp(argp, "on") == 0)
|
1998-05-21 21:49:08 +00:00
|
|
|
physical_SetRtsCts(arg->cx->physical, 1);
|
1999-05-08 11:07:56 +00:00
|
|
|
else if (strcasecmp(argp, "off") == 0)
|
1998-05-21 21:49:08 +00:00
|
|
|
physical_SetRtsCts(arg->cx->physical, 0);
|
1999-05-08 11:07:56 +00:00
|
|
|
else {
|
|
|
|
err = "RTS/CTS value must be on or off\n";
|
|
|
|
log_Printf(LogWARN, err);
|
|
|
|
}
|
|
|
|
break;
|
1999-09-04 00:00:21 +00:00
|
|
|
|
|
|
|
case VAR_URGENTPORTS:
|
1999-09-07 07:51:11 +00:00
|
|
|
if (arg->argn == arg->argc) {
|
|
|
|
ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp);
|
|
|
|
ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp);
|
|
|
|
} else if (!strcasecmp(arg->argv[arg->argn], "udp")) {
|
|
|
|
if (arg->argn == arg->argc - 1)
|
|
|
|
ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp);
|
|
|
|
else for (f = arg->argn + 1; f < arg->argc; f++)
|
|
|
|
if (*arg->argv[f] == '+')
|
|
|
|
ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1));
|
|
|
|
else if (*arg->argv[f] == '-')
|
|
|
|
ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp,
|
|
|
|
atoi(arg->argv[f] + 1));
|
|
|
|
else {
|
|
|
|
if (f == arg->argn)
|
|
|
|
ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp);
|
|
|
|
ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f]));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
first = arg->argn;
|
|
|
|
if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc)
|
|
|
|
ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp);
|
|
|
|
|
|
|
|
for (f = first; f < arg->argc; f++)
|
|
|
|
if (*arg->argv[f] == '+')
|
|
|
|
ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1));
|
|
|
|
else if (*arg->argv[f] == '-')
|
|
|
|
ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp,
|
|
|
|
atoi(arg->argv[f] + 1));
|
|
|
|
else {
|
|
|
|
if (f == first)
|
|
|
|
ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp);
|
|
|
|
ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f]));
|
|
|
|
}
|
|
|
|
}
|
1999-09-04 00:00:21 +00:00
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1999-05-08 11:07:56 +00:00
|
|
|
|
|
|
|
return err ? 1 : 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static struct cmdtab const SetCommands[] = {
|
1998-05-21 21:49:08 +00:00
|
|
|
{"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"authkey", "key", SetVariable, LOCAL_AUTH,
|
1998-05-21 21:49:08 +00:00
|
|
|
"authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"authname", NULL, SetVariable, LOCAL_AUTH,
|
1998-05-21 21:49:08 +00:00
|
|
|
"authentication name", "set authname name", (const void *)VAR_AUTHNAME},
|
|
|
|
{"autoload", NULL, SetVariable, LOCAL_AUTH,
|
|
|
|
"auto link [de]activation", "set autoload maxtime maxload mintime minload",
|
|
|
|
(const void *)VAR_AUTOLOAD},
|
1999-09-04 00:00:21 +00:00
|
|
|
{"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"datalink bandwidth", "set bandwidth value"},
|
1998-08-07 18:42:51 +00:00
|
|
|
{"callback", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"callback control", "set callback [none|auth|cbcp|"
|
|
|
|
"E.164 *|number[,number]...]...", (const void *)VAR_CALLBACK},
|
|
|
|
{"cbcp", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"CBCP control", "set cbcp [*|phone[,phone...] [delay [timeout]]]",
|
|
|
|
(const void *)VAR_CBCP},
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
{"ccpretry", "ccpretries", SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"CCP retries", "set ccpretry value [attempts]", (const void *)VAR_CCPRETRY},
|
1999-02-16 00:16:56 +00:00
|
|
|
{"cd", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "Carrier delay requirement",
|
|
|
|
"set cd value[!]", (const void *)VAR_CD},
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
{"chapretry", "chapretries", SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"CHAP retries", "set chapretry value [attempts]",
|
|
|
|
(const void *)VAR_CHAPRETRY},
|
1998-08-25 17:48:43 +00:00
|
|
|
{"choked", NULL, SetVariable, LOCAL_AUTH,
|
|
|
|
"choked timeout", "set choked [secs]", (const void *)VAR_CHOKED},
|
1999-05-08 11:07:56 +00:00
|
|
|
{"ctsrts", "crtscts", SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Use hardware flow control", "set ctsrts [on|off]",
|
|
|
|
(const char *)VAR_CRTSCTS},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"deflate window sizes", "set deflate out-winsize in-winsize",
|
|
|
|
(const void *) VAR_WINSIZE},
|
|
|
|
{"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX,
|
1999-05-08 11:07:56 +00:00
|
|
|
"physical device name", "set device|line device-name[,device-name]",
|
1998-05-21 21:49:08 +00:00
|
|
|
(const void *) VAR_DEVICE},
|
|
|
|
{"dial", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"dialing script", "set dial chat-script", (const void *) VAR_DIAL},
|
|
|
|
{"dns", NULL, SetVariable, LOCAL_AUTH, "Domain Name Server",
|
|
|
|
"set dns pri-addr [sec-addr]", (const void *)VAR_DNS},
|
|
|
|
{"enddisc", NULL, mp_SetEnddisc, LOCAL_AUTH,
|
|
|
|
"Endpoint Discriminator", "set enddisc [IP|magic|label|psn value]"},
|
|
|
|
{"escape", NULL, SetEscape, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"escape characters", "set escape hex-digit ..."},
|
|
|
|
{"filter", NULL, filter_Set, LOCAL_AUTH,
|
|
|
|
"packet filters", "set filter alive|dial|in|out rule-no permit|deny "
|
1999-08-02 21:45:36 +00:00
|
|
|
"[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp "
|
1999-06-23 16:48:24 +00:00
|
|
|
"[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"hangup script", "set hangup chat-script", (const void *) VAR_HANGUP},
|
|
|
|
{"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address",
|
1997-11-22 03:37:54 +00:00
|
|
|
"set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
{"ipcpretry", "ipcpretries", SetVariable, LOCAL_AUTH, "IPCP retries",
|
|
|
|
"set ipcpretry value [attempts]", (const void *)VAR_IPCPRETRY},
|
|
|
|
{"lcpretry", "lcpretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "LCP retries",
|
|
|
|
"set lcpretry value [attempts]", (const void *)VAR_LCPRETRY},
|
1998-06-06 23:00:33 +00:00
|
|
|
{"log", NULL, log_SetLevel, LOCAL_AUTH, "log level",
|
1998-08-29 18:37:02 +00:00
|
|
|
"set log [local] [+|-]async|cbcp|ccp|chat|command|connect|debug|hdlc|id0|"
|
1999-06-02 21:28:02 +00:00
|
|
|
"ipcp|lcp|lqm|phase|physical|sync|tcp/ip|timer|tun..."},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"login", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"login script", "set login chat-script", (const void *) VAR_LOGIN},
|
|
|
|
{"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD},
|
|
|
|
{"mode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "mode value",
|
|
|
|
"set mode interactive|auto|ddial|background", (const void *)VAR_MODE},
|
|
|
|
{"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value",
|
|
|
|
"set mrru value", (const void *)VAR_MRRU},
|
|
|
|
{"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"MRU value", "set mru value", (const void *)VAR_MRU},
|
|
|
|
{"mtu", NULL, SetVariable, LOCAL_AUTH,
|
|
|
|
"interface MTU value", "set mtu value", (const void *)VAR_MTU},
|
|
|
|
{"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server",
|
|
|
|
"set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS},
|
|
|
|
{"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode",
|
|
|
|
"set openmode active|passive [secs]", (const void *)VAR_OPENMODE},
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
{"papretry", "papretries", SetVariable, LOCAL_AUTH | LOCAL_CX, "PAP retries",
|
|
|
|
"set papretry value [attempts]", (const void *)VAR_PAPRETRY},
|
1999-05-08 11:07:56 +00:00
|
|
|
{"parity", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "serial parity",
|
|
|
|
"set parity [odd|even|none]", (const void *)VAR_PARITY},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)",
|
|
|
|
"set phone phone1[:phone2[...]]", (const void *)VAR_PHONE},
|
1998-10-27 22:53:22 +00:00
|
|
|
{"proctitle", "title", SetProcTitle, LOCAL_AUTH,
|
|
|
|
"Process title", "set proctitle [value]"},
|
1999-01-28 01:56:34 +00:00
|
|
|
#ifndef NORADIUS
|
|
|
|
{"radius", NULL, SetVariable, LOCAL_AUTH,
|
|
|
|
"RADIUS Config", "set radius cfgfile", (const void *)VAR_RADIUS},
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
{"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Reconnect timeout", "set reconnect value ntries"},
|
1998-10-26 19:07:39 +00:00
|
|
|
{"recvpipe", NULL, SetVariable, LOCAL_AUTH,
|
|
|
|
"RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX,
|
1999-03-04 17:42:15 +00:00
|
|
|
"Redial timeout", "set redial secs[+inc[-incmax]][.next] [attempts]"},
|
1998-10-26 19:07:39 +00:00
|
|
|
{"sendpipe", NULL, SetVariable, LOCAL_AUTH,
|
|
|
|
"SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"server", "socket", SetServer, LOCAL_AUTH,
|
1998-06-08 20:23:44 +00:00
|
|
|
"server port", "set server|socket TcpPort|LocalName|none password [mask]"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX,
|
1999-05-08 11:07:56 +00:00
|
|
|
"physical speed", "set speed value|sync"},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"STOPPED timeouts", "set stopped [LCPseconds [CCPseconds]]"},
|
|
|
|
{"timeout", NULL, SetVariable, LOCAL_AUTH, "Idle timeout",
|
|
|
|
"set timeout idletime", (const void *)VAR_IDLETIMEOUT},
|
1999-09-07 07:51:11 +00:00
|
|
|
{"urgent", NULL, SetVariable, LOCAL_AUTH, "urgent ports",
|
|
|
|
"set urgent [tcp|udp] [+|-]port...", (const void *)VAR_URGENTPORTS},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"vj", NULL, ipcp_vjset, LOCAL_AUTH,
|
|
|
|
"vj values", "set vj slots|slotcomp [value]"},
|
1997-08-25 00:29:32 +00:00
|
|
|
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
|
1997-11-22 03:37:54 +00:00
|
|
|
"Display this message", "set help|? [command]", SetCommands},
|
1997-08-25 00:29:32 +00:00
|
|
|
{NULL, NULL, NULL},
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
SetCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc > arg->argn)
|
|
|
|
FindExec(arg->bundle, SetCommands, arg->argc, arg->argn, arg->argv,
|
|
|
|
arg->prompt, arg->cx);
|
|
|
|
else if (arg->prompt)
|
|
|
|
prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for"
|
1997-06-09 03:27:43 +00:00
|
|
|
" syntax help.\n");
|
1995-01-31 06:29:58 +00:00
|
|
|
else
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "set command must have arguments\n");
|
1997-06-09 03:27:43 +00:00
|
|
|
|
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
AddCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
struct in_addr dest, gateway, netmask;
|
1998-05-21 21:49:08 +00:00
|
|
|
int gw, addrs;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2)
|
1997-12-07 04:09:15 +00:00
|
|
|
return -1;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
addrs = 0;
|
|
|
|
if (arg->argc == arg->argn+2) {
|
|
|
|
if (!strcasecmp(arg->argv[arg->argn], "default"))
|
1997-12-07 04:09:15 +00:00
|
|
|
dest.s_addr = netmask.s_addr = INADDR_ANY;
|
1998-05-21 21:49:08 +00:00
|
|
|
else {
|
|
|
|
int width;
|
|
|
|
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn],
|
1998-05-21 21:49:08 +00:00
|
|
|
&dest, &netmask, &width))
|
|
|
|
return -1;
|
|
|
|
if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6))
|
|
|
|
addrs = ROUTE_DSTMYADDR;
|
|
|
|
else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7))
|
|
|
|
addrs = ROUTE_DSTHISADDR;
|
1997-12-07 04:09:15 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
gw = 1;
|
1998-03-13 01:36:10 +00:00
|
|
|
} else {
|
1998-05-21 21:49:08 +00:00
|
|
|
if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) {
|
|
|
|
addrs = ROUTE_DSTMYADDR;
|
|
|
|
dest = arg->bundle->ncp.ipcp.my_ip;
|
|
|
|
} else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) {
|
|
|
|
addrs = ROUTE_DSTHISADDR;
|
|
|
|
dest = arg->bundle->ncp.ipcp.peer_ip;
|
|
|
|
} else
|
|
|
|
dest = GetIpAddr(arg->argv[arg->argn]);
|
|
|
|
netmask = GetIpAddr(arg->argv[arg->argn+1]);
|
1997-12-07 04:09:15 +00:00
|
|
|
gw = 2;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) {
|
|
|
|
gateway = arg->bundle->ncp.ipcp.peer_ip;
|
|
|
|
addrs |= ROUTE_GWHISADDR;
|
1998-10-22 02:32:50 +00:00
|
|
|
} else
|
1998-05-21 21:49:08 +00:00
|
|
|
gateway = GetIpAddr(arg->argv[arg->argn+gw]);
|
|
|
|
|
|
|
|
if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask,
|
1999-01-28 01:56:34 +00:00
|
|
|
arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0)
|
|
|
|
&& addrs != ROUTE_STATIC)
|
1998-05-21 21:49:08 +00:00
|
|
|
route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway);
|
|
|
|
|
1997-12-07 04:09:15 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
DeleteCommand(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1997-12-07 04:09:15 +00:00
|
|
|
struct in_addr dest, none;
|
1998-05-21 21:49:08 +00:00
|
|
|
int addrs;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc == arg->argn+1) {
|
|
|
|
if(strcasecmp(arg->argv[arg->argn], "all") == 0) {
|
|
|
|
route_IfDelete(arg->bundle, 0);
|
|
|
|
route_DeleteAll(&arg->bundle->ncp.ipcp.route);
|
|
|
|
} else {
|
|
|
|
addrs = 0;
|
|
|
|
if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) {
|
|
|
|
dest = arg->bundle->ncp.ipcp.my_ip;
|
|
|
|
addrs = ROUTE_DSTMYADDR;
|
|
|
|
} else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) {
|
|
|
|
dest = arg->bundle->ncp.ipcp.peer_ip;
|
|
|
|
addrs = ROUTE_DSTHISADDR;
|
|
|
|
} else {
|
1999-02-25 20:05:55 +00:00
|
|
|
dest = GetIpAddr(arg->argv[arg->argn]);
|
|
|
|
if (dest.s_addr == INADDR_NONE) {
|
|
|
|
log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]);
|
|
|
|
return -1;
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
addrs = ROUTE_STATIC;
|
|
|
|
}
|
1997-12-07 04:09:15 +00:00
|
|
|
none.s_addr = INADDR_ANY;
|
1998-05-21 21:49:08 +00:00
|
|
|
bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none,
|
1998-07-28 21:54:54 +00:00
|
|
|
arg->cmd->args ? 1 : 0, 0);
|
1998-05-21 21:49:08 +00:00
|
|
|
route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest);
|
1997-12-07 04:09:15 +00:00
|
|
|
}
|
1998-03-13 01:36:10 +00:00
|
|
|
} else
|
1997-06-09 03:27:43 +00:00
|
|
|
return -1;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
1997-05-23 04:54:03 +00:00
|
|
|
|
1999-08-19 18:15:52 +00:00
|
|
|
#ifndef NONAT
|
1997-05-23 04:54:03 +00:00
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
AliasEnable(struct cmdargs const *arg)
|
1997-05-23 04:54:03 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc == arg->argn+1) {
|
|
|
|
if (strcasecmp(arg->argv[arg->argn], "yes") == 0) {
|
1999-08-19 18:15:52 +00:00
|
|
|
if (!arg->bundle->NatEnabled) {
|
1999-05-08 11:07:56 +00:00
|
|
|
if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED)
|
|
|
|
PacketAliasSetAddress(arg->bundle->ncp.ipcp.my_ip);
|
1999-08-19 18:15:52 +00:00
|
|
|
arg->bundle->NatEnabled = 1;
|
1999-05-08 11:07:56 +00:00
|
|
|
}
|
1998-06-27 14:17:28 +00:00
|
|
|
return 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
} else if (strcasecmp(arg->argv[arg->argn], "no") == 0) {
|
1999-08-19 18:15:52 +00:00
|
|
|
arg->bundle->NatEnabled = 0;
|
1998-10-22 02:32:50 +00:00
|
|
|
arg->bundle->cfg.opt &= ~OPT_IFACEALIAS;
|
|
|
|
/* Don't iface_Clear() - there may be manually configured addresses */
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1997-05-26 00:44:10 +00:00
|
|
|
}
|
1998-04-25 09:16:23 +00:00
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return -1;
|
1997-05-23 04:54:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
1997-11-22 03:37:54 +00:00
|
|
|
AliasOption(struct cmdargs const *arg)
|
1997-05-23 04:54:03 +00:00
|
|
|
{
|
1998-08-26 18:07:57 +00:00
|
|
|
long param = (long)arg->cmd->args;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (arg->argc == arg->argn+1) {
|
|
|
|
if (strcasecmp(arg->argv[arg->argn], "yes") == 0) {
|
1999-08-19 18:15:52 +00:00
|
|
|
if (arg->bundle->NatEnabled) {
|
1998-06-27 14:17:28 +00:00
|
|
|
PacketAliasSetMode(param, param);
|
1997-08-25 00:29:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
1999-08-19 18:15:52 +00:00
|
|
|
log_Printf(LogWARN, "nat not enabled\n");
|
1998-05-21 21:49:08 +00:00
|
|
|
} else if (strcmp(arg->argv[arg->argn], "no") == 0) {
|
1999-08-19 18:15:52 +00:00
|
|
|
if (arg->bundle->NatEnabled) {
|
1998-06-27 14:17:28 +00:00
|
|
|
PacketAliasSetMode(0, param);
|
1997-08-25 00:29:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
1999-08-19 18:15:52 +00:00
|
|
|
log_Printf(LogWARN, "nat not enabled\n");
|
1997-08-25 00:29:32 +00:00
|
|
|
}
|
1998-04-25 09:16:23 +00:00
|
|
|
}
|
1997-08-25 00:29:32 +00:00
|
|
|
return -1;
|
1997-05-23 04:54:03 +00:00
|
|
|
}
|
1999-08-19 18:15:52 +00:00
|
|
|
#endif /* #ifndef NONAT */
|
1997-11-11 22:58:14 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static int
|
|
|
|
LinkCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
if (arg->argc > arg->argn+1) {
|
|
|
|
char namelist[LINE_LEN];
|
|
|
|
struct datalink *cx;
|
|
|
|
char *name;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
if (!strcmp(arg->argv[arg->argn], "*")) {
|
|
|
|
struct datalink *dl;
|
|
|
|
|
|
|
|
cx = arg->bundle->links;
|
|
|
|
while (cx) {
|
|
|
|
/* Watch it, the command could be a ``remove'' */
|
|
|
|
dl = cx->next;
|
|
|
|
FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv,
|
|
|
|
arg->prompt, cx);
|
|
|
|
for (cx = arg->bundle->links; cx; cx = cx->next)
|
|
|
|
if (cx == dl)
|
|
|
|
break; /* Pointer's still valid ! */
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1);
|
|
|
|
namelist[sizeof namelist - 1] = '\0';
|
|
|
|
for(name = strtok(namelist, ", "); name; name = strtok(NULL,", "))
|
|
|
|
if (!bundle2datalink(arg->bundle, name)) {
|
|
|
|
log_Printf(LogWARN, "link: %s: Invalid link name\n", name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(namelist, arg->argv[arg->argn], sizeof namelist - 1);
|
|
|
|
namelist[sizeof namelist - 1] = '\0';
|
|
|
|
for(name = strtok(namelist, ", "); name; name = strtok(NULL,", ")) {
|
|
|
|
cx = bundle2datalink(arg->bundle, name);
|
|
|
|
if (cx)
|
|
|
|
FindExec(arg->bundle, Commands, arg->argc, arg->argn+1, arg->argv,
|
|
|
|
arg->prompt, cx);
|
|
|
|
else {
|
|
|
|
log_Printf(LogWARN, "link: %s: Invalidated link name !\n", name);
|
|
|
|
result++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_Printf(LogWARN, "Usage: %s\n", arg->cmd->syntax);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct link *
|
|
|
|
command_ChooseLink(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
if (arg->cx)
|
|
|
|
return &arg->cx->physical->link;
|
1998-06-27 23:48:54 +00:00
|
|
|
else if (!arg->bundle->ncp.mp.cfg.mrru) {
|
1998-05-21 21:49:08 +00:00
|
|
|
struct datalink *dl = bundle2datalink(arg->bundle, NULL);
|
1998-06-27 23:48:54 +00:00
|
|
|
if (dl)
|
|
|
|
return &dl->physical->link;
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1998-06-27 23:48:54 +00:00
|
|
|
return &arg->bundle->ncp.mp.link;
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
ident_cmd(const char *cmd, unsigned *keep, unsigned *add)
|
|
|
|
{
|
|
|
|
const char *result;
|
|
|
|
|
|
|
|
switch (*cmd) {
|
|
|
|
case 'A':
|
|
|
|
case 'a':
|
|
|
|
result = "accept";
|
|
|
|
*keep = NEG_MYMASK;
|
|
|
|
*add = NEG_ACCEPTED;
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
case 'd':
|
|
|
|
switch (cmd[1]) {
|
|
|
|
case 'E':
|
|
|
|
case 'e':
|
|
|
|
result = "deny";
|
|
|
|
*keep = NEG_MYMASK;
|
|
|
|
*add = 0;
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
|
|
case 'i':
|
|
|
|
result = "disable";
|
|
|
|
*keep = NEG_HISMASK;
|
|
|
|
*add = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
case 'e':
|
|
|
|
result = "enable";
|
|
|
|
*keep = NEG_HISMASK;
|
|
|
|
*add = NEG_ENABLED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
OptSet(struct cmdargs const *arg)
|
|
|
|
{
|
1998-07-12 00:30:18 +00:00
|
|
|
int bit = (int)(long)arg->cmd->args;
|
1998-05-21 21:49:08 +00:00
|
|
|
const char *cmd;
|
|
|
|
unsigned keep; /* Keep these bits */
|
|
|
|
unsigned add; /* Add these bits */
|
|
|
|
|
|
|
|
if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (add)
|
|
|
|
arg->bundle->cfg.opt |= bit;
|
|
|
|
else
|
|
|
|
arg->bundle->cfg.opt &= ~bit;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1998-10-22 02:32:50 +00:00
|
|
|
static int
|
|
|
|
IfaceAliasOptSet(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
unsigned save = arg->bundle->cfg.opt;
|
|
|
|
int result = OptSet(arg);
|
|
|
|
|
|
|
|
if (result == 0)
|
1999-08-19 18:15:52 +00:00
|
|
|
if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->NatEnabled) {
|
1998-10-22 02:32:50 +00:00
|
|
|
arg->bundle->cfg.opt = save;
|
1999-08-19 18:15:52 +00:00
|
|
|
log_Printf(LogWARN, "Cannot enable iface-alias without NAT\n");
|
1998-10-22 02:32:50 +00:00
|
|
|
result = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static int
|
|
|
|
NegotiateSet(struct cmdargs const *arg)
|
|
|
|
{
|
1998-06-27 23:48:54 +00:00
|
|
|
long param = (long)arg->cmd->args;
|
1998-05-21 21:49:08 +00:00
|
|
|
struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */
|
|
|
|
struct datalink *cx = arg->cx; /* LOCAL_CX uses this */
|
|
|
|
const char *cmd;
|
|
|
|
unsigned keep; /* Keep these bits */
|
|
|
|
unsigned add; /* Add these bits */
|
|
|
|
|
|
|
|
if ((cmd = ident_cmd(arg->argv[arg->argn-2], &keep, &add)) == NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if ((arg->cmd->lauth & LOCAL_CX) && !cx) {
|
|
|
|
log_Printf(LogWARN, "%s %s: No context (use the `link' command)\n",
|
|
|
|
cmd, arg->cmd->name);
|
|
|
|
return 2;
|
|
|
|
} else if (cx && !(arg->cmd->lauth & (LOCAL_CX|LOCAL_CX_OPT))) {
|
|
|
|
log_Printf(LogWARN, "%s %s: Redundant context (%s) ignored\n",
|
|
|
|
cmd, arg->cmd->name, cx->name);
|
|
|
|
cx = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (param) {
|
|
|
|
case NEG_ACFCOMP:
|
|
|
|
cx->physical->link.lcp.cfg.acfcomp &= keep;
|
|
|
|
cx->physical->link.lcp.cfg.acfcomp |= add;
|
|
|
|
break;
|
1999-02-18 00:52:15 +00:00
|
|
|
case NEG_CHAP05:
|
|
|
|
cx->physical->link.lcp.cfg.chap05 &= keep;
|
|
|
|
cx->physical->link.lcp.cfg.chap05 |= add;
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
1999-02-18 00:52:15 +00:00
|
|
|
#ifdef HAVE_DES
|
|
|
|
case NEG_CHAP80:
|
|
|
|
cx->physical->link.lcp.cfg.chap80nt &= keep;
|
|
|
|
cx->physical->link.lcp.cfg.chap80nt |= add;
|
|
|
|
break;
|
|
|
|
case NEG_CHAP80LM:
|
|
|
|
cx->physical->link.lcp.cfg.chap80lm &= keep;
|
|
|
|
cx->physical->link.lcp.cfg.chap80lm |= add;
|
|
|
|
break;
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
case NEG_DEFLATE:
|
|
|
|
l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep;
|
|
|
|
l->ccp.cfg.neg[CCP_NEG_DEFLATE] |= add;
|
|
|
|
break;
|
|
|
|
case NEG_DNS:
|
|
|
|
arg->bundle->ncp.ipcp.cfg.ns.dns_neg &= keep;
|
|
|
|
arg->bundle->ncp.ipcp.cfg.ns.dns_neg |= add;
|
|
|
|
break;
|
1999-06-09 16:54:04 +00:00
|
|
|
case NEG_ENDDISC:
|
|
|
|
arg->bundle->ncp.mp.cfg.negenddisc &= keep;
|
|
|
|
arg->bundle->ncp.mp.cfg.negenddisc |= add;
|
|
|
|
break;
|
1998-05-21 21:49:08 +00:00
|
|
|
case NEG_LQR:
|
|
|
|
cx->physical->link.lcp.cfg.lqr &= keep;
|
|
|
|
cx->physical->link.lcp.cfg.lqr |= add;
|
|
|
|
break;
|
|
|
|
case NEG_PAP:
|
|
|
|
cx->physical->link.lcp.cfg.pap &= keep;
|
|
|
|
cx->physical->link.lcp.cfg.pap |= add;
|
|
|
|
break;
|
|
|
|
case NEG_PPPDDEFLATE:
|
|
|
|
l->ccp.cfg.neg[CCP_NEG_DEFLATE24] &= keep;
|
|
|
|
l->ccp.cfg.neg[CCP_NEG_DEFLATE24] |= add;
|
|
|
|
break;
|
|
|
|
case NEG_PRED1:
|
|
|
|
l->ccp.cfg.neg[CCP_NEG_PRED1] &= keep;
|
|
|
|
l->ccp.cfg.neg[CCP_NEG_PRED1] |= add;
|
|
|
|
break;
|
|
|
|
case NEG_PROTOCOMP:
|
|
|
|
cx->physical->link.lcp.cfg.protocomp &= keep;
|
|
|
|
cx->physical->link.lcp.cfg.protocomp |= add;
|
|
|
|
break;
|
|
|
|
case NEG_SHORTSEQ:
|
1998-10-24 01:08:45 +00:00
|
|
|
switch (bundle_Phase(arg->bundle)) {
|
|
|
|
case PHASE_DEAD:
|
|
|
|
break;
|
|
|
|
case PHASE_ESTABLISH:
|
|
|
|
/* Make sure none of our links are DATALINK_LCP or greater */
|
|
|
|
if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) {
|
|
|
|
log_Printf(LogWARN, "shortseq: Only changable before"
|
|
|
|
" LCP negotiations\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
log_Printf(LogWARN, "shortseq: Only changable at phase"
|
|
|
|
" DEAD/ESTABLISH\n");
|
|
|
|
return 1;
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1998-10-24 01:08:45 +00:00
|
|
|
arg->bundle->ncp.mp.cfg.shortseq &= keep;
|
|
|
|
arg->bundle->ncp.mp.cfg.shortseq |= add;
|
1998-05-21 21:49:08 +00:00
|
|
|
break;
|
|
|
|
case NEG_VJCOMP:
|
|
|
|
arg->bundle->ncp.ipcp.cfg.vj.neg &= keep;
|
|
|
|
arg->bundle->ncp.ipcp.cfg.vj.neg |= add;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct cmdtab const NegotiateCommands[] = {
|
|
|
|
{"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids",
|
|
|
|
"disable|enable", (const void *)OPT_IDCHECK},
|
1998-10-26 19:07:42 +00:00
|
|
|
{"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH,
|
|
|
|
"retain interface addresses", "disable|enable",
|
|
|
|
(const void *)OPT_IFACEALIAS},
|
1999-06-02 00:46:55 +00:00
|
|
|
{"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader",
|
|
|
|
"disable|enable", (const void *)OPT_KEEPSESSION},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface",
|
|
|
|
"disable|enable", (const void *)OPT_LOOPBACK},
|
|
|
|
{"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file",
|
|
|
|
"disable|enable", (const void *)OPT_PASSWDAUTH},
|
1998-10-26 19:07:39 +00:00
|
|
|
{"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry",
|
1998-05-21 21:49:08 +00:00
|
|
|
"disable|enable", (const void *)OPT_PROXY},
|
1998-10-26 19:07:39 +00:00
|
|
|
{"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts",
|
|
|
|
"disable|enable", (const void *)OPT_PROXYALL},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes",
|
|
|
|
"disable|enable", (const void *)OPT_SROUTES},
|
|
|
|
{"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput",
|
|
|
|
"disable|enable", (const void *)OPT_THROUGHPUT},
|
|
|
|
{"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp",
|
|
|
|
"disable|enable", (const void *)OPT_UTMP},
|
|
|
|
|
1999-06-02 00:46:55 +00:00
|
|
|
#define OPT_MAX 10 /* accept/deny allowed below and not above */
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
{"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Address & Control field compression", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_ACFCOMP},
|
1999-02-18 00:52:15 +00:00
|
|
|
{"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
1998-05-21 21:49:08 +00:00
|
|
|
"Challenge Handshake Authentication Protocol", "accept|deny|disable|enable",
|
1999-02-18 00:52:15 +00:00
|
|
|
(const void *)NEG_CHAP05},
|
|
|
|
#ifdef HAVE_DES
|
|
|
|
{"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Microsoft (NT) CHAP", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_CHAP80},
|
|
|
|
{"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Microsoft (NT) CHAP", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_CHAP80LM},
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
{"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"Deflate compression", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_DEFLATE},
|
|
|
|
{"deflate24", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"Deflate (type 24) compression", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_PPPDDEFLATE},
|
|
|
|
{"dns", NULL, NegotiateSet, LOCAL_AUTH,
|
|
|
|
"DNS specification", "accept|deny|disable|enable", (const void *)NEG_DNS},
|
1999-06-09 16:54:04 +00:00
|
|
|
{"enddisc", NULL, NegotiateSet, LOCAL_AUTH, "ENDDISC negotiation",
|
|
|
|
"accept|deny|disable|enable", (const void *)NEG_ENDDISC},
|
1998-05-21 21:49:08 +00:00
|
|
|
{"lqr", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Link Quality Reports", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_LQR},
|
|
|
|
{"pap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Password Authentication protocol", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_PAP},
|
|
|
|
{"pred1", "predictor1", NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
|
|
|
|
"Predictor 1 compression", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_PRED1},
|
|
|
|
{"protocomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
|
|
|
"Protocol field compression", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_PROTOCOMP},
|
|
|
|
{"shortseq", NULL, NegotiateSet, LOCAL_AUTH,
|
|
|
|
"MP Short Sequence Numbers", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_SHORTSEQ},
|
|
|
|
{"vjcomp", NULL, NegotiateSet, LOCAL_AUTH,
|
|
|
|
"Van Jacobson header compression", "accept|deny|disable|enable",
|
|
|
|
(const void *)NEG_VJCOMP},
|
|
|
|
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
|
|
|
|
"Display this message", "accept|deny|disable|enable help|? [value]",
|
|
|
|
NegotiateCommands},
|
|
|
|
{NULL, NULL, NULL},
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
NegotiateCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
if (arg->argc > arg->argn) {
|
|
|
|
char const *argv[3];
|
|
|
|
unsigned keep, add;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
if ((argv[0] = ident_cmd(arg->argv[arg->argn-1], &keep, &add)) == NULL)
|
|
|
|
return -1;
|
|
|
|
argv[2] = NULL;
|
|
|
|
|
|
|
|
for (n = arg->argn; n < arg->argc; n++) {
|
|
|
|
argv[1] = arg->argv[n];
|
|
|
|
FindExec(arg->bundle, NegotiateCommands + (keep == NEG_HISMASK ?
|
|
|
|
0 : OPT_MAX), 2, 1, argv, arg->prompt, arg->cx);
|
|
|
|
}
|
|
|
|
} else if (arg->prompt)
|
|
|
|
prompt_Printf(arg->prompt, "Use `%s ?' to get a list.\n",
|
|
|
|
arg->argv[arg->argn-1]);
|
|
|
|
else
|
|
|
|
log_Printf(LogWARN, "%s command must have arguments\n",
|
|
|
|
arg->argv[arg->argn] );
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
command_ShowNegval(unsigned val)
|
|
|
|
{
|
|
|
|
switch (val&3) {
|
|
|
|
case 1: return "disabled & accepted";
|
|
|
|
case 2: return "enabled & denied";
|
|
|
|
case 3: return "enabled & accepted";
|
|
|
|
}
|
|
|
|
return "disabled & denied";
|
|
|
|
}
|
1998-06-12 20:12:26 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
ClearCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
struct pppThroughput *t;
|
|
|
|
struct datalink *cx;
|
|
|
|
int i, clear_type;
|
|
|
|
|
|
|
|
if (arg->argc < arg->argn + 1)
|
|
|
|
return -1;
|
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
if (strcasecmp(arg->argv[arg->argn], "physical") == 0) {
|
1998-06-12 20:12:26 +00:00
|
|
|
cx = arg->cx;
|
|
|
|
if (!cx)
|
|
|
|
cx = bundle2datalink(arg->bundle, NULL);
|
|
|
|
if (!cx) {
|
1999-05-08 11:07:56 +00:00
|
|
|
log_Printf(LogWARN, "A link must be specified for ``clear physical''\n");
|
1998-06-12 20:12:26 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
t = &cx->physical->link.throughput;
|
|
|
|
} else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0)
|
|
|
|
t = &arg->bundle->ncp.ipcp.throughput;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (arg->argc > arg->argn + 1) {
|
|
|
|
clear_type = 0;
|
|
|
|
for (i = arg->argn + 1; i < arg->argc; i++)
|
|
|
|
if (strcasecmp(arg->argv[i], "overall") == 0)
|
|
|
|
clear_type |= THROUGHPUT_OVERALL;
|
|
|
|
else if (strcasecmp(arg->argv[i], "current") == 0)
|
|
|
|
clear_type |= THROUGHPUT_CURRENT;
|
|
|
|
else if (strcasecmp(arg->argv[i], "peak") == 0)
|
|
|
|
clear_type |= THROUGHPUT_PEAK;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
clear_type = THROUGHPUT_ALL;
|
|
|
|
|
|
|
|
throughput_clear(t, clear_type, arg->prompt);
|
|
|
|
return 0;
|
|
|
|
}
|
1998-10-22 02:32:50 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
RunListCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???";
|
|
|
|
|
|
|
|
if (arg->argc > arg->argn)
|
|
|
|
FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv,
|
|
|
|
arg->prompt, arg->cx);
|
|
|
|
else if (arg->prompt)
|
|
|
|
prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help"
|
|
|
|
" <option>' for syntax help.\n", cmd, cmd);
|
|
|
|
else
|
|
|
|
log_Printf(LogWARN, "%s command must have arguments\n", cmd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
IfaceAddCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
int bits, n, how;
|
|
|
|
struct in_addr ifa, mask, brd;
|
|
|
|
|
Fix the interface alias code. Previously, I was expecting something
like
tun0: flags=blah
10.0.0.1 -> 10.0.0.100
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 10.0.0.100
to DTRT, despite the SIOCAIFADDR for each new alias returning
-1 & EEXIST while adding the alias anyway. In real life, once
we have the second alias with the same destination, nothing will
route any more ! Also, because I was ignoring EEXIST, the
dynamic IP assignment code was assigning duplicate addresses
('cos it was being lied to by iface_inAdd()).
Now we have
tun0: flags=blah
10.0.0.1 -> 255.255.255.255
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 255.255.255.255
This works - stuff bound to 10.1 & 10.3 will be considered alive
by the kernel, and when they route back to the tun device, the
packets get aliased to 10.2 and go out to 10.100 (as with the
original plan).
We still see the EEXIST in SIOCAIFADDR, but ignore it when our
destination is 255.255.255.255, assuming that the alias *was*
actually added.
Additionally, ``iface add'' may now optionally be given only
the interface address. The mask & destination default to
255.255.255.255.
1998-10-26 19:07:36 +00:00
|
|
|
if (arg->argc == arg->argn + 1) {
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL))
|
1998-10-22 02:32:50 +00:00
|
|
|
return -1;
|
Fix the interface alias code. Previously, I was expecting something
like
tun0: flags=blah
10.0.0.1 -> 10.0.0.100
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 10.0.0.100
to DTRT, despite the SIOCAIFADDR for each new alias returning
-1 & EEXIST while adding the alias anyway. In real life, once
we have the second alias with the same destination, nothing will
route any more ! Also, because I was ignoring EEXIST, the
dynamic IP assignment code was assigning duplicate addresses
('cos it was being lied to by iface_inAdd()).
Now we have
tun0: flags=blah
10.0.0.1 -> 255.255.255.255
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 255.255.255.255
This works - stuff bound to 10.1 & 10.3 will be considered alive
by the kernel, and when they route back to the tun device, the
packets get aliased to 10.2 and go out to 10.100 (as with the
original plan).
We still see the EEXIST in SIOCAIFADDR, but ignore it when our
destination is 255.255.255.255, assuming that the alias *was*
actually added.
Additionally, ``iface add'' may now optionally be given only
the interface address. The mask & destination default to
255.255.255.255.
1998-10-26 19:07:36 +00:00
|
|
|
mask.s_addr = brd.s_addr = INADDR_BROADCAST;
|
|
|
|
} else {
|
|
|
|
if (arg->argc == arg->argn + 2) {
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits))
|
Fix the interface alias code. Previously, I was expecting something
like
tun0: flags=blah
10.0.0.1 -> 10.0.0.100
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 10.0.0.100
to DTRT, despite the SIOCAIFADDR for each new alias returning
-1 & EEXIST while adding the alias anyway. In real life, once
we have the second alias with the same destination, nothing will
route any more ! Also, because I was ignoring EEXIST, the
dynamic IP assignment code was assigning duplicate addresses
('cos it was being lied to by iface_inAdd()).
Now we have
tun0: flags=blah
10.0.0.1 -> 255.255.255.255
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 255.255.255.255
This works - stuff bound to 10.1 & 10.3 will be considered alive
by the kernel, and when they route back to the tun device, the
packets get aliased to 10.2 and go out to 10.100 (as with the
original plan).
We still see the EEXIST in SIOCAIFADDR, but ignore it when our
destination is 255.255.255.255, assuming that the alias *was*
actually added.
Additionally, ``iface add'' may now optionally be given only
the interface address. The mask & destination default to
255.255.255.255.
1998-10-26 19:07:36 +00:00
|
|
|
return -1;
|
|
|
|
n = 1;
|
|
|
|
} else if (arg->argc == arg->argn + 3) {
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL))
|
Fix the interface alias code. Previously, I was expecting something
like
tun0: flags=blah
10.0.0.1 -> 10.0.0.100
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 10.0.0.100
to DTRT, despite the SIOCAIFADDR for each new alias returning
-1 & EEXIST while adding the alias anyway. In real life, once
we have the second alias with the same destination, nothing will
route any more ! Also, because I was ignoring EEXIST, the
dynamic IP assignment code was assigning duplicate addresses
('cos it was being lied to by iface_inAdd()).
Now we have
tun0: flags=blah
10.0.0.1 -> 255.255.255.255
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 255.255.255.255
This works - stuff bound to 10.1 & 10.3 will be considered alive
by the kernel, and when they route back to the tun device, the
packets get aliased to 10.2 and go out to 10.100 (as with the
original plan).
We still see the EEXIST in SIOCAIFADDR, but ignore it when our
destination is 255.255.255.255, assuming that the alias *was*
actually added.
Additionally, ``iface add'' may now optionally be given only
the interface address. The mask & destination default to
255.255.255.255.
1998-10-26 19:07:36 +00:00
|
|
|
return -1;
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL))
|
Fix the interface alias code. Previously, I was expecting something
like
tun0: flags=blah
10.0.0.1 -> 10.0.0.100
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 10.0.0.100
to DTRT, despite the SIOCAIFADDR for each new alias returning
-1 & EEXIST while adding the alias anyway. In real life, once
we have the second alias with the same destination, nothing will
route any more ! Also, because I was ignoring EEXIST, the
dynamic IP assignment code was assigning duplicate addresses
('cos it was being lied to by iface_inAdd()).
Now we have
tun0: flags=blah
10.0.0.1 -> 255.255.255.255
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 255.255.255.255
This works - stuff bound to 10.1 & 10.3 will be considered alive
by the kernel, and when they route back to the tun device, the
packets get aliased to 10.2 and go out to 10.100 (as with the
original plan).
We still see the EEXIST in SIOCAIFADDR, but ignore it when our
destination is 255.255.255.255, assuming that the alias *was*
actually added.
Additionally, ``iface add'' may now optionally be given only
the interface address. The mask & destination default to
255.255.255.255.
1998-10-26 19:07:36 +00:00
|
|
|
return -1;
|
|
|
|
n = 2;
|
|
|
|
} else
|
1998-10-22 02:32:50 +00:00
|
|
|
return -1;
|
|
|
|
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL))
|
Fix the interface alias code. Previously, I was expecting something
like
tun0: flags=blah
10.0.0.1 -> 10.0.0.100
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 10.0.0.100
to DTRT, despite the SIOCAIFADDR for each new alias returning
-1 & EEXIST while adding the alias anyway. In real life, once
we have the second alias with the same destination, nothing will
route any more ! Also, because I was ignoring EEXIST, the
dynamic IP assignment code was assigning duplicate addresses
('cos it was being lied to by iface_inAdd()).
Now we have
tun0: flags=blah
10.0.0.1 -> 255.255.255.255
10.0.0.2 -> 10.0.0.100
10.0.0.3 -> 255.255.255.255
This works - stuff bound to 10.1 & 10.3 will be considered alive
by the kernel, and when they route back to the tun device, the
packets get aliased to 10.2 and go out to 10.100 (as with the
original plan).
We still see the EEXIST in SIOCAIFADDR, but ignore it when our
destination is 255.255.255.255, assuming that the alias *was*
actually added.
Additionally, ``iface add'' may now optionally be given only
the interface address. The mask & destination default to
255.255.255.255.
1998-10-26 19:07:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
1998-10-22 02:32:50 +00:00
|
|
|
|
|
|
|
how = IFACE_ADD_LAST;
|
|
|
|
if (arg->cmd->args)
|
|
|
|
how |= IFACE_FORCE_ADD;
|
|
|
|
|
|
|
|
return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
IfaceDeleteCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
struct in_addr ifa;
|
|
|
|
int ok;
|
|
|
|
|
|
|
|
if (arg->argc != arg->argn + 1)
|
|
|
|
return -1;
|
|
|
|
|
1999-01-28 01:56:34 +00:00
|
|
|
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL))
|
1998-10-22 02:32:50 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED &&
|
|
|
|
arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) {
|
|
|
|
log_Printf(LogWARN, "%s: Cannot remove active interface address\n",
|
|
|
|
inet_ntoa(ifa));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok = iface_inDelete(arg->bundle->iface, ifa);
|
|
|
|
if (!ok) {
|
|
|
|
if (arg->cmd->args)
|
|
|
|
ok = 1;
|
|
|
|
else if (arg->prompt)
|
|
|
|
prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa));
|
|
|
|
else
|
|
|
|
log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa));
|
|
|
|
}
|
|
|
|
|
|
|
|
return !ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
IfaceClearCommand(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
int how;
|
|
|
|
|
|
|
|
if (arg->argc != arg->argn)
|
|
|
|
return -1;
|
|
|
|
|
1998-11-05 21:59:48 +00:00
|
|
|
how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED ||
|
|
|
|
arg->bundle->phys_type.all & PHYS_AUTO ?
|
1998-10-22 02:32:50 +00:00
|
|
|
IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL;
|
|
|
|
iface_Clear(arg->bundle->iface, how);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1998-10-27 22:53:22 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
SetProcTitle(struct cmdargs const *arg)
|
|
|
|
{
|
|
|
|
static char title[LINE_LEN];
|
|
|
|
char *argv[MAXARGS], *ptr;
|
|
|
|
int len, remaining, f, argc = arg->argc - arg->argn;
|
|
|
|
|
|
|
|
if (arg->argc == arg->argn) {
|
|
|
|
arg->bundle->argv[0] = arg->bundle->argv0;
|
|
|
|
arg->bundle->argv[1] = arg->bundle->argv1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc >= sizeof argv / sizeof argv[0]) {
|
|
|
|
argc = sizeof argv / sizeof argv[0] - 1;
|
|
|
|
log_Printf(LogWARN, "Truncating proc title to %d args\n", argc);
|
|
|
|
}
|
1999-06-09 08:47:36 +00:00
|
|
|
command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1, getpid());
|
1998-10-27 22:53:22 +00:00
|
|
|
|
|
|
|
ptr = title;
|
|
|
|
remaining = sizeof title - 1;
|
|
|
|
for (f = 0; f < argc && remaining; f++) {
|
|
|
|
if (f) {
|
|
|
|
*ptr++ = ' ';
|
|
|
|
remaining--;
|
|
|
|
}
|
|
|
|
len = strlen(argv[f]);
|
|
|
|
if (len > remaining)
|
|
|
|
len = remaining;
|
|
|
|
memcpy(ptr, argv[f], len);
|
|
|
|
remaining -= len;
|
|
|
|
ptr += len;
|
|
|
|
}
|
|
|
|
*ptr = '\0';
|
|
|
|
|
|
|
|
arg->bundle->argv[0] = title;
|
|
|
|
arg->bundle->argv[1] = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|