aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Somers <brian@FreeBSD.org>1998-05-21 21:49:08 +0000
committerBrian Somers <brian@FreeBSD.org>1998-05-21 21:49:08 +0000
commitd91d286164db7f10f516a9d0bca0a3527e864714 (patch)
treed42fe77349e72dc800e8fbd2c8e2b8f200d35100
parent6cb0199d2346a87aeb63ba9355209029da769917 (diff)
parent641684cdbadb059ec03c02ffeb72040a9b1367d0 (diff)
downloadsrc-d91d286164db7f10f516a9d0bca0a3527e864714.tar.gz
src-d91d286164db7f10f516a9d0bca0a3527e864714.zip
MFMP: Make ppp multilink capable.
See the file README.changes, and re-read the man page.
Notes
Notes: svn path=/head/; revision=36285
-rw-r--r--usr.sbin/ppp/Makefile28
-rw-r--r--usr.sbin/ppp/README.changes70
-rw-r--r--usr.sbin/ppp/alias_cmd.c98
-rw-r--r--usr.sbin/ppp/alias_cmd.h8
-rw-r--r--usr.sbin/ppp/arp.c135
-rw-r--r--usr.sbin/ppp/arp.h10
-rw-r--r--usr.sbin/ppp/async.c124
-rw-r--r--usr.sbin/ppp/async.h30
-rw-r--r--usr.sbin/ppp/auth.c255
-rw-r--r--usr.sbin/ppp/auth.h33
-rw-r--r--usr.sbin/ppp/bundle.c1615
-rw-r--r--usr.sbin/ppp/bundle.h170
-rw-r--r--usr.sbin/ppp/ccp.c556
-rw-r--r--usr.sbin/ppp/ccp.h99
-rw-r--r--usr.sbin/ppp/chap.c201
-rw-r--r--usr.sbin/ppp/chap.h18
-rw-r--r--usr.sbin/ppp/chap_ms.c12
-rw-r--r--usr.sbin/ppp/chap_ms.h4
-rw-r--r--usr.sbin/ppp/chat.c1030
-rw-r--r--usr.sbin/ppp/chat.h95
-rw-r--r--usr.sbin/ppp/command.c2356
-rw-r--r--usr.sbin/ppp/command.h49
-rw-r--r--usr.sbin/ppp/datalink.c1096
-rw-r--r--usr.sbin/ppp/datalink.h130
-rw-r--r--usr.sbin/ppp/deflate.c466
-rw-r--r--usr.sbin/ppp/defs.c119
-rw-r--r--usr.sbin/ppp/defs.h68
-rw-r--r--usr.sbin/ppp/descriptor.h (renamed from usr.sbin/ppp/pathnames.h)49
-rw-r--r--usr.sbin/ppp/filter.c428
-rw-r--r--usr.sbin/ppp/filter.h37
-rw-r--r--usr.sbin/ppp/fsm.c710
-rw-r--r--usr.sbin/ppp/fsm.h93
-rw-r--r--usr.sbin/ppp/hdlc.c480
-rw-r--r--usr.sbin/ppp/hdlc.h67
-rw-r--r--usr.sbin/ppp/id.c77
-rw-r--r--usr.sbin/ppp/id.h7
-rw-r--r--usr.sbin/ppp/ip.c344
-rw-r--r--usr.sbin/ppp/ip.h20
-rw-r--r--usr.sbin/ppp/ipcp.c1166
-rw-r--r--usr.sbin/ppp/ipcp.h117
-rw-r--r--usr.sbin/ppp/iplist.c8
-rw-r--r--usr.sbin/ppp/lcp.c989
-rw-r--r--usr.sbin/ppp/lcp.h96
-rw-r--r--usr.sbin/ppp/lcpproto.h5
-rw-r--r--usr.sbin/ppp/link.c198
-rw-r--r--usr.sbin/ppp/link.h68
-rw-r--r--usr.sbin/ppp/loadalias.c73
-rw-r--r--usr.sbin/ppp/loadalias.h34
-rw-r--r--usr.sbin/ppp/log.c239
-rw-r--r--usr.sbin/ppp/log.h88
-rw-r--r--usr.sbin/ppp/lqr.c339
-rw-r--r--usr.sbin/ppp/lqr.h57
-rw-r--r--usr.sbin/ppp/main.c1104
-rw-r--r--usr.sbin/ppp/main.h10
-rw-r--r--usr.sbin/ppp/mbuf.c105
-rw-r--r--usr.sbin/ppp/mbuf.h30
-rw-r--r--usr.sbin/ppp/modem.c1107
-rw-r--r--usr.sbin/ppp/modem.h39
-rw-r--r--usr.sbin/ppp/mp.c992
-rw-r--r--usr.sbin/ppp/mp.h134
-rw-r--r--usr.sbin/ppp/nat_cmd.c98
-rw-r--r--usr.sbin/ppp/nat_cmd.h8
-rw-r--r--usr.sbin/ppp/os.c400
-rw-r--r--usr.sbin/ppp/os.h32
-rw-r--r--usr.sbin/ppp/pap.c171
-rw-r--r--usr.sbin/ppp/pap.h10
-rw-r--r--usr.sbin/ppp/phase.c105
-rw-r--r--usr.sbin/ppp/phase.h31
-rw-r--r--usr.sbin/ppp/physical.c230
-rw-r--r--usr.sbin/ppp/physical.h101
-rw-r--r--usr.sbin/ppp/ppp.81803
-rw-r--r--usr.sbin/ppp/ppp.8.m41803
-rw-r--r--usr.sbin/ppp/pred.c204
-rw-r--r--usr.sbin/ppp/prompt.c522
-rw-r--r--usr.sbin/ppp/prompt.h90
-rw-r--r--usr.sbin/ppp/route.c383
-rw-r--r--usr.sbin/ppp/route.h34
-rw-r--r--usr.sbin/ppp/server.c228
-rw-r--r--usr.sbin/ppp/server.h26
-rw-r--r--usr.sbin/ppp/sig.c10
-rw-r--r--usr.sbin/ppp/sig.h6
-rw-r--r--usr.sbin/ppp/slcompress.c129
-rw-r--r--usr.sbin/ppp/slcompress.h37
-rw-r--r--usr.sbin/ppp/systems.c255
-rw-r--r--usr.sbin/ppp/systems.h11
-rw-r--r--usr.sbin/ppp/throughput.c67
-rw-r--r--usr.sbin/ppp/throughput.h7
-rw-r--r--usr.sbin/ppp/timer.c179
-rw-r--r--usr.sbin/ppp/timer.h20
-rw-r--r--usr.sbin/ppp/tun.c38
-rw-r--r--usr.sbin/ppp/tun.h6
-rw-r--r--usr.sbin/ppp/vars.c192
-rw-r--r--usr.sbin/ppp/vars.h205
-rw-r--r--usr.sbin/ppp/vjcomp.c80
-rw-r--r--usr.sbin/ppp/vjcomp.h12
95 files changed, 16517 insertions, 9201 deletions
diff --git a/usr.sbin/ppp/Makefile b/usr.sbin/ppp/Makefile
index 4969b34940e2..5ad1c9d898e5 100644
--- a/usr.sbin/ppp/Makefile
+++ b/usr.sbin/ppp/Makefile
@@ -1,19 +1,27 @@
-# $Id: Makefile,v 1.35 1998/01/17 14:21:21 brian Exp $
+# $Id: Makefile,v 1.36.2.12 1998/05/04 03:01:34 brian Exp $
PROG= ppp
-SRCS= arp.c async.c auth.c ccp.c chap.c chat.c command.c deflate.c \
- defs.c filter.c fsm.c hdlc.c id.c ip.c ipcp.c iplist.c lcp.c \
- log.c lqr.c main.c mbuf.c modem.c os.c pap.c phase.c \
- pred.c route.c server.c sig.c slcompress.c systems.c throughput.c \
- timer.c tun.c vars.c vjcomp.c
-CFLAGS+=-Wall
-LDADD+= -lmd -lcrypt -lutil -lz
-DPADD+= ${LIBMD} ${LIBCRYPT} ${LIBUTIL} ${LIBZ}
-MAN8= ppp.8
+SRCS= arp.c async.c auth.c bundle.c ccp.c chap.c chat.c command.c \
+ datalink.c deflate.c defs.c filter.c fsm.c hdlc.c id.c ip.c \
+ ipcp.c iplist.c lcp.c link.c log.c lqr.c main.c mbuf.c modem.c \
+ mp.c pap.c physical.c pred.c prompt.c route.c server.c sig.c \
+ slcompress.c systems.c throughput.c timer.c tun.c vjcomp.c
+CFLAGS+=-Wall -Wpointer-arith
+LDADD+= -lutil -lz
+DPADD+= ${LIBUTIL} ${LIBZ}
BINMODE=4550
BINOWN= root
BINGRP= network
+OPSYS!= uname -s
+.if (${OPSYS} == "OpenBSD")
+MAN= ppp.8
+.else
+MAN8= ppp.8
+LDADD+= -lmd -lcrypt
+DPADD+= ${LIBMD} ${LIBCRYPT}
+.endif
+
.if defined(RELEASE_CRUNCH)
CFLAGS+=-DRELEASE_CRUNCH
.endif
diff --git a/usr.sbin/ppp/README.changes b/usr.sbin/ppp/README.changes
new file mode 100644
index 000000000000..2053cbf9576a
--- /dev/null
+++ b/usr.sbin/ppp/README.changes
@@ -0,0 +1,70 @@
+This file summarises changes made to ppp that effect
+its configuration.
+
+It does not describe new features, rather it attempts
+to answer any `this used to work, why doesn't it now?'
+questions.
+
+o The `set debug' command was replaced with `set log'.
+o The `set log LCP' command was split into LCP, IPCP and CCP logs.
+o Syslogd is used for logging. /etc/syslog.conf must be updated.
+o LQR is disabled by default.
+o Openmode is active by default.
+o Users must be a member of group `network' for ppp access. Furthermore,
+ they must be `allow'ed to run ppp via the `allow' command in the
+ configuration file.
+ For a brief period, ppp could only be run as root.
+o No diagnostic socket is created by default. The `set server' command
+ must be used.
+o The diagnostic socket password must be specified *only* on the `set
+ server' command line.
+o When `set server' is used to re-select a diagnostic port, all existing
+ diagnostic connections are dropped.
+o pppd-deflate is now called deflate24.
+o Filter IPs of 0.0.0.0 have a default width of 0, not 32.
+o Errors in `add' and `delete' are logged as warnings rather than being
+ written to the TCP/IP log.
+o Any number of diagnostic prompts are allowed, and they are allowed in
+ interactive mode.
+o The default `device' is cuaa1, then cuaa0
+o A password of "*" in ppp.secret causes a passwd database lookup in
+ pap mode.
+o The value of the CONNECT environment variable is logged in the
+ utmp host field in -direct mode.
+o Out-of-sequence FSM packets (IPCP/LCP/CCP) are dropped by default.
+o Reconnect values are used after an LQR timeout.
+o ^C works on the parent in -background mode.
+o The dial/call/open command works asyncronously. As a result, prompts
+ do not lose control while dialing.
+o The `display' command has been removed. All information is available
+ with the appropriate `show' command.
+o Msext does not need to be enabled/disabled. Setting the NBNS (set nbns)
+ will auto enable it. The DNS side may be enabled/disabled, and if
+ enabled without a `set dns' will use values from /etc/resolv.conf.
+o Filters are now called `allow', `dial', `in' and `out'. `set
+ ifilter ...' becomes `set filter in ...' etc.
+o Authname and Authkey may only be `set' in phase DEAD.
+o Set encrypt is no longer necessary. Ppp will respond to M$CHAP
+ servers correctly if it's built with DES.
+o Throughput statistics are enabled by default.
+o `Set stopped' only has two parameters. It's no longer possible to
+ have an IPCP stopped timer.
+o `Set timeout' only has one parameter. Use `set lqrperiod' and `set
+ {lcp,ccp,ipcp,chap,pap}retry' for the other timers. `show timeout'
+ is also now available using the relevent show commands.
+o `set loopback' is now `enable/disable loopback'.
+o `show auto', `show loopback' and `show mtu' are all part of `show bundle'.
+o `show mru' is part of `show lcp'
+o `show msext' and `show vj' are part of `show ipcp'
+o `show reconnect' and `show redial' are part of `show link'
+o A signal 15 (TERM) will now shut down the link gracefully.
+o A signal 2 (HUP) will drop all links immediately.
+o Signal 30 (USR1) is now ignored.
+o Add & delete commands are not necessary in ppp.linkup if they are
+ `sticky routes' (ie, contain MYADDR or HISADDR).
+o LINK and CARRIER logging are no longer available.
+o Timer based DEBUG messages are now logged in the new TIMER log.
+o Ppp can use tun devices > tun255.
+o Protocol-compressed packets are accepted even if they were denied
+ at LCP negotiation time.
+o Passwords aren't logged when logging the ``set server'' line.
diff --git a/usr.sbin/ppp/alias_cmd.c b/usr.sbin/ppp/alias_cmd.c
index d79ff328256d..c4265fdd7c1d 100644
--- a/usr.sbin/ppp/alias_cmd.c
+++ b/usr.sbin/ppp/alias_cmd.c
@@ -2,26 +2,25 @@
* The code in this file was written by Eivind Eklund <perhaps@yes.no>,
* who places it in the public domain without restriction.
*
- * $Id: alias_cmd.c,v 1.11 1997/12/24 10:28:37 brian Exp $
+ * $Id: alias_cmd.c,v 1.12.2.8 1998/05/01 19:23:43 brian Exp $
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
-#include "defs.h"
#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
-#include "vars.h"
#include "alias_cmd.h"
+#include "descriptor.h"
+#include "prompt.h"
static int StrToAddr(const char *, struct in_addr *);
@@ -30,13 +29,12 @@ static int StrToAddrAndPort(const char *, struct in_addr *, u_short *, const cha
int
-AliasRedirectPort(struct cmdargs const *arg)
+alias_RedirectPort(struct cmdargs const *arg)
{
- if (!(mode & MODE_ALIAS)) {
- if (VarTerm)
- fprintf(VarTerm, "Alias not enabled\n");
+ if (!alias_IsEnabled()) {
+ prompt_Printf(arg->prompt, "Alias not enabled\n");
return 1;
- } else if (arg->argc == 3) {
+ } else if (arg->argc == arg->argn+3) {
char proto_constant;
const char *proto;
u_short local_port;
@@ -46,45 +44,44 @@ AliasRedirectPort(struct cmdargs const *arg)
struct in_addr null_addr;
struct alias_link *link;
- proto = arg->argv[0];
+ proto = arg->argv[arg->argn];
if (strcmp(proto, "tcp") == 0) {
proto_constant = IPPROTO_TCP;
} else if (strcmp(proto, "udp") == 0) {
proto_constant = IPPROTO_UDP;
} else {
- if (VarTerm) {
- fprintf(VarTerm, "port redirect: protocol must be tcp or udp\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name,
- arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "port redirect: protocol must be"
+ " tcp or udp\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- error = StrToAddrAndPort(arg->argv[1], &local_addr, &local_port, proto);
+ error = StrToAddrAndPort(arg->argv[arg->argn+1], &local_addr, &local_port,
+ proto);
if (error) {
- if (VarTerm) {
- fprintf(VarTerm, "port redirect: error reading local addr:port\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "port redirect: error reading"
+ " local addr:port\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- error = StrToPort(arg->argv[2], &alias_port, proto);
+ error = StrToPort(arg->argv[arg->argn+2], &alias_port, proto);
if (error) {
- if (VarTerm) {
- fprintf(VarTerm, "port redirect: error reading alias port\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "port redirect: error reading alias port\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- null_addr.s_addr = 0;
+ null_addr.s_addr = INADDR_ANY;
- link = VarPacketAliasRedirectPort(local_addr, local_port,
+ link = (*PacketAlias.RedirectPort)(local_addr, local_port,
null_addr, 0,
null_addr, alias_port,
proto_constant);
- if (link == NULL && VarTerm)
- fprintf(VarTerm, "port redirect: error returned by packed"
+ if (link == NULL)
+ prompt_Printf(arg->prompt, "port redirect: error returned by packed"
" aliasing engine (code=%d)\n", error);
} else
return -1;
@@ -94,36 +91,35 @@ AliasRedirectPort(struct cmdargs const *arg)
int
-AliasRedirectAddr(struct cmdargs const *arg)
+alias_RedirectAddr(struct cmdargs const *arg)
{
- if (!(mode & MODE_ALIAS)) {
- if (VarTerm)
- fprintf(VarTerm, "alias not enabled\n");
+ if (!alias_IsEnabled()) {
+ prompt_Printf(arg->prompt, "alias not enabled\n");
return 1;
- } else if (arg->argc == 2) {
+ } else if (arg->argc == arg->argn+2) {
int error;
struct in_addr local_addr;
struct in_addr alias_addr;
struct alias_link *link;
- error = StrToAddr(arg->argv[0], &local_addr);
+ error = StrToAddr(arg->argv[arg->argn], &local_addr);
if (error) {
- if (VarTerm)
- fprintf(VarTerm, "address redirect: invalid local address\n");
+ prompt_Printf(arg->prompt, "address redirect: invalid local address\n");
return 1;
}
- error = StrToAddr(arg->argv[1], &alias_addr);
+ error = StrToAddr(arg->argv[arg->argn+1], &alias_addr);
if (error) {
- if (VarTerm) {
- fprintf(VarTerm, "address redirect: invalid alias address\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "address redirect: invalid alias address\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- link = VarPacketAliasRedirectAddr(local_addr, alias_addr);
- if (link == NULL && VarTerm) {
- fprintf(VarTerm, "address redirect: packet aliasing engine error\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
+ link = (*PacketAlias.RedirectAddr)(local_addr, alias_addr);
+ if (link == NULL) {
+ prompt_Printf(arg->prompt, "address redirect: packet aliasing"
+ " engine error\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
}
} else
return -1;
@@ -142,7 +138,7 @@ StrToAddr(const char *str, struct in_addr *addr)
hp = gethostbyname(str);
if (!hp) {
- LogPrintf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
+ log_Printf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
return -1;
}
*addr = *((struct in_addr *) hp->h_addr);
@@ -164,7 +160,7 @@ StrToPort(const char *str, u_short *port, const char *proto)
}
sp = getservbyname(str, proto);
if (!sp) {
- LogPrintf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
+ log_Printf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
str, proto);
return -1;
}
@@ -181,7 +177,7 @@ StrToAddrAndPort(const char *str, struct in_addr *addr, u_short *port, const cha
colon = strchr(str, ':');
if (!colon) {
- LogPrintf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
+ log_Printf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
return -1;
}
diff --git a/usr.sbin/ppp/alias_cmd.h b/usr.sbin/ppp/alias_cmd.h
index 31eaf12cbdc5..495397c14070 100644
--- a/usr.sbin/ppp/alias_cmd.h
+++ b/usr.sbin/ppp/alias_cmd.h
@@ -2,8 +2,10 @@
* The code in this file was written by Eivind Eklund <perhaps@yes.no>,
* who places it in the public domain without restriction.
*
- * $Id: alias_cmd.h,v 1.6 1997/12/21 14:28:24 brian Exp $
+ * $Id: alias_cmd.h,v 1.7.2.2 1998/05/01 19:23:44 brian Exp $
*/
-extern int AliasRedirectPort(struct cmdargs const *);
-extern int AliasRedirectAddr(struct cmdargs const *);
+struct cmdargs;
+
+extern int alias_RedirectPort(struct cmdargs const *);
+extern int alias_RedirectAddr(struct cmdargs const *);
diff --git a/usr.sbin/ppp/arp.c b/usr.sbin/ppp/arp.c
index b62f940cdb39..10fa51cce4df 100644
--- a/usr.sbin/ppp/arp.c
+++ b/usr.sbin/ppp/arp.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: arp.c,v 1.26 1998/01/23 22:29:16 brian Exp $
+ * $Id: arp.c,v 1.27.2.15 1998/05/01 19:23:46 brian Exp $
*
*/
@@ -25,57 +25,46 @@
* TODO:
*/
-#include <sys/param.h>
-#include <sys/time.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
-#include <net/if_types.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
-#include <sys/ioctl.h>
#include <sys/sysctl.h>
-#include <sys/uio.h>
#include <unistd.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "id.h"
-#include "route.h"
+#include "timer.h"
+#include "fsm.h"
+#include "defs.h"
+#include "iplist.h"
+#include "throughput.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
#include "arp.h"
-#ifdef DEBUG
-/*
- * To test the proxy arp stuff, just
- *
- * cc -o arp-test -DDEBUG arp.c
- *
- */
-#define LogIsKept(x) 1
-#define LogPrintf fprintf
-#undef LogDEBUG
-#define LogDEBUG stderr
-#undef LogERROR
-#define LogERROR stderr
-#undef LogPHASE
-#define LogPHASE stdout
-#define ID0socket socket
-#define ID0ioctl ioctl
-#endif
-
-static int rtm_seq;
-
-static int get_ether_addr(int, struct in_addr, struct sockaddr_dl *);
-
/*
* SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
* if it exists.
@@ -89,7 +78,7 @@ static int get_ether_addr(int, struct in_addr, struct sockaddr_dl *);
#if RTM_VERSION >= 3
/*
- * sifproxyarp - Make a proxy ARP entry for the peer.
+ * arp_SetProxy - Make a proxy ARP entry for the peer.
*/
static struct {
struct rt_msghdr hdr;
@@ -101,7 +90,7 @@ static struct {
static int arpmsg_valid;
int
-sifproxyarp(int unit, struct in_addr hisaddr)
+arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s)
{
int routes;
@@ -110,31 +99,31 @@ sifproxyarp(int unit, struct in_addr hisaddr)
* address.
*/
memset(&arpmsg, 0, sizeof arpmsg);
- if (!get_ether_addr(unit, hisaddr, &arpmsg.hwa)) {
- LogPrintf(LogERROR, "Cannot determine ethernet address for proxy ARP\n");
+ if (!get_ether_addr(s, addr, &arpmsg.hwa)) {
+ log_Printf(LogERROR, "Cannot determine ethernet address for proxy ARP\n");
return 0;
}
routes = ID0socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (routes < 0) {
- LogPrintf(LogERROR, "sifproxyarp: opening routing socket: %s\n",
+ log_Printf(LogERROR, "arp_SetProxy: opening routing socket: %s\n",
strerror(errno));
return 0;
}
arpmsg.hdr.rtm_type = RTM_ADD;
arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
arpmsg.hdr.rtm_version = RTM_VERSION;
- arpmsg.hdr.rtm_seq = ++rtm_seq;
+ arpmsg.hdr.rtm_seq = ++bundle->routing_seq;
arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
arpmsg.hdr.rtm_inits = RTV_EXPIRE;
arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
arpmsg.dst.sin_family = AF_INET;
- arpmsg.dst.sin_addr.s_addr = hisaddr.s_addr;
+ arpmsg.dst.sin_addr.s_addr = addr.s_addr;
arpmsg.dst.sin_other = SIN_PROXY;
arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
+ arpmsg.hwa.sdl_len;
if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
- LogPrintf(LogERROR, "Add proxy arp entry: %s\n", strerror(errno));
+ log_Printf(LogERROR, "Add proxy arp entry: %s\n", strerror(errno));
close(routes);
return 0;
}
@@ -144,10 +133,10 @@ sifproxyarp(int unit, struct in_addr hisaddr)
}
/*
- * cifproxyarp - Delete the proxy ARP entry for the peer.
+ * arp_ClearProxy - Delete the proxy ARP entry for the peer.
*/
int
-cifproxyarp(int unit, struct in_addr hisaddr)
+arp_ClearProxy(struct bundle *bundle, struct in_addr addr, int s)
{
int routes;
@@ -156,16 +145,16 @@ cifproxyarp(int unit, struct in_addr hisaddr)
arpmsg_valid = 0;
arpmsg.hdr.rtm_type = RTM_DELETE;
- arpmsg.hdr.rtm_seq = ++rtm_seq;
+ arpmsg.hdr.rtm_seq = ++bundle->routing_seq;
routes = ID0socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (routes < 0) {
- LogPrintf(LogERROR, "sifproxyarp: opening routing socket: %s\n",
+ log_Printf(LogERROR, "arp_SetProxy: opening routing socket: %s\n",
strerror(errno));
return 0;
}
if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
- LogPrintf(LogERROR, "Delete proxy arp entry: %s\n", strerror(errno));
+ log_Printf(LogERROR, "Delete proxy arp entry: %s\n", strerror(errno));
close(routes);
return 0;
}
@@ -176,10 +165,10 @@ cifproxyarp(int unit, struct in_addr hisaddr)
#else /* RTM_VERSION */
/*
- * sifproxyarp - Make a proxy ARP entry for the peer.
+ * arp_SetProxy - Make a proxy ARP entry for the peer.
*/
int
-sifproxyarp(int unit, struct in_addr hisaddr)
+arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s)
{
struct arpreq arpreq;
struct {
@@ -193,36 +182,36 @@ sifproxyarp(int unit, struct in_addr hisaddr)
* Get the hardware address of an interface on the same subnet as our local
* address.
*/
- if (!get_ether_addr(unit, hisaddr, &dls.sdl)) {
- LogPrintf(LOG_PHASE_BIT, "Cannot determine ethernet address for proxy ARP\n");
+ if (!get_ether_addr(s, addr, &dls.sdl)) {
+ log_Printf(LOG_PHASE_BIT, "Cannot determine ethernet address for proxy ARP\n");
return 0;
}
arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
arpreq.arp_ha.sa_family = AF_UNSPEC;
memcpy(arpreq.arp_ha.sa_data, LLADDR(&dls.sdl), dls.sdl.sdl_alen);
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
- ((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr.s_addr;
+ ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr;
arpreq.arp_flags = ATF_PERM | ATF_PUBL;
- if (ID0ioctl(unit, SIOCSARP, (caddr_t) & arpreq) < 0) {
- LogPrintf(LogERROR, "sifproxyarp: ioctl(SIOCSARP): %s\n", strerror(errno));
+ if (ID0ioctl(s, SIOCSARP, (caddr_t) & arpreq) < 0) {
+ log_Printf(LogERROR, "arp_SetProxy: ioctl(SIOCSARP): %s\n", strerror(errno));
return 0;
}
return 1;
}
/*
- * cifproxyarp - Delete the proxy ARP entry for the peer.
+ * arp_ClearProxy - Delete the proxy ARP entry for the peer.
*/
int
-cifproxyarp(int unit, struct in_addr hisaddr)
+arp_ClearProxy(struct bundle *bundle, struct in_addr addr, int s)
{
struct arpreq arpreq;
memset(&arpreq, '\0', sizeof arpreq);
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
- ((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr.s_addr;
- if (ID0ioctl(unit, SIOCDARP, (caddr_t) & arpreq) < 0) {
- LogPrintf(LogERROR, "cifproxyarp: ioctl(SIOCDARP): %s\n", strerror(errno));
+ ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr;
+ if (ID0ioctl(s, SIOCDARP, (caddr_t) & arpreq) < 0) {
+ log_Printf(LogERROR, "arp_ClearProxy: ioctl(SIOCDARP): %s\n", strerror(errno));
return 0;
}
return 1;
@@ -236,7 +225,7 @@ cifproxyarp(int unit, struct in_addr hisaddr)
* the same subnet as ipaddr.
*/
-static int
+int
get_ether_addr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr)
{
int mib[6], sa_len, skip, b;
@@ -256,7 +245,7 @@ get_ether_addr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr)
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
- LogPrintf(LogERROR, "get_ether_addr: sysctl: estimate: %s\n",
+ log_Printf(LogERROR, "get_ether_addr: sysctl: estimate: %s\n",
strerror(errno));
return 0;
}
@@ -289,9 +278,9 @@ get_ether_addr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr)
(RTA_NETMASK|RTA_IFA))
continue;
/* Found a candidate. Do the addresses match ? */
- if (LogIsKept(LogDEBUG) &&
+ if (log_IsKept(LogDEBUG) &&
ptr == (char *)ifm + ifm->ifm_msglen + ifam->ifam_msglen)
- LogPrintf(LogDEBUG, "%.*s interface is a candidate for proxy\n",
+ log_Printf(LogDEBUG, "%.*s interface is a candidate for proxy\n",
dl->sdl_nlen, dl->sdl_data);
b = 1;
ifa = mask = NULL;
@@ -315,18 +304,18 @@ get_ether_addr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr)
}
b <<= 1;
}
- if (LogIsKept(LogDEBUG)) {
+ if (log_IsKept(LogDEBUG)) {
char a[16];
strncpy(a, inet_ntoa(mask->sin_addr), sizeof a - 1);
a[sizeof a - 1] = '\0';
- LogPrintf(LogDEBUG, "Check addr %s, mask %s\n",
+ log_Printf(LogDEBUG, "Check addr %s, mask %s\n",
inet_ntoa(ifa->sin_addr), a);
}
if (ifa->sin_family == AF_INET &&
(ifa->sin_addr.s_addr & mask->sin_addr.s_addr) ==
(ipaddr.s_addr & mask->sin_addr.s_addr)) {
- LogPrintf(LogPHASE, "Found interface %.*s for proxy arp\n",
- dl->sdl_alen, dl->sdl_data);
+ log_Printf(LogPHASE, "Found interface %.*s for %s\n",
+ dl->sdl_alen, dl->sdl_data, inet_ntoa(ipaddr));
memcpy(hwaddr, dl, dl->sdl_len);
free(buf);
return 1;
@@ -337,19 +326,3 @@ get_ether_addr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr)
return 0;
}
-
-#ifdef DEBUG
-int
-main(int argc, char **argv)
-{
- struct in_addr ipaddr;
- int s, f;
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- for (f = 1; f < argc; f++) {
- if (inet_aton(argv[f], &ipaddr))
- sifproxyarp(s, ipaddr);
- }
- close(s);
-}
-#endif
diff --git a/usr.sbin/ppp/arp.h b/usr.sbin/ppp/arp.h
index 8d419d1c021c..25e4270c3421 100644
--- a/usr.sbin/ppp/arp.h
+++ b/usr.sbin/ppp/arp.h
@@ -17,9 +17,13 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: arp.h,v 1.6 1997/10/26 01:02:04 brian Exp $
+ * $Id: arp.h,v 1.7.2.7 1998/05/01 19:23:50 brian Exp $
*
*/
-extern int cifproxyarp(int, struct in_addr);
-extern int sifproxyarp(int, struct in_addr);
+struct sockaddr_dl;
+struct bundle;
+
+extern int arp_ClearProxy(struct bundle *, struct in_addr, int);
+extern int arp_SetProxy(struct bundle *, struct in_addr, int);
+extern int get_ether_addr(int, struct in_addr, struct sockaddr_dl *);
diff --git a/usr.sbin/ppp/async.c b/usr.sbin/ppp/async.c
index 835de42929d0..0692f2d9c118 100644
--- a/usr.sbin/ppp/async.c
+++ b/usr.sbin/ppp/async.c
@@ -17,78 +17,64 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: async.c,v 1.14 1997/11/22 03:37:23 brian Exp $
+ * $Id: async.c,v 1.15.2.14 1998/05/01 19:23:51 brian Exp $
*
*/
-#include <sys/param.h>
-#include <netinet/in.h>
+#include <sys/types.h>
-#include <stdio.h>
#include <string.h>
#include <termios.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
+#include "lqr.h"
#include "hdlc.h"
#include "lcp.h"
#include "lcpproto.h"
-#include "modem.h"
-#include "loadalias.h"
-#include "vars.h"
#include "async.h"
-
-#define HDLCSIZE (MAX_MRU*2+6)
-
-static struct async_state {
- int mode;
- int length;
- u_char hbuff[HDLCSIZE]; /* recv buffer */
- u_char xbuff[HDLCSIZE]; /* xmit buffer */
- u_long my_accmap;
- u_long his_accmap;
-} AsyncState;
+#include "throughput.h"
+#include "ccp.h"
+#include "link.h"
+#include "descriptor.h"
+#include "physical.h"
#define MODE_HUNT 0x01
#define MODE_ESC 0x02
void
-AsyncInit()
+async_Init(struct async *async)
{
- struct async_state *stp = &AsyncState;
-
- stp->mode = MODE_HUNT;
- stp->length = 0;
- stp->my_accmap = stp->his_accmap = 0xffffffff;
+ async->mode = MODE_HUNT;
+ async->length = 0;
+ async->my_accmap = async->his_accmap = 0xffffffff;
+ memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap);
}
void
-SetLinkParams(struct lcpstate *lcp)
+async_SetLinkParams(struct async *async, struct lcp *lcp)
{
- struct async_state *stp = &AsyncState;
-
- stp->my_accmap = lcp->want_accmap;
- stp->his_accmap = lcp->his_accmap;
+ async->my_accmap = lcp->want_accmap;
+ async->his_accmap = lcp->his_accmap;
}
/*
* Encode into async HDLC byte code if necessary
*/
static void
-HdlcPutByte(u_char **cp, u_char c, int proto)
+HdlcPutByte(struct async *async, u_char **cp, u_char c, int proto)
{
u_char *wp;
wp = *cp;
- if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c))))
+ if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c))))
|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
*wp++ = HDLC_ESC;
c ^= HDLC_XOR;
}
- if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) {
+ if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) {
*wp++ = HDLC_ESC;
c ^= HDLC_XOR;
}
@@ -97,27 +83,26 @@ HdlcPutByte(u_char **cp, u_char c, int proto)
}
void
-AsyncOutput(int pri, struct mbuf *bp, int proto)
+async_Output(int pri, struct mbuf *bp, int proto, struct physical *physical)
{
- struct async_state *hs = &AsyncState;
u_char *cp, *sp, *ep;
struct mbuf *wp;
int cnt;
- if (plength(bp) > HDLCSIZE) {
- pfree(bp);
+ if (mbuf_Length(bp) > HDLCSIZE) {
+ mbuf_Free(bp);
return;
}
- cp = hs->xbuff;
+ cp = physical->async.xbuff;
ep = cp + HDLCSIZE - 10;
wp = bp;
*cp++ = HDLC_SYN;
while (wp) {
sp = MBUF_CTOP(wp);
for (cnt = wp->cnt; cnt > 0; cnt--) {
- HdlcPutByte(&cp, *sp++, proto);
+ HdlcPutByte(&physical->async, &cp, *sp++, proto);
if (cp >= ep) {
- pfree(bp);
+ mbuf_Free(bp);
return;
}
}
@@ -125,72 +110,73 @@ AsyncOutput(int pri, struct mbuf *bp, int proto)
}
*cp++ = HDLC_SYN;
- cnt = cp - hs->xbuff;
- LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt);
- WriteModem(pri, (char *) hs->xbuff, cnt);
- ModemAddOutOctets(cnt);
- pfree(bp);
+ cnt = cp - physical->async.xbuff;
+ log_DumpBuff(LogASYNC, "WriteModem", physical->async.xbuff, cnt);
+ link_Write(&physical->link, pri, (char *)physical->async.xbuff, cnt);
+ link_AddOutOctets(&physical->link, cnt);
+ mbuf_Free(bp);
}
static struct mbuf *
-AsyncDecode(u_char c)
+async_Decode(struct async *async, u_char c)
{
- struct async_state *hs = &AsyncState;
struct mbuf *bp;
- if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
+ if ((async->mode & MODE_HUNT) && c != HDLC_SYN)
return NULL;
switch (c) {
case HDLC_SYN:
- hs->mode &= ~MODE_HUNT;
- if (hs->length) { /* packet is ready. */
- bp = mballoc(hs->length, MB_ASYNC);
- mbwrite(bp, hs->hbuff, hs->length);
- hs->length = 0;
+ async->mode &= ~MODE_HUNT;
+ if (async->length) { /* packet is ready. */
+ bp = mbuf_Alloc(async->length, MB_ASYNC);
+ mbuf_Write(bp, async->hbuff, async->length);
+ async->length = 0;
return bp;
}
break;
case HDLC_ESC:
- if (!(hs->mode & MODE_ESC)) {
- hs->mode |= MODE_ESC;
+ if (!(async->mode & MODE_ESC)) {
+ async->mode |= MODE_ESC;
break;
}
/* Fall into ... */
default:
- if (hs->length >= HDLCSIZE) {
+ if (async->length >= HDLCSIZE) {
/* packet is too large, discard it */
- LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length);
- hs->length = 0;
- hs->mode = MODE_HUNT;
+ log_Printf(LogERROR, "Packet too large (%d), discarding.\n", async->length);
+ async->length = 0;
+ async->mode = MODE_HUNT;
break;
}
- if (hs->mode & MODE_ESC) {
+ if (async->mode & MODE_ESC) {
c ^= HDLC_XOR;
- hs->mode &= ~MODE_ESC;
+ async->mode &= ~MODE_ESC;
}
- hs->hbuff[hs->length++] = c;
+ async->hbuff[async->length++] = c;
break;
}
return NULL;
}
void
-AsyncInput(u_char *buff, int cnt)
+async_Input(struct bundle *bundle, u_char *buff, int cnt,
+ struct physical *physical)
{
struct mbuf *bp;
- ModemAddInOctets(cnt);
- if (DEV_IS_SYNC) {
- bp = mballoc(cnt, MB_ASYNC);
+ link_AddInOctets(&physical->link, cnt);
+
+ if (physical_IsSync(physical)) {
+ bp = mbuf_Alloc(cnt, MB_ASYNC);
memcpy(MBUF_CTOP(bp), buff, cnt);
bp->cnt = cnt;
- HdlcInput(bp);
+ hdlc_Input(bundle, bp, physical);
} else {
while (cnt > 0) {
- bp = AsyncDecode(*buff++);
+ bp = async_Decode(&physical->async, *buff++);
if (bp)
- HdlcInput(bp);
+ hdlc_Input(bundle, bp, physical);
cnt--;
}
}
diff --git a/usr.sbin/ppp/async.h b/usr.sbin/ppp/async.h
index 13fa6b9b9060..492580713fb2 100644
--- a/usr.sbin/ppp/async.h
+++ b/usr.sbin/ppp/async.h
@@ -23,10 +23,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: async.h,v 1.2.4.7 1998/04/07 00:53:17 brian Exp $
*/
-extern void AsyncInit(void);
-extern void SetLinkParams(struct lcpstate *);
-extern void AsyncOutput(int, struct mbuf *, int);
-extern void AsyncInput(u_char *, int);
+#define HDLCSIZE (MAX_MRU*2+6)
+
+struct async {
+ int mode;
+ int length;
+ u_char hbuff[HDLCSIZE]; /* recv buffer */
+ u_char xbuff[HDLCSIZE]; /* xmit buffer */
+ u_long my_accmap;
+ u_long his_accmap;
+
+ struct {
+ u_char EscMap[33];
+ } cfg;
+};
+
+struct lcp;
+struct mbuf;
+struct physical;
+struct bundle;
+
+extern void async_Init(struct async *);
+extern void async_SetLinkParams(struct async *, struct lcp *);
+extern void async_Output(int, struct mbuf *, int, struct physical *);
+extern void async_Input(struct bundle *, u_char *, int, struct physical *);
diff --git a/usr.sbin/ppp/auth.c b/usr.sbin/ppp/auth.c
index 1347615c7cb8..ecc26f3e53d3 100644
--- a/usr.sbin/ppp/auth.c
+++ b/usr.sbin/ppp/auth.c
@@ -17,136 +17,176 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: auth.c,v 1.27 1998/01/21 02:15:09 brian Exp $
+ * $Id: auth.c,v 1.27.2.26 1998/05/01 19:23:52 brian Exp $
*
* TODO:
* o Implement check against with registered IP addresses.
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
+#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include "command.h"
#include "mbuf.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
+#include "iplist.h"
+#include "throughput.h"
+#include "slcompress.h"
#include "ipcp.h"
-#include "loadalias.h"
-#include "vars.h"
#include "auth.h"
-#include "chat.h"
#include "systems.h"
+#include "lcp.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "ccp.h"
+#include "link.h"
+#include "descriptor.h"
+#include "chat.h"
+#include "lcpproto.h"
+#include "filter.h"
+#include "mp.h"
+#include "bundle.h"
-void
-LocalAuthInit()
+const char *
+Auth2Nam(u_short auth)
{
- if (!(mode&MODE_DAEMON))
- /* We're allowed in interactive mode */
- VarLocalAuth = LOCAL_AUTH;
- else if (VarHaveLocalAuthKey)
- VarLocalAuth = *VarLocalAuthKey == '\0' ? LOCAL_AUTH : LOCAL_NO_AUTH;
- else
- switch (LocalAuthValidate(SECRETFILE, VarShortHost, "")) {
- case NOT_FOUND:
- VarLocalAuth = LOCAL_DENY;
- break;
- case VALID:
- VarLocalAuth = LOCAL_AUTH;
- break;
- case INVALID:
- VarLocalAuth = LOCAL_NO_AUTH;
- break;
- }
+ switch (auth) {
+ case PROTO_PAP:
+ return "PAP";
+ case PROTO_CHAP:
+ return "CHAP";
+ case 0:
+ return "none";
+ }
+ return "unknown";
}
-LOCAL_AUTH_VALID
-LocalAuthValidate(const char *fname, const char *system, const char *key)
+static int
+auth_CheckPasswd(const char *name, const char *data, const char *key)
+{
+ if (!strcmp(data, "*")) {
+ /* Then look up the real password database */
+ struct passwd *pw;
+ int result;
+
+ result = (pw = getpwnam(name)) &&
+ !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd);
+ endpwent();
+ return result;
+ }
+
+ return !strcmp(data, key);
+}
+
+int
+auth_Select(struct bundle *bundle, const char *name, struct physical *physical)
{
FILE *fp;
int n;
- char *vector[3];
+ char *vector[5];
char buff[LINE_LEN];
- LOCAL_AUTH_VALID rc;
- rc = NOT_FOUND; /* No system entry */
- fp = OpenSecret(fname);
- if (fp == NULL)
- return (rc);
- while (fgets(buff, sizeof buff, fp)) {
- if (buff[0] == '#')
- continue;
- buff[strlen(buff) - 1] = 0;
- memset(vector, '\0', sizeof vector);
- n = MakeArgs(buff, vector, VECSIZE(vector));
- if (n < 1)
- continue;
- if (strcmp(vector[0], system) == 0) {
- if ((vector[1] == (char *) NULL && (key == NULL || *key == '\0')) ||
- (vector[1] != (char *) NULL && strcmp(vector[1], key) == 0)) {
- rc = VALID; /* Valid */
- } else {
- rc = INVALID; /* Invalid */
- }
- break;
+ if (*name == '\0') {
+ ipcp_Setup(&bundle->ncp.ipcp);
+ return 1;
+ }
+
+ fp = OpenSecret(SECRETFILE);
+ if (fp != NULL) {
+ while (fgets(buff, sizeof buff, fp)) {
+ if (buff[0] == '#')
+ continue;
+ buff[strlen(buff) - 1] = 0;
+ memset(vector, '\0', sizeof vector);
+ n = MakeArgs(buff, vector, VECSIZE(vector));
+ if (n < 2)
+ continue;
+ if (strcmp(vector[0], name) == 0)
+ CloseSecret(fp);
+/*
+ memset(&bundle->ncp.ipcp.cfg.peer_range, '\0',
+ sizeof bundle->ncp.ipcp.cfg.peer_range);
+*/
+ if (n > 2 && !ipcp_UseHisaddr(bundle, vector[2], 1))
+ return 0;
+ ipcp_Setup(&bundle->ncp.ipcp);
+ if (n > 3)
+ bundle_SetLabel(bundle, vector[3]);
+ return 1; /* Valid */
}
+ CloseSecret(fp);
}
- CloseSecret(fp);
- return (rc);
+
+#ifndef NOPASSWDAUTH
+ /* Let 'em in anyway - they must have been in the passwd file */
+ ipcp_Setup(&bundle->ncp.ipcp);
+ return 1;
+#else
+ /* Disappeared from ppp.secret ? */
+ return 0;
+#endif
}
int
-AuthValidate(const char *fname, const char *system, const char *key)
+auth_Validate(struct bundle *bundle, const char *system,
+ const char *key, struct physical *physical)
{
+ /* Used by PAP routines */
+
FILE *fp;
int n;
char *vector[5];
char buff[LINE_LEN];
- char passwd[100];
- fp = OpenSecret(fname);
- if (fp == NULL)
- return (0);
- while (fgets(buff, sizeof buff, fp)) {
- if (buff[0] == '#')
- continue;
- buff[strlen(buff) - 1] = 0;
- memset(vector, '\0', sizeof vector);
- n = MakeArgs(buff, vector, VECSIZE(vector));
- if (n < 2)
- continue;
- if (strcmp(vector[0], system) == 0) {
- ExpandString(vector[1], passwd, sizeof passwd, 0);
- if (strcmp(passwd, key) == 0) {
+ fp = OpenSecret(SECRETFILE);
+ if (fp != NULL) {
+ while (fgets(buff, sizeof buff, fp)) {
+ if (buff[0] == '#')
+ continue;
+ buff[strlen(buff) - 1] = 0;
+ memset(vector, '\0', sizeof vector);
+ n = MakeArgs(buff, vector, VECSIZE(vector));
+ if (n < 2)
+ continue;
+ if (strcmp(vector[0], system) == 0) {
CloseSecret(fp);
- if (n > 2 && !UseHisaddr(vector[2], 1))
- return (0);
- IpcpInit();
- if (n > 3)
- SetLabel(vector[3]);
- return (1); /* Valid */
+ return auth_CheckPasswd(vector[0], vector[1], key);
}
}
+ CloseSecret(fp);
}
- CloseSecret(fp);
- return (0); /* Invalid */
+
+#ifndef NOPASSWDAUTH
+ if (Enabled(bundle, OPT_PASSWDAUTH))
+ return auth_CheckPasswd(system, "*", key);
+#endif
+
+ return 0; /* Invalid */
}
char *
-AuthGetSecret(const char *fname, const char *system, int len, int setaddr)
+auth_GetSecret(struct bundle *bundle, const char *system, int len,
+ struct physical *physical)
{
+ /* Used by CHAP routines */
+
FILE *fp;
int n;
char *vector[5];
- char buff[LINE_LEN];
- static char passwd[100];
+ static char buff[LINE_LEN];
- fp = OpenSecret(fname);
+ fp = OpenSecret(SECRETFILE);
if (fp == NULL)
return (NULL);
+
while (fgets(buff, sizeof buff, fp)) {
if (buff[0] == '#')
continue;
@@ -156,19 +196,8 @@ AuthGetSecret(const char *fname, const char *system, int len, int setaddr)
if (n < 2)
continue;
if (strlen(vector[0]) == len && strncmp(vector[0], system, len) == 0) {
- ExpandString(vector[1], passwd, sizeof passwd, 0);
- if (setaddr) {
- memset(&DefHisAddress, '\0', sizeof DefHisAddress);
- }
- if (n > 2 && setaddr) {
- if (UseHisaddr(vector[2], 1))
- IpcpInit();
- else
- return NULL;
- }
- if (n > 3)
- SetLabel(vector[3]);
- return (passwd);
+ CloseSecret(fp);
+ return vector[1];
}
}
CloseSecret(fp);
@@ -178,36 +207,42 @@ AuthGetSecret(const char *fname, const char *system, int len, int setaddr)
static void
AuthTimeout(void *vauthp)
{
- struct pppTimer *tp;
struct authinfo *authp = (struct authinfo *)vauthp;
- tp = &authp->authtimer;
- StopTimer(tp);
+ timer_Stop(&authp->authtimer);
if (--authp->retry > 0) {
- StartTimer(tp);
- (authp->ChallengeFunc) (++authp->id);
+ timer_Start(&authp->authtimer);
+ (*authp->ChallengeFunc)(authp, ++authp->id, authp->physical);
}
}
void
-StartAuthChallenge(struct authinfo *authp)
+auth_Init(struct authinfo *authinfo)
+{
+ memset(authinfo, '\0', sizeof(struct authinfo));
+ authinfo->cfg.fsmretry = DEF_FSMRETRY;
+}
+
+void
+auth_StartChallenge(struct authinfo *authp, struct physical *physical,
+ void (*fn)(struct authinfo *, int, struct physical *))
{
- struct pppTimer *tp;
-
- tp = &authp->authtimer;
- StopTimer(tp);
- tp->func = AuthTimeout;
- tp->load = VarRetryTimeout * SECTICKS;
- tp->state = TIMER_STOPPED;
- tp->arg = (void *) authp;
- StartTimer(tp);
+ authp->ChallengeFunc = fn;
+ authp->physical = physical;
+ timer_Stop(&authp->authtimer);
+ authp->authtimer.func = AuthTimeout;
+ authp->authtimer.name = "auth";
+ authp->authtimer.load = authp->cfg.fsmretry * SECTICKS;
+ authp->authtimer.arg = (void *) authp;
authp->retry = 3;
authp->id = 1;
- (authp->ChallengeFunc) (authp->id);
+ (*authp->ChallengeFunc)(authp, authp->id, physical);
+ timer_Start(&authp->authtimer);
}
void
-StopAuthTimer(struct authinfo *authp)
+auth_StopTimer(struct authinfo *authp)
{
- StopTimer(&authp->authtimer);
+ timer_Stop(&authp->authtimer);
+ authp->physical = NULL;
}
diff --git a/usr.sbin/ppp/auth.h b/usr.sbin/ppp/auth.h
index a0fa77968608..8e751becccdb 100644
--- a/usr.sbin/ppp/auth.h
+++ b/usr.sbin/ppp/auth.h
@@ -15,27 +15,34 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: auth.h,v 1.9 1997/10/26 01:02:09 brian Exp $
+ * $Id: auth.h,v 1.10.2.9 1998/05/01 19:23:54 brian Exp $
*
* TODO:
*/
-typedef enum {
- VALID,
- INVALID,
- NOT_FOUND
-} LOCAL_AUTH_VALID;
+struct physical;
+struct bundle;
struct authinfo {
- void (*ChallengeFunc) (int);
+ void (*ChallengeFunc)(struct authinfo *, int, struct physical *);
struct pppTimer authtimer;
int retry;
int id;
+ struct physical *physical;
+ struct {
+ u_int fsmretry;
+ } cfg;
};
-extern LOCAL_AUTH_VALID LocalAuthValidate(const char *, const char *, const char *);
-extern void StopAuthTimer(struct authinfo *);
-extern void StartAuthChallenge(struct authinfo *);
-extern void LocalAuthInit(void);
-extern int AuthValidate(const char *, const char *, const char *);
-extern char *AuthGetSecret(const char *, const char *, int, int);
+extern const char *Auth2Nam(u_short);
+
+extern void auth_Init(struct authinfo *);
+extern void auth_StopTimer(struct authinfo *);
+extern void auth_StartChallenge(struct authinfo *, struct physical *,
+ void (*fn)(struct authinfo *, int,
+ struct physical *));
+extern int auth_Validate(struct bundle *, const char *, const char *,
+ struct physical *);
+extern char *auth_GetSecret(struct bundle *, const char *, int,
+ struct physical *);
+extern int auth_Select(struct bundle *, const char *, struct physical *);
diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c
new file mode 100644
index 000000000000..60ba2f3d7923
--- /dev/null
+++ b/usr.sbin/ppp/bundle.c
@@ -0,0 +1,1615 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: bundle.c,v 1.1.2.89 1998/05/21 01:13:19 brian Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <net/if_tun.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "command.h"
+#include "mbuf.h"
+#include "log.h"
+#include "id.h"
+#include "defs.h"
+#include "timer.h"
+#include "fsm.h"
+#include "iplist.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "throughput.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "route.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
+#include "async.h"
+#include "physical.h"
+#include "modem.h"
+#include "loadalias.h"
+#include "auth.h"
+#include "lcpproto.h"
+#include "chap.h"
+#include "tun.h"
+#include "prompt.h"
+#include "chat.h"
+#include "datalink.h"
+#include "ip.h"
+
+#define SCATTER_SEGMENTS 4 /* version, datalink, name, physical */
+#define SOCKET_OVERHEAD 100 /* additional buffer space for large */
+ /* {recv,send}msg() calls */
+
+static int bundle_RemainingIdleTime(struct bundle *);
+static int bundle_RemainingAutoLoadTime(struct bundle *);
+
+static const char *PhaseNames[] = {
+ "Dead", "Establish", "Authenticate", "Network", "Terminate"
+};
+
+const char *
+bundle_PhaseName(struct bundle *bundle)
+{
+ return bundle->phase <= PHASE_TERMINATE ?
+ PhaseNames[bundle->phase] : "unknown";
+}
+
+void
+bundle_NewPhase(struct bundle *bundle, u_int new)
+{
+ if (new == bundle->phase)
+ return;
+
+ if (new <= PHASE_TERMINATE)
+ log_Printf(LogPHASE, "bundle: %s\n", PhaseNames[new]);
+
+ switch (new) {
+ case PHASE_DEAD:
+ bundle->phase = new;
+ break;
+
+ case PHASE_ESTABLISH:
+ bundle->phase = new;
+ break;
+
+ case PHASE_AUTHENTICATE:
+ bundle->phase = new;
+ bundle_DisplayPrompt(bundle);
+ break;
+
+ case PHASE_NETWORK:
+ ipcp_Setup(&bundle->ncp.ipcp);
+ fsm_Up(&bundle->ncp.ipcp.fsm);
+ fsm_Open(&bundle->ncp.ipcp.fsm);
+ bundle->phase = new;
+ bundle_DisplayPrompt(bundle);
+ break;
+
+ case PHASE_TERMINATE:
+ bundle->phase = new;
+ mp_Down(&bundle->ncp.mp);
+ bundle_DisplayPrompt(bundle);
+ break;
+ }
+}
+
+static int
+bundle_CleanInterface(const struct bundle *bundle)
+{
+ int s;
+ struct ifreq ifrq;
+ struct ifaliasreq ifra;
+
+ s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "bundle_CleanInterface: socket(): %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ strncpy(ifrq.ifr_name, bundle->ifp.Name, sizeof ifrq.ifr_name - 1);
+ ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
+ while (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0) {
+ memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
+ strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1);
+ ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
+ ifra.ifra_addr = ifrq.ifr_addr;
+ if (ID0ioctl(s, SIOCGIFDSTADDR, &ifrq) < 0) {
+ if (ifra.ifra_addr.sa_family == AF_INET)
+ log_Printf(LogERROR,
+ "bundle_CleanInterface: Can't get dst for %s on %s !\n",
+ inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
+ bundle->ifp.Name);
+ close(s);
+ return 0;
+ }
+ ifra.ifra_broadaddr = ifrq.ifr_dstaddr;
+ if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
+ if (ifra.ifra_addr.sa_family == AF_INET)
+ log_Printf(LogERROR,
+ "bundle_CleanInterface: Can't delete %s address on %s !\n",
+ inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
+ bundle->ifp.Name);
+ close(s);
+ return 0;
+ }
+ }
+ close(s);
+
+ return 1;
+}
+
+static void
+bundle_LayerStart(void *v, struct fsm *fp)
+{
+ /* The given FSM is about to start up ! */
+}
+
+
+static void
+bundle_Notify(struct bundle *bundle, char c)
+{
+ if (bundle->notify.fd != -1) {
+ if (write(bundle->notify.fd, &c, 1) == 1)
+ log_Printf(LogPHASE, "Parent notified of success.\n");
+ else
+ log_Printf(LogPHASE, "Failed to notify parent of success.\n");
+ close(bundle->notify.fd);
+ bundle->notify.fd = -1;
+ }
+}
+
+static void
+bundle_AutoLoadTimeout(void *v)
+{
+ struct bundle *bundle = (struct bundle *)v;
+
+ if (bundle->autoload.comingup) {
+ log_Printf(LogPHASE, "autoload: Another link is required\n");
+ /* bundle_Open() stops the timer */
+ bundle_Open(bundle, NULL, PHYS_DEMAND);
+ } else {
+ struct datalink *dl, *last;
+
+ timer_Stop(&bundle->autoload.timer);
+ for (last = NULL, dl = bundle->links; dl; dl = dl->next)
+ if (dl->physical->type == PHYS_DEMAND && dl->state == DATALINK_OPEN)
+ last = dl;
+
+ if (last)
+ datalink_Close(last, 1);
+ }
+}
+
+static void
+bundle_StartAutoLoadTimer(struct bundle *bundle, int up)
+{
+ struct datalink *dl;
+
+ timer_Stop(&bundle->autoload.timer);
+
+ if (bundle->CleaningUp || bundle->phase != PHASE_NETWORK) {
+ dl = NULL;
+ bundle->autoload.running = 0;
+ } else if (up) {
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (dl->state == DATALINK_CLOSED && dl->physical->type == PHYS_DEMAND) {
+ if (bundle->cfg.autoload.max.timeout) {
+ bundle->autoload.timer.func = bundle_AutoLoadTimeout;
+ bundle->autoload.timer.name = "autoload up";
+ bundle->autoload.timer.load =
+ bundle->cfg.autoload.max.timeout * SECTICKS;
+ bundle->autoload.timer.arg = bundle;
+ timer_Start(&bundle->autoload.timer);
+ bundle->autoload.done = time(NULL) + bundle->cfg.autoload.max.timeout;
+ } else
+ bundle_AutoLoadTimeout(bundle);
+ break;
+ }
+ bundle->autoload.running = (dl || bundle->cfg.autoload.min.timeout) ? 1 : 0;
+ } else {
+ int nlinks;
+ struct datalink *adl;
+
+ for (nlinks = 0, adl = NULL, dl = bundle->links; dl; dl = dl->next)
+ if (dl->state == DATALINK_OPEN) {
+ if (dl->physical->type == PHYS_DEMAND)
+ adl = dl;
+ if (++nlinks > 1 && adl) {
+ if (bundle->cfg.autoload.min.timeout) {
+ bundle->autoload.timer.func = bundle_AutoLoadTimeout;
+ bundle->autoload.timer.name = "autoload down";
+ bundle->autoload.timer.load =
+ bundle->cfg.autoload.min.timeout * SECTICKS;
+ bundle->autoload.timer.arg = bundle;
+ timer_Start(&bundle->autoload.timer);
+ bundle->autoload.done =
+ time(NULL) + bundle->cfg.autoload.min.timeout;
+ }
+ break;
+ }
+ }
+
+ bundle->autoload.running = 1;
+ }
+
+ bundle->autoload.comingup = up ? 1 : 0;
+}
+
+static void
+bundle_StopAutoLoadTimer(struct bundle *bundle)
+{
+ timer_Stop(&bundle->autoload.timer);
+ bundle->autoload.done = 0;
+}
+
+static int
+bundle_RemainingAutoLoadTime(struct bundle *bundle)
+{
+ if (bundle->autoload.done)
+ return bundle->autoload.done - time(NULL);
+ return -1;
+}
+
+
+static void
+bundle_LayerUp(void *v, struct fsm *fp)
+{
+ /*
+ * The given fsm is now up
+ * If it's an LCP set our mtu (if we're multilink, add up the link
+ * speeds and set the MRRU) and start our autoload timer.
+ * If it's an NCP, tell our -background parent to go away.
+ * If it's the first NCP, start the idle timer.
+ */
+ struct bundle *bundle = (struct bundle *)v;
+
+ if (fp->proto == PROTO_LCP) {
+ if (bundle->ncp.mp.active) {
+ struct datalink *dl;
+
+ bundle->ifp.Speed = 0;
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (dl->state == DATALINK_OPEN)
+ bundle->ifp.Speed += modem_Speed(dl->physical);
+ tun_configure(bundle, bundle->ncp.mp.peer_mrru);
+ bundle->autoload.running = 1;
+ } else {
+ bundle->ifp.Speed = modem_Speed(link2physical(fp->link));
+ tun_configure(bundle, fsm2lcp(fp)->his_mru);
+ }
+ } else if (fp->proto == PROTO_IPCP) {
+ bundle_StartIdleTimer(bundle);
+ bundle_Notify(bundle, EX_NORMAL);
+ }
+}
+
+static void
+bundle_LayerDown(void *v, struct fsm *fp)
+{
+ /*
+ * The given FSM has been told to come down.
+ * If it's our last NCP, stop the idle timer.
+ * If it's an LCP and we're in multilink mode, adjust our tun speed.
+ */
+
+ struct bundle *bundle = (struct bundle *)v;
+
+ if (fp->proto == PROTO_IPCP)
+ bundle_StopIdleTimer(bundle);
+ else if (fp->proto == PROTO_LCP && bundle->ncp.mp.active) {
+ struct datalink *dl;
+
+ bundle->ifp.Speed = 0;
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (fp != &dl->physical->link.lcp.fsm && dl->state == DATALINK_OPEN)
+ bundle->ifp.Speed += modem_Speed(dl->physical);
+ if (bundle->ifp.Speed)
+ /* Don't configure down to a speed of 0 */
+ tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru);
+ }
+}
+
+static void
+bundle_LayerFinish(void *v, struct fsm *fp)
+{
+ /* The given fsm is now down (fp cannot be NULL)
+ *
+ * If it's the last LCP, fsm_Down all NCPs
+ * If it's the last NCP, fsm_Close all LCPs
+ */
+
+ struct bundle *bundle = (struct bundle *)v;
+ struct datalink *dl;
+
+ if (fp->proto == PROTO_IPCP) {
+ if (bundle_Phase(bundle) != PHASE_DEAD)
+ bundle_NewPhase(bundle, PHASE_TERMINATE);
+ for (dl = bundle->links; dl; dl = dl->next)
+ datalink_Close(dl, 0);
+ fsm_Down(fp);
+ fsm_Close(fp);
+ } else if (fp->proto == PROTO_LCP) {
+ int others_active;
+
+ others_active = 0;
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (fp != &dl->physical->link.lcp.fsm &&
+ dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP)
+ others_active++;
+
+ if (!others_active) {
+ fsm_Down(&bundle->ncp.ipcp.fsm);
+ fsm_Close(&bundle->ncp.ipcp.fsm); /* ST_INITIAL please */
+ }
+ }
+}
+
+int
+bundle_LinkIsUp(const struct bundle *bundle)
+{
+ return bundle->ncp.ipcp.fsm.state == ST_OPENED;
+}
+
+void
+bundle_Close(struct bundle *bundle, const char *name, int staydown)
+{
+ /*
+ * Please close the given datalink.
+ * If name == NULL or name is the last datalink, fsm_Close all NCPs
+ * (except our MP)
+ * If it isn't the last datalink, just Close that datalink.
+ */
+
+ struct datalink *dl, *this_dl;
+ int others_active;
+
+ if (bundle->phase == PHASE_TERMINATE || bundle->phase == PHASE_DEAD)
+ return;
+
+ others_active = 0;
+ this_dl = NULL;
+
+ for (dl = bundle->links; dl; dl = dl->next) {
+ if (name && !strcasecmp(name, dl->name))
+ this_dl = dl;
+ if (name == NULL || this_dl == dl) {
+ if (staydown)
+ datalink_StayDown(dl);
+ } else if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP)
+ others_active++;
+ }
+
+ if (name && this_dl == NULL) {
+ log_Printf(LogWARN, "%s: Invalid datalink name\n", name);
+ return;
+ }
+
+ if (!others_active) {
+ bundle_StopIdleTimer(bundle);
+ bundle_StopAutoLoadTimer(bundle);
+ if (bundle->ncp.ipcp.fsm.state > ST_CLOSED ||
+ bundle->ncp.ipcp.fsm.state == ST_STARTING)
+ fsm_Close(&bundle->ncp.ipcp.fsm);
+ else {
+ if (bundle->ncp.ipcp.fsm.state > ST_INITIAL) {
+ fsm_Close(&bundle->ncp.ipcp.fsm);
+ fsm_Down(&bundle->ncp.ipcp.fsm);
+ }
+ for (dl = bundle->links; dl; dl = dl->next)
+ datalink_Close(dl, staydown);
+ }
+ } else if (this_dl && this_dl->state != DATALINK_CLOSED &&
+ this_dl->state != DATALINK_HANGUP)
+ datalink_Close(this_dl, staydown);
+}
+
+void
+bundle_Down(struct bundle *bundle)
+{
+ struct datalink *dl;
+
+ for (dl = bundle->links; dl; dl = dl->next)
+ datalink_Down(dl, 1);
+}
+
+static int
+bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
+{
+ struct bundle *bundle = descriptor2bundle(d);
+ struct datalink *dl;
+ struct descriptor *desc;
+ int result, want, queued, nlinks;
+
+ result = 0;
+ for (dl = bundle->links; dl; dl = dl->next)
+ result += descriptor_UpdateSet(&dl->desc, r, w, e, n);
+
+ for (desc = bundle->desc.next; desc; desc = desc->next)
+ result += descriptor_UpdateSet(desc, r, w, e, n);
+
+ /* If there are aren't many packets queued, look for some more. */
+ for (nlinks = 0, dl = bundle->links; dl; dl = dl->next)
+ nlinks++;
+
+ if (nlinks) {
+ queued = r ? bundle_FillQueues(bundle) : ip_QueueLen();
+ if (bundle->autoload.running) {
+ if (queued < bundle->cfg.autoload.max.packets) {
+ if (queued > bundle->cfg.autoload.min.packets)
+ bundle_StopAutoLoadTimer(bundle);
+ else if (bundle->autoload.timer.state != TIMER_RUNNING ||
+ bundle->autoload.comingup)
+ bundle_StartAutoLoadTimer(bundle, 0);
+ } else if (bundle->autoload.timer.state != TIMER_RUNNING ||
+ !bundle->autoload.comingup)
+ bundle_StartAutoLoadTimer(bundle, 1);
+ }
+
+ if (r) {
+ /* enough surplus so that we can tell if we're getting swamped */
+ want = bundle->cfg.autoload.max.packets + nlinks * 2;
+ /* but at least 20 packets ! */
+ if (want < 20)
+ want = 20;
+ if (queued < want) {
+ /* Not enough - select() for more */
+ FD_SET(bundle->dev.fd, r);
+ if (*n < bundle->dev.fd + 1)
+ *n = bundle->dev.fd + 1;
+ log_Printf(LogTIMER, "tun: fdset(r) %d\n", bundle->dev.fd);
+ result++;
+ }
+ }
+ }
+
+ /*
+ * This *MUST* be called after the datalink UpdateSet()s as it
+ * might be ``holding'' one of the datalinks (death-row) and
+ * wants to be able to de-select() it from the descriptor set.
+ */
+ descriptor_UpdateSet(&bundle->ncp.mp.server.desc, r, w, e, n);
+
+ return result;
+}
+
+static int
+bundle_IsSet(struct descriptor *d, const fd_set *fdset)
+{
+ struct bundle *bundle = descriptor2bundle(d);
+ struct datalink *dl;
+ struct descriptor *desc;
+
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (descriptor_IsSet(&dl->desc, fdset))
+ return 1;
+
+ for (desc = bundle->desc.next; desc; desc = desc->next)
+ if (descriptor_IsSet(desc, fdset))
+ return 1;
+
+ if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
+ return 1;
+
+ return FD_ISSET(bundle->dev.fd, fdset);
+}
+
+static void
+bundle_DescriptorRead(struct descriptor *d, struct bundle *bundle,
+ const fd_set *fdset)
+{
+ struct datalink *dl;
+ struct descriptor *desc;
+
+ if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
+ descriptor_Read(&bundle->ncp.mp.server.desc, bundle, fdset);
+
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (descriptor_IsSet(&dl->desc, fdset))
+ descriptor_Read(&dl->desc, bundle, fdset);
+
+ for (desc = bundle->desc.next; desc; desc = desc->next)
+ if (descriptor_IsSet(desc, fdset))
+ descriptor_Read(desc, bundle, fdset);
+
+ if (FD_ISSET(bundle->dev.fd, fdset)) {
+ struct tun_data tun;
+ int n, pri;
+
+ /* something to read from tun */
+ n = read(bundle->dev.fd, &tun, sizeof tun);
+ if (n < 0) {
+ log_Printf(LogERROR, "read from tun: %s\n", strerror(errno));
+ return;
+ }
+ n -= sizeof tun - sizeof tun.data;
+ if (n <= 0) {
+ log_Printf(LogERROR, "read from tun: Only %d bytes read\n", n);
+ return;
+ }
+ if (!tun_check_header(tun, AF_INET))
+ return;
+
+ if (((struct ip *)tun.data)->ip_dst.s_addr ==
+ bundle->ncp.ipcp.my_ip.s_addr) {
+ /* we've been asked to send something addressed *to* us :( */
+ if (Enabled(bundle, OPT_LOOPBACK)) {
+ pri = PacketCheck(bundle, tun.data, n, &bundle->filter.in);
+ if (pri >= 0) {
+ struct mbuf *bp;
+
+#ifndef NOALIAS
+ if (alias_IsEnabled()) {
+ (*PacketAlias.In)(tun.data, sizeof tun.data);
+ n = ntohs(((struct ip *)tun.data)->ip_len);
+ }
+#endif
+ bp = mbuf_Alloc(n, MB_IPIN);
+ memcpy(MBUF_CTOP(bp), tun.data, n);
+ ip_Input(bundle, bp);
+ log_Printf(LogDEBUG, "Looped back packet addressed to myself\n");
+ }
+ return;
+ } else
+ log_Printf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
+ }
+
+ /*
+ * Process on-demand dialup. Output packets are queued within tunnel
+ * device until IPCP is opened.
+ */
+
+ if (bundle_Phase(bundle) == PHASE_DEAD) {
+ /*
+ * Note, we must be in AUTO mode :-/ otherwise our interface should
+ * *not* be UP and we can't receive data
+ */
+ if ((pri = PacketCheck(bundle, tun.data, n, &bundle->filter.dial)) >= 0)
+ bundle_Open(bundle, NULL, PHYS_DEMAND);
+ else
+ /*
+ * Drop the packet. If we were to queue it, we'd just end up with
+ * a pile of timed-out data in our output queue by the time we get
+ * around to actually dialing. We'd also prematurely reach the
+ * threshold at which we stop select()ing to read() the tun
+ * device - breaking auto-dial.
+ */
+ return;
+ }
+
+ pri = PacketCheck(bundle, tun.data, n, &bundle->filter.out);
+ if (pri >= 0) {
+#ifndef NOALIAS
+ if (alias_IsEnabled()) {
+ (*PacketAlias.Out)(tun.data, sizeof tun.data);
+ n = ntohs(((struct ip *)tun.data)->ip_len);
+ }
+#endif
+ ip_Enqueue(pri, tun.data, n);
+ }
+ }
+}
+
+static void
+bundle_DescriptorWrite(struct descriptor *d, struct bundle *bundle,
+ const fd_set *fdset)
+{
+ struct datalink *dl;
+ struct descriptor *desc;
+
+ /* This is not actually necessary as struct mpserver doesn't Write() */
+ if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
+ descriptor_Write(&bundle->ncp.mp.server.desc, bundle, fdset);
+
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (descriptor_IsSet(&dl->desc, fdset))
+ descriptor_Write(&dl->desc, bundle, fdset);
+
+ for (desc = bundle->desc.next; desc; desc = desc->next)
+ if (descriptor_IsSet(desc, fdset))
+ descriptor_Write(desc, bundle, fdset);
+}
+
+
+struct bundle *
+bundle_Create(const char *prefix, struct prompt *prompt, int type)
+{
+ int s, enoentcount, err;
+ struct ifreq ifrq;
+ static struct bundle bundle; /* there can be only one */
+
+ if (bundle.ifp.Name != NULL) { /* Already allocated ! */
+ log_Printf(LogERROR, "bundle_Create: There's only one BUNDLE !\n");
+ return NULL;
+ }
+
+ err = ENOENT;
+ enoentcount = 0;
+ for (bundle.unit = 0; ; bundle.unit++) {
+ snprintf(bundle.dev.Name, sizeof bundle.dev.Name, "%s%d",
+ prefix, bundle.unit);
+ bundle.dev.fd = ID0open(bundle.dev.Name, O_RDWR);
+ if (bundle.dev.fd >= 0)
+ break;
+ else if (errno == ENXIO) {
+ err = errno;
+ break;
+ } else if (errno == ENOENT) {
+ if (++enoentcount > 2)
+ break;
+ } else
+ err = errno;
+ }
+
+ if (bundle.dev.fd < 0) {
+ log_Printf(LogWARN, "No available tunnel devices found (%s).\n",
+ strerror(err));
+ return NULL;
+ }
+
+ log_SetTun(bundle.unit);
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "bundle_Create: socket(): %s\n", strerror(errno));
+ close(bundle.dev.fd);
+ return NULL;
+ }
+
+ bundle.ifp.Name = strrchr(bundle.dev.Name, '/');
+ if (bundle.ifp.Name == NULL)
+ bundle.ifp.Name = bundle.dev.Name;
+ else
+ bundle.ifp.Name++;
+
+ /*
+ * Now, bring up the interface.
+ */
+ memset(&ifrq, '\0', sizeof ifrq);
+ strncpy(ifrq.ifr_name, bundle.ifp.Name, sizeof ifrq.ifr_name - 1);
+ ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
+ if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
+ log_Printf(LogERROR, "OpenTunnel: ioctl(SIOCGIFFLAGS): %s\n",
+ strerror(errno));
+ close(s);
+ close(bundle.dev.fd);
+ bundle.ifp.Name = NULL;
+ return NULL;
+ }
+ ifrq.ifr_flags |= IFF_UP;
+ if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
+ log_Printf(LogERROR, "OpenTunnel: ioctl(SIOCSIFFLAGS): %s\n",
+ strerror(errno));
+ close(s);
+ close(bundle.dev.fd);
+ bundle.ifp.Name = NULL;
+ return NULL;
+ }
+
+ close(s);
+
+ if ((bundle.ifp.Index = GetIfIndex(bundle.ifp.Name)) < 0) {
+ log_Printf(LogERROR, "OpenTunnel: Can't find interface index.\n");
+ close(bundle.dev.fd);
+ bundle.ifp.Name = NULL;
+ return NULL;
+ }
+ prompt_Printf(prompt, "Using interface: %s\n", bundle.ifp.Name);
+ log_Printf(LogPHASE, "Using interface: %s\n", bundle.ifp.Name);
+
+ bundle.ifp.Speed = 0;
+
+ bundle.routing_seq = 0;
+ bundle.phase = PHASE_DEAD;
+ bundle.CleaningUp = 0;
+
+ bundle.fsm.LayerStart = bundle_LayerStart;
+ bundle.fsm.LayerUp = bundle_LayerUp;
+ bundle.fsm.LayerDown = bundle_LayerDown;
+ bundle.fsm.LayerFinish = bundle_LayerFinish;
+ bundle.fsm.object = &bundle;
+
+ bundle.cfg.idle_timeout = NCP_IDLE_TIMEOUT;
+ *bundle.cfg.auth.name = '\0';
+ *bundle.cfg.auth.key = '\0';
+ bundle.cfg.opt = OPT_SROUTES | OPT_IDCHECK | OPT_LOOPBACK |
+ OPT_THROUGHPUT | OPT_UTMP;
+ *bundle.cfg.label = '\0';
+ bundle.cfg.mtu = DEF_MTU;
+ bundle.cfg.autoload.max.packets = 0;
+ bundle.cfg.autoload.max.timeout = 0;
+ bundle.cfg.autoload.min.packets = 0;
+ bundle.cfg.autoload.min.timeout = 0;
+ bundle.phys_type = type;
+
+ bundle.links = datalink_Create("deflink", &bundle, type);
+ if (bundle.links == NULL) {
+ log_Printf(LogERROR, "Cannot create data link: %s\n", strerror(errno));
+ close(bundle.dev.fd);
+ bundle.ifp.Name = NULL;
+ return NULL;
+ }
+
+ bundle.desc.type = BUNDLE_DESCRIPTOR;
+ bundle.desc.next = NULL;
+ bundle.desc.UpdateSet = bundle_UpdateSet;
+ bundle.desc.IsSet = bundle_IsSet;
+ bundle.desc.Read = bundle_DescriptorRead;
+ bundle.desc.Write = bundle_DescriptorWrite;
+
+ mp_Init(&bundle.ncp.mp, &bundle);
+
+ /* Send over the first physical link by default */
+ ipcp_Init(&bundle.ncp.ipcp, &bundle, &bundle.links->physical->link,
+ &bundle.fsm);
+
+ memset(&bundle.filter, '\0', sizeof bundle.filter);
+ bundle.filter.in.fragok = bundle.filter.in.logok = 1;
+ bundle.filter.in.name = "IN";
+ bundle.filter.out.fragok = bundle.filter.out.logok = 1;
+ bundle.filter.out.name = "OUT";
+ bundle.filter.dial.name = "DIAL";
+ bundle.filter.dial.logok = 1;
+ bundle.filter.alive.name = "ALIVE";
+ bundle.filter.alive.logok = 1;
+ memset(&bundle.idle.timer, '\0', sizeof bundle.idle.timer);
+ bundle.idle.done = 0;
+ bundle.notify.fd = -1;
+ memset(&bundle.autoload.timer, '\0', sizeof bundle.autoload.timer);
+ bundle.autoload.done = 0;
+ bundle.autoload.running = 0;
+
+ /* Clean out any leftover crud */
+ bundle_CleanInterface(&bundle);
+
+ if (prompt) {
+ /* Retrospectively introduce ourselves to the prompt */
+ prompt->bundle = &bundle;
+ bundle_RegisterDescriptor(&bundle, &prompt->desc);
+ }
+
+ return &bundle;
+}
+
+static void
+bundle_DownInterface(struct bundle *bundle)
+{
+ struct ifreq ifrq;
+ int s;
+
+ route_IfDelete(bundle, 1);
+
+ s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "bundle_DownInterface: socket: %s\n", strerror(errno));
+ return;
+ }
+
+ memset(&ifrq, '\0', sizeof ifrq);
+ strncpy(ifrq.ifr_name, bundle->ifp.Name, sizeof ifrq.ifr_name - 1);
+ ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
+ if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
+ log_Printf(LogERROR, "bundle_DownInterface: ioctl(SIOCGIFFLAGS): %s\n",
+ strerror(errno));
+ close(s);
+ return;
+ }
+ ifrq.ifr_flags &= ~IFF_UP;
+ if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
+ log_Printf(LogERROR, "bundle_DownInterface: ioctl(SIOCSIFFLAGS): %s\n",
+ strerror(errno));
+ close(s);
+ return;
+ }
+ close(s);
+}
+
+void
+bundle_Destroy(struct bundle *bundle)
+{
+ struct datalink *dl;
+ struct descriptor *desc, *ndesc;
+
+ /*
+ * Clean up the interface. We don't need to timer_Stop()s, mp_Down(),
+ * ipcp_CleanInterface() and bundle_DownInterface() unless we're getting
+ * out under exceptional conditions such as a descriptor exception.
+ */
+ timer_Stop(&bundle->idle.timer);
+ timer_Stop(&bundle->autoload.timer);
+ mp_Down(&bundle->ncp.mp);
+ ipcp_CleanInterface(&bundle->ncp.ipcp);
+ bundle_DownInterface(bundle);
+
+ /* Again, these are all DATALINK_CLOSED unless we're abending */
+ dl = bundle->links;
+ while (dl)
+ dl = datalink_Destroy(dl);
+
+ /* In case we never made PHASE_NETWORK */
+ bundle_Notify(bundle, EX_ERRDEAD);
+
+ /* Finally, destroy our prompts */
+ desc = bundle->desc.next;
+ while (desc) {
+ ndesc = desc->next;
+ if (desc->type == PROMPT_DESCRIPTOR)
+ prompt_Destroy((struct prompt *)desc, 1);
+ else
+ log_Printf(LogERROR, "bundle_Destroy: Don't know how to delete descriptor"
+ " type %d\n", desc->type);
+ desc = ndesc;
+ }
+ bundle->desc.next = NULL;
+ bundle->ifp.Name = NULL;
+}
+
+struct rtmsg {
+ struct rt_msghdr m_rtm;
+ char m_space[64];
+};
+
+int
+bundle_SetRoute(struct bundle *bundle, int cmd, struct in_addr dst,
+ struct in_addr gateway, struct in_addr mask, int bang)
+{
+ struct rtmsg rtmes;
+ int s, nb, wb;
+ char *cp;
+ const char *cmdstr;
+ struct sockaddr_in rtdata;
+ int result = 1;
+
+ if (bang)
+ cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!");
+ else
+ cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
+ s = ID0socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "bundle_SetRoute: socket(): %s\n", strerror(errno));
+ return result;
+ }
+ memset(&rtmes, '\0', sizeof rtmes);
+ rtmes.m_rtm.rtm_version = RTM_VERSION;
+ rtmes.m_rtm.rtm_type = cmd;
+ rtmes.m_rtm.rtm_addrs = RTA_DST;
+ rtmes.m_rtm.rtm_seq = ++bundle->routing_seq;
+ rtmes.m_rtm.rtm_pid = getpid();
+ rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
+
+ memset(&rtdata, '\0', sizeof rtdata);
+ rtdata.sin_len = sizeof rtdata;
+ rtdata.sin_family = AF_INET;
+ rtdata.sin_port = 0;
+ rtdata.sin_addr = dst;
+
+ cp = rtmes.m_space;
+ memcpy(cp, &rtdata, rtdata.sin_len);
+ cp += rtdata.sin_len;
+ if (cmd == RTM_ADD) {
+ if (gateway.s_addr == INADDR_ANY) {
+ /* Add a route through the interface */
+ struct sockaddr_dl dl;
+ const char *iname;
+ int ilen;
+
+ iname = Index2Nam(bundle->ifp.Index);
+ ilen = strlen(iname);
+ dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen;
+ dl.sdl_family = AF_LINK;
+ dl.sdl_index = bundle->ifp.Index;
+ dl.sdl_type = 0;
+ dl.sdl_nlen = ilen;
+ dl.sdl_alen = 0;
+ dl.sdl_slen = 0;
+ strncpy(dl.sdl_data, iname, sizeof dl.sdl_data);
+ memcpy(cp, &dl, dl.sdl_len);
+ cp += dl.sdl_len;
+ rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
+ } else {
+ rtdata.sin_addr = gateway;
+ memcpy(cp, &rtdata, rtdata.sin_len);
+ cp += rtdata.sin_len;
+ rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
+ }
+ }
+
+ if (dst.s_addr == INADDR_ANY)
+ mask.s_addr = INADDR_ANY;
+
+ if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) {
+ rtdata.sin_addr = mask;
+ memcpy(cp, &rtdata, rtdata.sin_len);
+ cp += rtdata.sin_len;
+ rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
+ }
+
+ nb = cp - (char *) &rtmes;
+ rtmes.m_rtm.rtm_msglen = nb;
+ wb = ID0write(s, &rtmes, nb);
+ if (wb < 0) {
+ log_Printf(LogTCPIP, "bundle_SetRoute failure:\n");
+ log_Printf(LogTCPIP, "bundle_SetRoute: Cmd = %s\n", cmdstr);
+ log_Printf(LogTCPIP, "bundle_SetRoute: Dst = %s\n", inet_ntoa(dst));
+ log_Printf(LogTCPIP, "bundle_SetRoute: Gateway = %s\n", inet_ntoa(gateway));
+ log_Printf(LogTCPIP, "bundle_SetRoute: Mask = %s\n", inet_ntoa(mask));
+failed:
+ if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST ||
+ (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) {
+ if (!bang) {
+ log_Printf(LogWARN, "Add route failed: %s already exists\n",
+ inet_ntoa(dst));
+ result = 0; /* Don't add to our dynamic list */
+ } else {
+ rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE;
+ if ((wb = ID0write(s, &rtmes, nb)) < 0)
+ goto failed;
+ }
+ } else if (cmd == RTM_DELETE &&
+ (rtmes.m_rtm.rtm_errno == ESRCH ||
+ (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) {
+ if (!bang)
+ log_Printf(LogWARN, "Del route failed: %s: Non-existent\n",
+ inet_ntoa(dst));
+ } else if (rtmes.m_rtm.rtm_errno == 0)
+ log_Printf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr,
+ inet_ntoa(dst), strerror(errno));
+ else
+ log_Printf(LogWARN, "%s route failed: %s: %s\n",
+ cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
+ }
+ log_Printf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n",
+ wb, cmdstr, (unsigned)dst.s_addr, (unsigned)gateway.s_addr);
+ close(s);
+
+ return result;
+}
+
+void
+bundle_LinkClosed(struct bundle *bundle, struct datalink *dl)
+{
+ /*
+ * Our datalink has closed.
+ * CleanDatalinks() (called from DoLoop()) will remove closed
+ * 1OFF and DIRECT links.
+ * If it's the last data link, enter phase DEAD.
+ *
+ * NOTE: dl may not be in our list (bundle_SendDatalink()) !
+ */
+
+ struct datalink *odl;
+ int other_links;
+
+ other_links = 0;
+ for (odl = bundle->links; odl; odl = odl->next)
+ if (odl != dl && odl->state != DATALINK_CLOSED)
+ other_links++;
+
+ if (!other_links) {
+ if (dl->physical->type != PHYS_DEMAND) /* Not in -auto mode */
+ bundle_DownInterface(bundle);
+ if (bundle->ncp.ipcp.fsm.state > ST_CLOSED ||
+ bundle->ncp.ipcp.fsm.state == ST_STARTING) {
+ fsm_Down(&bundle->ncp.ipcp.fsm);
+ fsm_Close(&bundle->ncp.ipcp.fsm); /* ST_INITIAL please */
+ }
+ bundle_NewPhase(bundle, PHASE_DEAD);
+ bundle_DisplayPrompt(bundle);
+ bundle_StopAutoLoadTimer(bundle);
+ bundle->autoload.running = 0;
+ } else
+ bundle->autoload.running = 1;
+}
+
+void
+bundle_Open(struct bundle *bundle, const char *name, int mask)
+{
+ /*
+ * Please open the given datalink, or all if name == NULL
+ */
+ struct datalink *dl;
+
+ timer_Stop(&bundle->autoload.timer);
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (name == NULL || !strcasecmp(dl->name, name)) {
+ if (dl->state == DATALINK_CLOSED && (mask & dl->physical->type)) {
+ datalink_Up(dl, 1, 1);
+ if (mask == PHYS_DEMAND)
+ /* Only one DEMAND link at a time (see the AutoLoad timer) */
+ break;
+ }
+ if (name != NULL)
+ break;
+ }
+}
+
+struct datalink *
+bundle2datalink(struct bundle *bundle, const char *name)
+{
+ struct datalink *dl;
+
+ if (name != NULL) {
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (!strcasecmp(dl->name, name))
+ return dl;
+ } else if (bundle->links && !bundle->links->next)
+ return bundle->links;
+
+ return NULL;
+}
+
+int
+bundle_FillQueues(struct bundle *bundle)
+{
+ int total;
+
+ if (bundle->ncp.mp.active)
+ total = mp_FillQueues(bundle);
+ else {
+ struct datalink *dl;
+ int add;
+
+ for (total = 0, dl = bundle->links; dl; dl = dl->next)
+ if (dl->state == DATALINK_OPEN) {
+ add = link_QueueLen(&dl->physical->link);
+ if (add == 0 && dl->physical->out == NULL)
+ add = ip_FlushPacket(&dl->physical->link, bundle);
+ total += add;
+ }
+ }
+
+ return total + ip_QueueLen();
+}
+
+int
+bundle_ShowLinks(struct cmdargs const *arg)
+{
+ struct datalink *dl;
+
+ for (dl = arg->bundle->links; dl; dl = dl->next) {
+ prompt_Printf(arg->prompt, "Name: %s [%s]", dl->name, datalink_State(dl));
+ if (dl->physical->link.throughput.rolling && dl->state == DATALINK_OPEN)
+ prompt_Printf(arg->prompt, " (weight %d, %d bytes/sec)",
+ dl->mp.weight,
+ dl->physical->link.throughput.OctetsPerSecond);
+ prompt_Printf(arg->prompt, "\n");
+ }
+
+ return 0;
+}
+
+static const char *
+optval(struct bundle *bundle, int bit)
+{
+ return (bundle->cfg.opt & bit) ? "enabled" : "disabled";
+}
+
+int
+bundle_ShowStatus(struct cmdargs const *arg)
+{
+ int remaining;
+
+ prompt_Printf(arg->prompt, "Phase %s\n", bundle_PhaseName(arg->bundle));
+ prompt_Printf(arg->prompt, " Device: %s\n", arg->bundle->dev.Name);
+ prompt_Printf(arg->prompt, " Interface: %s @ %lubps\n",
+ arg->bundle->ifp.Name, arg->bundle->ifp.Speed);
+
+ prompt_Printf(arg->prompt, "\nDefaults:\n");
+ prompt_Printf(arg->prompt, " Label: %s\n", arg->bundle->cfg.label);
+ prompt_Printf(arg->prompt, " Auth name: %s\n",
+ arg->bundle->cfg.auth.name);
+ prompt_Printf(arg->prompt, " Auto Load: Up after %ds of >= %d packets\n",
+ arg->bundle->cfg.autoload.max.timeout,
+ arg->bundle->cfg.autoload.max.packets);
+ prompt_Printf(arg->prompt, " Down after %ds of <= %d"
+ " packets\n", arg->bundle->cfg.autoload.min.timeout,
+ arg->bundle->cfg.autoload.min.packets);
+ if (arg->bundle->autoload.timer.state == TIMER_RUNNING)
+ prompt_Printf(arg->prompt, " %ds remaining 'till "
+ "a link comes %s\n",
+ bundle_RemainingAutoLoadTime(arg->bundle),
+ arg->bundle->autoload.comingup ? "up" : "down");
+ else
+ prompt_Printf(arg->prompt, " %srunning with %d"
+ " packets queued\n", arg->bundle->autoload.running ?
+ "" : "not ", ip_QueueLen());
+
+ prompt_Printf(arg->prompt, " Idle Timer: ");
+ if (arg->bundle->cfg.idle_timeout) {
+ prompt_Printf(arg->prompt, "%ds", arg->bundle->cfg.idle_timeout);
+ remaining = bundle_RemainingIdleTime(arg->bundle);
+ if (remaining != -1)
+ prompt_Printf(arg->prompt, " (%ds remaining)", remaining);
+ prompt_Printf(arg->prompt, "\n");
+ } else
+ prompt_Printf(arg->prompt, "disabled\n");
+ prompt_Printf(arg->prompt, " MTU: ");
+ if (arg->bundle->cfg.mtu)
+ prompt_Printf(arg->prompt, "%d\n", arg->bundle->cfg.mtu);
+ else
+ prompt_Printf(arg->prompt, "unspecified\n");
+
+ prompt_Printf(arg->prompt, " Sticky Routes: %s\n",
+ optval(arg->bundle, OPT_SROUTES));
+ prompt_Printf(arg->prompt, " ID check: %s\n",
+ optval(arg->bundle, OPT_IDCHECK));
+ prompt_Printf(arg->prompt, " Loopback: %s\n",
+ optval(arg->bundle, OPT_LOOPBACK));
+ prompt_Printf(arg->prompt, " PasswdAuth: %s\n",
+ optval(arg->bundle, OPT_PASSWDAUTH));
+ prompt_Printf(arg->prompt, " Proxy: %s\n",
+ optval(arg->bundle, OPT_PROXY));
+ prompt_Printf(arg->prompt, " Throughput: %s\n",
+ optval(arg->bundle, OPT_THROUGHPUT));
+ prompt_Printf(arg->prompt, " Utmp Logging: %s\n",
+ optval(arg->bundle, OPT_UTMP));
+
+ return 0;
+}
+
+static void
+bundle_IdleTimeout(void *v)
+{
+ struct bundle *bundle = (struct bundle *)v;
+
+ log_Printf(LogPHASE, "Idle timer expired.\n");
+ bundle_StopIdleTimer(bundle);
+ bundle_Close(bundle, NULL, 1);
+}
+
+/*
+ * Start Idle timer. If timeout is reached, we call bundle_Close() to
+ * close LCP and link.
+ */
+void
+bundle_StartIdleTimer(struct bundle *bundle)
+{
+ timer_Stop(&bundle->idle.timer);
+ if ((bundle->phys_type & (PHYS_DEDICATED|PHYS_PERM)) != bundle->phys_type &&
+ bundle->cfg.idle_timeout) {
+ bundle->idle.timer.func = bundle_IdleTimeout;
+ bundle->idle.timer.name = "idle";
+ bundle->idle.timer.load = bundle->cfg.idle_timeout * SECTICKS;
+ bundle->idle.timer.arg = bundle;
+ timer_Start(&bundle->idle.timer);
+ bundle->idle.done = time(NULL) + bundle->cfg.idle_timeout;
+ }
+}
+
+void
+bundle_SetIdleTimer(struct bundle *bundle, int value)
+{
+ bundle->cfg.idle_timeout = value;
+ if (bundle_LinkIsUp(bundle))
+ bundle_StartIdleTimer(bundle);
+}
+
+void
+bundle_StopIdleTimer(struct bundle *bundle)
+{
+ timer_Stop(&bundle->idle.timer);
+ bundle->idle.done = 0;
+}
+
+static int
+bundle_RemainingIdleTime(struct bundle *bundle)
+{
+ if (bundle->idle.done)
+ return bundle->idle.done - time(NULL);
+ return -1;
+}
+
+int
+bundle_IsDead(struct bundle *bundle)
+{
+ return !bundle->links || (bundle->phase == PHASE_DEAD && bundle->CleaningUp);
+}
+
+void
+bundle_RegisterDescriptor(struct bundle *bundle, struct descriptor *d)
+{
+ d->next = bundle->desc.next;
+ bundle->desc.next = d;
+}
+
+void
+bundle_UnRegisterDescriptor(struct bundle *bundle, struct descriptor *d)
+{
+ struct descriptor **desc;
+
+ for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next)
+ if (*desc == d) {
+ *desc = d->next;
+ break;
+ }
+}
+
+void
+bundle_DelPromptDescriptors(struct bundle *bundle, struct server *s)
+{
+ struct descriptor **desc;
+ struct prompt *p;
+
+ desc = &bundle->desc.next;
+ while (*desc) {
+ if ((*desc)->type == PROMPT_DESCRIPTOR) {
+ p = (struct prompt *)*desc;
+ if (p->owner == s) {
+ prompt_Destroy(p, 1);
+ desc = &bundle->desc.next;
+ continue;
+ }
+ }
+ desc = &(*desc)->next;
+ }
+}
+
+void
+bundle_DisplayPrompt(struct bundle *bundle)
+{
+ struct descriptor **desc;
+
+ for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next)
+ if ((*desc)->type == PROMPT_DESCRIPTOR)
+ prompt_Required((struct prompt *)*desc);
+}
+
+void
+bundle_WriteTermPrompt(struct bundle *bundle, struct datalink *dl,
+ const char *data, int len)
+{
+ struct descriptor *desc;
+ struct prompt *p;
+
+ for (desc = bundle->desc.next; desc; desc = desc->next)
+ if (desc->type == PROMPT_DESCRIPTOR) {
+ p = (struct prompt *)desc;
+ if (prompt_IsTermMode(p, dl))
+ prompt_Printf(p, "%.*s", len, data);
+ }
+}
+
+void
+bundle_SetTtyCommandMode(struct bundle *bundle, struct datalink *dl)
+{
+ struct descriptor *desc;
+ struct prompt *p;
+
+ for (desc = bundle->desc.next; desc; desc = desc->next)
+ if (desc->type == PROMPT_DESCRIPTOR) {
+ p = (struct prompt *)desc;
+ if (prompt_IsTermMode(p, dl))
+ prompt_TtyCommandMode(p);
+ }
+}
+
+static void
+bundle_LinkAdded(struct bundle *bundle, struct datalink *dl)
+{
+ bundle->phys_type |= dl->physical->type;
+ if (dl->physical->type == PHYS_DEMAND &&
+ bundle->autoload.timer.state == TIMER_STOPPED &&
+ bundle->phase == PHASE_NETWORK)
+ bundle->autoload.running = 1;
+}
+
+static void
+bundle_LinksRemoved(struct bundle *bundle)
+{
+ struct datalink *dl;
+
+ bundle->phys_type = 0;
+ for (dl = bundle->links; dl; dl = dl->next)
+ bundle_LinkAdded(bundle, dl);
+
+ if ((bundle->phys_type & (PHYS_DEDICATED|PHYS_PERM)) == bundle->phys_type)
+ timer_Stop(&bundle->idle.timer);
+}
+
+static struct datalink *
+bundle_DatalinkLinkout(struct bundle *bundle, struct datalink *dl)
+{
+ struct datalink **dlp;
+
+ if (dl->state == DATALINK_CLOSED)
+ for (dlp = &bundle->links; *dlp; dlp = &(*dlp)->next)
+ if (*dlp == dl) {
+ *dlp = dl->next;
+ dl->next = NULL;
+ bundle_LinksRemoved(bundle);
+ return dl;
+ }
+
+ return NULL;
+}
+
+static void
+bundle_DatalinkLinkin(struct bundle *bundle, struct datalink *dl)
+{
+ struct datalink **dlp = &bundle->links;
+
+ while (*dlp)
+ dlp = &(*dlp)->next;
+
+ *dlp = dl;
+ dl->next = NULL;
+
+ bundle_LinkAdded(bundle, dl);
+}
+
+void
+bundle_CleanDatalinks(struct bundle *bundle)
+{
+ struct datalink **dlp = &bundle->links;
+ int found = 0;
+
+ while (*dlp)
+ if ((*dlp)->state == DATALINK_CLOSED &&
+ (*dlp)->physical->type & (PHYS_DIRECT|PHYS_1OFF)) {
+ *dlp = datalink_Destroy(*dlp);
+ found++;
+ } else
+ dlp = &(*dlp)->next;
+
+ if (found)
+ bundle_LinksRemoved(bundle);
+}
+
+int
+bundle_DatalinkClone(struct bundle *bundle, struct datalink *dl,
+ const char *name)
+{
+ if (bundle2datalink(bundle, name)) {
+ log_Printf(LogWARN, "Clone: %s: name already exists\n", name);
+ return 0;
+ }
+
+ bundle_DatalinkLinkin(bundle, datalink_Clone(dl, name));
+ return 1;
+}
+
+void
+bundle_DatalinkRemove(struct bundle *bundle, struct datalink *dl)
+{
+ dl = bundle_DatalinkLinkout(bundle, dl);
+ if (dl)
+ datalink_Destroy(dl);
+}
+
+void
+bundle_SetLabel(struct bundle *bundle, const char *label)
+{
+ if (label)
+ strncpy(bundle->cfg.label, label, sizeof bundle->cfg.label - 1);
+ else
+ *bundle->cfg.label = '\0';
+}
+
+const char *
+bundle_GetLabel(struct bundle *bundle)
+{
+ return *bundle->cfg.label ? bundle->cfg.label : NULL;
+}
+
+void
+bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun)
+{
+ char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)];
+ struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf;
+ struct msghdr msg;
+ struct iovec iov[SCATTER_SEGMENTS];
+ struct datalink *dl;
+ int niov, link_fd, expect, f;
+
+ log_Printf(LogPHASE, "Receiving datalink\n");
+
+ /* Create our scatter/gather array */
+ niov = 1;
+ iov[0].iov_len = strlen(Version) + 1;
+ iov[0].iov_base = (char *)malloc(iov[0].iov_len);
+ if (datalink2iov(NULL, iov, &niov, sizeof iov / sizeof *iov) == -1)
+ return;
+
+ for (f = expect = 0; f < niov; f++)
+ expect += iov[f].iov_len;
+
+ /* Set up our message */
+ cmsg->cmsg_len = sizeof cmsgbuf;
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ memset(&msg, '\0', sizeof msg);
+ msg.msg_name = (caddr_t)sun;
+ msg.msg_namelen = sizeof *sun;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = niov;
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = sizeof cmsgbuf;
+
+ log_Printf(LogDEBUG, "Expecting %d scatter/gather bytes\n", expect);
+ f = expect + 100;
+ setsockopt(s, SOL_SOCKET, SO_RCVBUF, &f, sizeof f);
+ if ((f = recvmsg(s, &msg, MSG_WAITALL)) != expect) {
+ if (f == -1)
+ log_Printf(LogERROR, "Failed recvmsg: %s\n", strerror(errno));
+ else
+ log_Printf(LogERROR, "Failed recvmsg: Got %d, not %d\n", f, expect);
+ while (niov--)
+ free(iov[niov].iov_base);
+ return;
+ }
+
+ /* We've successfully received an open file descriptor through our socket */
+ link_fd = *(int *)CMSG_DATA(cmsg);
+
+ write(s, "!",1 ); /* ACK */
+
+ if (strncmp(Version, iov[0].iov_base, iov[0].iov_len)) {
+ log_Printf(LogWARN, "Cannot receive datalink, incorrect version"
+ " (\"%.*s\", not \"%s\")\n", (int)iov[0].iov_len,
+ iov[0].iov_base, Version);
+ close(link_fd);
+ while (niov--)
+ free(iov[niov].iov_base);
+ return;
+ }
+
+ niov = 1;
+ dl = iov2datalink(bundle, iov, &niov, sizeof iov / sizeof *iov, link_fd);
+ if (dl) {
+ bundle_DatalinkLinkin(bundle, dl);
+ datalink_AuthOk(dl);
+ } else
+ close(link_fd);
+
+ free(iov[0].iov_base);
+}
+
+void
+bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun)
+{
+ char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)], ack;
+ struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf;
+ struct msghdr msg;
+ struct iovec iov[SCATTER_SEGMENTS];
+ int niov, link_fd, f, expect;
+
+ log_Printf(LogPHASE, "Transmitting datalink %s\n", dl->name);
+
+ bundle_DatalinkLinkout(dl->bundle, dl);
+ bundle_LinkClosed(dl->bundle, dl);
+
+ /* Build our scatter/gather array */
+ iov[0].iov_len = strlen(Version) + 1;
+ iov[0].iov_base = strdup(Version);
+ niov = 1;
+
+ link_fd = datalink2iov(dl, iov, &niov, sizeof iov / sizeof *iov);
+
+ if (link_fd != -1) {
+ cmsg->cmsg_len = sizeof cmsgbuf;
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(cmsg) = link_fd;
+
+ memset(&msg, '\0', sizeof msg);
+ msg.msg_name = (caddr_t)sun;
+ msg.msg_namelen = sizeof *sun;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = niov;
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = sizeof cmsgbuf;
+
+ for (f = expect = 0; f < niov; f++)
+ expect += iov[f].iov_len;
+
+ log_Printf(LogDEBUG, "Sending %d bytes in scatter/gather array\n", expect);
+
+ f = expect + SOCKET_OVERHEAD;
+ setsockopt(s, SOL_SOCKET, SO_SNDBUF, &f, sizeof f);
+ if (sendmsg(s, &msg, 0) == -1)
+ log_Printf(LogERROR, "Failed sendmsg: %s\n", strerror(errno));
+ /* We must get the ACK before closing the descriptor ! */
+ read(s, &ack, 1);
+ close(link_fd);
+ }
+
+ while (niov--)
+ free(iov[niov].iov_base);
+}
+
+int
+bundle_RenameDatalink(struct bundle *bundle, struct datalink *ndl,
+ const char *name)
+{
+ struct datalink *dl;
+
+ if (!strcasecmp(ndl->name, name))
+ return 1;
+
+ for (dl = bundle->links; dl; dl = dl->next)
+ if (!strcasecmp(dl->name, name))
+ return 0;
+
+ datalink_Rename(ndl, name);
+ return 1;
+}
+
+int
+bundle_SetMode(struct bundle *bundle, struct datalink *dl, int mode)
+{
+ int omode;
+
+ omode = dl->physical->type;
+ if (omode == mode)
+ return 1;
+
+ if (mode == PHYS_DEMAND && !(bundle->phys_type & PHYS_DEMAND))
+ /* Changing to demand-dial mode */
+ if (bundle->ncp.ipcp.peer_ip.s_addr == INADDR_ANY) {
+ log_Printf(LogWARN, "You must `set ifaddr' before changing mode to %s\n",
+ mode2Nam(mode));
+ return 0;
+ }
+
+ if (!datalink_SetMode(dl, mode))
+ return 0;
+
+ if (mode == PHYS_DEMAND && !(bundle->phys_type & PHYS_DEMAND))
+ ipcp_InterfaceUp(&bundle->ncp.ipcp);
+
+ /* Regenerate phys_type and adjust autoload & idle timers */
+ bundle_LinksRemoved(bundle);
+
+ if (omode == PHYS_DEMAND && !(bundle->phys_type & PHYS_DEMAND))
+ /* Changing from demand-dial mode */
+ ipcp_CleanInterface(&bundle->ncp.ipcp);
+
+ return 1;
+}
diff --git a/usr.sbin/ppp/bundle.h b/usr.sbin/ppp/bundle.h
new file mode 100644
index 000000000000..52930c50bd99
--- /dev/null
+++ b/usr.sbin/ppp/bundle.h
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: bundle.h,v 1.1.2.42 1998/05/21 01:13:24 brian Exp $
+ */
+
+#define PHASE_DEAD 0 /* Link is dead */
+#define PHASE_ESTABLISH 1 /* Establishing link */
+#define PHASE_AUTHENTICATE 2 /* Being authenticated */
+#define PHASE_NETWORK 3 /* We're alive ! */
+#define PHASE_TERMINATE 4 /* Terminating link */
+
+/* cfg.opt bit settings */
+#define OPT_IDCHECK 0x01
+#define OPT_LOOPBACK 0x02
+#define OPT_PASSWDAUTH 0x04
+#define OPT_PROXY 0x08
+#define OPT_SROUTES 0x10
+#define OPT_THROUGHPUT 0x20
+#define OPT_UTMP 0x40
+
+#define MAX_ENDDISC_CLASS 5
+
+#define Enabled(b, o) ((b)->cfg.opt & (o))
+
+struct sockaddr_un;
+struct datalink;
+struct physical;
+struct link;
+struct server;
+struct prompt;
+
+struct bundle {
+ struct descriptor desc; /* really all our datalinks */
+ int unit; /* The device/interface unit number */
+
+ struct {
+ char Name[20]; /* The /dev/XXXX name */
+ int fd; /* The /dev/XXXX descriptor */
+ } dev;
+
+ struct {
+ u_long Speed; /* struct tuninfo speed */
+ int Index; /* The interface index */
+ char *Name; /* The interface name */
+ } ifp;
+
+ int routing_seq; /* The current routing sequence number */
+ u_int phase; /* Curent phase */
+ int phys_type; /* Union of all physical::type's */
+
+ unsigned CleaningUp : 1; /* Going to exit.... */
+
+ struct fsm_parent fsm; /* Our callback functions */
+ struct datalink *links; /* Our data links */
+
+ struct {
+ int idle_timeout; /* NCP Idle timeout value */
+ struct {
+ char name[50]; /* PAP/CHAP system name */
+ char key[50]; /* PAP/CHAP key */
+ } auth;
+ unsigned opt; /* Uses OPT_ bits from above */
+ char label[50]; /* last thing `load'ed */
+ u_short mtu; /* Interface mtu */
+
+ struct { /* We need/don't need another link when */
+ struct { /* more/less than */
+ int packets; /* this number of packets are queued for */
+ int timeout; /* this number of seconds */
+ } max, min;
+ } autoload;
+ } cfg;
+
+ struct {
+ struct ipcp ipcp; /* Our IPCP FSM */
+ struct mp mp; /* Our MP */
+ } ncp;
+
+ struct {
+ struct filter in; /* incoming packet filter */
+ struct filter out; /* outgoing packet filter */
+ struct filter dial; /* dial-out packet filter */
+ struct filter alive; /* keep-alive packet filter */
+ } filter;
+
+ struct {
+ struct pppTimer timer; /* timeout after cfg.idle_timeout */
+ time_t done;
+ } idle;
+
+ struct {
+ int fd; /* write status here */
+ } notify;
+
+ struct {
+ struct pppTimer timer;
+ time_t done;
+ unsigned running : 1;
+ unsigned comingup : 1;
+ } autoload;
+};
+
+#define descriptor2bundle(d) \
+ ((d)->type == BUNDLE_DESCRIPTOR ? (struct bundle *)(d) : NULL)
+
+extern struct bundle *bundle_Create(const char *, struct prompt *, int);
+extern void bundle_Destroy(struct bundle *);
+extern const char *bundle_PhaseName(struct bundle *);
+#define bundle_Phase(b) ((b)->phase)
+extern void bundle_NewPhase(struct bundle *, u_int);
+extern int bundle_LinkIsUp(const struct bundle *);
+extern int bundle_SetRoute(struct bundle *, int, struct in_addr,
+ struct in_addr, struct in_addr, int);
+extern void bundle_Close(struct bundle *, const char *, int);
+extern void bundle_Down(struct bundle *);
+extern void bundle_Open(struct bundle *, const char *, int);
+extern void bundle_LinkClosed(struct bundle *, struct datalink *);
+
+extern int bundle_FillQueues(struct bundle *);
+extern int bundle_ShowLinks(struct cmdargs const *);
+extern int bundle_ShowStatus(struct cmdargs const *);
+extern void bundle_StartIdleTimer(struct bundle *);
+extern void bundle_SetIdleTimer(struct bundle *, int);
+extern void bundle_StopIdleTimer(struct bundle *);
+extern int bundle_IsDead(struct bundle *);
+extern struct datalink *bundle2datalink(struct bundle *, const char *);
+
+extern void bundle_RegisterDescriptor(struct bundle *, struct descriptor *);
+extern void bundle_UnRegisterDescriptor(struct bundle *, struct descriptor *);
+
+extern void bundle_DelPromptDescriptors(struct bundle *, struct server *);
+extern void bundle_DisplayPrompt(struct bundle *);
+extern void bundle_WriteTermPrompt(struct bundle *, struct datalink *,
+ const char *, int);
+extern void bundle_SetTtyCommandMode(struct bundle *, struct datalink *);
+
+extern int bundle_DatalinkClone(struct bundle *, struct datalink *,
+ const char *);
+extern void bundle_DatalinkRemove(struct bundle *, struct datalink *);
+extern void bundle_CleanDatalinks(struct bundle *);
+extern void bundle_SetLabel(struct bundle *, const char *);
+extern const char *bundle_GetLabel(struct bundle *);
+extern void bundle_SendDatalink(struct datalink *, int, struct sockaddr_un *);
+extern void bundle_ReceiveDatalink(struct bundle *, int, struct sockaddr_un *);
+extern int bundle_SetMode(struct bundle *, struct datalink *, int);
+extern int bundle_RenameDatalink(struct bundle *, struct datalink *,
+ const char *);
diff --git a/usr.sbin/ppp/ccp.c b/usr.sbin/ppp/ccp.c
index 9b5de4b87b48..12ace1a49597 100644
--- a/usr.sbin/ppp/ccp.c
+++ b/usr.sbin/ppp/ccp.c
@@ -17,16 +17,20 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ccp.c,v 1.30 1998/01/21 02:15:10 brian Exp $
+ * $Id: ccp.c,v 1.30.2.45 1998/05/21 01:26:05 brian Exp $
*
* TODO:
* o Support other compression protocols
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <stdio.h>
-#include <string.h>
+#include <stdlib.h>
+#include <termios.h>
#include "command.h"
#include "mbuf.h"
@@ -37,47 +41,53 @@
#include "lcpproto.h"
#include "lcp.h"
#include "ccp.h"
-#include "phase.h"
-#include "loadalias.h"
-#include "vars.h"
#include "pred.h"
#include "deflate.h"
-
-struct ccpstate CcpInfo = { -1, -1, -1, -1 };
+#include "throughput.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "prompt.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "link.h"
+#include "mp.h"
+#include "async.h"
+#include "physical.h"
+#include "bundle.h"
static void CcpSendConfigReq(struct fsm *);
-static void CcpSendTerminateReq(struct fsm *);
-static void CcpSendTerminateAck(struct fsm *);
-static void CcpDecodeConfig(u_char *, int, int);
+static void CcpSentTerminateReq(struct fsm *);
+static void CcpSendTerminateAck(struct fsm *, u_char);
+static void CcpDecodeConfig(struct fsm *, u_char *, int, int,
+ struct fsm_decode *);
static void CcpLayerStart(struct fsm *);
static void CcpLayerFinish(struct fsm *);
-static void CcpLayerUp(struct fsm *);
+static int CcpLayerUp(struct fsm *);
static void CcpLayerDown(struct fsm *);
static void CcpInitRestartCounter(struct fsm *);
+static void CcpRecvResetReq(struct fsm *);
+static void CcpRecvResetAck(struct fsm *, u_char);
-struct fsm CcpFsm = {
- "CCP",
- PROTO_CCP,
- CCP_MAXCODE,
- 0,
- ST_INITIAL,
- 0, 0, 0,
- {0, 0, 0, NULL, NULL, NULL}, /* FSM timer */
- {0, 0, 0, NULL, NULL, NULL}, /* Open timer */
- {0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */
- LogCCP,
-
+static struct fsm_callbacks ccp_Callbacks = {
CcpLayerUp,
CcpLayerDown,
CcpLayerStart,
CcpLayerFinish,
CcpInitRestartCounter,
CcpSendConfigReq,
- CcpSendTerminateReq,
+ CcpSentTerminateReq,
CcpSendTerminateAck,
CcpDecodeConfig,
+ CcpRecvResetReq,
+ CcpRecvResetAck
};
+static const char *ccp_TimerNames[] =
+ {"CCP restart", "CCP openmode", "CCP stopped"};
+
static char const *cftypes[] = {
/* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */
"OUI", /* 0: OUI */
@@ -88,14 +98,14 @@ static char const *cftypes[] = {
"???", "???", "???", "???", "???", "???",
"HWPPC", /* 16: Hewlett-Packard PPC */
"STAC", /* 17: Stac Electronics LZS (rfc1974) */
- "MSPPC", /* 18: Microsoft PPC */
+ "MPPC", /* 18: Microsoft PPC (rfc2118) */
"GAND", /* 19: Gandalf FZA (rfc1993) */
"V42BIS", /* 20: ARG->DATA.42bis compression */
"BSD", /* 21: BSD LZW Compress */
"???",
"LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */
"MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */
- /* 24: Deflate (according to pppd-2.3.1) */
+ /* 24: Deflate (according to pppd-2.3.*) */
"DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */
"DEFLATE", /* 26: Deflate (rfc1979) */
};
@@ -117,316 +127,464 @@ static const struct ccp_algorithm *algorithm[] = {
&PppdDeflateAlgorithm
};
-static int in_algorithm = -1;
-static int out_algorithm = -1;
#define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
int
-ReportCcpStatus(struct cmdargs const *arg)
+ccp_ReportStatus(struct cmdargs const *arg)
{
- if (VarTerm) {
- fprintf(VarTerm, "%s [%s]\n", CcpFsm.name, StateNames[CcpFsm.state]);
- fprintf(VarTerm, "My protocol = %s, His protocol = %s\n",
- protoname(CcpInfo.my_proto), protoname(CcpInfo.his_proto));
- fprintf(VarTerm, "Output: %ld --> %ld, Input: %ld --> %ld\n",
- CcpInfo.uncompout, CcpInfo.compout,
- CcpInfo.compin, CcpInfo.uncompin);
- }
+ struct link *l;
+ struct ccp *ccp;
+
+ if (!(l = command_ChooseLink(arg)))
+ return -1;
+ ccp = &l->ccp;
+
+ prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name,
+ State2Nam(ccp->fsm.state));
+ prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n",
+ protoname(ccp->my_proto), protoname(ccp->his_proto));
+ prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n",
+ ccp->uncompout, ccp->compout,
+ ccp->compin, ccp->uncompin);
+
+ prompt_Printf(arg->prompt, "\n Defaults: ");
+ prompt_Printf(arg->prompt, "FSM retry = %us\n", ccp->cfg.fsmretry);
+ prompt_Printf(arg->prompt, " deflate windows: ");
+ prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize);
+ prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize);
+ prompt_Printf(arg->prompt, " DEFLATE: %s\n",
+ command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE]));
+ prompt_Printf(arg->prompt, " PREDICTOR1: %s\n",
+ command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1]));
+ prompt_Printf(arg->prompt, " DEFLATE24: %s\n",
+ command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24]));
return 0;
}
-static void
-ccpstateInit(void)
+void
+ccp_SetupCallbacks(struct ccp *ccp)
+{
+ ccp->fsm.fn = &ccp_Callbacks;
+ ccp->fsm.FsmTimer.name = ccp_TimerNames[0];
+ ccp->fsm.OpenTimer.name = ccp_TimerNames[1];
+ ccp->fsm.StoppedTimer.name = ccp_TimerNames[2];
+}
+
+void
+ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l,
+ const struct fsm_parent *parent)
{
- if (CcpInfo.in_init)
- (*algorithm[in_algorithm]->i.Term)();
- if (CcpInfo.out_init)
- (*algorithm[out_algorithm]->o.Term)();
- in_algorithm = -1;
- out_algorithm = -1;
- memset(&CcpInfo, '\0', sizeof CcpInfo);
- CcpInfo.his_proto = CcpInfo.my_proto = -1;
- CcpInfo.reset_sent = CcpInfo.last_reset = -1;
+ /* Initialise ourselves */
+
+ fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, 10, LogCCP,
+ bundle, l, parent, &ccp_Callbacks, ccp_TimerNames);
+
+ ccp->cfg.deflate.in.winsize = 0;
+ ccp->cfg.deflate.out.winsize = 15;
+ ccp->cfg.fsmretry = DEF_FSMRETRY;
+ ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED;
+ ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED;
+ ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0;
+
+ ccp_Setup(ccp);
}
void
-CcpInit()
+ccp_Setup(struct ccp *ccp)
{
- FsmInit(&CcpFsm);
- ccpstateInit();
- CcpFsm.maxconfig = 10;
+ /* Set ourselves up for a startup */
+ ccp->fsm.open_mode = 0;
+ ccp->fsm.maxconfig = 10;
+ ccp->his_proto = ccp->my_proto = -1;
+ ccp->reset_sent = ccp->last_reset = -1;
+ ccp->in.algorithm = ccp->out.algorithm = -1;
+ ccp->in.state = ccp->out.state = NULL;
+ ccp->in.opt.id = -1;
+ ccp->out.opt = NULL;
+ ccp->his_reject = ccp->my_reject = 0;
+ ccp->uncompout = ccp->compout = 0;
+ ccp->uncompin = ccp->compin = 0;
}
static void
CcpInitRestartCounter(struct fsm *fp)
{
- fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
+ /* Set fsm timer load */
+ struct ccp *ccp = fsm2ccp(fp);
+
+ fp->FsmTimer.load = ccp->cfg.fsmretry * SECTICKS;
fp->restart = 5;
}
static void
CcpSendConfigReq(struct fsm *fp)
{
- u_char *cp;
- int f;
-
- LogPrintf(LogCCP, "CcpSendConfigReq\n");
- cp = ReqBuff;
- CcpInfo.my_proto = -1;
- out_algorithm = -1;
+ /* Send config REQ please */
+ struct ccp *ccp = fsm2ccp(fp);
+ struct ccp_opt **o;
+ u_char *cp, buff[100];
+ int f, alloc;
+
+ cp = buff;
+ o = &ccp->out.opt;
+ alloc = ccp->his_reject == 0 && ccp->out.opt == NULL;
+ ccp->my_proto = -1;
+ ccp->out.algorithm = -1;
for (f = 0; f < NALGORITHMS; f++)
- if (Enabled(algorithm[f]->Conf) && !REJECTED(&CcpInfo, algorithm[f]->id)) {
- struct lcp_opt o;
-
- (*algorithm[f]->o.Get)(&o);
- cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id],
- (*algorithm[f]->Disp)(&o));
- CcpInfo.my_proto = o.id;
- out_algorithm = f;
+ if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) &&
+ !REJECTED(ccp, algorithm[f]->id)) {
+
+ if (!alloc)
+ for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next)
+ if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f)
+ break;
+
+ if (alloc || *o == NULL) {
+ *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt));
+ (*o)->val.id = algorithm[f]->id;
+ (*o)->val.len = 2;
+ (*o)->next = NULL;
+ (*o)->algorithm = f;
+ (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg);
+ }
+
+ if (cp + (*o)->val.len > buff + sizeof buff) {
+ log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name);
+ break;
+ }
+ memcpy(cp, &(*o)->val, (*o)->val.len);
+ cp += (*o)->val.len;
+
+ ccp->my_proto = (*o)->val.id;
+ ccp->out.algorithm = f;
+
+ if (alloc)
+ o = &(*o)->next;
}
- FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
+
+ fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff);
}
void
-CcpSendResetReq(struct fsm *fp)
+ccp_SendResetReq(struct fsm *fp)
{
- LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid);
- CcpInfo.reset_sent = fp->reqid;
- CcpInfo.last_reset = -1;
- FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
+ /* We can't read our input - ask peer to reset */
+ struct ccp *ccp = fsm2ccp(fp);
+
+ ccp->reset_sent = fp->reqid;
+ ccp->last_reset = -1;
+ fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
}
static void
-CcpSendTerminateReq(struct fsm *fp)
+CcpSentTerminateReq(struct fsm *fp)
{
- /* XXX: No code yet */
+ /* Term REQ just sent by FSM */
}
static void
-CcpSendTerminateAck(struct fsm *fp)
+CcpSendTerminateAck(struct fsm *fp, u_char id)
{
- LogPrintf(LogCCP, "CcpSendTerminateAck\n");
- FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
+ /* Send Term ACK please */
+ fsm_Output(fp, CODE_TERMACK, id, NULL, 0);
}
-void
+static void
CcpRecvResetReq(struct fsm *fp)
{
- if (out_algorithm >= 0 && out_algorithm < NALGORITHMS)
- (*algorithm[out_algorithm]->o.Reset)();
+ /* Got a reset REQ, reset outgoing dictionary */
+ struct ccp *ccp = fsm2ccp(fp);
+ if (ccp->out.state != NULL)
+ (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state);
}
static void
CcpLayerStart(struct fsm *fp)
{
- LogPrintf(LogCCP, "CcpLayerStart.\n");
+ /* We're about to start up ! */
+ log_Printf(LogCCP, "%s: CcpLayerStart.\n", fp->link->name);
}
static void
CcpLayerFinish(struct fsm *fp)
{
- LogPrintf(LogCCP, "CcpLayerFinish.\n");
- ccpstateInit();
+ /* We're now down */
+ struct ccp *ccp = fsm2ccp(fp);
+ struct ccp_opt *next;
+
+ log_Printf(LogCCP, "%s: CcpLayerFinish.\n", fp->link->name);
+ if (ccp->in.state != NULL) {
+ (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state);
+ ccp->in.state = NULL;
+ ccp->in.algorithm = -1;
+ }
+ if (ccp->out.state != NULL) {
+ (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state);
+ ccp->out.state = NULL;
+ ccp->out.algorithm = -1;
+ }
+ ccp->his_reject = ccp->my_reject = 0;
+
+ while (ccp->out.opt) {
+ next = ccp->out.opt->next;
+ free(ccp->out.opt);
+ ccp->out.opt = next;
+ }
}
static void
CcpLayerDown(struct fsm *fp)
{
- LogPrintf(LogCCP, "CcpLayerDown.\n");
- ccpstateInit();
+ /* About to come down */
+ log_Printf(LogCCP, "%s: CcpLayerDown.\n", fp->link->name);
}
/*
* Called when CCP has reached the OPEN state
*/
-static void
+static int
CcpLayerUp(struct fsm *fp)
{
- LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state);
- LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n",
- protoname(CcpInfo.my_proto), CcpInfo.my_proto,
- protoname(CcpInfo.his_proto), CcpInfo.his_proto);
- if (!CcpInfo.in_init && in_algorithm >= 0 && in_algorithm < NALGORITHMS) {
- (*algorithm[in_algorithm]->i.Init)();
- CcpInfo.in_init = 1;
- }
- if (!CcpInfo.out_init && out_algorithm >= 0 && out_algorithm < NALGORITHMS) {
- (*algorithm[out_algorithm]->o.Init)();
- CcpInfo.out_init = 1;
+ /* We're now up */
+ struct ccp *ccp = fsm2ccp(fp);
+ log_Printf(LogCCP, "%s: CcpLayerUp.\n", fp->link->name);
+ if (ccp->in.state == NULL && ccp->in.algorithm >= 0 &&
+ ccp->in.algorithm < NALGORITHMS) {
+ ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt);
+ if (ccp->in.state == NULL) {
+ log_Printf(LogERROR, "%s: %s (in) initialisation failure\n",
+ fp->link->name, protoname(ccp->his_proto));
+ ccp->his_proto = ccp->my_proto = -1;
+ fsm_Close(fp);
+ }
}
-}
-void
-CcpUp()
-{
- FsmUp(&CcpFsm);
- LogPrintf(LogCCP, "CCP Up event!!\n");
-}
-
-void
-CcpOpen()
-{
- int f;
-
- for (f = 0; f < NALGORITHMS; f++)
- if (Enabled(algorithm[f]->Conf)) {
- CcpFsm.open_mode = 0;
- FsmOpen(&CcpFsm);
- break;
+ if (ccp->out.state == NULL && ccp->out.algorithm >= 0 &&
+ ccp->out.algorithm < NALGORITHMS) {
+ ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)
+ (&ccp->out.opt->val);
+ if (ccp->out.state == NULL) {
+ log_Printf(LogERROR, "%s: %s (out) initialisation failure\n",
+ fp->link->name, protoname(ccp->my_proto));
+ ccp->his_proto = ccp->my_proto = -1;
+ fsm_Close(fp);
}
+ }
- if (f == NALGORITHMS)
- for (f = 0; f < NALGORITHMS; f++)
- if (Acceptable(algorithm[f]->Conf)) {
- CcpFsm.open_mode = OPEN_PASSIVE;
- FsmOpen(&CcpFsm);
- break;
- }
+ log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n",
+ fp->link->name, protoname(ccp->my_proto), ccp->my_proto,
+ protoname(ccp->his_proto), ccp->his_proto);
+ return 1;
}
static void
-CcpDecodeConfig(u_char *cp, int plen, int mode_type)
+CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
+ struct fsm_decode *dec)
{
+ /* Deal with incoming data */
+ struct ccp *ccp = fsm2ccp(fp);
int type, length;
int f;
-
- ackp = AckBuff;
- nakp = NakBuff;
- rejp = RejBuff;
+ const char *end;
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
- if (type < NCFTYPES)
- LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length);
- else
- LogPrintf(LogCCP, " ???[%d]\n", length);
+
+ if (length == 0) {
+ log_Printf(LogCCP, "%s: CCP size zero\n", fp->link->name);
+ break;
+ }
+
+ if (length > sizeof(struct lcp_opt)) {
+ length = sizeof(struct lcp_opt);
+ log_Printf(LogCCP, "%s: Warning: Truncating length to %d\n",
+ fp->link->name, length);
+ }
for (f = NALGORITHMS-1; f > -1; f--)
if (algorithm[f]->id == type)
break;
+ end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp);
+ if (end == NULL)
+ end = "";
+
+ if (type < NCFTYPES)
+ log_Printf(LogCCP, " %s[%d] %s\n", cftypes[type], length, end);
+ else
+ log_Printf(LogCCP, " ???[%d] %s\n", length, end);
+
if (f == -1) {
/* Don't understand that :-( */
if (mode_type == MODE_REQ) {
- CcpInfo.my_reject |= (1 << type);
- memcpy(rejp, cp, length);
- rejp += length;
+ ccp->my_reject |= (1 << type);
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
}
} else {
- struct lcp_opt o;
+ struct ccp_opt *o;
switch (mode_type) {
case MODE_REQ:
- if (Acceptable(algorithm[f]->Conf) && in_algorithm == -1) {
- memcpy(&o, cp, length);
- switch ((*algorithm[f]->i.Set)(&o)) {
+ if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) &&
+ ccp->in.algorithm == -1) {
+ memcpy(&ccp->in.opt, cp, length);
+ switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) {
case MODE_REJ:
- memcpy(rejp, &o, o.len);
- rejp += o.len;
+ memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len);
+ dec->rejend += ccp->in.opt.len;
break;
case MODE_NAK:
- memcpy(nakp, &o, o.len);
- nakp += o.len;
+ memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len);
+ dec->nakend += ccp->in.opt.len;
break;
case MODE_ACK:
- memcpy(ackp, cp, length);
- ackp += length;
- CcpInfo.his_proto = type;
- in_algorithm = f; /* This one'll do ! */
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
+ ccp->his_proto = type;
+ ccp->in.algorithm = f; /* This one'll do :-) */
break;
}
} else {
- memcpy(rejp, cp, length);
- rejp += length;
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
}
break;
case MODE_NAK:
- memcpy(&o, cp, length);
- if ((*algorithm[f]->o.Set)(&o) == MODE_ACK)
- CcpInfo.my_proto = algorithm[f]->id;
+ for (o = ccp->out.opt; o != NULL; o = o->next)
+ if (o->val.id == cp[0])
+ break;
+ if (o == NULL)
+ log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent option\n",
+ fp->link->name);
else {
- CcpInfo.his_reject |= (1 << type);
- CcpInfo.my_proto = -1;
+ memcpy(&o->val, cp, length);
+ if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK)
+ ccp->my_proto = algorithm[f]->id;
+ else {
+ ccp->his_reject |= (1 << type);
+ ccp->my_proto = -1;
+ }
}
break;
case MODE_REJ:
- CcpInfo.his_reject |= (1 << type);
- CcpInfo.my_proto = -1;
+ ccp->his_reject |= (1 << type);
+ ccp->my_proto = -1;
break;
}
}
- plen -= length;
- cp += length;
+ plen -= cp[1];
+ cp += cp[1];
}
- if (rejp != RejBuff) {
- ackp = AckBuff; /* let's not send both ! */
- CcpInfo.his_proto = -1;
- in_algorithm = -1;
+ if (mode_type != MODE_NOP) {
+ if (dec->rejend != dec->rej) {
+ /* rejects are preferred */
+ dec->ackend = dec->ack;
+ dec->nakend = dec->nak;
+ if (ccp->in.state == NULL) {
+ ccp->his_proto = -1;
+ ccp->in.algorithm = -1;
+ }
+ } else if (dec->nakend != dec->nak) {
+ /* then NAKs */
+ dec->ackend = dec->ack;
+ if (ccp->in.state == NULL) {
+ ccp->his_proto = -1;
+ ccp->in.algorithm = -1;
+ }
+ }
}
}
void
-CcpInput(struct mbuf *bp)
+ccp_Input(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp)
{
- if (phase == PHASE_NETWORK)
- FsmInput(&CcpFsm, bp);
+ /* Got PROTO_CCP from link */
+ if (bundle_Phase(bundle) == PHASE_NETWORK)
+ fsm_Input(&ccp->fsm, bp);
else {
- if (phase > PHASE_NETWORK)
- LogPrintf(LogCCP, "Error: Unexpected CCP in phase %d\n", phase);
- pfree(bp);
+ if (bundle_Phase(bundle) < PHASE_NETWORK)
+ log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n",
+ ccp->fsm.link->name, bundle_PhaseName(bundle));
+ mbuf_Free(bp);
}
}
-void
-CcpResetInput(u_char id)
+static void
+CcpRecvResetAck(struct fsm *fp, u_char id)
{
- if (CcpInfo.reset_sent != -1) {
- if (id != CcpInfo.reset_sent) {
- LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n",
- id, CcpInfo.reset_sent);
+ /* Got a reset ACK, reset incoming dictionary */
+ struct ccp *ccp = fsm2ccp(fp);
+
+ if (ccp->reset_sent != -1) {
+ if (id != ccp->reset_sent) {
+ log_Printf(LogWARN, "CCP: %s: Incorrect ResetAck (id %d, not %d)"
+ " ignored\n", fp->link->name, id, ccp->reset_sent);
return;
}
/* Whaddaya know - a correct reset ack */
- } else if (id == CcpInfo.last_reset)
- LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n");
+ } else if (id == ccp->last_reset)
+ log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n",
+ fp->link->name);
else {
- LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id);
+ log_Printf(LogWARN, "CCP: %s: Unexpected ResetAck (id %d) ignored\n",
+ fp->link->name, id);
return;
}
- CcpInfo.last_reset = CcpInfo.reset_sent;
- CcpInfo.reset_sent = -1;
- if (in_algorithm >= 0 && in_algorithm < NALGORITHMS)
- (*algorithm[in_algorithm]->i.Reset)();
+ ccp->last_reset = ccp->reset_sent;
+ ccp->reset_sent = -1;
+ if (ccp->in.state != NULL)
+ (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state);
}
int
-CcpOutput(int pri, u_short proto, struct mbuf *m)
+ccp_Compress(struct ccp *ccp, struct link *l, int pri, u_short proto,
+ struct mbuf *m)
{
- if (out_algorithm >= 0 && out_algorithm < NALGORITHMS)
- return (*algorithm[out_algorithm]->o.Write)(pri, proto, m);
+ /*
+ * Compress outgoing data. It's already deemed to be suitable Network
+ * Layer data.
+ */
+ if (ccp->fsm.state == ST_OPENED && ccp->out.state != NULL)
+ return (*algorithm[ccp->out.algorithm]->o.Write)
+ (ccp->out.state, ccp, l, pri, proto, m);
return 0;
}
struct mbuf *
-CompdInput(u_short *proto, struct mbuf *m)
+ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp)
{
- if (CcpInfo.reset_sent != -1) {
- /* Send another REQ and put the packet in the bit bucket */
- LogPrintf(LogCCP, "ReSendResetReq(%d)\n", CcpInfo.reset_sent);
- FsmOutput(&CcpFsm, CODE_RESETREQ, CcpInfo.reset_sent, NULL, 0);
- } else if (in_algorithm >= 0 && in_algorithm < NALGORITHMS)
- return (*algorithm[in_algorithm]->i.Read)(proto, m);
- pfree(m);
- return NULL;
+ /*
+ * If proto isn't PROTO_[I]COMPD, we still want to pass it to the
+ * decompression routines so that the dictionary's updated
+ */
+ if (ccp->fsm.state == ST_OPENED) {
+ if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) {
+ /* Decompress incoming data */
+ if (ccp->reset_sent != -1)
+ /* Send another REQ and put the packet in the bit bucket */
+ fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0);
+ else if (ccp->in.state != NULL)
+ return (*algorithm[ccp->in.algorithm]->i.Read)
+ (ccp->in.state, ccp, proto, bp);
+ mbuf_Free(bp);
+ bp = NULL;
+ } else if (PROTO_COMPRESSIBLE(*proto) && ccp->in.state != NULL)
+ /* Add incoming Network Layer traffic to our dictionary */
+ (*algorithm[ccp->in.algorithm]->i.DictSetup)
+ (ccp->in.state, ccp, *proto, bp);
+ }
+
+ return bp;
}
-void
-CcpDictSetup(u_short proto, struct mbuf *m)
+u_short
+ccp_Proto(struct ccp *ccp)
{
- if (in_algorithm >= 0 && in_algorithm < NALGORITHMS)
- (*algorithm[in_algorithm]->i.DictSetup)(proto, m);
+ return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ?
+ PROTO_COMPD : PROTO_ICOMPD;
}
diff --git a/usr.sbin/ppp/ccp.h b/usr.sbin/ppp/ccp.h
index d84a2afd7c14..4652fd93a723 100644
--- a/usr.sbin/ppp/ccp.h
+++ b/usr.sbin/ppp/ccp.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ccp.h,v 1.13 1998/01/10 01:55:09 brian Exp $
+ * $Id: ccp.h,v 1.14.2.20 1998/05/01 19:24:00 brian Exp $
*
* TODO:
*/
@@ -35,58 +35,93 @@
#define TY_PPPD_DEFLATE 24 /* Deflate (gzip) - (mis) numbered by pppd */
#define TY_DEFLATE 26 /* Deflate (gzip) - rfc 1979 */
-struct ccpstate {
+#define CCP_NEG_DEFLATE 0
+#define CCP_NEG_PRED1 1
+#define CCP_NEG_DEFLATE24 2
+#define CCP_NEG_TOTAL 3
+
+struct mbuf;
+struct link;
+
+struct ccp_config {
+ struct {
+ struct {
+ int winsize;
+ } in, out;
+ } deflate;
+ u_int fsmretry; /* FSM retry frequency */
+ unsigned neg[CCP_NEG_TOTAL];
+};
+
+struct ccp_opt {
+ struct ccp_opt *next;
+ int algorithm;
+ struct lcp_opt val;
+};
+
+struct ccp {
+ struct fsm fsm; /* The finite state machine */
+
int his_proto; /* peer's compression protocol */
int my_proto; /* our compression protocol */
int reset_sent; /* If != -1, ignore compressed 'till ack */
int last_reset; /* We can receive more (dups) w/ this id */
+ struct {
+ int algorithm; /* Algorithm in use */
+ void *state; /* Returned by implementations Init() */
+ struct lcp_opt opt; /* Set by implementations OptInit() */
+ } in;
+
+ struct {
+ int algorithm; /* Algorithm in use */
+ void *state; /* Returned by implementations Init() */
+ struct ccp_opt *opt; /* Set by implementations OptInit() */
+ } out;
+
u_int32_t his_reject; /* Request codes rejected by peer */
u_int32_t my_reject; /* Request codes I have rejected */
- int out_init; /* Init called for out algorithm */
- int in_init; /* Init called for in algorithm */
-
u_long uncompout, compout;
u_long uncompin, compin;
+
+ struct ccp_config cfg;
};
-extern struct ccpstate CcpInfo;
+#define fsm2ccp(fp) (fp->proto == PROTO_CCP ? (struct ccp *)fp : NULL)
struct ccp_algorithm {
int id;
- int Conf; /* A Conf value from vars.h */
+ int Neg; /* ccp_config neg array item */
const char *(*Disp)(struct lcp_opt *);
struct {
- void (*Get)(struct lcp_opt *);
- int (*Set)(struct lcp_opt *);
- int (*Init)(void);
- void (*Term)(void);
- void (*Reset)(void);
- struct mbuf *(*Read)(u_short *, struct mbuf *);
- void (*DictSetup)(u_short, struct mbuf *);
+ int (*Set)(struct lcp_opt *, const struct ccp_config *);
+ void *(*Init)(struct lcp_opt *);
+ void (*Term)(void *);
+ void (*Reset)(void *);
+ struct mbuf *(*Read)(void *, struct ccp *, u_short *, struct mbuf *);
+ void (*DictSetup)(void *, struct ccp *, u_short, struct mbuf *);
} i;
struct {
- void (*Get)(struct lcp_opt *);
+ void (*OptInit)(struct lcp_opt *, const struct ccp_config *);
int (*Set)(struct lcp_opt *);
- int (*Init)(void);
- void (*Term)(void);
- void (*Reset)(void);
- int (*Write)(int, u_short, struct mbuf *);
+ void *(*Init)(struct lcp_opt *);
+ void (*Term)(void *);
+ void (*Reset)(void *);
+ int (*Write)(void *, struct ccp *, struct link *, int, u_short,
+ struct mbuf *);
} o;
};
-extern struct fsm CcpFsm;
-
-extern void CcpRecvResetReq(struct fsm *);
-extern void CcpSendResetReq(struct fsm *);
-extern void CcpInput(struct mbuf *);
-extern void CcpUp(void);
-extern void CcpOpen(void);
-extern void CcpInit(void);
-extern int ReportCcpStatus(struct cmdargs const *);
-extern void CcpResetInput(u_char);
-extern int CcpOutput(int, u_short, struct mbuf *);
-extern struct mbuf *CompdInput(u_short *, struct mbuf *);
-extern void CcpDictSetup(u_short, struct mbuf *);
+extern void ccp_Init(struct ccp *, struct bundle *, struct link *,
+ const struct fsm_parent *);
+extern void ccp_Setup(struct ccp *);
+
+extern void ccp_SendResetReq(struct fsm *);
+extern void ccp_Input(struct ccp *, struct bundle *, struct mbuf *);
+extern int ccp_ReportStatus(struct cmdargs const *);
+extern int ccp_Compress(struct ccp *, struct link *, int, u_short, struct mbuf *);
+extern struct mbuf *ccp_Decompress(struct ccp *, u_short *, struct mbuf *);
+extern u_short ccp_Proto(struct ccp *);
+extern void ccp_SetupCallbacks(struct ccp *);
diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c
index 870298fc7685..18c42ce536cc 100644
--- a/usr.sbin/ppp/chap.c
+++ b/usr.sbin/ppp/chap.c
@@ -17,53 +17,53 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: chap.c,v 1.29 1998/02/19 02:10:06 brian Exp $
+ * $Id: chap.c,v 1.28.2.27 1998/05/01 19:24:03 brian Exp $
*
* TODO:
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
-#include <ctype.h>
-#ifdef HAVE_DES
-#include <md4.h>
-#endif
#include <md5.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#ifdef __OpenBSD__
-#include <util.h>
-#else
-#include <libutil.h>
-#endif
-#include <utmp.h>
+#include <termios.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
-#include "chap.h"
-#include "chap_ms.h"
#include "lcpproto.h"
#include "lcp.h"
+#include "lqr.h"
#include "hdlc.h"
-#include "phase.h"
-#include "loadalias.h"
-#include "vars.h"
#include "auth.h"
-#include "id.h"
+#include "chap.h"
+#include "async.h"
+#include "throughput.h"
+#include "descriptor.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "ccp.h"
+#include "link.h"
+#include "physical.h"
+#include "mp.h"
+#include "bundle.h"
+#include "chat.h"
+#include "datalink.h"
static const char *chapcodes[] = {
"???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE"
};
static void
-ChapOutput(u_int code, u_int id, const u_char * ptr, int count)
+ChapOutput(struct physical *physical, u_int code, u_int id,
+ const u_char * ptr, int count)
{
int plen;
struct fsmheader lh;
@@ -73,42 +73,37 @@ ChapOutput(u_int code, u_int id, const u_char * ptr, int count)
lh.code = code;
lh.id = id;
lh.length = htons(plen);
- bp = mballoc(plen, MB_FSM);
+ bp = mbuf_Alloc(plen, MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
if (count)
memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
- LogDumpBp(LogDEBUG, "ChapOutput", bp);
- LogPrintf(LogLCP, "ChapOutput: %s\n", chapcodes[code]);
- HdlcOutput(PRI_LINK, PROTO_CHAP, bp);
+ log_DumpBp(LogDEBUG, "ChapOutput", bp);
+ log_Printf(LogLCP, "ChapOutput: %s\n", chapcodes[code]);
+ hdlc_Output(&physical->link, PRI_LINK, PROTO_CHAP, bp);
}
-
-static char challenge_data[80];
-static int challenge_len;
-
-static void
-SendChapChallenge(int chapid)
+void
+chap_SendChallenge(struct authinfo *auth, int chapid, struct physical *physical)
{
+ struct chap *chap = auth2chap(auth);
int len, i;
char *cp;
randinit();
- cp = challenge_data;
- *cp++ = challenge_len = random() % 32 + 16;
- for (i = 0; i < challenge_len; i++)
+ cp = chap->challenge_data;
+ *cp++ = chap->challenge_len = random() % 32 + 16;
+ for (i = 0; i < chap->challenge_len; i++)
*cp++ = random() & 0xff;
- len = strlen(VarAuthName);
- memcpy(cp, VarAuthName, len);
+ len = strlen(physical->dl->bundle->cfg.auth.name);
+ memcpy(cp, physical->dl->bundle->cfg.auth.name, len);
cp += len;
- ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data);
+ ChapOutput(physical, CHAP_CHALLENGE, chapid, chap->challenge_data,
+ cp - chap->challenge_data);
}
-struct authinfo AuthChapInfo = {
- SendChapChallenge,
-};
-
static void
-RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
+RecvChapTalk(struct bundle *bundle, struct fsmheader *chp, struct mbuf *bp,
+ struct physical *physical)
{
int valsize, len;
int arglen, keylen, namelen;
@@ -123,35 +118,35 @@ RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
#endif
len = ntohs(chp->length);
- LogPrintf(LogDEBUG, "RecvChapTalk: length: %d\n", len);
+ log_Printf(LogDEBUG, "RecvChapTalk: length: %d\n", len);
arglen = len - sizeof(struct fsmheader);
cp = (char *) MBUF_CTOP(bp);
valsize = *cp++ & 255;
name = cp + valsize;
namelen = arglen - valsize - 1;
name[namelen] = 0;
- LogPrintf(LogLCP, " Valsize = %d, Name = \"%s\"\n", valsize, name);
+ log_Printf(LogLCP, " Valsize = %d, Name = \"%s\"\n", valsize, name);
switch (chp->code) {
case CHAP_CHALLENGE:
- keyp = VarAuthKey;
- keylen = strlen(VarAuthKey);
- name = VarAuthName;
- namelen = strlen(VarAuthName);
+ keyp = bundle->cfg.auth.key;
+ keylen = strlen(bundle->cfg.auth.key);
+ name = bundle->cfg.auth.name;
+ namelen = strlen(bundle->cfg.auth.name);
#ifdef HAVE_DES
- if (VarMSChap)
+ if (physical->dl->chap.using_MSChap)
argp = malloc(1 + namelen + MS_CHAP_RESPONSE_LEN);
else
#endif
argp = malloc(1 + valsize + namelen + 16);
if (argp == NULL) {
- ChapOutput(CHAP_FAILURE, chp->id, "Out of memory!", 14);
+ ChapOutput(physical, CHAP_FAILURE, chp->id, "Out of memory!", 14);
return;
}
#ifdef HAVE_DES
- if (VarMSChap) {
+ if (physical->dl->chap.using_MSChap) {
digest = argp; /* this is the response */
*digest++ = MS_CHAP_RESPONSE_LEN; /* 49 */
memset(digest, '\0', 24);
@@ -161,7 +156,7 @@ RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
memcpy(ap, keyp, keylen);
ap += 2 * keylen;
memcpy(ap, cp, valsize);
- LogDumpBuff(LogDEBUG, "recv", ap, valsize);
+ log_DumpBuff(LogDEBUG, "recv", ap, valsize);
ap += valsize;
for (ix = keylen; ix > 0 ; ix--) {
answer[2*ix-2] = answer[ix-1];
@@ -172,9 +167,10 @@ RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
MD4Final(digest, &MD4context);
memcpy(digest + 25, name, namelen);
ap += 2 * keylen;
- ChapMS(digest, answer + 2 * keylen, valsize);
- LogDumpBuff(LogDEBUG, "answer", digest, 24);
- ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + MS_CHAP_RESPONSE_LEN + 1);
+ chap_MS(digest, answer + 2 * keylen, valsize);
+ log_DumpBuff(LogDEBUG, "answer", digest, 24);
+ ChapOutput(physical, CHAP_RESPONSE, chp->id, argp,
+ namelen + MS_CHAP_RESPONSE_LEN + 1);
} else {
#endif
digest = argp;
@@ -184,16 +180,16 @@ RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
memcpy(ap, keyp, keylen);
ap += keylen;
memcpy(ap, cp, valsize);
- LogDumpBuff(LogDEBUG, "recv", ap, valsize);
+ log_DumpBuff(LogDEBUG, "recv", ap, valsize);
ap += valsize;
MD5Init(&MD5context);
MD5Update(&MD5context, answer, ap - answer);
MD5Final(digest, &MD5context);
- LogDumpBuff(LogDEBUG, "answer", digest, 16);
+ log_DumpBuff(LogDEBUG, "answer", digest, 16);
memcpy(digest + 16, name, namelen);
ap += namelen;
/* Send answer to the peer */
- ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17);
+ ChapOutput(physical, CHAP_RESPONSE, chp->id, argp, namelen + 17);
#ifdef HAVE_DES
}
#endif
@@ -203,7 +199,7 @@ RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
/*
* Get a secret key corresponds to the peer
*/
- keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE);
+ keyp = auth_GetSecret(bundle, name, namelen, physical);
if (keyp) {
/*
* Compute correct digest value
@@ -215,31 +211,28 @@ RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
ap += keylen;
MD5Init(&MD5context);
MD5Update(&MD5context, answer, ap - answer);
- MD5Update(&MD5context, challenge_data + 1, challenge_len);
+ MD5Update(&MD5context, physical->dl->chap.challenge_data + 1,
+ physical->dl->chap.challenge_len);
MD5Final(cdigest, &MD5context);
- LogDumpBuff(LogDEBUG, "got", cp, 16);
- LogDumpBuff(LogDEBUG, "expect", cdigest, 16);
+ log_DumpBuff(LogDEBUG, "got", cp, 16);
+ log_DumpBuff(LogDEBUG, "expect", cdigest, 16);
/*
* Compare with the response
*/
if (memcmp(cp, cdigest, 16) == 0) {
- ChapOutput(CHAP_SUCCESS, chp->id, "Welcome!!", 10);
- if ((mode & MODE_DIRECT) && isatty(modem) && Enabled(ConfUtmp)) {
- if (Utmp)
- LogPrintf(LogERROR, "Oops, already logged in on %s\n",
- VarBaseDevice);
- else {
- struct utmp ut;
- memset(&ut, 0, sizeof ut);
- time(&ut.ut_time);
- strncpy(ut.ut_name, name, sizeof ut.ut_name);
- strncpy(ut.ut_line, VarBaseDevice, sizeof ut.ut_line - 1);
- ID0login(&ut);
- Utmp = 1;
- }
- }
- NewPhase(PHASE_NETWORK);
+ datalink_GotAuthname(physical->dl, name, namelen);
+ ChapOutput(physical, CHAP_SUCCESS, chp->id, "Welcome!!", 10);
+ if (Enabled(bundle, OPT_UTMP))
+ physical_Login(physical, name);
+
+ if (physical->link.lcp.auth_iwait == 0)
+ /*
+ * Either I didn't need to authenticate, or I've already been
+ * told that I got the answer right.
+ */
+ datalink_AuthOk(physical->dl);
+
break;
}
}
@@ -247,40 +240,42 @@ RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
/*
* Peer is not registerd, or response digest is wrong.
*/
- ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9);
- reconnect(RECON_FALSE);
- LcpClose();
+ ChapOutput(physical, CHAP_FAILURE, chp->id, "Invalid!!", 9);
+ datalink_AuthNotOk(physical->dl);
break;
}
}
static void
-RecvChapResult(struct fsmheader *chp, struct mbuf *bp)
+RecvChapResult(struct bundle *bundle, struct fsmheader *chp, struct mbuf *bp,
+ struct physical *physical)
{
int len;
- struct lcpstate *lcp = &LcpInfo;
len = ntohs(chp->length);
- LogPrintf(LogDEBUG, "RecvChapResult: length: %d\n", len);
+ log_Printf(LogDEBUG, "RecvChapResult: length: %d\n", len);
if (chp->code == CHAP_SUCCESS) {
- if (lcp->auth_iwait == PROTO_CHAP) {
- lcp->auth_iwait = 0;
- if (lcp->auth_ineed == 0)
- NewPhase(PHASE_NETWORK);
+ if (physical->link.lcp.auth_iwait == PROTO_CHAP) {
+ physical->link.lcp.auth_iwait = 0;
+ if (physical->link.lcp.auth_ineed == 0)
+ /*
+ * We've succeeded in our ``login''
+ * If we're not expecting the peer to authenticate (or he already
+ * has), proceed to network phase.
+ */
+ datalink_AuthOk(physical->dl);
}
} else {
-
- /*
- * Maybe, we shoud close LCP. Of cause, peer may take close action, too.
- */
- ;
+ /* CHAP failed - it's not going to get any better */
+ log_Printf(LogPHASE, "Received CHAP_FAILURE\n");
+ datalink_AuthNotOk(physical->dl);
}
}
void
-ChapInput(struct mbuf *bp)
+chap_Input(struct bundle *bundle, struct mbuf *bp, struct physical *physical)
{
- int len = plength(bp);
+ int len = mbuf_Length(bp);
struct fsmheader *chp;
if (len >= sizeof(struct fsmheader)) {
@@ -288,24 +283,24 @@ ChapInput(struct mbuf *bp)
if (len >= ntohs(chp->length)) {
if (chp->code < 1 || chp->code > 4)
chp->code = 0;
- LogPrintf(LogLCP, "ChapInput: %s\n", chapcodes[chp->code]);
+ log_Printf(LogLCP, "chap_Input: %s\n", chapcodes[chp->code]);
bp->offset += sizeof(struct fsmheader);
bp->cnt -= sizeof(struct fsmheader);
switch (chp->code) {
case CHAP_RESPONSE:
- StopAuthTimer(&AuthChapInfo);
+ auth_StopTimer(&physical->dl->chap.auth);
/* Fall into.. */
case CHAP_CHALLENGE:
- RecvChapTalk(chp, bp);
+ RecvChapTalk(bundle, chp, bp, physical);
break;
case CHAP_SUCCESS:
case CHAP_FAILURE:
- RecvChapResult(chp, bp);
+ RecvChapResult(bundle, chp, bp, physical);
break;
}
}
}
- pfree(bp);
+ mbuf_Free(bp);
}
diff --git a/usr.sbin/ppp/chap.h b/usr.sbin/ppp/chap.h
index ba178b6dab80..c5043543aa16 100644
--- a/usr.sbin/ppp/chap.h
+++ b/usr.sbin/ppp/chap.h
@@ -15,16 +15,28 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: chap.h,v 1.8 1997/10/26 01:02:19 brian Exp $
+ * $Id: chap.h,v 1.9.2.6 1998/05/01 19:24:05 brian Exp $
*
* TODO:
*/
+struct mbuf;
+struct physical;
+struct bundle;
+
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
#define CHAP_FAILURE 4
-extern struct authinfo AuthChapInfo;
+struct chap {
+ struct authinfo auth;
+ char challenge_data[80];
+ int challenge_len;
+ unsigned using_MSChap : 1; /* A combination of MD4 & DES */
+};
+
+#define auth2chap(a) ((struct chap *)(a))
-extern void ChapInput(struct mbuf *);
+extern void chap_Input(struct bundle *, struct mbuf *, struct physical *);
+extern void chap_SendChallenge(struct authinfo *, int, struct physical *);
diff --git a/usr.sbin/ppp/chap_ms.c b/usr.sbin/ppp/chap_ms.c
index 5ae1d2942c74..2649706e1c05 100644
--- a/usr.sbin/ppp/chap_ms.c
+++ b/usr.sbin/ppp/chap_ms.c
@@ -19,28 +19,24 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: chap_ms.c,v 1.4 1997/12/24 09:28:53 brian Exp $
+ * $Id: chap_ms.c,v 1.5.4.3 1998/05/01 19:24:07 brian Exp $
*
*/
#include <sys/types.h>
#include <des.h>
-#include <stdio.h>
#include <string.h>
-#include <sys/time.h>
-#include "command.h"
-#include "mbuf.h"
#include "chap_ms.h"
/* unused, for documentation only */
/* only NTResp is filled in for FreeBSD */
-typedef struct {
+struct MS_ChapResponse {
u_char LANManResp[24];
u_char NTResp[24];
u_char UseNT; /* If 1, ignore the LANMan response field */
-} MS_ChapResponse;
+};
static void DesEncrypt(u_char *, u_char *, u_char *);
static void MakeKey(u_char *, u_char *);
@@ -101,7 +97,7 @@ static void MakeKey(u_char *key, u_char *des_key)
challenge 8-bytes peer CHAP challenge
since passwordHash is in a 24-byte buffer, response is written in there */
void
-ChapMS(char *passwordHash, char *challenge, int challenge_len)
+chap_MS(char *passwordHash, char *challenge, int challenge_len)
{
u_char response[24];
diff --git a/usr.sbin/ppp/chap_ms.h b/usr.sbin/ppp/chap_ms.h
index 0f6c3182634d..19538983a39f 100644
--- a/usr.sbin/ppp/chap_ms.h
+++ b/usr.sbin/ppp/chap_ms.h
@@ -19,7 +19,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: chap_ms.h,v 1.1 1997/09/25 00:58:20 brian Exp $
+ * $Id: chap_ms.h,v 1.2.4.1 1998/05/01 19:24:08 brian Exp $
*/
/* Max # of (Unicode) chars in an NT password */
@@ -28,4 +28,4 @@
/* Don't rely on sizeof(MS_ChapResponse) in case of struct padding */
#define MS_CHAP_RESPONSE_LEN 49
-extern void ChapMS(char *, char *, int);
+extern void chap_MS(char *, char *, int);
diff --git a/usr.sbin/ppp/chat.c b/usr.sbin/ppp/chat.c
index 61d9877ebe22..3791cbad8d99 100644
--- a/usr.sbin/ppp/chat.c
+++ b/usr.sbin/ppp/chat.c
@@ -1,73 +1,562 @@
-/*
- * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
- *
- * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
- *
- * Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com).
- *
- * Chat -- a program for automatic session establishment (i.e. dial
- * the phone and log in).
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
*
- * This software is in the public domain.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * Please send all bug reports, requests for information, etc. to:
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*
- * Karl Fox <karl@MorningStar.Com>
- * Morning Star Technologies, Inc.
- * 1760 Zollinger Road
- * Columbus, OH 43221
- * (614)451-1883
- *
- * $Id: chat.c,v 1.43 1997/12/27 07:22:11 brian Exp $
- *
- * TODO:
- * o Support more UUCP compatible control sequences.
- * o Dialing shoud not block monitor process.
- * o Reading modem by select should be unified into main.c
+ * $Id: chat.c,v 1.44.2.29 1998/05/01 19:24:11 brian Exp $
*/
-#include <sys/param.h>
+
+#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
-#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#include <setjmp.h>
+#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/time.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
-#include "loadalias.h"
-#include "vars.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "throughput.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "async.h"
+#include "descriptor.h"
+#include "physical.h"
#include "chat.h"
-#include "modem.h"
+#include "mp.h"
+#include "auth.h"
+#include "chap.h"
+#include "slcompress.h"
+#include "iplist.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "datalink.h"
+#include "bundle.h"
+
+#define BUFLEFT(c) (sizeof (c)->buf - ((c)->bufend - (c)->buf))
+#define issep(c) ((c) == '\t' || (c) == ' ')
+
+static void ExecStr(struct physical *, char *, char *, int);
+static char *ExpandString(struct chat *, const char *, char *, int, int);
+
+static void
+chat_PauseTimer(void *v)
+{
+ struct chat *c = (struct chat *)v;
+ timer_Stop(&c->pause);
+ c->pause.load = 0;
+}
+
+static void
+chat_Pause(struct chat *c, u_long load)
+{
+ timer_Stop(&c->pause);
+ c->pause.load += load;
+ c->pause.func = chat_PauseTimer;
+ c->pause.name = "chat pause";
+ c->pause.arg = c;
+ timer_Start(&c->pause);
+}
+
+static void
+chat_TimeoutTimer(void *v)
+{
+ struct chat *c = (struct chat *)v;
+ timer_Stop(&c->timeout);
+ c->TimedOut = 1;
+}
+
+static void
+chat_SetTimeout(struct chat *c)
+{
+ timer_Stop(&c->timeout);
+ if (c->TimeoutSec > 0) {
+ c->timeout.load = SECTICKS * c->TimeoutSec;
+ c->timeout.func = chat_TimeoutTimer;
+ c->timeout.name = "chat timeout";
+ c->timeout.arg = c;
+ timer_Start(&c->timeout);
+ }
+}
+
+static char *
+chat_NextChar(char *ptr, char ch)
+{
+ for (; *ptr; ptr++)
+ if (*ptr == ch)
+ return ptr;
+ else if (*ptr == '\\')
+ if (*++ptr == '\0')
+ return NULL;
+
+ return NULL;
+}
+
+static int
+chat_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
+{
+ struct chat *c = descriptor2chat(d);
+ int special, gotabort, gottimeout, needcr;
+ int TimedOut = c->TimedOut;
+ static char arg_term;
+
+ if (c->pause.state == TIMER_RUNNING)
+ return 0;
+
+ if (TimedOut) {
+ log_Printf(LogCHAT, "Expect timeout\n");
+ if (c->nargptr == NULL)
+ c->state = CHAT_FAILED;
+ else {
+ /* c->state = CHAT_EXPECT; */
+ c->argptr = &arg_term;
+ }
+ c->TimedOut = 0;
+ }
+
+ if (c->state != CHAT_EXPECT && c->state != CHAT_SEND)
+ return 0;
+
+ gottimeout = gotabort = 0;
+
+ if (c->arg < c->argc && (c->arg < 0 || *c->argptr == '\0')) {
+ /* Go get the next string */
+ if (c->arg < 0 || c->state == CHAT_SEND)
+ c->state = CHAT_EXPECT;
+ else
+ c->state = CHAT_SEND;
+
+ special = 1;
+ while (special && (c->nargptr || c->arg < c->argc - 1)) {
+ if (c->arg < 0 || (!TimedOut && c->state == CHAT_SEND))
+ c->nargptr = NULL;
+
+ if (c->nargptr != NULL) {
+ /* We're doing expect-send-expect.... */
+ c->argptr = c->nargptr;
+ /* Put the '-' back in case we ever want to rerun our script */
+ c->nargptr[-1] = '-';
+ c->nargptr = chat_NextChar(c->nargptr, '-');
+ if (c->nargptr != NULL)
+ *c->nargptr++ = '\0';
+ } else {
+ int minus;
+
+ c->argptr = c->argv[++c->arg];
+
+ if (c->state == CHAT_EXPECT) {
+ /* Look for expect-send-expect sequence */
+ c->nargptr = c->argptr;
+ minus = 0;
+ while ((c->nargptr = chat_NextChar(c->nargptr, '-'))) {
+ c->nargptr++;
+ minus++;
+ }
+
+ if (minus % 2)
+ log_Printf(LogWARN, "chat_UpdateSet: \"%s\": Uneven number of"
+ " '-' chars, all ignored\n", c->argptr);
+ else if (minus) {
+ c->nargptr = chat_NextChar(c->argptr, '-');
+ *c->nargptr++ = '\0';
+ }
+ }
+ }
+
+ /*
+ * c->argptr now temporarily points into c->script (via c->argv)
+ * If it's an expect-send-expect sequence, we've just got the correct
+ * portion of that sequence.
+ */
+
+ needcr = c->state == CHAT_SEND && *c->argptr != '!';
+
+ /* We leave room for a potential HDLC header in the target string */
+ ExpandString(c, c->argptr, c->exp + 2, sizeof c->exp - 2, needcr);
+
+ if (gotabort) {
+ if (c->abort.num < MAXABORTS) {
+ int len, i;
+
+ len = strlen(c->exp+2);
+ for (i = 0; i < c->abort.num; i++)
+ if (len > c->abort.string[i].len) {
+ int last;
+
+ for (last = c->abort.num; last > i; last--) {
+ c->abort.string[last].data = c->abort.string[last-1].data;
+ c->abort.string[last].len = c->abort.string[last-1].len;
+ }
+ break;
+ }
+ c->abort.string[i].len = len;
+ c->abort.string[i].data = (char *)malloc(len+1);
+ memcpy(c->abort.string[i].data, c->exp+2, len+1);
+ c->abort.num++;
+ } else
+ log_Printf(LogERROR, "chat_UpdateSet: too many abort strings\n");
+ gotabort = 0;
+ } else if (gottimeout) {
+ c->TimeoutSec = atoi(c->exp + 2);
+ if (c->TimeoutSec <= 0)
+ c->TimeoutSec = 30;
+ gottimeout = 0;
+ } else if (c->nargptr == NULL && !strcmp(c->exp+2, "ABORT"))
+ gotabort = 1;
+ else if (c->nargptr == NULL && !strcmp(c->exp+2, "TIMEOUT"))
+ gottimeout = 1;
+ else {
+ if (c->exp[2] == '!')
+ ExecStr(c->physical, c->exp + 3, c->exp + 2, sizeof c->exp - 2);
+
+ if (c->exp[2] == '\0') {
+ /* Empty string, reparse (this may be better as a `goto start') */
+ c->argptr = &arg_term;
+ return chat_UpdateSet(d, r, w, e, n);
+ }
+
+ special = 0;
+ }
+ }
+
+ if (special) {
+ if (gottimeout)
+ log_Printf(LogWARN, "chat_UpdateSet: TIMEOUT: Argument expected\n");
+ else if (gotabort)
+ log_Printf(LogWARN, "chat_UpdateSet: ABORT: Argument expected\n");
+
+ /* End of script - all ok */
+ c->state = CHAT_DONE;
+ return 0;
+ }
+
+ /* set c->argptr to point in the right place */
+ c->argptr = c->exp + 2;
+ c->arglen = strlen(c->argptr);
+
+ if (c->state == CHAT_EXPECT) {
+ /* We must check to see if the string's already been found ! */
+ char *begin, *end;
+
+ end = c->bufend - c->arglen + 1;
+ if (end < c->bufstart)
+ end = c->bufstart;
+ for (begin = c->bufstart; begin < end; begin++)
+ if (!strncmp(begin, c->argptr, c->arglen)) {
+ c->bufstart = begin + c->arglen;
+ c->argptr += c->arglen;
+ c->arglen = 0;
+ /* Continue - we've already read our expect string */
+ return chat_UpdateSet(d, r, w, e, n);
+ }
+
+ log_Printf(LogCHAT, "Expect(%d): %s\n", c->TimeoutSec, c->argptr);
+ chat_SetTimeout(c);
+ }
+ }
+
+ /*
+ * We now have c->argptr pointing at what we want to expect/send and
+ * c->state saying what we want to do... we now know what to put in
+ * the fd_set :-)
+ */
+
+ if (c->state == CHAT_EXPECT)
+ return physical_UpdateSet(&c->physical->desc, r, NULL, e, n, 1);
+ else
+ return physical_UpdateSet(&c->physical->desc, NULL, w, e, n, 1);
+}
+
+static int
+chat_IsSet(struct descriptor *d, const fd_set *fdset)
+{
+ struct chat *c = descriptor2chat(d);
+ return physical_IsSet(&c->physical->desc, fdset);
+}
+
+static void
+chat_UpdateLog(struct chat *c, int in)
+{
+ if (log_IsKept(LogCHAT) || log_IsKept(LogCONNECT)) {
+ /*
+ * If a linefeed appears in the last `in' characters of `c's input
+ * buffer, output from there, all the way back to the last linefeed.
+ * This is called for every read of `in' bytes.
+ */
+ char *ptr, *end, *stop, ch;
+ int level;
+
+ level = log_IsKept(LogCHAT) ? LogCHAT : LogCONNECT;
+ if (in == -1)
+ end = ptr = c->bufend;
+ else {
+ ptr = c->bufend - in;
+ for (end = c->bufend - 1; end >= ptr; end--)
+ if (*end == '\n')
+ break;
+ }
+
+ if (end >= ptr) {
+ for (ptr = c->bufend - (in == -1 ? 1 : in + 1); ptr >= c->bufstart; ptr--)
+ if (*ptr == '\n')
+ break;
+ ptr++;
+ stop = NULL;
+ while (stop < end) {
+ if ((stop = memchr(ptr, '\n', end - ptr)) == NULL)
+ stop = end;
+ ch = *stop;
+ *stop = '\0';
+ if (level == LogCHAT || strstr(ptr, "CONNECT"))
+ log_Printf(level, "Received: %s\n", ptr);
+ *stop = ch;
+ ptr = stop + 1;
+ }
+ }
+ }
+}
+
+static void
+chat_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ struct chat *c = descriptor2chat(d);
+
+ if (c->state == CHAT_EXPECT) {
+ ssize_t in;
+ char *abegin, *ebegin, *begin, *aend, *eend, *end;
+ int n;
+
+ /*
+ * XXX - should this read only 1 byte to guarantee that we don't
+ * swallow any ppp talk from the peer ?
+ */
+ in = BUFLEFT(c);
+ if (in > sizeof c->buf / 2)
+ in = sizeof c->buf / 2;
+
+ in = physical_Read(c->physical, c->bufend, in);
+ if (in <= 0)
+ return;
+
+ /* `begin' and `end' delimit where we're going to strncmp() from */
+ ebegin = c->bufend - c->arglen + 1;
+ eend = ebegin + in;
+ if (ebegin < c->bufstart)
+ ebegin = c->bufstart;
+
+ if (c->abort.num) {
+ abegin = c->bufend - c->abort.string[0].len + 1;
+ aend = c->bufend - c->abort.string[c->abort.num-1].len + in + 1;
+ if (abegin < c->bufstart)
+ abegin = c->bufstart;
+ } else {
+ abegin = ebegin;
+ aend = eend;
+ }
+ begin = abegin < ebegin ? abegin : ebegin;
+ end = aend < eend ? eend : aend;
+
+ c->bufend += in;
+
+ chat_UpdateLog(c, in);
+
+ if (c->bufend > c->buf + sizeof c->buf / 2) {
+ /* Shuffle our receive buffer back a bit */
+ int chop;
+
+ for (chop = begin - c->buf; chop; chop--)
+ if (c->buf[chop] == '\n')
+ /* found some already-logged garbage to remove :-) */
+ break;
+
+ if (!chop)
+ chop = begin - c->buf;
+
+ if (chop) {
+ char *from, *to;
+
+ to = c->buf;
+ from = to + chop;
+ while (from < c->bufend)
+ *to++ = *from++;
+ c->bufstart -= chop;
+ c->bufend -= chop;
+ begin -= chop;
+ end -= chop;
+ abegin -= chop;
+ aend -= chop;
+ ebegin -= chop;
+ eend -= chop;
+ }
+ }
+
+ for (; begin < end; begin++)
+ if (begin >= ebegin && begin < eend &&
+ !strncmp(begin, c->argptr, c->arglen)) {
+ /* Got it ! */
+ if (memchr(begin + c->arglen - 1, '\n',
+ c->bufend - begin - c->arglen + 1) == NULL) {
+ /* force it into the log */
+ end = c->bufend;
+ c->bufend = begin + c->arglen;
+ chat_UpdateLog(c, -1);
+ c->bufend = end;
+ }
+ c->bufstart = begin + c->arglen;
+ c->argptr += c->arglen;
+ c->arglen = 0;
+ break;
+ } else if (begin >= abegin && begin < aend) {
+ for (n = c->abort.num - 1; n >= 0; n--) {
+ if (begin + c->abort.string[n].len > c->bufend)
+ break;
+ if (!strncmp(begin, c->abort.string[n].data,
+ c->abort.string[n].len)) {
+ if (memchr(begin + c->abort.string[n].len - 1, '\n',
+ c->bufend - begin - c->abort.string[n].len + 1) == NULL) {
+ /* force it into the log */
+ end = c->bufend;
+ c->bufend = begin + c->abort.string[n].len;
+ chat_UpdateLog(c, -1);
+ c->bufend = end;
+ }
+ c->bufstart = begin + c->abort.string[n].len;
+ c->state = CHAT_FAILED;
+ return;
+ }
+ }
+ }
+ }
+}
+
+static void
+chat_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ struct chat *c = descriptor2chat(d);
+
+ if (c->state == CHAT_SEND) {
+ int wrote;
+
+ if (strstr(c->argv[c->arg], "\\P")) /* Don't log the password */
+ log_Printf(LogCHAT, "Send: %s\n", c->argv[c->arg]);
+ else {
+ int sz;
+
+ sz = c->arglen - 1;
+ while (sz >= 0 && c->argptr[sz] == '\n')
+ sz--;
+ log_Printf(LogCHAT, "Send: %.*s\n", sz + 1, c->argptr);
+ }
+
+ if (physical_IsSync(c->physical)) {
+ /* There's always room for the HDLC header */
+ c->argptr -= 2;
+ c->arglen += 2;
+ memcpy(c->argptr, "\377\003", 2); /* Prepend HDLC header */
+ }
+
+ wrote = physical_Write(c->physical, c->argptr, c->arglen);
+ if (wrote == -1) {
+ if (errno != EINTR)
+ log_Printf(LogERROR, "chat_Write: %s\n", strerror(errno));
+ if (physical_IsSync(c->physical)) {
+ c->argptr += 2;
+ c->arglen -= 2;
+ }
+ } else if (wrote < 2 && physical_IsSync(c->physical)) {
+ /* Oops - didn't even write our HDLC header ! */
+ c->argptr += 2;
+ c->arglen -= 2;
+ } else {
+ c->argptr += wrote;
+ c->arglen -= wrote;
+ }
+ }
+}
+
+void
+chat_Init(struct chat *c, struct physical *p, const char *data, int emptybuf,
+ const char *phone)
+{
+ c->desc.type = CHAT_DESCRIPTOR;
+ c->desc.next = NULL;
+ c->desc.UpdateSet = chat_UpdateSet;
+ c->desc.IsSet = chat_IsSet;
+ c->desc.Read = chat_Read;
+ c->desc.Write = chat_Write;
+ c->physical = p;
+
+ c->state = CHAT_EXPECT;
+
+ if (data == NULL) {
+ *c->script = '\0';
+ c->argc = 0;
+ } else {
+ strncpy(c->script, data, sizeof c->script - 1);
+ c->script[sizeof c->script - 1] = '\0';
+ c->argc = MakeArgs(c->script, c->argv, VECSIZE(c->argv));
+ }
-#ifndef isblank
-#define isblank(c) ((c) == '\t' || (c) == ' ')
-#endif
+ c->arg = -1;
+ c->argptr = NULL;
+ c->nargptr = NULL;
+ if (emptybuf)
+ c->bufstart = c->bufend = c->buf;
-#define IBSIZE LINE_LEN
+ c->TimeoutSec = 30;
+ c->TimedOut = 0;
+ c->phone = phone;
+ c->abort.num = 0;
-static int TimeoutSec;
-static int abort_next, timeout_next;
-static int numaborts;
-static char *AbortStrings[50];
-static char inbuff[IBSIZE * 2 + 1];
-static jmp_buf ChatEnv;
+ memset(&c->pause, '\0', sizeof c->pause);
+ memset(&c->timeout, '\0', sizeof c->timeout);
+}
-#define MATCH 1
-#define NOMATCH 0
-#define ABORT -1
+void
+chat_Destroy(struct chat *c)
+{
+ timer_Stop(&c->pause);
+ timer_Stop(&c->timeout);
+ while (c->abort.num)
+ free(c->abort.string[--c->abort.num].data);
+ c->abort.num = 0;
+}
static char *
findblank(char *p, int instring)
@@ -84,7 +573,7 @@ findblank(char *p, int instring)
}
} else {
while (*p) {
- if (isblank(*p))
+ if (issep(*p))
return (p);
p++;
}
@@ -136,11 +625,11 @@ MakeArgs(char *script, char **pvect, int maxargs)
* \t Tab character
* \U Auth User
*/
-char *
-ExpandString(const char *str, char *result, int reslen, int sendmode)
+static char *
+ExpandString(struct chat *c, const char *str, char *result, int reslen,
+ int sendmode)
{
int addcr = 0;
- char *phone;
result[--reslen] = '\0';
if (sendmode)
@@ -155,10 +644,10 @@ ExpandString(const char *str, char *result, int reslen, int sendmode)
addcr = 0;
break;
case 'd': /* Delay 2 seconds */
- nointr_sleep(2);
+ chat_Pause(c, 2 * SECTICKS);
break;
case 'p':
- nointr_usleep(250000);
+ chat_Pause(c, SECTICKS / 4);
break; /* Pause 0.25 sec */
case 'n':
*result++ = '\n';
@@ -177,29 +666,17 @@ ExpandString(const char *str, char *result, int reslen, int sendmode)
reslen--;
break;
case 'P':
- strncpy(result, VarAuthKey, reslen);
+ strncpy(result, c->physical->dl->bundle->cfg.auth.key, reslen);
reslen -= strlen(result);
result += strlen(result);
break;
case 'T':
- if (VarAltPhone == NULL) {
- if (VarNextPhone == NULL) {
- strncpy(VarPhoneCopy, VarPhoneList, sizeof VarPhoneCopy - 1);
- VarPhoneCopy[sizeof VarPhoneCopy - 1] = '\0';
- VarNextPhone = VarPhoneCopy;
- }
- VarAltPhone = strsep(&VarNextPhone, ":");
- }
- phone = strsep(&VarAltPhone, "|");
- strncpy(result, phone, reslen);
- reslen -= strlen(result);
- result += strlen(result);
- if (VarTerm)
- fprintf(VarTerm, "Phone: %s\n", phone);
- LogPrintf(LogPHASE, "Phone: %s\n", phone);
+ strncpy(result, c->phone, reslen);
+ reslen -= strlen(result);
+ result += strlen(result);
break;
case 'U':
- strncpy(result, VarAuthName, reslen);
+ strncpy(result, c->physical->dl->bundle->cfg.auth.name, reslen);
reslen -= strlen(result);
result += strlen(result);
break;
@@ -233,84 +710,35 @@ ExpandString(const char *str, char *result, int reslen, int sendmode)
return (result);
}
-#define MAXLOGBUFF LINE_LEN
-static char logbuff[MAXLOGBUFF];
-static int loglen = 0;
-
-static void
-clear_log(void)
-{
- memset(logbuff, 0, MAXLOGBUFF);
- loglen = 0;
-}
-
-static void
-flush_log(void)
-{
- if (LogIsKept(LogCONNECT))
- LogPrintf(LogCONNECT, "%s\n", logbuff);
- else if (LogIsKept(LogCARRIER) && strstr(logbuff, "CARRIER"))
- LogPrintf(LogCARRIER, "%s\n", logbuff);
-
- clear_log();
-}
-
-static void
-connect_log(const char *str, int single_p)
-{
- int space = MAXLOGBUFF - loglen - 1;
-
- while (space--) {
- if (*str == '\n') {
- flush_log();
- } else {
- logbuff[loglen++] = *str;
- }
- if (single_p || !*++str)
- break;
- }
- if (!space)
- flush_log();
-}
-
static void
-ExecStr(char *command, char *out, int olen)
+ExecStr(struct physical *physical, char *command, char *out, int olen)
{
pid_t pid;
int fids[2];
char *vector[MAXARGS], *startout, *endout;
int stat, nb;
- LogPrintf(LogCHAT, "Exec: %s\n", command);
+ log_Printf(LogCHAT, "Exec: %s\n", command);
MakeArgs(command, vector, VECSIZE(vector));
if (pipe(fids) < 0) {
- LogPrintf(LogCHAT, "Unable to create pipe in ExecStr: %s\n",
+ log_Printf(LogCHAT, "Unable to create pipe in ExecStr: %s\n",
strerror(errno));
- longjmp(ChatEnv, 2);
+ *out = '\0';
+ return;
}
if ((pid = fork()) == 0) {
- TermTimerService();
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- signal(SIGALRM, SIG_DFL);
- if (modem == 2) {
- int nmodem;
- nmodem = dup(modem);
- close(modem);
- modem = nmodem;
- }
- close(fids[0]);
- dup2(fids[1], 2);
- close(fids[1]);
- dup2(modem, 0);
- dup2(modem, 1);
- if ((nb = open("/dev/tty", O_RDWR)) > 3) {
- dup2(nb, 3);
- close(nb);
- }
+ timer_TermService();
+
+ fids[1] = fcntl(fids[1], F_DUPFD, 4);
+ dup2(physical_GetFD(physical), STDIN_FILENO);
+ dup2(STDIN_FILENO, STDOUT_FILENO);
+ dup2(fids[1], STDERR_FILENO);
+ close(3);
+ if (open(_PATH_TTY, O_RDWR) == 3)
+ fcntl(3, F_SETFD, 0); /* Clear close-on-exec flag */
+ else
+ fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */
setuid(geteuid());
execvp(vector[0], vector);
fprintf(stderr, "execvp failed: %s: %s\n", vector[0], strerror(errno));
@@ -332,347 +760,33 @@ ExecStr(char *command, char *out, int olen)
close(fids[1]);
waitpid(pid, &stat, WNOHANG);
if (WIFSIGNALED(stat)) {
- LogPrintf(LogWARN, "%s: signal %d\n", name, WTERMSIG(stat));
+ log_Printf(LogWARN, "%s: signal %d\n", name, WTERMSIG(stat));
free(name);
- longjmp(ChatEnv, 3);
+ *out = '\0';
+ return;
} else if (WIFEXITED(stat)) {
switch (WEXITSTATUS(stat)) {
case 0:
free(name);
break;
case 127:
- LogPrintf(LogWARN, "%s: %s\n", name, startout);
+ log_Printf(LogWARN, "%s: %s\n", name, startout);
free(name);
- longjmp(ChatEnv, 4);
+ *out = '\0';
+ return;
break;
default:
- LogPrintf(LogWARN, "%s: exit %d\n", name, WEXITSTATUS(stat));
+ log_Printf(LogWARN, "%s: exit %d\n", name, WEXITSTATUS(stat));
free(name);
- longjmp(ChatEnv, 5);
+ *out = '\0';
+ return;
break;
}
} else {
- LogPrintf(LogWARN, "%s: Unexpected exit result\n", name);
+ log_Printf(LogWARN, "%s: Unexpected exit result\n", name);
free(name);
- longjmp(ChatEnv, 6);
- }
- }
-}
-
-static int
-WaitforString(const char *estr)
-{
- struct timeval timeout;
- char *s, *str, ch;
- char *inp;
- fd_set rfds;
- int i, nfds, nb;
- char buff[IBSIZE];
-#ifdef SIGALRM
- int omask;
-
- omask = sigblock(sigmask(SIGALRM));
-#endif
- clear_log();
- if (*estr == '!') {
- ExpandString(estr + 1, buff, sizeof buff, 0);
- ExecStr(buff, buff, sizeof buff);
- } else {
- ExpandString(estr, buff, sizeof buff, 0);
- }
- if (LogIsKept(LogCHAT)) {
- s = buff + strlen(buff) - 1;
- while (s >= buff && *s == '\n')
- s--;
- if (!strcmp(estr, buff))
- LogPrintf(LogCHAT, "Wait for (%d): %.*s\n",
- TimeoutSec, s - buff + 1, buff);
- else
- LogPrintf(LogCHAT, "Wait for (%d): %s --> %.*s\n",
- TimeoutSec, estr, s - buff + 1, buff);
- }
-
- if (buff[0] == '\0')
- return (MATCH);
-
- str = buff;
- inp = inbuff;
-
- if (strlen(str) >= IBSIZE) {
- str[IBSIZE - 1] = 0;
- LogPrintf(LogCHAT, "Truncating String to %d character: %s\n", IBSIZE, str);
- }
- nfds = modem + 1;
- s = str;
- for (;;) {
- FD_ZERO(&rfds);
- FD_SET(modem, &rfds);
-
- /*
- * Because it is not clear whether select() modifies timeout value, it is
- * better to initialize timeout values everytime.
- */
- timeout.tv_sec = TimeoutSec;
- timeout.tv_usec = 0;
- i = select(nfds, &rfds, NULL, NULL, &timeout);
-#ifdef notdef
- TimerService();
-#endif
- if (i < 0) {
-#ifdef SIGALRM
- if (errno == EINTR)
- continue;
- sigsetmask(omask);
-#endif
- LogPrintf(LogERROR, "WaitForString: select(): %s\n", strerror(errno));
- *inp = 0;
- return (NOMATCH);
- } else if (i == 0) { /* Timeout reached! */
- *inp = 0;
- if (inp != inbuff)
- LogPrintf(LogCHAT, "Got: %s\n", inbuff);
- LogPrintf(LogCHAT, "Can't get (%d).\n", timeout.tv_sec);
-#ifdef SIGALRM
- sigsetmask(omask);
-#endif
- return (NOMATCH);
- }
- if (FD_ISSET(modem, &rfds)) { /* got something */
- if (DEV_IS_SYNC) {
- int length;
-
- if ((length = strlen(inbuff)) > IBSIZE) {
- /* shuffle down next part */
- memcpy(inbuff, &(inbuff[IBSIZE]), IBSIZE + 1);
- length = strlen(inbuff);
- }
- nb = read(modem, &(inbuff[length]), IBSIZE);
- inbuff[nb + length] = 0;
- connect_log(inbuff, 0);
- if (strstr(inbuff, str)) {
-#ifdef SIGALRM
- sigsetmask(omask);
-#endif
- flush_log();
- return (MATCH);
- }
- for (i = 0; i < numaborts; i++) {
- if (strstr(inbuff, AbortStrings[i])) {
- LogPrintf(LogCHAT, "Abort: %s\n", AbortStrings[i]);
-#ifdef SIGALRM
- sigsetmask(omask);
-#endif
- flush_log();
- return (ABORT);
- }
- }
- } else {
- if (read(modem, &ch, 1) < 0) {
- LogPrintf(LogERROR, "read error: %s\n", strerror(errno));
- *inp = '\0';
- return (NOMATCH);
- }
- connect_log(&ch, 1);
- *inp++ = ch;
- if (ch == *s) {
- s++;
- if (*s == '\0') {
-#ifdef SIGALRM
- sigsetmask(omask);
-#endif
- *inp = 0;
- flush_log();
- return (MATCH);
- }
- } else
- s = str;
- if (inp == inbuff + IBSIZE) {
- memcpy(inbuff, inp - 100, 100);
- inp = inbuff + 100;
- }
- if (s == str) {
- for (i = 0; i < numaborts; i++) { /* Look for Abort strings */
- int len;
- char *s1;
-
- s1 = AbortStrings[i];
- len = strlen(s1);
- if ((len <= inp - inbuff) && (strncmp(inp - len, s1, len) == 0)) {
- LogPrintf(LogCHAT, "Abort: %s\n", s1);
- *inp = 0;
-#ifdef SIGALRM
- sigsetmask(omask);
-#endif
- flush_log();
- return (ABORT);
- }
- }
- }
- }
- }
- }
-}
-
-static void
-SendString(const char *str)
-{
- char *cp;
- int on;
- char buff[LINE_LEN];
-
- if (abort_next) {
- abort_next = 0;
- ExpandString(str, buff, sizeof buff, 0);
- AbortStrings[numaborts++] = strdup(buff);
- } else if (timeout_next) {
- timeout_next = 0;
- TimeoutSec = atoi(str);
- if (TimeoutSec <= 0)
- TimeoutSec = 30;
- } else {
- if (*str == '!') {
- ExpandString(str + 1, buff + 2, sizeof buff - 2, 0);
- ExecStr(buff + 2, buff + 2, sizeof buff - 2);
- } else {
- ExpandString(str, buff + 2, sizeof buff - 2, 1);
- }
- if (strstr(str, "\\P")) /* Do not log the password itself. */
- LogPrintf(LogCHAT, "Sending: %s", str);
- else {
- cp = buff + strlen(buff + 2) + 1;
- while (cp >= buff + 2 && *cp == '\n')
- cp--;
- LogPrintf(LogCHAT, "Sending: %.*s\n", cp - buff - 1, buff + 2);
- }
- cp = buff;
- if (DEV_IS_SYNC)
- memcpy(buff, "\377\003", 2); /* Prepend HDLC header */
- else
- cp += 2;
- on = strlen(cp);
- write(modem, cp, on);
- }
-}
-
-static int
-ExpectString(char *str)
-{
- char *minus;
- int state;
-
- if (strcmp(str, "ABORT") == 0) {
- ++abort_next;
- return (MATCH);
- }
- if (strcmp(str, "TIMEOUT") == 0) {
- ++timeout_next;
- return (MATCH);
- }
- LogPrintf(LogCHAT, "Expecting: %s\n", str);
- while (*str) {
- /*
- * Check whether if string contains sub-send-expect.
- */
- for (minus = str; *minus; minus++) {
- if (*minus == '-') {
- if (minus == str || minus[-1] != '\\')
- break;
- }
- }
- if (*minus == '-') { /* We have sub-send-expect. */
- *minus = '\0'; /* XXX: Cheat with the const string */
- state = WaitforString(str);
- *minus = '-'; /* XXX: Cheat with the const string */
- minus++;
- if (state != NOMATCH)
- return (state);
-
- /*
- * Can't get expect string. Sendout send part.
- */
- str = minus;
- for (minus = str; *minus; minus++) {
- if (*minus == '-') {
- if (minus == str || minus[-1] != '\\')
- break;
- }
- }
- if (*minus == '-') {
- *minus = '\0'; /* XXX: Cheat with the const string */
- SendString(str);
- *minus = '-'; /* XXX: Cheat with the const string */
- str = ++minus;
- } else {
- SendString(str);
- return (MATCH);
- }
- } else {
- /*
- * Simple case. Wait for string.
- */
- return (WaitforString(str));
- }
- }
- return (MATCH);
-}
-
-static void (*oint) (int);
-
-static void
-StopDial(int sig)
-{
- LogPrintf(LogPHASE, "DoChat: Caught signal %d, abort connect\n", sig);
- longjmp(ChatEnv, 1);
-}
-
-int
-DoChat(char *script)
-{
- char *vector[MAXARGS];
- char *const *argv;
- int argc, n, state, err;
-
- if (!script || !*script)
- return MATCH;
-
- if ((err = setjmp(ChatEnv))) {
- signal(SIGINT, oint);
- if (err == 1)
- /* Caught a SIGINT during chat */
- return (-1);
- return (NOMATCH);
- }
- oint = signal(SIGINT, StopDial);
-
- timeout_next = abort_next = 0;
- for (n = 0; AbortStrings[n]; n++) {
- free(AbortStrings[n]);
- AbortStrings[n] = NULL;
- }
- numaborts = 0;
-
- memset(vector, '\0', sizeof vector);
- argc = MakeArgs(script, vector, VECSIZE(vector));
- argv = vector;
- TimeoutSec = 30;
- while (*argv) {
- if (strcmp(*argv, "P_ZERO") == 0 ||
- strcmp(*argv, "P_ODD") == 0 || strcmp(*argv, "P_EVEN") == 0) {
- ChangeParity(*argv++);
- continue;
- }
- state = ExpectString(*argv++);
- switch (state) {
- case MATCH:
- if (*argv)
- SendString(*argv++);
- break;
- case ABORT:
- case NOMATCH:
- signal(SIGINT, oint);
- return (NOMATCH);
+ *out = '\0';
+ return;
}
}
- signal(SIGINT, oint);
- return (MATCH);
}
diff --git a/usr.sbin/ppp/chat.h b/usr.sbin/ppp/chat.h
index 53f67fa4e254..e57f32ef3009 100644
--- a/usr.sbin/ppp/chat.h
+++ b/usr.sbin/ppp/chat.h
@@ -1,29 +1,82 @@
-/*
- * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
*
- * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com).
- *
- * Chat -- a program for automatic session establishment (i.e. dial
- * the phone and log in).
- *
- * This software is in the public domain.
- *
- * Please send all bug reports, requests for information, etc. to:
- *
- * Karl Fox <karl@MorningStar.Com>
- * Morning Star Technologies, Inc.
- * 1760 Zollinger Road
- * Columbus, OH 43221
- * (614)451-1883
- *
- * $Id: chat.h,v 1.8 1997/10/26 01:02:23 brian Exp $
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*
+ * $Id: chat.h,v 1.9.2.8 1998/05/01 19:24:13 brian Exp $
*/
+#define CHAT_EXPECT 0
+#define CHAT_SEND 1
+#define CHAT_DONE 2
+#define CHAT_FAILED 3
+
+#define MAXABORTS 50
+
+struct physical;
+
+struct chat {
+ struct descriptor desc;
+ struct physical *physical;
+
+ int state; /* Our CHAT_* status */
+
+ char script[LINE_LEN]; /* Our arg buffer */
+ char *argv[MAXARGS]; /* Our arguments (pointing to script) */
+ int argc; /* Number of argv's */
+
+ int arg; /* Our current arg number */
+ char exp[LINE_LEN]; /* Our translated current argument */
+ char *argptr; /* Our current arg pointer */
+ int arglen; /* The length of argptr */
+ char *nargptr; /* Our next for expect-send-expect */
+
+ char buf[LINE_LEN*2]; /* Our input */
+ char *bufstart; /* start of relevent data */
+ char *bufend; /* end of relevent data */
+
+ int TimeoutSec; /* Expect timeout value */
+ int TimedOut; /* We timed out */
+
+ const char *phone; /* Our phone number */
+
+ struct {
+ struct {
+ char *data; /* Abort the dial if we get one */
+ int len;
+ } string[MAXABORTS];
+ int num; /* How many AbortStrings */
+ } abort;
+
+ struct pppTimer pause; /* Inactivity timer */
+ struct pppTimer timeout; /* TimeoutSec timer */
+};
+
+#define descriptor2chat(d) \
+ ((d)->type == CHAT_DESCRIPTOR ? (struct chat *)(d) : NULL)
#define VECSIZE(v) (sizeof(v) / sizeof(v[0]))
-extern char *ExpandString(const char *, char *, int, int);
+extern void chat_Init(struct chat *, struct physical *, const char *, int,
+ const char *);
+extern void chat_Destroy(struct chat *);
extern int MakeArgs(char *, char **, int); /* Mangles the first arg ! */
-extern int DoChat(char *); /* passes arg to MakeArgs() */
diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c
index 4658eea9fac3..dcaa0ec15e75 100644
--- a/usr.sbin/ppp/command.c
+++ b/usr.sbin/ppp/command.c
@@ -17,10 +17,10 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: command.c,v 1.133 1998/03/13 01:36:08 brian Exp $
+ * $Id: command.c,v 1.131.2.88 1998/05/21 01:13:26 brian Exp $
*
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
@@ -28,21 +28,20 @@
#include <sys/socket.h>
#include <net/route.h>
#include <netdb.h>
+#include <sys/un.h>
#ifndef NOALIAS
#include <alias.h>
#endif
-#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
#include <sys/wait.h>
#include <termios.h>
-#include <time.h>
#include <unistd.h>
#include "command.h"
@@ -51,72 +50,138 @@
#include "defs.h"
#include "timer.h"
#include "fsm.h"
-#include "phase.h"
#include "lcp.h"
#include "iplist.h"
+#include "throughput.h"
+#include "slcompress.h"
#include "ipcp.h"
#include "modem.h"
-#include "filter.h"
#ifndef NOALIAS
#include "alias_cmd.h"
#endif
+#include "lqr.h"
#include "hdlc.h"
#include "loadalias.h"
-#include "vars.h"
#include "systems.h"
-#include "chat.h"
-#include "os.h"
-#include "server.h"
+#include "filter.h"
+#include "descriptor.h"
#include "main.h"
#include "route.h"
#include "ccp.h"
-#include "ip.h"
-#include "slcompress.h"
#include "auth.h"
-
-struct in_addr ifnetmask;
-static const char *HIDDEN = "********";
-
-static int ShowCommand(struct cmdargs const *arg);
-static int TerminalCommand(struct cmdargs const *arg);
-static int QuitCommand(struct cmdargs const *arg);
-static int CloseCommand(struct cmdargs const *arg);
-static int DialCommand(struct cmdargs const *arg);
-static int DownCommand(struct cmdargs const *arg);
-static int AllowCommand(struct cmdargs const *arg);
-static int SetCommand(struct cmdargs const *arg);
-static int AddCommand(struct cmdargs const *arg);
-static int DeleteCommand(struct cmdargs const *arg);
-static int BgShellCommand(struct cmdargs const *arg);
-static int FgShellCommand(struct cmdargs const *arg);
+#include "async.h"
+#include "link.h"
+#include "physical.h"
+#include "mp.h"
+#include "bundle.h"
+#include "server.h"
+#include "prompt.h"
+#include "chat.h"
+#include "chap.h"
+#include "datalink.h"
+
+/* ``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
+
+/* ``accept|deny|disable|enable'' masks */
+#define NEG_HISMASK (1)
+#define NEG_MYMASK (2)
+
+/* ``accept|deny|disable|enable'' values */
+#define NEG_ACFCOMP 40
+#define NEG_CHAP 41
+#define NEG_DEFLATE 42
+#define NEG_LQR 43
+#define NEG_PAP 44
+#define NEG_PPPDDEFLATE 45
+#define NEG_PRED1 46
+#define NEG_PROTOCOMP 47
+#define NEG_SHORTSEQ 48
+#define NEG_VJCOMP 49
+#define NEG_DNS 50
+
+const char Version[] = "2.0-beta";
+const char VersionDate[] = "$Date: 1998/05/21 01:13:26 $";
+
+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 AllowCommand(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 *);
#ifndef NOALIAS
-static int AliasCommand(struct cmdargs const *arg);
-static int AliasEnable(struct cmdargs const *arg);
-static int AliasOption(struct cmdargs const *arg);
+static int AliasCommand(struct cmdargs const *);
+static int AliasEnable(struct cmdargs const *);
+static int AliasOption(struct cmdargs const *);
#endif
+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 "";
+}
+
static int
HelpCommand(struct cmdargs const *arg)
{
struct cmdtab const *cmd;
- int n, cmax, dmax, cols;
+ int n, cmax, dmax, cols, cxlen;
+ const char *cx;
- if (!VarTerm)
+ if (!arg->prompt) {
+ log_Printf(LogWARN, "help: Cannot help without a prompt\n");
return 0;
+ }
- if (arg->argc > 0) {
- for (cmd = arg->cmd; cmd->name; cmd++)
- if (strcasecmp(cmd->name, *arg->argv) == 0 &&
- (cmd->lauth & VarLocalAuth)) {
- fprintf(VarTerm, "%s\n", cmd->syntax);
+ 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));
return 0;
}
return -1;
}
+
cmax = dmax = 0;
- for (cmd = arg->cmd; cmd->func; cmd++)
- if (cmd->name && (cmd->lauth & VarLocalAuth)) {
- if ((n = strlen(cmd->name)) > cmax)
+ for (cmd = arg->cmdtab; cmd->func; cmd++)
+ if (cmd->name && (cmd->lauth & arg->prompt->auth)) {
+ if ((n = strlen(cmd->name) + strlen(showcx(cmd))) > cmax)
cmax = n;
if ((n = strlen(cmd->helpmes)) > dmax)
dmax = n;
@@ -124,102 +189,126 @@ HelpCommand(struct cmdargs const *arg)
cols = 80 / (dmax + cmax + 3);
n = 0;
- for (cmd = arg->cmd; cmd->func; cmd++)
- if (cmd->name && (cmd->lauth & VarLocalAuth)) {
- fprintf(VarTerm, " %-*.*s: %-*.*s",
- cmax, cmax, cmd->name, dmax, dmax, cmd->helpmes);
+ 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);
+ prompt_Printf(arg->prompt, " %s%-*.*s: %-*.*s",
+ cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes);
if (++n % cols == 0)
- fprintf(VarTerm, "\n");
+ prompt_Printf(arg->prompt, "\n");
}
if (n % cols != 0)
- fprintf(VarTerm, "\n");
+ prompt_Printf(arg->prompt, "\n");
return 0;
}
-int
-IsInteractive(int Display)
+static int
+CloneCommand(struct cmdargs const *arg)
{
- const char *m = NULL;
-
- if (mode & MODE_DDIAL)
- m = "direct dial";
- else if (mode & MODE_BACKGROUND)
- m = "background";
- else if (mode & MODE_AUTO)
- m = "auto";
- else if (mode & MODE_DIRECT)
- m = "direct";
- else if (mode & MODE_DEDICATED)
- m = "dedicated";
- else if (mode & MODE_INTER)
- m = "interactive";
- if (m) {
- if (Display && VarTerm)
- fprintf(VarTerm, "Working in %s mode\n", m);
+ 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);
}
- return mode & MODE_INTER;
+
+ return 0;
}
static int
-DialCommand(struct cmdargs const *arg)
+RemoveCommand(struct cmdargs const *arg)
{
- int tries;
- int res;
+ if (arg->argc != arg->argn)
+ return -1;
- if (LcpFsm.state > ST_CLOSED) {
- if (VarTerm)
- fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
- return 0;
+ if (arg->cx->state != DATALINK_CLOSED) {
+ log_Printf(LogWARN, "remove: Cannot delete links that aren't closed\n");
+ return 2;
}
- if ((mode & MODE_DAEMON) && !(mode & MODE_AUTO)) {
- LogPrintf(LogWARN,
- "Manual dial is only available in auto and interactive mode\n");
- return 1;
- }
+ bundle_DatalinkRemove(arg->bundle, arg->cx);
+ return 0;
+}
- if (arg->argc > 0 && (res = LoadCommand(arg)) != 0)
- return res;
+static int
+RenameCommand(struct cmdargs const *arg)
+{
+ if (arg->argc != arg->argn + 1)
+ return -1;
- tries = 0;
- do {
- if (tries) {
- LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
- VarRedialNextTimeout);
- nointr_sleep(VarRedialNextTimeout);
- }
- if (VarTerm)
- fprintf(VarTerm, "Dial attempt %u of %d\n", ++tries, VarDialTries);
- if (OpenModem() < 0) {
- if (VarTerm)
- fprintf(VarTerm, "Failed to open modem.\n");
- break;
- }
- if ((res = DialModem()) == EX_DONE) {
- ModemTimeout(NULL);
- PacketMode(VarOpenMode);
- break;
- } else if (res == EX_SIG)
- return 1;
- } while (VarDialTries == 0 || tries < VarDialTries);
+ if (bundle_RenameDatalink(arg->bundle, arg->cx, arg->argv[arg->argn]))
+ return 0;
+ 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)
+{
+ const char *name;
+
+ if (arg->argc > arg->argn)
+ name = arg->argv[arg->argn];
+ else
+ name = "default";
+
+ if (!system_IsValid(name, arg->prompt, arg->bundle->phys_type)) {
+ log_Printf(LogERROR, "%s: Label not allowed\n", name);
+ return 1;
+ } else {
+ /*
+ * Set the label before & after so that `set enddisc' works and
+ * we handle nested `load' commands.
+ */
+ bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL);
+ if (system_Select(arg->bundle, name, CONFFILE, arg->prompt) < 0) {
+ bundle_SetLabel(arg->bundle, NULL);
+ log_Printf(LogWARN, "%s: label not found.\n", name);
+ return -1;
+ }
+ bundle_SetLabel(arg->bundle, arg->argc > arg->argn ? name : NULL);
+ }
return 0;
}
+int
+SaveCommand(struct cmdargs const *arg)
+{
+ log_Printf(LogWARN, "save command is not implemented (yet).\n");
+ return 1;
+}
+
static int
-SetLoopback(struct cmdargs const *arg)
+DialCommand(struct cmdargs const *arg)
{
- if (arg->argc == 1) {
- if (!strcasecmp(*arg->argv, "on")) {
- VarLoopback = 1;
- return 0;
- } else if (!strcasecmp(*arg->argv, "off")) {
- VarLoopback = 0;
- return 0;
- }
+ int res;
+
+ if ((arg->cx && !(arg->cx->physical->type & (PHYS_MANUAL|PHYS_DEMAND)))
+ || (!arg->cx && (arg->bundle->phys_type & ~(PHYS_MANUAL|PHYS_DEMAND)))) {
+ log_Printf(LogWARN, "Manual dial is only available for auto and"
+ " interactive links\n");
+ return 1;
}
- return -1;
+
+ if (arg->argc > arg->argn && (res = LoadCommand(arg)) != 0)
+ return res;
+
+ bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL);
+
+ return 0;
}
static int
@@ -232,78 +321,61 @@ ShellCommand(struct cmdargs const *arg, int bg)
#ifdef SHELL_ONLY_INTERACTIVELY
/* we're only allowed to shell when we run ppp interactively */
- if (mode != MODE_INTER) {
- LogPrintf(LogWARN, "Can only start a shell in interactive mode\n");
- return 1;
- }
-#endif
-#ifdef NO_SHELL_IN_AUTO_INTERACTIVE
-
- /*
- * we want to stop shell commands when we've got a telnet connection to an
- * auto mode ppp
- */
- if (VarTerm && !(mode & MODE_INTER)) {
- LogPrintf(LogWARN, "Shell is not allowed interactively in auto mode\n");
+ if (arg->prompt && arg->prompt->owner) {
+ log_Printf(LogWARN, "Can't start a shell from a network connection\n");
return 1;
}
#endif
- if (arg->argc == 0) {
- if (!(mode & MODE_INTER)) {
- if (VarTerm)
- LogPrintf(LogWARN, "Can't start an interactive shell from"
- " a telnet session\n");
- else
- LogPrintf(LogWARN, "Can only start an interactive shell in"
- " interactive mode\n");
+ 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");
return 1;
} else if (bg) {
- LogPrintf(LogWARN, "Can only start an interactive shell in"
+ log_Printf(LogWARN, "Can only start an interactive shell in"
" the foreground mode\n");
return 1;
}
}
- if ((shell = getenv("SHELL")) == 0)
- shell = _PATH_BSHELL;
-
if ((shpid = fork()) == 0) {
- int dtablesize, i, fd;
-
- TermTimerService();
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- signal(SIGALRM, SIG_DFL);
-
- if (VarTerm)
- fd = fileno(VarTerm);
- else if ((fd = open("/dev/null", O_RDWR)) == -1) {
- LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno));
+ 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));
exit(1);
}
for (i = 0; i < 3; i++)
dup2(fd, i);
- for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++)
- close(i);
+ fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */
- TtyOldMode();
setuid(geteuid());
- if (arg->argc > 0) {
+ if (arg->argc > arg->argn) {
/* substitute pseudo args */
- argv[0] = strdup(arg->argv[0]);
- for (argc = 1; argc < arg->argc; argc++) {
- if (strcasecmp(arg->argv[argc], "HISADDR") == 0)
- argv[argc] = strdup(inet_ntoa(IpcpInfo.his_ipaddr));
- else if (strcasecmp(arg->argv[argc], "INTERFACE") == 0)
- argv[argc] = strdup(IfDevName);
- else if (strcasecmp(arg->argv[argc], "MYADDR") == 0)
- argv[argc] = strdup(inet_ntoa(IpcpInfo.want_ipaddr));
+ argv[0] = strdup(arg->argv[arg->argn]);
+ for (argc = 1; argc < arg->argc - arg->argn; argc++) {
+ if (strcasecmp(arg->argv[argc + arg->argn], "HISADDR") == 0)
+ argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.peer_ip));
+ else if (strcasecmp(arg->argv[argc + arg->argn], "INTERFACE") == 0)
+ argv[argc] = strdup(arg->bundle->ifp.Name);
+ else if (strcasecmp(arg->argv[argc + arg->argn], "MYADDR") == 0)
+ argv[argc] = strdup(inet_ntoa(arg->bundle->ncp.ipcp.my_ip));
else
- argv[argc] = strdup(arg->argv[argc]);
+ argv[argc] = strdup(arg->argv[argc + arg->argn]);
}
argv[argc] = NULL;
if (bg) {
@@ -311,39 +383,41 @@ ShellCommand(struct cmdargs const *arg, int bg)
p = getpid();
if (daemon(1, 1) == -1) {
- LogPrintf(LogERROR, "%d: daemon: %s\n", p, strerror(errno));
+ log_Printf(LogERROR, "%d: daemon: %s\n", p, strerror(errno));
exit(1);
}
- } else if (VarTerm)
- printf("ppp: Pausing until %s finishes\n", arg->argv[0]);
+ } else if (arg->prompt)
+ printf("ppp: Pausing until %s finishes\n", arg->argv[arg->argn]);
execvp(argv[0], argv);
} else {
- if (VarTerm)
+ if (arg->prompt)
printf("ppp: Pausing until %s finishes\n", shell);
+ prompt_TtyOldMode(arg->prompt);
execl(shell, shell, NULL);
}
- LogPrintf(LogWARN, "exec() of %s failed\n",
- arg->argc > 0 ? arg->argv[0] : shell);
+ log_Printf(LogWARN, "exec() of %s failed\n",
+ arg->argc > arg->argn ? arg->argv[arg->argn] : shell);
exit(255);
}
- if (shpid == (pid_t) - 1) {
- LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno));
- } else {
- int status;
+ if (shpid == (pid_t) - 1)
+ log_Printf(LogERROR, "Fork failed: %s\n", strerror(errno));
+ else {
+ int status;
waitpid(shpid, &status, 0);
}
- TtyCommandMode(0);
+ if (arg->prompt && !arg->prompt->owner)
+ prompt_TtyCommandMode(arg->prompt);
- return (0);
+ return 0;
}
static int
BgShellCommand(struct cmdargs const *arg)
{
- if (arg->argc == 0)
+ if (arg->argc == arg->argn)
return -1;
return ShellCommand(arg, 1);
}
@@ -355,304 +429,175 @@ FgShellCommand(struct cmdargs const *arg)
}
static struct cmdtab const Commands[] = {
- {"accept", NULL, AcceptCommand, LOCAL_AUTH,
+ {"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"accept option request", "accept option .."},
{"add", NULL, AddCommand, LOCAL_AUTH,
"add route", "add dest mask gateway", NULL},
- {"add!", NULL, AddCommand, LOCAL_AUTH,
+ {NULL, "add!", AddCommand, LOCAL_AUTH,
"add or change route", "add! dest mask gateway", (void *)1},
+#ifndef NOALIAS
+ {"alias", NULL, AliasCommand, LOCAL_AUTH,
+ "alias control", "alias option [yes|no]"},
+#endif
{"allow", "auth", AllowCommand, LOCAL_AUTH,
"Allow ppp access", "allow users|modes ...."},
{"bg", "!bg", BgShellCommand, LOCAL_AUTH,
"Run a background command", "[!]bg command"},
- {"close", NULL, CloseCommand, LOCAL_AUTH,
- "Close connection", "close"},
+ {"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]"},
{"delete", NULL, DeleteCommand, LOCAL_AUTH,
"delete route", "delete dest", NULL},
- {"delete!", NULL, DeleteCommand, LOCAL_AUTH,
+ {NULL, "delete!", DeleteCommand, LOCAL_AUTH,
"delete a route if it exists", "delete! dest", (void *)1},
- {"deny", NULL, DenyCommand, LOCAL_AUTH,
+ {"deny", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"Deny option request", "deny option .."},
- {"dial", "call", DialCommand, LOCAL_AUTH,
+ {"dial", "call", DialCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"Dial and login", "dial|call [remote]"},
- {"disable", NULL, DisableCommand, LOCAL_AUTH,
+ {"disable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"Disable option", "disable option .."},
- {"display", NULL, DisplayCommand, LOCAL_AUTH,
- "Display option configs", "display"},
- {"enable", NULL, EnableCommand, LOCAL_AUTH,
+ {"down", NULL, DownCommand, LOCAL_AUTH | LOCAL_CX_OPT,
+ "Generate a down event", "down"},
+ {"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"Enable option", "enable option .."},
- {"passwd", NULL, LocalAuthCommand, LOCAL_NO_AUTH,
- "Password for manipulation", "passwd LocalPassword"},
+ {"link", "datalink", LinkCommand, LOCAL_AUTH,
+ "Link specific commands", "link name command ..."},
{"load", NULL, LoadCommand, LOCAL_AUTH,
"Load settings", "load [remote]"},
+ {"open", NULL, OpenCommand, LOCAL_AUTH | LOCAL_CX_OPT,
+ "Open an FSM", "open [lcp|ccp]"},
+ {"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"},
{"save", NULL, SaveCommand, LOCAL_AUTH,
"Save settings", "save"},
- {"set", "setup", SetCommand, LOCAL_AUTH,
+ {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"Set parameters", "set[up] var value"},
{"shell", "!", FgShellCommand, LOCAL_AUTH,
"Run a subshell", "shell|! [sh command]"},
- {"show", NULL, ShowCommand, LOCAL_AUTH,
+ {"show", NULL, ShowCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"Show status and stats", "show var"},
- {"term", NULL, TerminalCommand, LOCAL_AUTH,
+ {"term", NULL, TerminalCommand, LOCAL_AUTH | LOCAL_CX,
"Enter terminal mode", "term"},
-#ifndef NOALIAS
- {"alias", NULL, AliasCommand, LOCAL_AUTH,
- "alias control", "alias option [yes|no]"},
-#endif
- {"quit", "bye", QuitCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
- "Quit PPP program", "quit|bye [all]"},
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
"Display this message", "help|? [command]", Commands},
- {NULL, "down", DownCommand, LOCAL_AUTH,
- "Generate down event", "down"},
{NULL, NULL, NULL},
};
static int
-ShowLoopback(struct cmdargs const *arg)
-{
- if (VarTerm)
- fprintf(VarTerm, "Local loopback is %s\n", VarLoopback ? "on" : "off");
-
- return 0;
-}
-
-static int
-ShowLogLevel(struct cmdargs const *arg)
-{
- int i;
-
- if (!VarTerm)
- return 0;
-
- fprintf(VarTerm, "Log: ");
- for (i = LogMIN; i <= LogMAX; i++)
- if (LogIsKept(i) & LOG_KEPT_SYSLOG)
- fprintf(VarTerm, " %s", LogName(i));
-
- fprintf(VarTerm, "\nLocal:");
- for (i = LogMIN; i <= LogMAX; i++)
- if (LogIsKept(i) & LOG_KEPT_LOCAL)
- fprintf(VarTerm, " %s", LogName(i));
-
- fprintf(VarTerm, "\n");
-
- return 0;
-}
-
-static int
ShowEscape(struct cmdargs const *arg)
{
- int code, bit;
+ if (arg->cx->physical->async.cfg.EscMap[32]) {
+ int code, bit;
+ const char *sep = "";
- if (!VarTerm)
- return 0;
- if (EscMap[32]) {
for (code = 0; code < 32; code++)
- if (EscMap[code])
+ if (arg->cx->physical->async.cfg.EscMap[code])
for (bit = 0; bit < 8; bit++)
- if (EscMap[code] & (1 << bit))
- fprintf(VarTerm, " 0x%02x", (code << 3) + bit);
- fprintf(VarTerm, "\n");
+ 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");
}
return 0;
}
static int
-ShowTimeout(struct cmdargs const *arg)
+ShowTimerList(struct cmdargs const *arg)
{
- if (VarTerm) {
- int remaining;
-
- fprintf(VarTerm, " Idle Timer: %d secs LQR Timer: %d secs"
- " Retry Timer: %d secs\n", VarIdleTimeout, VarLqrTimeout,
- VarRetryTimeout);
- remaining = RemainingIdleTime();
- if (remaining != -1)
- fprintf(VarTerm, " %d secs remaining\n", remaining);
- }
+ timer_Show(0, arg->prompt);
return 0;
}
static int
ShowStopped(struct cmdargs const *arg)
{
- if (!VarTerm)
- return 0;
-
- fprintf(VarTerm, " Stopped Timer: LCP: ");
- if (!LcpFsm.StoppedTimer.load)
- fprintf(VarTerm, "Disabled");
+ prompt_Printf(arg->prompt, " Stopped Timer: LCP: ");
+ if (!arg->cx->physical->link.lcp.fsm.StoppedTimer.load)
+ prompt_Printf(arg->prompt, "Disabled");
else
- fprintf(VarTerm, "%ld secs", LcpFsm.StoppedTimer.load / SECTICKS);
+ prompt_Printf(arg->prompt, "%ld secs",
+ arg->cx->physical->link.lcp.fsm.StoppedTimer.load / SECTICKS);
- fprintf(VarTerm, ", IPCP: ");
- if (!IpcpFsm.StoppedTimer.load)
- fprintf(VarTerm, "Disabled");
+ prompt_Printf(arg->prompt, ", CCP: ");
+ if (!arg->cx->physical->link.ccp.fsm.StoppedTimer.load)
+ prompt_Printf(arg->prompt, "Disabled");
else
- fprintf(VarTerm, "%ld secs", IpcpFsm.StoppedTimer.load / SECTICKS);
+ prompt_Printf(arg->prompt, "%ld secs",
+ arg->cx->physical->link.ccp.fsm.StoppedTimer.load / SECTICKS);
- fprintf(VarTerm, ", CCP: ");
- if (!CcpFsm.StoppedTimer.load)
- fprintf(VarTerm, "Disabled");
- else
- fprintf(VarTerm, "%ld secs", CcpFsm.StoppedTimer.load / SECTICKS);
-
- fprintf(VarTerm, "\n");
+ prompt_Printf(arg->prompt, "\n");
return 0;
}
static int
-ShowAuthKey(struct cmdargs const *arg)
-{
- if (!VarTerm)
- return 0;
- fprintf(VarTerm, "AuthName = %s\n", VarAuthName);
- fprintf(VarTerm, "AuthKey = %s\n", HIDDEN);
-#ifdef HAVE_DES
- fprintf(VarTerm, "Encrypt = %s\n", VarMSChap ? "MSChap" : "MD5" );
-#endif
- return 0;
-}
-
-static int
ShowVersion(struct cmdargs const *arg)
{
- if (VarTerm)
- fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
- return 0;
-}
-
-static int
-ShowInitialMRU(struct cmdargs const *arg)
-{
- if (VarTerm)
- fprintf(VarTerm, " Initial MRU: %d\n", VarMRU);
- return 0;
-}
-
-static int
-ShowPreferredMTU(struct cmdargs const *arg)
-{
- if (VarTerm) {
- if (VarPrefMTU)
- fprintf(VarTerm, " Preferred MTU: %d\n", VarPrefMTU);
- else
- fprintf(VarTerm, " Preferred MTU: unspecified\n");
- }
- return 0;
-}
-
-static int
-ShowReconnect(struct cmdargs const *arg)
-{
- if (VarTerm)
- fprintf(VarTerm, " Reconnect Timer: %d, %d tries\n",
- VarReconnectTimer, VarReconnectTries);
+ prompt_Printf(arg->prompt, "PPP Version %s - %s\n", Version, VersionDate);
return 0;
}
static int
-ShowRedial(struct cmdargs const *arg)
+ShowProtocolStats(struct cmdargs const *arg)
{
- if (!VarTerm)
- return 0;
- fprintf(VarTerm, " Redial Timer: ");
-
- if (VarRedialTimeout >= 0) {
- fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
- } else {
- fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
- }
-
- fprintf(VarTerm, " Redial Next Timer: ");
-
- if (VarRedialNextTimeout >= 0) {
- fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
- } else {
- fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
- }
-
- if (VarDialTries)
- fprintf(VarTerm, "%d dial tries", VarDialTries);
-
- fprintf(VarTerm, "\n");
+ struct link *l = command_ChooseLink(arg);
+ if (!l)
+ return -1;
+ prompt_Printf(arg->prompt, "%s:\n", l->name);
+ link_ReportProtocolStatus(l, arg->prompt);
return 0;
}
-#ifndef NOMSEXT
-static int
-ShowMSExt(struct cmdargs const *arg)
-{
- if (VarTerm) {
- fprintf(VarTerm, " MS PPP extention values \n");
- fprintf(VarTerm, " Primary NS : %s\n", inet_ntoa(ns_entries[0]));
- fprintf(VarTerm, " Secondary NS : %s\n", inet_ntoa(ns_entries[1]));
- fprintf(VarTerm, " Primary NBNS : %s\n", inet_ntoa(nbns_entries[0]));
- fprintf(VarTerm, " Secondary NBNS : %s\n", inet_ntoa(nbns_entries[1]));
- }
- return 0;
-}
-
-#endif
-
static struct cmdtab const ShowCommands[] = {
- {"afilter", NULL, ShowAfilter, LOCAL_AUTH,
- "Show keep-alive filters", "show afilter option .."},
- {"auth", NULL, ShowAuthKey, LOCAL_AUTH,
- "Show auth details", "show auth"},
- {"ccp", NULL, ReportCcpStatus, LOCAL_AUTH,
- "Show CCP status", "show cpp"},
- {"compress", NULL, ReportCompress, LOCAL_AUTH,
- "Show compression stats", "show compress"},
- {"dfilter", NULL, ShowDfilter, LOCAL_AUTH,
- "Show Demand filters", "show dfilteroption .."},
- {"escape", NULL, ShowEscape, LOCAL_AUTH,
- "Show escape characters", "show escape"},
- {"hdlc", NULL, ReportHdlcStatus, LOCAL_AUTH,
- "Show HDLC errors", "show hdlc"},
- {"ifilter", NULL, ShowIfilter, LOCAL_AUTH,
- "Show Input filters", "show ifilter option .."},
- {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH,
- "Show IPCP status", "show ipcp"},
- {"lcp", NULL, ReportLcpStatus, LOCAL_AUTH,
- "Show LCP status", "show lcp"},
- {"loopback", NULL, ShowLoopback, LOCAL_AUTH,
- "Show loopback setting", "show loopback"},
- {"log", NULL, ShowLogLevel, LOCAL_AUTH,
- "Show log levels", "show log"},
- {"mem", NULL, ShowMemMap, LOCAL_AUTH,
- "Show memory map", "show mem"},
- {"modem", NULL, ShowModemStatus, LOCAL_AUTH,
- "Show modem setups", "show modem"},
- {"mru", NULL, ShowInitialMRU, LOCAL_AUTH,
- "Show Initial MRU", "show mru"},
-#ifndef NOMSEXT
- {"msext", NULL, ShowMSExt, LOCAL_AUTH,
- "Show MS PPP extentions", "show msext"},
-#endif
- {"mtu", NULL, ShowPreferredMTU, LOCAL_AUTH,
- "Show Preferred MTU", "show mtu"},
- {"ofilter", NULL, ShowOfilter, LOCAL_AUTH,
- "Show Output filters", "show ofilter option .."},
- {"proto", NULL, ReportProtStatus, LOCAL_AUTH,
- "Show protocol summary", "show proto"},
- {"reconnect", NULL, ShowReconnect, LOCAL_AUTH,
- "Show reconnect timer", "show reconnect"},
- {"redial", NULL, ShowRedial, LOCAL_AUTH,
- "Show Redial timeout", "show redial"},
- {"route", NULL, ShowRoute, LOCAL_AUTH,
- "Show routing table", "show route"},
- {"timeout", NULL, ShowTimeout, LOCAL_AUTH,
- "Show Idle timeout", "show timeout"},
- {"stopped", NULL, ShowStopped, LOCAL_AUTH,
- "Show STOPPED timeout", "show stopped"},
+ {"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"},
+ {"ipcp", NULL, ipcp_Show, LOCAL_AUTH,
+ "IPCP status", "show ipcp"},
+ {"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"},
+ {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX,
+ "(low-level) link info", "show modem"},
+ {"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"},
{"version", NULL, ShowVersion, LOCAL_NO_AUTH | LOCAL_AUTH,
- "Show version string", "show version"},
- {"vj", NULL, ShowInitVJ, LOCAL_AUTH,
- "Show VJ values", "show vj"},
+ "version string", "show version"},
+ {"who", NULL, log_ShowWho, LOCAL_AUTH,
+ "client list", "show who"},
{"help", "?", HelpCommand, LOCAL_NO_AUTH | LOCAL_AUTH,
"Display this message", "show help|? [command]", ShowCommands},
{NULL, NULL, NULL},
@@ -690,64 +635,78 @@ FindCommand(struct cmdtab const *cmds, const char *str, int *pmatch)
return found;
}
+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;
+}
+
static int
-FindExec(struct cmdtab const *cmds, int argc, char const *const *argv,
- const char *prefix)
+FindExec(struct bundle *bundle, struct cmdtab const *cmds, int argc, int argn,
+ char const *const *argv, struct prompt *prompt, struct datalink *cx)
{
struct cmdtab const *cmd;
int val = 1;
int nmatch;
struct cmdargs arg;
+ char prefix[100];
- cmd = FindCommand(cmds, *argv, &nmatch);
+ cmd = FindCommand(cmds, argv[argn], &nmatch);
if (nmatch > 1)
- LogPrintf(LogWARN, "%s%s: Ambiguous command\n", prefix, *argv);
- else if (cmd && (cmd->lauth & VarLocalAuth)) {
- arg.cmd = cmds;
- arg.argc = argc-1;
- arg.argv = argv+1;
- arg.data = cmd->args;
- val = (cmd->func) (&arg);
+ 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);
+ }
} else
- LogPrintf(LogWARN, "%s%s: Invalid command\n", prefix, *argv);
+ log_Printf(LogWARN, "%s: Invalid command\n",
+ mkPrefix(argn+1, argv, prefix, sizeof prefix));
if (val == -1)
- LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
+ log_Printf(LogWARN, "Usage: %s\n", cmd->syntax);
else if (val)
- LogPrintf(LogWARN, "%s%s: Failed %d\n", prefix, *argv, val);
+ log_Printf(LogWARN, "%s: Failed %d\n",
+ mkPrefix(argn+1, argv, prefix, sizeof prefix), val);
return val;
}
-int aft_cmd = 1;
-
-void
-Prompt()
-{
- const char *pconnect, *pauth;
-
- if (!VarTerm || TermMode)
- return;
-
- if (!aft_cmd)
- fprintf(VarTerm, "\n");
- else
- aft_cmd = 0;
-
- if (VarLocalAuth == LOCAL_AUTH)
- pauth = " ON ";
- else
- pauth = " on ";
- if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
- pconnect = "PPP";
- else
- pconnect = "ppp";
- fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
- fflush(VarTerm);
-}
-
void
-InterpretCommand(char *buff, int nb, int *argc, char ***argv)
+command_Interpret(char *buff, int nb, int *argc, char ***argv)
{
static char *vector[MAXARGS];
char *cp;
@@ -777,14 +736,20 @@ arghidden(int argc, char const *const *argv, int n)
if (n == 1 && !strncasecmp(argv[0], "p", 1))
return 1;
+ /* set server port xxxxx .... */
+ if (n == 3 && !strncasecmp(argv[0], "se", 2) &&
+ !strncasecmp(argv[1], "se", 2))
+ return 1;
+
return 0;
}
void
-RunCommand(int argc, char const *const *argv, const char *label)
+command_Run(struct bundle *bundle, int argc, char const *const *argv,
+ struct prompt *prompt, const char *label)
{
if (argc > 0) {
- if (LogIsKept(LogCOMMAND)) {
+ if (log_IsKept(LogCOMMAND)) {
static char buf[LINE_LEN];
int f, n;
@@ -799,36 +764,38 @@ RunCommand(int argc, char const *const *argv, const char *label)
if (n < sizeof buf - 1 && f)
buf[n++] = ' ';
if (arghidden(argc, argv, f))
- strncpy(buf+n, HIDDEN, sizeof buf - n - 1);
+ strncpy(buf+n, "********", sizeof buf - n - 1);
else
strncpy(buf+n, argv[f], sizeof buf - n - 1);
n += strlen(buf+n);
}
- LogPrintf(LogCOMMAND, "%s\n", buf);
+ log_Printf(LogCOMMAND, "%s\n", buf);
}
- FindExec(Commands, argc, argv, "");
+ FindExec(bundle, Commands, argc, 0, argv, prompt, NULL);
}
}
void
-DecodeCommand(char *buff, int nb, const char *label)
+command_Decode(struct bundle *bundle, char *buff, int nb, struct prompt *prompt,
+ const char *label)
{
int argc;
char **argv;
- InterpretCommand(buff, nb, &argc, &argv);
- RunCommand(argc, (char const *const *)argv, label);
+ command_Interpret(buff, nb, &argc, &argv);
+ command_Run(bundle, argc, (char const *const *)argv, prompt, label);
}
static int
ShowCommand(struct cmdargs const *arg)
{
- if (arg->argc > 0)
- FindExec(ShowCommands, arg->argc, arg->argv, "show ");
- else if (VarTerm)
- fprintf(VarTerm, "Use ``show ?'' to get a arg->cmd.\n");
+ 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);
else
- LogPrintf(LogWARN, "show command must have arguments\n");
+ prompt_Printf(arg->prompt, "Use ``show ?'' to get a list.\n");
return 0;
}
@@ -836,155 +803,161 @@ ShowCommand(struct cmdargs const *arg)
static int
TerminalCommand(struct cmdargs const *arg)
{
- if (LcpFsm.state > ST_CLOSED) {
- if (VarTerm)
- fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
+ if (!arg->prompt) {
+ log_Printf(LogWARN, "term: Need a prompt\n");
return 1;
}
- if (!IsInteractive(1))
- return (1);
- if (OpenModem() < 0) {
- if (VarTerm)
- fprintf(VarTerm, "Failed to open modem.\n");
- return (1);
- }
- if (VarTerm) {
- fprintf(VarTerm, "Entering terminal mode.\n");
- fprintf(VarTerm, "Type `~?' for help.\n");
- }
- TtyTermMode();
- return (0);
-}
-static int
-QuitCommand(struct cmdargs const *arg)
-{
- if (VarTerm) {
- DropClient(1);
- if (mode & MODE_INTER)
- Cleanup(EX_NORMAL);
- else if (arg->argc > 0 && !strcasecmp(*arg->argv, "all") && VarLocalAuth&LOCAL_AUTH)
- Cleanup(EX_NORMAL);
+ 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;
}
+ datalink_Up(arg->cx, 0, 0);
+ prompt_TtyTermMode(arg->prompt, arg->cx);
return 0;
}
static int
-CloseCommand(struct cmdargs const *arg)
+QuitCommand(struct cmdargs const *arg)
{
- reconnect(RECON_FALSE);
- LcpClose();
+ 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);
+
return 0;
}
static int
-DownCommand(struct cmdargs const *arg)
+OpenCommand(struct cmdargs const *arg)
{
- LcpDown();
+ if (arg->argc == arg->argn ||
+ (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp")))
+ bundle_Open(arg->bundle, arg->cx ? arg->cx->name : NULL, PHYS_ALL);
+ else if (arg->argc == arg->argn+1 &&
+ !strcasecmp(arg->argv[arg->argn], "ccp")) {
+ struct link *l;
+ struct fsm *fp;
+
+ if (!(l = command_ChooseLink(arg)))
+ return -1;
+ fp = &l->ccp.fsm;
+
+ 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) {
+ 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);
+ }
+ }
+ } else
+ return -1;
+
return 0;
}
static int
-SetModemSpeed(struct cmdargs const *arg)
+CloseCommand(struct cmdargs const *arg)
{
- int speed;
+ if (arg->argc == arg->argn ||
+ (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp")))
+ bundle_Close(arg->bundle, arg->cx ? arg->cx->name : NULL, 1);
+ else if (arg->argc == arg->argn+1 &&
+ (!strcasecmp(arg->argv[arg->argn], "ccp") ||
+ !strcasecmp(arg->argv[arg->argn], "ccp!"))) {
+ struct link *l;
+ struct fsm *fp;
+
+ if (!(l = command_ChooseLink(arg)))
+ return -1;
+ fp = &l->ccp.fsm;
- if (arg->argc > 0) {
- if (strcasecmp(*arg->argv, "sync") == 0) {
- VarSpeed = 0;
- return 0;
- }
- speed = atoi(*arg->argv);
- if (IntToSpeed(speed) != B0) {
- VarSpeed = speed;
- return 0;
+ 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 */
}
- LogPrintf(LogWARN, "%s: Invalid speed\n", *arg->argv);
- }
- return -1;
+ } else
+ return -1;
+
+ return 0;
}
static int
-SetReconnect(struct cmdargs const *arg)
+DownCommand(struct cmdargs const *arg)
{
- if (arg->argc == 2) {
- VarReconnectTimer = atoi(arg->argv[0]);
- VarReconnectTries = atoi(arg->argv[1]);
- return 0;
- }
- return -1;
+ if (arg->argc == arg->argn ||
+ (arg->argc == arg->argn+1 && !strcasecmp(arg->argv[arg->argn], "lcp"))) {
+ if (arg->cx)
+ datalink_Down(arg->cx, 1);
+ else
+ bundle_Down(arg->bundle);
+ } else if (arg->argc == arg->argn+1 &&
+ !strcasecmp(arg->argv[arg->argn], "ccp")) {
+ struct fsm *fp = arg->cx ? &arg->cx->physical->link.ccp.fsm :
+ &arg->bundle->ncp.mp.link.ccp.fsm;
+ fsm_Down(fp);
+ fsm_Close(fp);
+ } else
+ return -1;
+
+ return 0;
}
static int
-SetRedialTimeout(struct cmdargs const *arg)
+SetModemSpeed(struct cmdargs const *arg)
{
- int timeout;
- int tries;
- char *dot;
-
- if (arg->argc == 1 || arg->argc == 2) {
- if (strncasecmp(arg->argv[0], "random", 6) == 0 &&
- (arg->argv[0][6] == '\0' || arg->argv[0][6] == '.')) {
- VarRedialTimeout = -1;
- randinit();
- } else {
- timeout = atoi(arg->argv[0]);
+ long speed;
+ char *end;
- if (timeout >= 0)
- VarRedialTimeout = timeout;
- else {
- LogPrintf(LogWARN, "Invalid redial timeout\n");
- return -1;
- }
+ if (arg->argc > arg->argn && *arg->argv[arg->argn]) {
+ if (arg->argc > arg->argn+1) {
+ log_Printf(LogWARN, "SetModemSpeed: Too many arguments");
+ return -1;
}
-
- dot = strchr(arg->argv[0], '.');
- if (dot) {
- if (strcasecmp(++dot, "random") == 0) {
- VarRedialNextTimeout = -1;
- randinit();
- } else {
- timeout = atoi(dot);
- if (timeout >= 0)
- VarRedialNextTimeout = timeout;
- else {
- LogPrintf(LogWARN, "Invalid next redial timeout\n");
- return -1;
- }
- }
- } else
- VarRedialNextTimeout = NEXT_REDIAL_PERIOD; /* Default next timeout */
-
- if (arg->argc == 2) {
- tries = atoi(arg->argv[1]);
-
- if (tries >= 0) {
- VarDialTries = tries;
- } else {
- LogPrintf(LogWARN, "Invalid retry value\n");
- return 1;
- }
+ if (strcasecmp(arg->argv[arg->argn], "sync") == 0) {
+ physical_SetSync(arg->cx->physical);
+ return 0;
}
- return 0;
- }
+ 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");
+
return -1;
}
static int
SetStoppedTimeout(struct cmdargs const *arg)
{
- LcpFsm.StoppedTimer.load = 0;
- IpcpFsm.StoppedTimer.load = 0;
- CcpFsm.StoppedTimer.load = 0;
- if (arg->argc <= 3) {
- if (arg->argc > 0) {
- LcpFsm.StoppedTimer.load = atoi(arg->argv[0]) * SECTICKS;
- if (arg->argc > 1) {
- IpcpFsm.StoppedTimer.load = atoi(arg->argv[1]) * SECTICKS;
- if (arg->argc > 2)
- CcpFsm.StoppedTimer.load = atoi(arg->argv[2]) * SECTICKS;
- }
+ 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;
}
return 0;
}
@@ -999,48 +972,32 @@ SetServer(struct cmdargs const *arg)
{
int res = -1;
- if (arg->argc > 0 && arg->argc < 4) {
+ if (arg->argc > arg->argn && arg->argc < arg->argn+4) {
const char *port, *passwd, *mask;
/* What's what ? */
- port = arg->argv[0];
- if (arg->argc == 2) {
- if (ismask(arg->argv[1])) {
- passwd = NULL;
- mask = arg->argv[1];
- } else {
- passwd = arg->argv[1];
- mask = NULL;
- }
- } else if (arg->argc == 3) {
- passwd = arg->argv[1];
- mask = arg->argv[2];
+ 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];
if (!ismask(mask))
return -1;
+ } else if (strcasecmp(port, "none") == 0) {
+ if (server_Close(arg->bundle))
+ log_Printf(LogPHASE, "Disabled server port.\n");
+ return 0;
} else
- passwd = mask = NULL;
-
- if (passwd == NULL)
- VarHaveLocalAuthKey = 0;
- else {
- strncpy(VarLocalAuthKey, passwd, sizeof VarLocalAuthKey - 1);
- VarLocalAuthKey[sizeof VarLocalAuthKey - 1] = '\0';
- VarHaveLocalAuthKey = 1;
- }
- LocalAuthInit();
+ return -1;
- if (strcasecmp(port, "none") == 0) {
- int oserver;
+ strncpy(server.passwd, passwd, sizeof server.passwd - 1);
+ server.passwd[sizeof server.passwd - 1] = '\0';
- if (mask != NULL || passwd != NULL)
- return -1;
- oserver = server;
- ServerClose();
- if (oserver != -1)
- LogPrintf(LogPHASE, "Disabling server port.\n");
- res = 0;
- } else if (*port == '/') {
+ if (*port == '/') {
mode_t imask;
+ char *ptr, name[LINE_LEN + 12];
if (mask != NULL) {
unsigned m;
@@ -1051,24 +1008,41 @@ SetServer(struct cmdargs const *arg)
return -1;
} else
imask = (mode_t)-1;
- res = ServerLocalOpen(port, imask);
+
+ ptr = strstr(port, "%d");
+ if (ptr) {
+ snprintf(name, sizeof name, "%.*s%d%s",
+ ptr - port, port, arg->bundle->unit, ptr + 2);
+ port = name;
+ }
+ res = server_LocalOpen(arg->bundle, port, imask);
} else {
- int iport;
+ int iport, add = 0;
if (mask != NULL)
return -1;
+ if (*port == '+') {
+ port++;
+ add = 1;
+ }
if (strspn(port, "0123456789") != strlen(port)) {
struct servent *s;
if ((s = getservbyname(port, "tcp")) == NULL) {
iport = 0;
- LogPrintf(LogWARN, "%s: Invalid port or service\n", port);
+ log_Printf(LogWARN, "%s: Invalid port or service\n", port);
} else
iport = ntohs(s->s_port);
} else
iport = atoi(port);
- res = iport ? ServerTcpOpen(iport) : -1;
+
+ if (iport) {
+ if (add)
+ iport += arg->bundle->unit;
+ res = server_TcpOpen(arg->bundle, iport);
+ } else
+ res = -1;
}
}
@@ -1078,140 +1052,29 @@ SetServer(struct cmdargs const *arg)
static int
SetModemParity(struct cmdargs const *arg)
{
- return arg->argc > 0 ? ChangeParity(*arg->argv) : -1;
-}
-
-static int
-SetLogLevel(struct cmdargs const *arg)
-{
- int i;
- int res;
- int argc;
- char const *const *argv, *argp;
- void (*Discard)(int), (*Keep)(int);
- void (*DiscardAll)(void);
-
- argc = arg->argc;
- argv = arg->argv;
- res = 0;
- if (argc == 0 || strcasecmp(argv[0], "local")) {
- Discard = LogDiscard;
- Keep = LogKeep;
- DiscardAll = LogDiscardAll;
- } else {
- argc--;
- argv++;
- Discard = LogDiscardLocal;
- Keep = LogKeepLocal;
- DiscardAll = LogDiscardAllLocal;
- }
-
- if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-'))
- DiscardAll();
- while (argc--) {
- argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
- for (i = LogMIN; i <= LogMAX; i++)
- if (strcasecmp(argp, LogName(i)) == 0) {
- if (**argv == '-')
- (*Discard)(i);
- else
- (*Keep)(i);
- break;
- }
- if (i > LogMAX) {
- LogPrintf(LogWARN, "%s: Invalid log value\n", argp);
- res = -1;
- }
- argv++;
- }
- return res;
+ return arg->argc > arg->argn ? modem_SetParity(arg->cx->physical,
+ arg->argv[arg->argn]) : -1;
}
static int
SetEscape(struct cmdargs const *arg)
{
int code;
- int argc = arg->argc;
- char const *const *argv = arg->argv;
+ int argc = arg->argc - arg->argn;
+ char const *const *argv = arg->argv + arg->argn;
for (code = 0; code < 33; code++)
- EscMap[code] = 0;
+ arg->cx->physical->async.cfg.EscMap[code] = 0;
while (argc-- > 0) {
sscanf(*argv++, "%x", &code);
code &= 0xff;
- EscMap[code >> 3] |= (1 << (code & 7));
- EscMap[32] = 1;
+ arg->cx->physical->async.cfg.EscMap[code >> 3] |= (1 << (code & 7));
+ arg->cx->physical->async.cfg.EscMap[32] = 1;
}
return 0;
}
-static int
-SetInitialMRU(struct cmdargs const *arg)
-{
- long mru;
- const char *err;
-
- if (arg->argc > 0) {
- mru = atol(*arg->argv);
- if (mru < MIN_MRU)
- err = "Given MRU value (%ld) is too small.\n";
- else if (mru > MAX_MRU)
- err = "Given MRU value (%ld) is too big.\n";
- else {
- VarMRU = mru;
- return 0;
- }
- LogPrintf(LogWARN, err, mru);
- }
- return -1;
-}
-
-static int
-SetPreferredMTU(struct cmdargs const *arg)
-{
- long mtu;
- const char *err;
-
- if (arg->argc > 0) {
- mtu = atol(*arg->argv);
- if (mtu == 0) {
- VarPrefMTU = 0;
- return 0;
- } else if (mtu < MIN_MTU)
- err = "Given MTU value (%ld) is too small.\n";
- else if (mtu > MAX_MTU)
- err = "Given MTU value (%ld) is too big.\n";
- else {
- VarPrefMTU = mtu;
- return 0;
- }
- LogPrintf(LogWARN, err, mtu);
- }
- return -1;
-}
-
-static int
-SetTimeout(struct cmdargs const *arg)
-{
- if (arg->argc > 0) {
- VarIdleTimeout = atoi(arg->argv[0]);
- UpdateIdleTimer(); /* If we're connected, restart the idle timer */
- if (arg->argc > 1) {
- VarLqrTimeout = atoi(arg->argv[1]);
- if (VarLqrTimeout < 1)
- VarLqrTimeout = 30;
- if (arg->argc > 2) {
- VarRetryTimeout = atoi(arg->argv[2]);
- if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
- VarRetryTimeout = 3;
- }
- }
- return 0;
- }
- return -1;
-}
-
static struct in_addr
GetIpAddr(const char *cp)
{
@@ -1231,29 +1094,32 @@ GetIpAddr(const char *cp)
static int
SetInterfaceAddr(struct cmdargs const *arg)
{
+ struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
const char *hisaddr;
hisaddr = NULL;
- DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
+ ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY;
+ ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY;
- if (arg->argc > 4)
+ if (arg->argc > arg->argn + 4)
return -1;
- HaveTriggerAddress = 0;
- ifnetmask.s_addr = 0;
- iplist_reset(&DefHisChoice);
+ ipcp->cfg.HaveTriggerAddress = 0;
+ ipcp->cfg.netmask.s_addr = INADDR_ANY;
+ iplist_reset(&ipcp->cfg.peer_list);
- if (arg->argc > 0) {
- if (!ParseAddr(arg->argc, arg->argv, &DefMyAddress.ipaddr,
- &DefMyAddress.mask, &DefMyAddress.width))
+ if (arg->argc > arg->argn) {
+ if (!ParseAddr(ipcp, arg->argc - arg->argn, arg->argv + arg->argn,
+ &ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask,
+ &ipcp->cfg.my_range.width))
return 1;
- if (arg->argc > 1) {
- hisaddr = arg->argv[1];
- if (arg->argc > 2) {
- ifnetmask = GetIpAddr(arg->argv[2]);
- if (arg->argc > 3) {
- TriggerAddress = GetIpAddr(arg->argv[3]);
- HaveTriggerAddress = 1;
+ if (arg->argc > arg->argn+1) {
+ hisaddr = arg->argv[arg->argn+1];
+ if (arg->argc > arg->argn+2) {
+ ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]);
+ if (arg->argc > arg->argn+3) {
+ ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]);
+ ipcp->cfg.HaveTriggerAddress = 1;
}
}
}
@@ -1262,157 +1128,294 @@ SetInterfaceAddr(struct cmdargs const *arg)
/*
* For backwards compatibility, 0.0.0.0 means any address.
*/
- if (DefMyAddress.ipaddr.s_addr == 0) {
- DefMyAddress.mask.s_addr = 0;
- DefMyAddress.width = 0;
- }
- IpcpInfo.want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
- if (DefHisAddress.ipaddr.s_addr == 0) {
- DefHisAddress.mask.s_addr = 0;
- DefHisAddress.width = 0;
+ 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;
}
+ ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr;
- if (hisaddr && !UseHisaddr(hisaddr, mode & MODE_AUTO))
- return 4;
-
- return 0;
-}
-
-#ifndef NOMSEXT
-
-static void
-SetMSEXT(struct in_addr * pri_addr,
- struct in_addr * sec_addr,
- int argc,
- char const *const *argv)
-{
- int dummyint;
- struct in_addr dummyaddr;
-
- pri_addr->s_addr = sec_addr->s_addr = 0L;
-
- if (argc > 0) {
- ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
- if (--argc > 0)
- ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
- else
- sec_addr->s_addr = pri_addr->s_addr;
+ if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) {
+ ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY;
+ ipcp->cfg.peer_range.width = 0;
}
- /*
- * if the primary/secondary ns entries are 0.0.0.0 we should set them to
- * either the localhost's ip, or the values in /etc/resolv.conf ??
- *
- * up to you if you want to implement this...
- */
-
-}
+ if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr,
+ arg->bundle->phys_type & PHYS_DEMAND))
+ return 4;
-static int
-SetNS(struct cmdargs const *arg)
-{
- SetMSEXT(&ns_entries[0], &ns_entries[1], arg->argc, arg->argv);
return 0;
}
static int
-SetNBNS(struct cmdargs const *arg)
-{
- SetMSEXT(&nbns_entries[0], &nbns_entries[1], arg->argc, arg->argv);
- return 0;
-}
-
-#endif /* MS_EXT */
-
-int
SetVariable(struct cmdargs const *arg)
{
- u_long map;
+ u_long ulong_val;
const char *argp;
- int param = (int)arg->data;
+ int param = (int)arg->cmd->args, mode;
+ struct datalink *cx = arg->cx; /* LOCAL_CX uses this */
+ const char *err = NULL;
+ struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */
+ int dummyint;
+ struct in_addr dummyaddr, *addr;
- if (arg->argc > 0)
- argp = *arg->argv;
+ if (!l)
+ return -1;
+
+ if (arg->argc > arg->argn)
+ argp = arg->argv[arg->argn];
else
argp = "";
+ 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;
+ }
+
switch (param) {
case VAR_AUTHKEY:
- strncpy(VarAuthKey, argp, sizeof VarAuthKey - 1);
- VarAuthKey[sizeof VarAuthKey - 1] = '\0';
+ if (bundle_Phase(arg->bundle) == PHASE_DEAD) {
+ 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';
+ } else {
+ err = "set authkey: Only available at phase DEAD\n";
+ log_Printf(LogWARN, err);
+ }
break;
case VAR_AUTHNAME:
- strncpy(VarAuthName, argp, sizeof VarAuthName - 1);
- VarAuthName[sizeof VarAuthName - 1] = '\0';
+ if (bundle_Phase(arg->bundle) == PHASE_DEAD) {
+ 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';
+ } else {
+ err = "set authname: Only available at phase DEAD\n";
+ log_Printf(LogWARN, err);
+ }
+ break;
+ case VAR_AUTOLOAD:
+ if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) {
+ arg->bundle->autoload.running = 1;
+ arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]);
+ arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]);
+ if (arg->argc == arg->argn + 4) {
+ arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]);
+ arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]);
+ } else {
+ arg->bundle->cfg.autoload.min.timeout = 0;
+ arg->bundle->cfg.autoload.min.packets = 0;
+ }
+ } else {
+ err = "Set autoload requires two or four arguments\n";
+ log_Printf(LogWARN, err);
+ }
break;
case VAR_DIAL:
- strncpy(VarDialScript, argp, sizeof VarDialScript - 1);
- VarDialScript[sizeof VarDialScript - 1] = '\0';
+ strncpy(cx->cfg.script.dial, argp, sizeof cx->cfg.script.dial - 1);
+ cx->cfg.script.dial[sizeof cx->cfg.script.dial - 1] = '\0';
break;
case VAR_LOGIN:
- strncpy(VarLoginScript, argp, sizeof VarLoginScript - 1);
- VarLoginScript[sizeof VarLoginScript - 1] = '\0';
+ strncpy(cx->cfg.script.login, argp, sizeof cx->cfg.script.login - 1);
+ cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0';
+ break;
+ 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);
+ }
break;
case VAR_DEVICE:
- if (mode & MODE_INTER)
- HangupModem(0);
- if (modem != -1)
- LogPrintf(LogWARN, "Cannot change device to \"%s\" when \"%s\" is open\n",
- argp, VarDevice);
+ physical_SetDeviceList(cx->physical, arg->argc - arg->argn,
+ arg->argv + arg->argn);
+ break;
+ case VAR_ACCMAP:
+ if (arg->argc > arg->argn) {
+ sscanf(argp, "%lx", &ulong_val);
+ cx->physical->link.lcp.cfg.accmap = ulong_val;
+ } else {
+ err = "No accmap specified\n";
+ log_Printf(LogWARN, err);
+ }
+ break;
+ 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;
+ case VAR_MRRU:
+ if (bundle_Phase(arg->bundle) != PHASE_DEAD)
+ log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n");
else {
- strncpy(VarDeviceList, argp, sizeof VarDeviceList - 1);
- VarDeviceList[sizeof VarDeviceList - 1] = '\0';
+ ulong_val = atol(argp);
+ if (ulong_val < MIN_MRU)
+ err = "Given MRRU value (%lu) is too small.\n";
+ else if (ulong_val > MAX_MRU)
+ err = "Given MRRU value (%lu) is too big.\n";
+ else
+ arg->bundle->ncp.mp.cfg.mrru = ulong_val;
+ if (err)
+ log_Printf(LogWARN, err, ulong_val);
}
break;
- case VAR_ACCMAP:
- sscanf(argp, "%lx", &map);
- VarAccmap = map;
+ case VAR_MRU:
+ ulong_val = atol(argp);
+ if (ulong_val < MIN_MRU)
+ err = "Given MRU value (%lu) is too small.\n";
+ else if (ulong_val > MAX_MRU)
+ err = "Given MRU value (%lu) is too big.\n";
+ else
+ l->lcp.cfg.mru = ulong_val;
+ if (err)
+ log_Printf(LogWARN, err, ulong_val);
+ break;
+ case VAR_MTU:
+ ulong_val = atol(argp);
+ if (ulong_val == 0)
+ arg->bundle->cfg.mtu = 0;
+ else if (ulong_val < MIN_MTU)
+ err = "Given MTU value (%lu) is too small.\n";
+ else if (ulong_val > MAX_MTU)
+ err = "Given MTU value (%lu) is too big.\n";
+ else
+ arg->bundle->cfg.mtu = ulong_val;
+ if (err)
+ log_Printf(LogWARN, err, ulong_val);
+ break;
+ 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);
+ }
break;
case VAR_PHONE:
- strncpy(VarPhoneList, argp, sizeof VarPhoneList - 1);
- VarPhoneList[sizeof VarPhoneList - 1] = '\0';
- strncpy(VarPhoneCopy, VarPhoneList, sizeof VarPhoneCopy - 1);
- VarPhoneCopy[sizeof VarPhoneCopy - 1] = '\0';
- VarNextPhone = VarPhoneCopy;
- VarAltPhone = NULL;
+ strncpy(cx->cfg.phone.list, argp, sizeof cx->cfg.phone.list - 1);
+ cx->cfg.phone.list[sizeof cx->cfg.phone.list - 1] = '\0';
break;
case VAR_HANGUP:
- strncpy(VarHangupScript, argp, sizeof VarHangupScript - 1);
- VarHangupScript[sizeof VarHangupScript - 1] = '\0';
+ strncpy(cx->cfg.script.hangup, argp, sizeof cx->cfg.script.hangup - 1);
+ cx->cfg.script.hangup[sizeof cx->cfg.script.hangup - 1] = '\0';
break;
-#ifdef HAVE_DES
- case VAR_ENC:
- VarMSChap = !strcasecmp(argp, "mschap");
+ case VAR_IDLETIMEOUT:
+ if (arg->argc > arg->argn+1)
+ err = "Too many idle timeout values\n";
+ else if (arg->argc == arg->argn+1)
+ bundle_SetIdleTimer(arg->bundle, atoi(argp));
+ if (err)
+ log_Printf(LogWARN, err);
break;
-#endif
- }
- return 0;
-}
-
-static int
-SetCtsRts(struct cmdargs const *arg)
-{
- if (arg->argc > 0) {
- if (strcmp(*arg->argv, "on") == 0)
- VarCtsRts = 1;
- else if (strcmp(*arg->argv, "off") == 0)
- VarCtsRts = 0;
+ case VAR_LQRPERIOD:
+ ulong_val = atol(argp);
+ if (ulong_val <= 0) {
+ err = "%s: Invalid lqr period\n";
+ log_Printf(LogWARN, err, argp);
+ } else
+ l->lcp.cfg.lqrperiod = ulong_val;
+ break;
+ case VAR_LCPRETRY:
+ ulong_val = atol(argp);
+ if (ulong_val <= 0) {
+ err = "%s: Invalid LCP FSM retry period\n";
+ log_Printf(LogWARN, err, argp);
+ } else
+ cx->physical->link.lcp.cfg.fsmretry = ulong_val;
+ break;
+ case VAR_CHAPRETRY:
+ ulong_val = atol(argp);
+ if (ulong_val <= 0) {
+ err = "%s: Invalid CHAP retry period\n";
+ log_Printf(LogWARN, err, argp);
+ } else
+ cx->chap.auth.cfg.fsmretry = ulong_val;
+ break;
+ case VAR_PAPRETRY:
+ ulong_val = atol(argp);
+ if (ulong_val <= 0) {
+ err = "%s: Invalid PAP retry period\n";
+ log_Printf(LogWARN, err, argp);
+ } else
+ cx->pap.cfg.fsmretry = ulong_val;
+ break;
+ case VAR_CCPRETRY:
+ ulong_val = atol(argp);
+ if (ulong_val <= 0) {
+ err = "%s: Invalid CCP FSM retry period\n";
+ log_Printf(LogWARN, err, argp);
+ } else
+ l->ccp.cfg.fsmretry = ulong_val;
+ break;
+ case VAR_IPCPRETRY:
+ ulong_val = atol(argp);
+ if (ulong_val <= 0) {
+ err = "%s: Invalid IPCP FSM retry period\n";
+ log_Printf(LogWARN, err, argp);
+ } else
+ arg->bundle->ncp.ipcp.cfg.fsmretry = ulong_val;
+ break;
+ case VAR_NBNS:
+ case VAR_DNS:
+ if (param == VAR_DNS)
+ addr = arg->bundle->ncp.ipcp.cfg.ns.dns;
else
- return -1;
- return 0;
+ addr = arg->bundle->ncp.ipcp.cfg.ns.nbns;
+
+ addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
+
+ if (arg->argc > arg->argn) {
+ ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn,
+ addr, &dummyaddr, &dummyint);
+ if (arg->argc > arg->argn+1)
+ ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn + 1,
+ 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;
}
- return -1;
-}
+ return err ? 1 : 0;
+}
static int
-SetOpenMode(struct cmdargs const *arg)
+SetCtsRts(struct cmdargs const *arg)
{
- if (arg->argc > 0) {
- if (strcasecmp(*arg->argv, "active") == 0)
- VarOpenMode = arg->argc > 1 ? atoi(arg->argv[1]) : 1;
- else if (strcasecmp(*arg->argv, "passive") == 0)
- VarOpenMode = OPEN_PASSIVE;
+ if (arg->argc == arg->argn+1) {
+ if (strcmp(arg->argv[arg->argn], "on") == 0)
+ physical_SetRtsCts(arg->cx->physical, 1);
+ else if (strcmp(arg->argv[arg->argn], "off") == 0)
+ physical_SetRtsCts(arg->cx->physical, 0);
else
return -1;
return 0;
@@ -1421,72 +1424,87 @@ SetOpenMode(struct cmdargs const *arg)
}
static struct cmdtab const SetCommands[] = {
- {"accmap", NULL, SetVariable, LOCAL_AUTH,
- "Set accmap value", "set accmap hex-value", (const void *) VAR_ACCMAP},
- {"afilter", NULL, SetAfilter, LOCAL_AUTH,
- "Set keep Alive filter", "set afilter ..."},
+ {"accmap", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
+ "accmap value", "set accmap hex-value", (const void *)VAR_ACCMAP},
{"authkey", "key", SetVariable, LOCAL_AUTH,
- "Set authentication key", "set authkey|key key", (const void *) VAR_AUTHKEY},
+ "authentication key", "set authkey|key key", (const void *)VAR_AUTHKEY},
{"authname", NULL, SetVariable, LOCAL_AUTH,
- "Set authentication name", "set authname name", (const void *) VAR_AUTHNAME},
- {"ctsrts", NULL, SetCtsRts, LOCAL_AUTH,
- "Use CTS/RTS modem signalling", "set ctsrts [on|off]"},
- {"device", "line", SetVariable, LOCAL_AUTH, "Set modem device name",
- "set device|line device-name[,device-name]", (const void *) VAR_DEVICE},
- {"dfilter", NULL, SetDfilter, LOCAL_AUTH,
- "Set demand filter", "set dfilter ..."},
- {"dial", NULL, SetVariable, LOCAL_AUTH,
- "Set dialing script", "set dial chat-script", (const void *) VAR_DIAL},
-#ifdef HAVE_DES
- {"encrypt", NULL, SetVariable, LOCAL_AUTH, "Set CHAP encryption algorithm",
- "set encrypt MSChap|MD5", (const void *) VAR_ENC},
-#endif
- {"escape", NULL, SetEscape, LOCAL_AUTH,
- "Set escape characters", "set escape hex-digit ..."},
- {"hangup", NULL, SetVariable, LOCAL_AUTH,
- "Set hangup script", "set hangup chat-script", (const void *) VAR_HANGUP},
- {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "Set destination address",
+ "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},
+ {"ccpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
+ "FSM retry period", "set ccpretry value", (const void *)VAR_CCPRETRY},
+ {"chapretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
+ "CHAP retry period", "set chapretry value", (const void *)VAR_CHAPRETRY},
+ {"ctsrts", "crtscts", SetCtsRts, LOCAL_AUTH | LOCAL_CX,
+ "Use hardware flow control", "set ctsrts [on|off]"},
+ {"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,
+ "modem device name", "set device|line device-name[,device-name]",
+ (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 "
+ "[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp [src [lt|eq|gt port]] "
+ "[dst [lt|eq|gt port]] [estab] [syn] [finrst]]"},
+ {"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
+ "hangup script", "set hangup chat-script", (const void *) VAR_HANGUP},
+ {"ifaddr", NULL, SetInterfaceAddr, LOCAL_AUTH, "destination address",
"set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
- {"ifilter", NULL, SetIfilter, LOCAL_AUTH,
- "Set input filter", "set ifilter ..."},
- {"loopback", NULL, SetLoopback, LOCAL_AUTH,
- "Set loopback facility", "set loopback on|off"},
- {"log", NULL, SetLogLevel, LOCAL_AUTH,
- "Set log level", "set log [local] [+|-]value..."},
- {"login", NULL, SetVariable, LOCAL_AUTH,
- "Set login script", "set login chat-script", (const void *) VAR_LOGIN},
- {"mru", NULL, SetInitialMRU, LOCAL_AUTH,
- "Set Initial MRU value", "set mru value"},
- {"mtu", NULL, SetPreferredMTU, LOCAL_AUTH,
- "Set Preferred MTU value", "set mtu value"},
-#ifndef NOMSEXT
- {"nbns", NULL, SetNBNS, LOCAL_AUTH,
- "Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"},
- {"ns", NULL, SetNS, LOCAL_AUTH,
- "Set NameServer", "set ns pri-addr [sec-addr]"},
-#endif
- {"ofilter", NULL, SetOfilter, LOCAL_AUTH,
- "Set output filter", "set ofilter ..."},
- {"openmode", NULL, SetOpenMode, LOCAL_AUTH,
- "Set open mode", "set openmode [active|passive]"},
- {"parity", NULL, SetModemParity, LOCAL_AUTH,
- "Set modem parity", "set parity [odd|even|none]"},
- {"phone", NULL, SetVariable, LOCAL_AUTH, "Set telephone number(s)",
- "set phone phone1[:phone2[...]]", (const void *) VAR_PHONE},
- {"reconnect", NULL, SetReconnect, LOCAL_AUTH,
- "Set Reconnect timeout", "set reconnect value ntries"},
- {"redial", NULL, SetRedialTimeout, LOCAL_AUTH, "Set Redial timeout",
- "set redial value|random[.value|random] [dial_attempts]"},
- {"stopped", NULL, SetStoppedTimeout, LOCAL_AUTH, "Set STOPPED timeouts",
- "set stopped [LCPseconds [IPCPseconds [CCPseconds]]]"},
+ {"ipcpretry", NULL, SetVariable, LOCAL_AUTH,
+ "FSM retry period", "set ipcpretry value", (const void *)VAR_IPCPRETRY},
+ {"lcpretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
+ "FSM retry period", "set lcpretry value", (const void *)VAR_LCPRETRY},
+ {"log", NULL, log_SetLevel, LOCAL_AUTH,
+ "log level", "set log [local] [+|-]value..."},
+ {"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},
+ {"papretry", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
+ "PAP retry period", "set papretry value", (const void *)VAR_PAPRETRY},
+ {"parity", NULL, SetModemParity, LOCAL_AUTH | LOCAL_CX,
+ "modem parity", "set parity [odd|even|none]"},
+ {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)",
+ "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE},
+ {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX,
+ "Reconnect timeout", "set reconnect value ntries"},
+ {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX,
+ "Redial timeout", "set redial value|random[.value|random] [attempts]"},
{"server", "socket", SetServer, LOCAL_AUTH,
- "Set server port", "set server|socket TcpPort|LocalName|none [mask]"},
- {"speed", NULL, SetModemSpeed, LOCAL_AUTH,
- "Set modem speed", "set speed value"},
- {"timeout", NULL, SetTimeout, LOCAL_AUTH,
- "Set Idle timeout", "set timeout idle LQR FSM-resend"},
- {"vj", NULL, SetInitVJ, LOCAL_AUTH,
- "Set vj values", "set vj slots|slotcomp"},
+ "server port", "set server|socket TcpPort|LocalName|none [mask]"},
+ {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX,
+ "modem speed", "set speed value"},
+ {"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},
+ {"vj", NULL, ipcp_vjset, LOCAL_AUTH,
+ "vj values", "set vj slots|slotcomp [value]"},
+ {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX,
+ "datalink weighting", "set weight n"},
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
"Display this message", "set help|? [command]", SetCommands},
{NULL, NULL, NULL},
@@ -1495,13 +1513,14 @@ static struct cmdtab const SetCommands[] = {
static int
SetCommand(struct cmdargs const *arg)
{
- if (arg->argc > 0)
- FindExec(SetCommands, arg->argc, arg->argv, "set ");
- else if (VarTerm)
- fprintf(VarTerm, "Use `set ?' to get a arg->cmd or `set ? <var>' for"
+ 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"
" syntax help.\n");
else
- LogPrintf(LogWARN, "set command must have arguments\n");
+ log_Printf(LogWARN, "set command must have arguments\n");
return 0;
}
@@ -1511,35 +1530,52 @@ static int
AddCommand(struct cmdargs const *arg)
{
struct in_addr dest, gateway, netmask;
- int gw;
+ int gw, addrs;
- if (arg->argc != 3 && arg->argc != 2)
+ if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2)
return -1;
- if (arg->argc == 2) {
- if (strcasecmp(arg->argv[0], "default"))
- return -1;
- else {
+ addrs = 0;
+ if (arg->argc == arg->argn+2) {
+ if (!strcasecmp(arg->argv[arg->argn], "default"))
dest.s_addr = netmask.s_addr = INADDR_ANY;
- gw = 1;
+ else {
+ int width;
+
+ if (!ParseAddr(&arg->bundle->ncp.ipcp, 1, arg->argv + arg->argn,
+ &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;
}
+ gw = 1;
} else {
- if (strcasecmp(arg->argv[0], "MYADDR") == 0)
- dest = IpcpInfo.want_ipaddr;
- else if (strcasecmp(arg->argv[0], "HISADDR") == 0)
- dest = IpcpInfo.his_ipaddr;
- else
- dest = GetIpAddr(arg->argv[0]);
- netmask = GetIpAddr(arg->argv[1]);
+ 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]);
gw = 2;
}
- if (strcasecmp(arg->argv[gw], "HISADDR") == 0)
- gateway = IpcpInfo.his_ipaddr;
- else if (strcasecmp(arg->argv[gw], "INTERFACE") == 0)
+
+ if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) {
+ gateway = arg->bundle->ncp.ipcp.peer_ip;
+ addrs |= ROUTE_GWHISADDR;
+ } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0)
gateway.s_addr = INADDR_ANY;
else
- gateway = GetIpAddr(arg->argv[gw]);
- OsSetRoute(RTM_ADD, dest, gateway, netmask, arg->data ? 1 : 0);
+ gateway = GetIpAddr(arg->argv[arg->argn+gw]);
+
+ if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask,
+ arg->cmd->args ? 1 : 0))
+ route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway);
+
return 0;
}
@@ -1547,19 +1583,31 @@ static int
DeleteCommand(struct cmdargs const *arg)
{
struct in_addr dest, none;
+ int addrs;
- if (arg->argc == 1) {
- if(strcasecmp(arg->argv[0], "all") == 0)
- DeleteIfRoutes(0);
- else {
- if (strcasecmp(arg->argv[0], "MYADDR") == 0)
- dest = IpcpInfo.want_ipaddr;
- else if (strcasecmp(arg->argv[0], "default") == 0)
- dest.s_addr = INADDR_ANY;
- else
- dest = GetIpAddr(arg->argv[0]);
+ 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 {
+ if (strcasecmp(arg->argv[arg->argn], "default") == 0)
+ dest.s_addr = INADDR_ANY;
+ else
+ dest = GetIpAddr(arg->argv[arg->argn]);
+ addrs = ROUTE_STATIC;
+ }
none.s_addr = INADDR_ANY;
- OsSetRoute(RTM_DELETE, dest, none, none, arg->data ? 1 : 0);
+ bundle_SetRoute(arg->bundle, RTM_DELETE, dest, none, none,
+ arg->cmd->args ? 1 : 0);
+ route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest);
}
} else
return -1;
@@ -1570,30 +1618,30 @@ DeleteCommand(struct cmdargs const *arg)
#ifndef NOALIAS
static struct cmdtab const AliasCommands[] =
{
- {"enable", NULL, AliasEnable, LOCAL_AUTH,
- "enable IP aliasing", "alias enable [yes|no]"},
- {"port", NULL, AliasRedirectPort, LOCAL_AUTH,
- "port redirection", "alias port [proto addr_local:port_local port_alias]"},
- {"addr", NULL, AliasRedirectAddr, LOCAL_AUTH,
- "static address translation", "alias addr [addr_local addr_alias]"},
+ {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH,
+ "static address translation", "alias addr [addr_local addr_alias]"},
{"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
- "stop incoming connections", "alias deny_incoming [yes|no]",
- (const void *) PKT_ALIAS_DENY_INCOMING},
+ "stop incoming connections", "alias deny_incoming [yes|no]",
+ (const void *) PKT_ALIAS_DENY_INCOMING},
+ {"enable", NULL, AliasEnable, LOCAL_AUTH,
+ "enable IP aliasing", "alias enable [yes|no]"},
{"log", NULL, AliasOption, LOCAL_AUTH,
- "log aliasing link creation", "alias log [yes|no]",
- (const void *) PKT_ALIAS_LOG},
+ "log aliasing link creation", "alias log [yes|no]",
+ (const void *) PKT_ALIAS_LOG},
+ {"port", NULL, alias_RedirectPort, LOCAL_AUTH,
+ "port redirection", "alias port [proto addr_local:port_local port_alias]"},
{"same_ports", NULL, AliasOption, LOCAL_AUTH,
- "try to leave port numbers unchanged", "alias same_ports [yes|no]",
- (const void *) PKT_ALIAS_SAME_PORTS},
- {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
- "allocate host sockets", "alias use_sockets [yes|no]",
- (const void *) PKT_ALIAS_USE_SOCKETS},
+ "try to leave port numbers unchanged", "alias same_ports [yes|no]",
+ (const void *) PKT_ALIAS_SAME_PORTS},
{"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
- "alias unregistered (private) IP address space only",
- "alias unregistered_only [yes|no]",
- (const void *) PKT_ALIAS_UNREGISTERED_ONLY},
+ "alias unregistered (private) IP address space only",
+ "alias unregistered_only [yes|no]",
+ (const void *) PKT_ALIAS_UNREGISTERED_ONLY},
+ {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
+ "allocate host sockets", "alias use_sockets [yes|no]",
+ (const void *) PKT_ALIAS_USE_SOCKETS},
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
- "Display this message", "alias help|? [command]", AliasCommands},
+ "Display this message", "alias help|? [command]", AliasCommands},
{NULL, NULL, NULL},
};
@@ -1601,13 +1649,14 @@ static struct cmdtab const AliasCommands[] =
static int
AliasCommand(struct cmdargs const *arg)
{
- if (arg->argc > 0)
- FindExec(AliasCommands, arg->argc, arg->argv, "alias ");
- else if (VarTerm)
- fprintf(VarTerm, "Use `alias help' to get a arg->cmd or `alias help <option>'"
- " for syntax help.\n");
+ if (arg->argc > arg->argn)
+ FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv,
+ arg->prompt, arg->cx);
+ else if (arg->prompt)
+ prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help"
+ " <option>' for syntax help.\n");
else
- LogPrintf(LogWARN, "alias command must have arguments\n");
+ log_Printf(LogWARN, "alias command must have arguments\n");
return 0;
}
@@ -1615,25 +1664,18 @@ AliasCommand(struct cmdargs const *arg)
static int
AliasEnable(struct cmdargs const *arg)
{
- if (arg->argc == 1) {
- if (strcasecmp(arg->argv[0], "yes") == 0) {
- if (!(mode & MODE_ALIAS)) {
- if (loadAliasHandlers(&VarAliasHandlers) == 0) {
- mode |= MODE_ALIAS;
- return 0;
- }
- LogPrintf(LogWARN, "Cannot load alias library\n");
- return 1;
- }
- return 0;
- } else if (strcasecmp(arg->argv[0], "no") == 0) {
- if (mode & MODE_ALIAS) {
- unloadAliasHandlers();
- mode &= ~MODE_ALIAS;
- }
+ if (arg->argc == arg->argn+1) {
+ if (strcasecmp(arg->argv[arg->argn], "yes") == 0) {
+ if (alias_Load() == 0)
+ return 0;
+ log_Printf(LogWARN, "Cannot load alias library\n");
+ return 1;
+ } else if (strcasecmp(arg->argv[arg->argn], "no") == 0) {
+ alias_Unload();
return 0;
}
}
+
return -1;
}
@@ -1641,20 +1683,20 @@ AliasEnable(struct cmdargs const *arg)
static int
AliasOption(struct cmdargs const *arg)
{
- unsigned param = (unsigned)arg->data;
- if (arg->argc == 1) {
- if (strcasecmp(arg->argv[0], "yes") == 0) {
- if (mode & MODE_ALIAS) {
- VarPacketAliasSetMode(param, param);
+ unsigned param = (unsigned)arg->cmd->args;
+ if (arg->argc == arg->argn+1) {
+ if (strcasecmp(arg->argv[arg->argn], "yes") == 0) {
+ if (alias_IsEnabled()) {
+ (*PacketAlias.SetMode)(param, param);
return 0;
}
- LogPrintf(LogWARN, "alias not enabled\n");
- } else if (strcmp(arg->argv[0], "no") == 0) {
- if (mode & MODE_ALIAS) {
- VarPacketAliasSetMode(0, param);
+ log_Printf(LogWARN, "alias not enabled\n");
+ } else if (strcmp(arg->argv[arg->argn], "no") == 0) {
+ if (alias_IsEnabled()) {
+ (*PacketAlias.SetMode)(0, param);
return 0;
}
- LogPrintf(LogWARN, "alias not enabled\n");
+ log_Printf(LogWARN, "alias not enabled\n");
}
}
return -1;
@@ -1662,10 +1704,10 @@ AliasOption(struct cmdargs const *arg)
#endif /* #ifndef NOALIAS */
static struct cmdtab const AllowCommands[] = {
- {"users", "user", AllowUsers, LOCAL_AUTH,
- "Allow users access to ppp", "allow users logname..."},
{"modes", "mode", AllowModes, LOCAL_AUTH,
"Only allow certain ppp modes", "allow modes mode..."},
+ {"users", "user", AllowUsers, LOCAL_AUTH,
+ "Allow users access to ppp", "allow users logname..."},
{"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
"Display this message", "allow help|? [command]", AllowCommands},
{NULL, NULL, NULL},
@@ -1674,13 +1716,315 @@ static struct cmdtab const AllowCommands[] = {
static int
AllowCommand(struct cmdargs const *arg)
{
- if (arg->argc > 0)
- FindExec(AllowCommands, arg->argc, arg->argv, "allow ");
- else if (VarTerm)
- fprintf(VarTerm, "Use `allow ?' to get a arg->cmd or `allow ? <cmd>' for"
- " syntax help.\n");
+ /* arg->bundle may be NULL (see system_IsValid()) ! */
+ if (arg->argc > arg->argn)
+ FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv,
+ arg->prompt, arg->cx);
+ else if (arg->prompt)
+ prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'"
+ " for syntax help.\n");
else
- LogPrintf(LogWARN, "allow command must have arguments\n");
+ log_Printf(LogWARN, "allow command must have arguments\n");
return 0;
}
+
+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;
+ else if (arg->bundle->ncp.mp.cfg.mrru)
+ return &arg->bundle->ncp.mp.link;
+ else {
+ struct datalink *dl = bundle2datalink(arg->bundle, NULL);
+ return dl ? &dl->physical->link : NULL;
+ }
+}
+
+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)
+{
+ int bit = (int)arg->cmd->args;
+ 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;
+}
+
+static int
+NegotiateSet(struct cmdargs const *arg)
+{
+ int param = (int)arg->cmd->args;
+ 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 (!l)
+ return -1;
+
+ 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;
+ case NEG_CHAP:
+ cx->physical->link.lcp.cfg.chap &= keep;
+ cx->physical->link.lcp.cfg.chap |= add;
+ break;
+ 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;
+ 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:
+ if (bundle_Phase(arg->bundle) != PHASE_DEAD)
+ log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n");
+ else {
+ arg->bundle->ncp.mp.cfg.shortseq &= keep;
+ arg->bundle->ncp.mp.cfg.shortseq |= add;
+ }
+ 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},
+ {"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},
+ {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry",
+ "disable|enable", (const void *)OPT_PROXY},
+ {"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},
+
+#define OPT_MAX 7 /* accept/deny allowed below and not above */
+
+ {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
+ "Address & Control field compression", "accept|deny|disable|enable",
+ (const void *)NEG_ACFCOMP},
+ {"chap", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
+ "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable",
+ (const void *)NEG_CHAP},
+ {"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},
+ {"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";
+}
diff --git a/usr.sbin/ppp/command.h b/usr.sbin/ppp/command.h
index e83114dc8d27..ff5c33a1db0b 100644
--- a/usr.sbin/ppp/command.h
+++ b/usr.sbin/ppp/command.h
@@ -15,18 +15,25 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: command.h,v 1.11 1997/11/13 14:43:15 brian Exp $
+ * $Id: command.h,v 1.12.2.13 1998/05/01 19:24:18 brian Exp $
*
* TODO:
*/
struct cmdtab;
+struct bundle;
+struct datalink;
+struct prompt;
struct cmdargs {
- struct cmdtab const *cmd;
- int argc;
- char const *const *argv;
- const void *data;
+ struct cmdtab const *cmdtab; /* The entire command table */
+ struct cmdtab const *cmd; /* This command entry */
+ int argc; /* Number of arguments (excluding cmd */
+ int argn; /* Argument to start processing from */
+ char const *const *argv; /* Arguments */
+ struct bundle *bundle; /* Our bundle */
+ struct datalink *cx; /* Our context */
+ struct prompt *prompt; /* Who executed us */
};
struct cmdtab {
@@ -39,24 +46,18 @@ struct cmdtab {
const void *args;
};
-#define VAR_AUTHKEY 0
-#define VAR_DIAL 1
-#define VAR_LOGIN 2
-#define VAR_AUTHNAME 3
-#define VAR_DEVICE 4
-#define VAR_ACCMAP 5
-#define VAR_PHONE 6
-#define VAR_HANGUP 7
-#ifdef HAVE_DES
-#define VAR_ENC 8
-#endif
+#define NEG_ACCEPTED (1)
+#define NEG_ENABLED (2)
+#define IsAccepted(x) ((x) & NEG_ACCEPTED)
+#define IsEnabled(x) ((x) & NEG_ENABLED)
-extern struct in_addr ifnetmask;
-extern int aft_cmd;
+extern const char Version[];
+extern const char VersionDate[];
-extern int SetVariable(struct cmdargs const *);
-extern void Prompt(void);
-extern int IsInteractive(int);
-extern void InterpretCommand(char *, int, int *, char ***);
-extern void RunCommand(int, char const *const *, const char *label);
-extern void DecodeCommand(char *, int, const char *label);
+extern void command_Interpret(char *, int, int *, char ***);
+extern void command_Run(struct bundle *, int, char const *const *,
+ struct prompt *, const char *);
+extern void command_Decode(struct bundle *, char *, int, struct prompt *,
+ const char *);
+extern struct link *command_ChooseLink(struct cmdargs const *);
+extern const char *command_ShowNegval(unsigned);
diff --git a/usr.sbin/ppp/datalink.c b/usr.sbin/ppp/datalink.c
new file mode 100644
index 000000000000..0965f0a5a2d5
--- /dev/null
+++ b/usr.sbin/ppp/datalink.c
@@ -0,0 +1,1096 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: datalink.c,v 1.1.2.63 1998/05/16 23:47:24 brian Exp $
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "mbuf.h"
+#include "log.h"
+#include "defs.h"
+#include "timer.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "descriptor.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "async.h"
+#include "throughput.h"
+#include "ccp.h"
+#include "link.h"
+#include "physical.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "mp.h"
+#include "bundle.h"
+#include "chat.h"
+#include "auth.h"
+#include "modem.h"
+#include "prompt.h"
+#include "lcpproto.h"
+#include "pap.h"
+#include "chap.h"
+#include "command.h"
+#include "datalink.h"
+
+static void datalink_LoginDone(struct datalink *);
+static void datalink_NewState(struct datalink *, int);
+
+static void
+datalink_OpenTimeout(void *v)
+{
+ struct datalink *dl = (struct datalink *)v;
+
+ timer_Stop(&dl->dial_timer);
+ if (dl->state == DATALINK_OPENING)
+ log_Printf(LogPHASE, "%s: Redial timer expired.\n", dl->name);
+}
+
+static void
+datalink_StartDialTimer(struct datalink *dl, int Timeout)
+{
+ timer_Stop(&dl->dial_timer);
+
+ if (Timeout) {
+ if (Timeout > 0)
+ dl->dial_timer.load = Timeout * SECTICKS;
+ else
+ dl->dial_timer.load = (random() % DIAL_TIMEOUT) * SECTICKS;
+ dl->dial_timer.func = datalink_OpenTimeout;
+ dl->dial_timer.name = "dial";
+ dl->dial_timer.arg = dl;
+ timer_Start(&dl->dial_timer);
+ if (dl->state == DATALINK_OPENING)
+ log_Printf(LogPHASE, "%s: Enter pause (%d) for redialing.\n",
+ dl->name, Timeout);
+ }
+}
+
+static void
+datalink_HangupDone(struct datalink *dl)
+{
+ if (dl->physical->type == PHYS_DEDICATED && !dl->bundle->CleaningUp &&
+ physical_GetFD(dl->physical) != -1) {
+ /* Don't close our modem if the link is dedicated */
+ datalink_LoginDone(dl);
+ return;
+ }
+
+ modem_Close(dl->physical);
+ dl->phone.chosen = "N/A";
+
+ if (dl->bundle->CleaningUp ||
+ (dl->physical->type == PHYS_DIRECT) ||
+ ((!dl->dial_tries || (dl->dial_tries < 0 && !dl->reconnect_tries)) &&
+ !(dl->physical->type & (PHYS_PERM|PHYS_DEDICATED)))) {
+ datalink_NewState(dl, DATALINK_CLOSED);
+ dl->dial_tries = -1;
+ dl->reconnect_tries = 0;
+ bundle_LinkClosed(dl->bundle, dl);
+ if (!dl->bundle->CleaningUp)
+ datalink_StartDialTimer(dl, dl->cfg.dial.timeout);
+ } else {
+ datalink_NewState(dl, DATALINK_OPENING);
+ if (dl->dial_tries < 0) {
+ datalink_StartDialTimer(dl, dl->cfg.reconnect.timeout);
+ dl->dial_tries = dl->cfg.dial.max;
+ dl->reconnect_tries--;
+ } else {
+ if (dl->phone.next == NULL)
+ datalink_StartDialTimer(dl, dl->cfg.dial.timeout);
+ else
+ datalink_StartDialTimer(dl, dl->cfg.dial.next_timeout);
+ }
+ }
+}
+
+static const char *
+datalink_ChoosePhoneNumber(struct datalink *dl)
+{
+ char *phone;
+
+ if (dl->phone.alt == NULL) {
+ if (dl->phone.next == NULL) {
+ strncpy(dl->phone.list, dl->cfg.phone.list, sizeof dl->phone.list - 1);
+ dl->phone.list[sizeof dl->phone.list - 1] = '\0';
+ dl->phone.next = dl->phone.list;
+ }
+ dl->phone.alt = strsep(&dl->phone.next, ":");
+ }
+ phone = strsep(&dl->phone.alt, "|");
+ dl->phone.chosen = *phone ? phone : "[NONE]";
+ if (*phone)
+ log_Printf(LogPHASE, "Phone: %s\n", phone);
+ return phone;
+}
+
+static void
+datalink_LoginDone(struct datalink *dl)
+{
+ if (!dl->script.packetmode) {
+ dl->dial_tries = -1;
+ datalink_NewState(dl, DATALINK_READY);
+ } else if (modem_Raw(dl->physical, dl->bundle) < 0) {
+ dl->dial_tries = 0;
+ log_Printf(LogWARN, "datalink_LoginDone: Not connected.\n");
+ if (dl->script.run) {
+ datalink_NewState(dl, DATALINK_HANGUP);
+ modem_Offline(dl->physical);
+ chat_Init(&dl->chat, dl->physical, dl->cfg.script.hangup, 1, NULL);
+ } else {
+ if (dl->physical->type == PHYS_DEDICATED)
+ /* force a redial timeout */
+ modem_Close(dl->physical);
+ datalink_HangupDone(dl);
+ }
+ } else {
+ dl->dial_tries = -1;
+
+ hdlc_Init(&dl->physical->hdlc, &dl->physical->link.lcp);
+ async_Init(&dl->physical->async);
+
+ lcp_Setup(&dl->physical->link.lcp, dl->state == DATALINK_READY ?
+ 0 : dl->physical->link.lcp.cfg.openmode);
+ ccp_Setup(&dl->physical->link.ccp);
+
+ datalink_NewState(dl, DATALINK_LCP);
+ fsm_Up(&dl->physical->link.lcp.fsm);
+ fsm_Open(&dl->physical->link.lcp.fsm);
+ }
+}
+
+static int
+datalink_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
+ int *n)
+{
+ struct datalink *dl = descriptor2datalink(d);
+ int result;
+
+ result = 0;
+ switch (dl->state) {
+ case DATALINK_CLOSED:
+ if ((dl->physical->type & (PHYS_DIRECT|PHYS_DEDICATED|PHYS_1OFF)) &&
+ !bundle_IsDead(dl->bundle))
+ /*
+ * Our first time in - DEDICATED never comes down, and STDIN & 1OFF
+ * get deleted when they enter DATALINK_CLOSED. Go to
+ * DATALINK_OPENING via datalink_Up() and fall through.
+ */
+ datalink_Up(dl, 1, 1);
+ else
+ break;
+ /* fall through */
+
+ case DATALINK_OPENING:
+ if (dl->dial_timer.state != TIMER_RUNNING) {
+ if (--dl->dial_tries < 0)
+ dl->dial_tries = 0;
+ if (modem_Open(dl->physical, dl->bundle) >= 0) {
+ if (dl->script.run) {
+ datalink_NewState(dl, DATALINK_DIAL);
+ chat_Init(&dl->chat, dl->physical, dl->cfg.script.dial, 1,
+ datalink_ChoosePhoneNumber(dl));
+ if (!(dl->physical->type & (PHYS_PERM|PHYS_DEDICATED)) &&
+ dl->cfg.dial.max)
+ log_Printf(LogCHAT, "%s: Dial attempt %u of %d\n",
+ dl->name, dl->cfg.dial.max - dl->dial_tries,
+ dl->cfg.dial.max);
+ return datalink_UpdateSet(d, r, w, e, n);
+ } else
+ datalink_LoginDone(dl);
+ } else {
+ if (!(dl->physical->type & (PHYS_PERM|PHYS_DEDICATED)) &&
+ dl->cfg.dial.max)
+ log_Printf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
+ dl->cfg.dial.max - dl->dial_tries, dl->cfg.dial.max);
+ else
+ log_Printf(LogCHAT, "Failed to open modem\n");
+
+ if (dl->bundle->CleaningUp ||
+ (!(dl->physical->type & (PHYS_PERM|PHYS_DEDICATED)) &&
+ dl->cfg.dial.max && dl->dial_tries == 0)) {
+ datalink_NewState(dl, DATALINK_CLOSED);
+ dl->reconnect_tries = 0;
+ dl->dial_tries = -1;
+ bundle_LinkClosed(dl->bundle, dl);
+ }
+ if (!dl->bundle->CleaningUp)
+ datalink_StartDialTimer(dl, dl->cfg.dial.timeout);
+ }
+ }
+ break;
+
+ case DATALINK_HANGUP:
+ case DATALINK_DIAL:
+ case DATALINK_LOGIN:
+ result = descriptor_UpdateSet(&dl->chat.desc, r, w, e, n);
+ switch (dl->chat.state) {
+ case CHAT_DONE:
+ /* script succeeded */
+ chat_Destroy(&dl->chat);
+ switch(dl->state) {
+ case DATALINK_HANGUP:
+ datalink_HangupDone(dl);
+ break;
+ case DATALINK_DIAL:
+ datalink_NewState(dl, DATALINK_LOGIN);
+ chat_Init(&dl->chat, dl->physical, dl->cfg.script.login, 0, NULL);
+ return datalink_UpdateSet(d, r, w, e, n);
+ case DATALINK_LOGIN:
+ datalink_LoginDone(dl);
+ break;
+ }
+ break;
+ case CHAT_FAILED:
+ /* Going down - script failed */
+ log_Printf(LogWARN, "Chat script failed\n");
+ chat_Destroy(&dl->chat);
+ switch(dl->state) {
+ case DATALINK_HANGUP:
+ datalink_HangupDone(dl);
+ break;
+ case DATALINK_DIAL:
+ case DATALINK_LOGIN:
+ datalink_NewState(dl, DATALINK_HANGUP);
+ modem_Offline(dl->physical);
+ chat_Init(&dl->chat, dl->physical, dl->cfg.script.hangup, 1, NULL);
+ return datalink_UpdateSet(d, r, w, e, n);
+ }
+ break;
+ }
+ break;
+
+ case DATALINK_READY:
+ case DATALINK_LCP:
+ case DATALINK_AUTH:
+ case DATALINK_OPEN:
+ result = descriptor_UpdateSet(&dl->physical->desc, r, w, e, n);
+ break;
+ }
+ return result;
+}
+
+int
+datalink_RemoveFromSet(struct datalink *dl, fd_set *r, fd_set *w, fd_set *e)
+{
+ return physical_RemoveFromSet(dl->physical, r, w, e);
+}
+
+static int
+datalink_IsSet(struct descriptor *d, const fd_set *fdset)
+{
+ struct datalink *dl = descriptor2datalink(d);
+
+ switch (dl->state) {
+ case DATALINK_CLOSED:
+ case DATALINK_OPENING:
+ break;
+
+ case DATALINK_HANGUP:
+ case DATALINK_DIAL:
+ case DATALINK_LOGIN:
+ return descriptor_IsSet(&dl->chat.desc, fdset);
+
+ case DATALINK_READY:
+ case DATALINK_LCP:
+ case DATALINK_AUTH:
+ case DATALINK_OPEN:
+ return descriptor_IsSet(&dl->physical->desc, fdset);
+ }
+ return 0;
+}
+
+static void
+datalink_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ struct datalink *dl = descriptor2datalink(d);
+
+ switch (dl->state) {
+ case DATALINK_CLOSED:
+ case DATALINK_OPENING:
+ break;
+
+ case DATALINK_HANGUP:
+ case DATALINK_DIAL:
+ case DATALINK_LOGIN:
+ descriptor_Read(&dl->chat.desc, bundle, fdset);
+ break;
+
+ case DATALINK_READY:
+ case DATALINK_LCP:
+ case DATALINK_AUTH:
+ case DATALINK_OPEN:
+ descriptor_Read(&dl->physical->desc, bundle, fdset);
+ break;
+ }
+}
+
+static void
+datalink_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ struct datalink *dl = descriptor2datalink(d);
+
+ switch (dl->state) {
+ case DATALINK_CLOSED:
+ case DATALINK_OPENING:
+ break;
+
+ case DATALINK_HANGUP:
+ case DATALINK_DIAL:
+ case DATALINK_LOGIN:
+ descriptor_Write(&dl->chat.desc, bundle, fdset);
+ break;
+
+ case DATALINK_READY:
+ case DATALINK_LCP:
+ case DATALINK_AUTH:
+ case DATALINK_OPEN:
+ descriptor_Write(&dl->physical->desc, bundle, fdset);
+ break;
+ }
+}
+
+static void
+datalink_ComeDown(struct datalink *dl, int stay)
+{
+ if (stay) {
+ dl->dial_tries = -1;
+ dl->reconnect_tries = 0;
+ }
+
+ if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) {
+ modem_Offline(dl->physical);
+ if (dl->script.run && dl->state != DATALINK_OPENING) {
+ datalink_NewState(dl, DATALINK_HANGUP);
+ chat_Init(&dl->chat, dl->physical, dl->cfg.script.hangup, 1, NULL);
+ } else
+ datalink_HangupDone(dl);
+ }
+}
+
+static void
+datalink_LayerStart(void *v, struct fsm *fp)
+{
+ /* The given FSM is about to start up ! */
+ struct datalink *dl = (struct datalink *)v;
+
+ if (fp->proto == PROTO_LCP)
+ (*dl->parent->LayerStart)(dl->parent->object, fp);
+}
+
+static void
+datalink_LayerUp(void *v, struct fsm *fp)
+{
+ /* The given fsm is now up */
+ struct datalink *dl = (struct datalink *)v;
+
+ if (fp->proto == PROTO_LCP) {
+ datalink_GotAuthname(dl, "", 0);
+ dl->physical->link.lcp.auth_ineed = dl->physical->link.lcp.want_auth;
+ dl->physical->link.lcp.auth_iwait = dl->physical->link.lcp.his_auth;
+ if (dl->physical->link.lcp.his_auth || dl->physical->link.lcp.want_auth) {
+ if (bundle_Phase(dl->bundle) == PHASE_ESTABLISH)
+ bundle_NewPhase(dl->bundle, PHASE_AUTHENTICATE);
+ log_Printf(LogPHASE, "%s: his = %s, mine = %s\n", dl->name,
+ Auth2Nam(dl->physical->link.lcp.his_auth),
+ Auth2Nam(dl->physical->link.lcp.want_auth));
+ if (dl->physical->link.lcp.his_auth == PROTO_PAP)
+ auth_StartChallenge(&dl->pap, dl->physical, pap_SendChallenge);
+ if (dl->physical->link.lcp.want_auth == PROTO_CHAP)
+ auth_StartChallenge(&dl->chap.auth, dl->physical, chap_SendChallenge);
+ } else
+ datalink_AuthOk(dl);
+ }
+}
+
+void
+datalink_GotAuthname(struct datalink *dl, const char *name, int len)
+{
+ if (len >= sizeof dl->peer.authname)
+ len = sizeof dl->peer.authname - 1;
+ strncpy(dl->peer.authname, name, len);
+ dl->peer.authname[len] = '\0';
+}
+
+void
+datalink_AuthOk(struct datalink *dl)
+{
+ if (dl->physical->link.lcp.want_mrru && dl->physical->link.lcp.his_mrru) {
+ /* we've authenticated in multilink mode ! */
+ switch (mp_Up(&dl->bundle->ncp.mp, dl)) {
+ case MP_LINKSENT:
+ /* We've handed the link off to another ppp (well, we will soon) ! */
+ return;
+ case MP_UP:
+ /* First link in the bundle */
+ auth_Select(dl->bundle, dl->peer.authname, dl->physical);
+ /* fall through */
+ case MP_ADDED:
+ /* We're in multilink mode ! */
+ dl->physical->link.ccp.fsm.open_mode = OPEN_PASSIVE;
+ break;
+ case MP_FAILED:
+ datalink_AuthNotOk(dl);
+ return;
+ }
+ } else if (bundle_Phase(dl->bundle) == PHASE_NETWORK) {
+ log_Printf(LogPHASE, "%s: Already in NETWORK phase\n", dl->name);
+ datalink_AuthNotOk(dl);
+ return;
+ } else {
+ dl->bundle->ncp.mp.peer = dl->peer;
+ ipcp_SetLink(&dl->bundle->ncp.ipcp, &dl->physical->link);
+ auth_Select(dl->bundle, dl->peer.authname, dl->physical);
+ }
+
+ fsm_Up(&dl->physical->link.ccp.fsm);
+ fsm_Open(&dl->physical->link.ccp.fsm);
+ datalink_NewState(dl, DATALINK_OPEN);
+ bundle_NewPhase(dl->bundle, PHASE_NETWORK);
+ (*dl->parent->LayerUp)(dl->parent->object, &dl->physical->link.lcp.fsm);
+}
+
+void
+datalink_AuthNotOk(struct datalink *dl)
+{
+ datalink_NewState(dl, DATALINK_LCP);
+ fsm_Close(&dl->physical->link.lcp.fsm);
+}
+
+static void
+datalink_LayerDown(void *v, struct fsm *fp)
+{
+ /* The given FSM has been told to come down */
+ struct datalink *dl = (struct datalink *)v;
+
+ if (fp->proto == PROTO_LCP) {
+ switch (dl->state) {
+ case DATALINK_OPEN:
+ peerid_Init(&dl->peer);
+ fsm_Down(&dl->physical->link.ccp.fsm);
+ fsm_Close(&dl->physical->link.ccp.fsm);
+ (*dl->parent->LayerDown)(dl->parent->object, fp);
+ /* fall through */
+
+ case DATALINK_AUTH:
+ timer_Stop(&dl->pap.authtimer);
+ timer_Stop(&dl->chap.auth.authtimer);
+ }
+ datalink_NewState(dl, DATALINK_LCP);
+ }
+}
+
+static void
+datalink_LayerFinish(void *v, struct fsm *fp)
+{
+ /* The given fsm is now down */
+ struct datalink *dl = (struct datalink *)v;
+
+ if (fp->proto == PROTO_LCP) {
+ fsm_Down(fp); /* Bring us to INITIAL or STARTING */
+ (*dl->parent->LayerFinish)(dl->parent->object, fp);
+ datalink_ComeDown(dl, 0);
+ } else if (fp->state == ST_CLOSED && fp->open_mode == OPEN_PASSIVE)
+ fsm_Open(fp); /* CCP goes to ST_STOPPED */
+}
+
+struct datalink *
+datalink_Create(const char *name, struct bundle *bundle, int type)
+{
+ struct datalink *dl;
+
+ dl = (struct datalink *)malloc(sizeof(struct datalink));
+ if (dl == NULL)
+ return dl;
+
+ dl->desc.type = DATALINK_DESCRIPTOR;
+ dl->desc.next = NULL;
+ dl->desc.UpdateSet = datalink_UpdateSet;
+ dl->desc.IsSet = datalink_IsSet;
+ dl->desc.Read = datalink_Read;
+ dl->desc.Write = datalink_Write;
+
+ dl->state = DATALINK_CLOSED;
+
+ *dl->cfg.script.dial = '\0';
+ *dl->cfg.script.login = '\0';
+ *dl->cfg.script.hangup = '\0';
+ *dl->cfg.phone.list = '\0';
+ *dl->phone.list = '\0';
+ dl->phone.next = NULL;
+ dl->phone.alt = NULL;
+ dl->phone.chosen = "N/A";
+ dl->script.run = 1;
+ dl->script.packetmode = 1;
+ mp_linkInit(&dl->mp);
+
+ dl->bundle = bundle;
+ dl->next = NULL;
+
+ memset(&dl->dial_timer, '\0', sizeof dl->dial_timer);
+
+ dl->dial_tries = 0;
+ dl->cfg.dial.max = 1;
+ dl->cfg.dial.next_timeout = DIAL_NEXT_TIMEOUT;
+ dl->cfg.dial.timeout = DIAL_TIMEOUT;
+
+ dl->reconnect_tries = 0;
+ dl->cfg.reconnect.max = 0;
+ dl->cfg.reconnect.timeout = RECONNECT_TIMEOUT;
+
+ dl->name = strdup(name);
+ peerid_Init(&dl->peer);
+ dl->parent = &bundle->fsm;
+ dl->fsmp.LayerStart = datalink_LayerStart;
+ dl->fsmp.LayerUp = datalink_LayerUp;
+ dl->fsmp.LayerDown = datalink_LayerDown;
+ dl->fsmp.LayerFinish = datalink_LayerFinish;
+ dl->fsmp.object = dl;
+
+ auth_Init(&dl->pap);
+ auth_Init(&dl->chap.auth);
+
+ if ((dl->physical = modem_Create(dl, type)) == NULL) {
+ free(dl->name);
+ free(dl);
+ return NULL;
+ }
+ chat_Init(&dl->chat, dl->physical, NULL, 1, NULL);
+
+ log_Printf(LogPHASE, "%s: Created in %s state\n",
+ dl->name, datalink_State(dl));
+
+ return dl;
+}
+
+struct datalink *
+datalink_Clone(struct datalink *odl, const char *name)
+{
+ struct datalink *dl;
+
+ dl = (struct datalink *)malloc(sizeof(struct datalink));
+ if (dl == NULL)
+ return dl;
+
+ dl->desc.type = DATALINK_DESCRIPTOR;
+ dl->desc.next = NULL;
+ dl->desc.UpdateSet = datalink_UpdateSet;
+ dl->desc.IsSet = datalink_IsSet;
+ dl->desc.Read = datalink_Read;
+ dl->desc.Write = datalink_Write;
+
+ dl->state = DATALINK_CLOSED;
+
+ memcpy(&dl->cfg, &odl->cfg, sizeof dl->cfg);
+ mp_linkInit(&dl->mp);
+ *dl->phone.list = '\0';
+ dl->phone.next = NULL;
+ dl->phone.alt = NULL;
+ dl->phone.chosen = "N/A";
+ dl->bundle = odl->bundle;
+ dl->next = NULL;
+ memset(&dl->dial_timer, '\0', sizeof dl->dial_timer);
+ dl->dial_tries = 0;
+ dl->reconnect_tries = 0;
+ dl->name = strdup(name);
+ peerid_Init(&dl->peer);
+ dl->parent = odl->parent;
+ memcpy(&dl->fsmp, &odl->fsmp, sizeof dl->fsmp);
+ dl->fsmp.object = dl;
+ auth_Init(&dl->pap);
+ dl->pap.cfg.fsmretry = odl->pap.cfg.fsmretry;
+
+ auth_Init(&dl->chap.auth);
+ dl->chap.auth.cfg.fsmretry = odl->chap.auth.cfg.fsmretry;
+
+ if ((dl->physical = modem_Create(dl, PHYS_MANUAL)) == NULL) {
+ free(dl->name);
+ free(dl);
+ return NULL;
+ }
+ memcpy(&dl->physical->cfg, &odl->physical->cfg, sizeof dl->physical->cfg);
+ memcpy(&dl->physical->link.lcp.cfg, &odl->physical->link.lcp.cfg,
+ sizeof dl->physical->link.lcp.cfg);
+ memcpy(&dl->physical->link.ccp.cfg, &odl->physical->link.ccp.cfg,
+ sizeof dl->physical->link.ccp.cfg);
+ memcpy(&dl->physical->async.cfg, &odl->physical->async.cfg,
+ sizeof dl->physical->async.cfg);
+
+ chat_Init(&dl->chat, dl->physical, NULL, 1, NULL);
+
+ log_Printf(LogPHASE, "%s: Cloned in %s state\n",
+ dl->name, datalink_State(dl));
+
+ return dl;
+}
+
+struct datalink *
+datalink_Destroy(struct datalink *dl)
+{
+ struct datalink *result;
+
+ if (dl->state != DATALINK_CLOSED) {
+ log_Printf(LogERROR, "Oops, destroying a datalink in state %s\n",
+ datalink_State(dl));
+ switch (dl->state) {
+ case DATALINK_HANGUP:
+ case DATALINK_DIAL:
+ case DATALINK_LOGIN:
+ chat_Destroy(&dl->chat); /* Gotta blat the timers ! */
+ break;
+ }
+ }
+
+ result = dl->next;
+ modem_Destroy(dl->physical);
+ free(dl->name);
+ free(dl);
+
+ return result;
+}
+
+void
+datalink_Up(struct datalink *dl, int runscripts, int packetmode)
+{
+ if (dl->physical->type & (PHYS_DIRECT|PHYS_DEDICATED))
+ /* Ignore scripts */
+ runscripts = 0;
+
+ switch (dl->state) {
+ case DATALINK_CLOSED:
+ if (bundle_Phase(dl->bundle) == PHASE_DEAD ||
+ bundle_Phase(dl->bundle) == PHASE_TERMINATE)
+ bundle_NewPhase(dl->bundle, PHASE_ESTABLISH);
+ datalink_NewState(dl, DATALINK_OPENING);
+ dl->reconnect_tries =
+ dl->physical->type == PHYS_DIRECT ? 0 : dl->cfg.reconnect.max;
+ dl->dial_tries = dl->cfg.dial.max;
+ dl->script.run = runscripts;
+ dl->script.packetmode = packetmode;
+ break;
+
+ case DATALINK_OPENING:
+ if (!dl->script.run && runscripts)
+ dl->script.run = 1;
+ /* fall through */
+
+ case DATALINK_DIAL:
+ case DATALINK_LOGIN:
+ case DATALINK_READY:
+ if (!dl->script.packetmode && packetmode) {
+ dl->script.packetmode = 1;
+ if (dl->state == DATALINK_READY)
+ datalink_LoginDone(dl);
+ }
+ break;
+ }
+}
+
+void
+datalink_Close(struct datalink *dl, int stay)
+{
+ /* Please close */
+ switch (dl->state) {
+ case DATALINK_OPEN:
+ peerid_Init(&dl->peer);
+ fsm_Down(&dl->physical->link.ccp.fsm);
+ fsm_Close(&dl->physical->link.ccp.fsm);
+ /* fall through */
+
+ case DATALINK_AUTH:
+ case DATALINK_LCP:
+ fsm_Close(&dl->physical->link.lcp.fsm);
+ if (stay) {
+ dl->dial_tries = -1;
+ dl->reconnect_tries = 0;
+ }
+ break;
+
+ default:
+ datalink_ComeDown(dl, stay);
+ }
+}
+
+void
+datalink_Down(struct datalink *dl, int stay)
+{
+ /* Carrier is lost */
+ switch (dl->state) {
+ case DATALINK_OPEN:
+ peerid_Init(&dl->peer);
+ fsm_Down(&dl->physical->link.ccp.fsm);
+ fsm_Close(&dl->physical->link.ccp.fsm);
+ /* fall through */
+
+ case DATALINK_AUTH:
+ case DATALINK_LCP:
+ fsm_Down(&dl->physical->link.lcp.fsm);
+ if (stay)
+ fsm_Close(&dl->physical->link.lcp.fsm);
+ else
+ fsm_Open(&dl->physical->link.ccp.fsm);
+ /* fall through */
+
+ default:
+ datalink_ComeDown(dl, stay);
+ }
+}
+
+void
+datalink_StayDown(struct datalink *dl)
+{
+ dl->reconnect_tries = 0;
+}
+
+int
+datalink_Show(struct cmdargs const *arg)
+{
+ prompt_Printf(arg->prompt, "Name: %s\n", arg->cx->name);
+ prompt_Printf(arg->prompt, " State: %s\n",
+ datalink_State(arg->cx));
+ prompt_Printf(arg->prompt, " CHAP Encryption: %s\n",
+ arg->cx->chap.using_MSChap ? "MSChap" : "MD5" );
+ prompt_Printf(arg->prompt, " Peer name: ");
+ if (*arg->cx->peer.authname)
+ prompt_Printf(arg->prompt, "%s\n", arg->cx->peer.authname);
+ else if (arg->cx->state == DATALINK_OPEN)
+ prompt_Printf(arg->prompt, "None requested\n");
+ else
+ prompt_Printf(arg->prompt, "N/A\n");
+ prompt_Printf(arg->prompt, " Discriminator: %s\n",
+ mp_Enddisc(arg->cx->peer.enddisc.class,
+ arg->cx->peer.enddisc.address,
+ arg->cx->peer.enddisc.len));
+
+ prompt_Printf(arg->prompt, "\nDefaults:\n");
+ prompt_Printf(arg->prompt, " Phone List: %s\n",
+ arg->cx->cfg.phone.list);
+ if (arg->cx->cfg.dial.max)
+ prompt_Printf(arg->prompt, " Dial tries: %d, delay ",
+ arg->cx->cfg.dial.max);
+ else
+ prompt_Printf(arg->prompt, " Dial tries: infinite, delay ");
+ if (arg->cx->cfg.dial.next_timeout > 0)
+ prompt_Printf(arg->prompt, "%ds/", arg->cx->cfg.dial.next_timeout);
+ else
+ prompt_Printf(arg->prompt, "random/");
+ if (arg->cx->cfg.dial.timeout > 0)
+ prompt_Printf(arg->prompt, "%ds\n", arg->cx->cfg.dial.timeout);
+ else
+ prompt_Printf(arg->prompt, "random\n");
+ prompt_Printf(arg->prompt, " Reconnect tries: %d, delay ",
+ arg->cx->cfg.reconnect.max);
+ if (arg->cx->cfg.reconnect.timeout > 0)
+ prompt_Printf(arg->prompt, "%ds\n", arg->cx->cfg.reconnect.timeout);
+ else
+ prompt_Printf(arg->prompt, "random\n");
+ prompt_Printf(arg->prompt, " Dial Script: %s\n",
+ arg->cx->cfg.script.dial);
+ prompt_Printf(arg->prompt, " Login Script: %s\n",
+ arg->cx->cfg.script.login);
+ prompt_Printf(arg->prompt, " Hangup Script: %s\n",
+ arg->cx->cfg.script.hangup);
+ return 0;
+}
+
+int
+datalink_SetReconnect(struct cmdargs const *arg)
+{
+ if (arg->argc == arg->argn+2) {
+ arg->cx->cfg.reconnect.timeout = atoi(arg->argv[arg->argn]);
+ arg->cx->cfg.reconnect.max = atoi(arg->argv[arg->argn+1]);
+ return 0;
+ }
+ return -1;
+}
+
+int
+datalink_SetRedial(struct cmdargs const *arg)
+{
+ int timeout;
+ int tries;
+ char *dot;
+
+ if (arg->argc == arg->argn+1 || arg->argc == arg->argn+2) {
+ if (strncasecmp(arg->argv[arg->argn], "random", 6) == 0 &&
+ (arg->argv[arg->argn][6] == '\0' || arg->argv[arg->argn][6] == '.')) {
+ arg->cx->cfg.dial.timeout = -1;
+ randinit();
+ } else {
+ timeout = atoi(arg->argv[arg->argn]);
+
+ if (timeout >= 0)
+ arg->cx->cfg.dial.timeout = timeout;
+ else {
+ log_Printf(LogWARN, "Invalid redial timeout\n");
+ return -1;
+ }
+ }
+
+ dot = strchr(arg->argv[arg->argn], '.');
+ if (dot) {
+ if (strcasecmp(++dot, "random") == 0) {
+ arg->cx->cfg.dial.next_timeout = -1;
+ randinit();
+ } else {
+ timeout = atoi(dot);
+ if (timeout >= 0)
+ arg->cx->cfg.dial.next_timeout = timeout;
+ else {
+ log_Printf(LogWARN, "Invalid next redial timeout\n");
+ return -1;
+ }
+ }
+ } else
+ /* Default next timeout */
+ arg->cx->cfg.dial.next_timeout = DIAL_NEXT_TIMEOUT;
+
+ if (arg->argc == arg->argn+2) {
+ tries = atoi(arg->argv[arg->argn+1]);
+
+ if (tries >= 0) {
+ arg->cx->cfg.dial.max = tries;
+ } else {
+ log_Printf(LogWARN, "Invalid retry value\n");
+ return 1;
+ }
+ }
+ return 0;
+ }
+ return -1;
+}
+
+static const char *states[] = {
+ "closed",
+ "opening",
+ "hangup",
+ "dial",
+ "login",
+ "ready",
+ "lcp",
+ "auth",
+ "open"
+};
+
+const char *
+datalink_State(struct datalink *dl)
+{
+ if (dl->state < 0 || dl->state >= sizeof states / sizeof states[0])
+ return "unknown";
+ return states[dl->state];
+}
+
+static void
+datalink_NewState(struct datalink *dl, int state)
+{
+ if (state != dl->state) {
+ if (state >= 0 && state < sizeof states / sizeof states[0]) {
+ log_Printf(LogPHASE, "%s: %s -> %s\n", dl->name, datalink_State(dl),
+ states[state]);
+ dl->state = state;
+ } else
+ log_Printf(LogERROR, "%s: Can't enter state %d !\n", dl->name, state);
+ }
+}
+
+struct datalink *
+iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov,
+ int fd)
+{
+ struct datalink *dl, *cdl;
+ u_int retry;
+ char *oname;
+
+ dl = (struct datalink *)iov[(*niov)++].iov_base;
+ dl->name = iov[*niov].iov_base;
+
+ if (dl->name[DATALINK_MAXNAME-1]) {
+ dl->name[DATALINK_MAXNAME-1] = '\0';
+ if (strlen(dl->name) == DATALINK_MAXNAME - 1)
+ log_Printf(LogWARN, "Datalink name truncated to \"%s\"\n", dl->name);
+ }
+
+ /* Make sure the name is unique ! */
+ oname = NULL;
+ do {
+ for (cdl = bundle->links; cdl; cdl = cdl->next)
+ if (!strcasecmp(dl->name, cdl->name)) {
+ if (oname)
+ free(datalink_NextName(dl));
+ else
+ oname = datalink_NextName(dl);
+ break; /* Keep renaming 'till we have no conflicts */
+ }
+ } while (cdl);
+
+ if (oname) {
+ log_Printf(LogPHASE, "Rename link %s to %s\n", oname, dl->name);
+ free(oname);
+ } else {
+ dl->name = strdup(dl->name);
+ dl->physical->link.name = dl->name;
+ free(iov[*niov].iov_base);
+ }
+ (*niov)++;
+
+ dl->desc.type = DATALINK_DESCRIPTOR;
+ dl->desc.next = NULL;
+ dl->desc.UpdateSet = datalink_UpdateSet;
+ dl->desc.IsSet = datalink_IsSet;
+ dl->desc.Read = datalink_Read;
+ dl->desc.Write = datalink_Write;
+
+ mp_linkInit(&dl->mp);
+ *dl->phone.list = '\0';
+ dl->phone.next = NULL;
+ dl->phone.alt = NULL;
+ dl->phone.chosen = "N/A";
+
+ dl->bundle = bundle;
+ dl->next = NULL;
+ memset(&dl->dial_timer, '\0', sizeof dl->dial_timer);
+ dl->dial_tries = 0;
+ dl->reconnect_tries = 0;
+ dl->parent = &bundle->fsm;
+ dl->fsmp.LayerStart = datalink_LayerStart;
+ dl->fsmp.LayerUp = datalink_LayerUp;
+ dl->fsmp.LayerDown = datalink_LayerDown;
+ dl->fsmp.LayerFinish = datalink_LayerFinish;
+ dl->fsmp.object = dl;
+
+ retry = dl->pap.cfg.fsmretry;
+ auth_Init(&dl->pap);
+ dl->pap.cfg.fsmretry = retry;
+
+ retry = dl->chap.auth.cfg.fsmretry;
+ auth_Init(&dl->chap.auth);
+ dl->chap.auth.cfg.fsmretry = retry;
+
+ dl->physical = iov2modem(dl, iov, niov, maxiov, fd);
+
+ if (!dl->physical) {
+ free(dl->name);
+ free(dl);
+ dl = NULL;
+ } else {
+ chat_Init(&dl->chat, dl->physical, NULL, 1, NULL);
+
+ log_Printf(LogPHASE, "%s: Transferred in %s state\n",
+ dl->name, datalink_State(dl));
+ }
+
+ return dl;
+}
+
+int
+datalink2iov(struct datalink *dl, struct iovec *iov, int *niov, int maxiov)
+{
+ /* If `dl' is NULL, we're allocating before a Fromiov() */
+ int link_fd;
+
+ if (dl) {
+ timer_Stop(&dl->dial_timer);
+ timer_Stop(&dl->pap.authtimer);
+ timer_Stop(&dl->chap.auth.authtimer);
+ }
+
+ if (*niov >= maxiov - 1) {
+ log_Printf(LogERROR, "Toiov: No room for datalink !\n");
+ if (dl) {
+ free(dl->name);
+ free(dl);
+ }
+ return -1;
+ }
+
+ iov[*niov].iov_base = dl ? dl : malloc(sizeof *dl);
+ iov[(*niov)++].iov_len = sizeof *dl;
+ iov[*niov].iov_base =
+ dl ? realloc(dl->name, DATALINK_MAXNAME) : malloc(DATALINK_MAXNAME);
+ iov[(*niov)++].iov_len = DATALINK_MAXNAME;
+
+ link_fd = modem2iov(dl ? dl->physical : NULL, iov, niov, maxiov);
+
+ if (link_fd == -1 && dl) {
+ free(dl->name);
+ free(dl);
+ }
+
+ return link_fd;
+}
+
+void
+datalink_Rename(struct datalink *dl, const char *name)
+{
+ free(dl->name);
+ dl->physical->link.name = dl->name = strdup(name);
+}
+
+char *
+datalink_NextName(struct datalink *dl)
+{
+ int f, n;
+ char *name, *oname;
+
+ n = strlen(dl->name);
+ name = (char *)malloc(n+3);
+ for (f = n - 1; f >= 0; f--)
+ if (!isdigit(dl->name[f]))
+ break;
+ n = sprintf(name, "%.*s-", dl->name[f] == '-' ? f : f + 1, dl->name);
+ sprintf(name + n, "%d", atoi(dl->name + f + 1) + 1);
+ oname = dl->name;
+ dl->physical->link.name = dl->name = name;
+ return oname;
+}
+
+int
+datalink_SetMode(struct datalink *dl, int mode)
+{
+ if (!physical_SetMode(dl->physical, mode))
+ return 0;
+ if (dl->physical->type & (PHYS_DIRECT|PHYS_DEDICATED))
+ dl->script.run = 0;
+ if (dl->physical->type == PHYS_DIRECT)
+ dl->reconnect_tries = 0;
+ if (mode & (PHYS_PERM|PHYS_1OFF) && dl->state <= DATALINK_READY)
+ datalink_Up(dl, 1, 1);
+ return 1;
+}
diff --git a/usr.sbin/ppp/datalink.h b/usr.sbin/ppp/datalink.h
new file mode 100644
index 000000000000..93a5ef224e1a
--- /dev/null
+++ b/usr.sbin/ppp/datalink.h
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: datalink.h,v 1.1.2.26 1998/05/16 23:47:25 brian Exp $
+ */
+
+#define DATALINK_CLOSED (0)
+#define DATALINK_OPENING (1)
+#define DATALINK_HANGUP (2)
+#define DATALINK_DIAL (3)
+#define DATALINK_LOGIN (4)
+#define DATALINK_READY (5)
+#define DATALINK_LCP (6)
+#define DATALINK_AUTH (7)
+#define DATALINK_OPEN (8)
+
+#define DATALINK_MAXNAME (20)
+
+struct iovec;
+struct prompt;
+struct physical;
+struct bundle;
+
+struct datalink {
+ struct descriptor desc; /* We play either a physical or a chat */
+ int state; /* Our DATALINK_* state */
+ struct physical *physical; /* Our link */
+
+ struct chat chat; /* For bringing the link up & down */
+
+ struct {
+ unsigned run : 1; /* run scripts ? */
+ unsigned packetmode : 1; /* Go into packet mode after login ? */
+ } script;
+
+ struct pppTimer dial_timer; /* For timing between opens & scripts */
+
+ struct {
+ struct {
+ char dial[SCRIPT_LEN]; /* dial */
+ char login[SCRIPT_LEN]; /* login */
+ char hangup[SCRIPT_LEN]; /* hangup */
+ } script;
+ struct {
+ char list[SCRIPT_LEN]; /* Telephone Numbers */
+ } phone;
+ struct {
+ int max; /* initially try again this number of times */
+ int next_timeout; /* Redial next timeout value */
+ int timeout; /* Redial timeout value (end of phone list) */
+ } dial;
+ struct {
+ int max; /* initially try again this number of times */
+ int timeout; /* Timeout before reconnect on carrier loss */
+ } reconnect;
+ } cfg; /* All our config data is in here */
+
+ struct {
+ char list[SCRIPT_LEN]; /* copy of cfg.list for strsep() */
+ char *next; /* Next phone from the list */
+ char *alt; /* Next phone from the list */
+ const char *chosen; /* Chosen phone number after DIAL */
+ } phone;
+
+ int dial_tries; /* currently try again this number of times */
+ unsigned reconnect_tries; /* currently try again this number of times */
+
+ char *name; /* Our name */
+
+ struct peerid peer; /* Peer identification */
+
+ struct fsm_parent fsmp; /* Our callback functions */
+ const struct fsm_parent *parent; /* Our parent */
+
+ struct authinfo pap; /* Authentication using pap */
+ struct chap chap; /* Authentication using chap */
+
+ struct mp_link mp; /* multilink data */
+
+ struct bundle *bundle; /* for the moment */
+ struct datalink *next; /* Next in the list */
+};
+
+#define descriptor2datalink(d) \
+ ((d)->type == DATALINK_DESCRIPTOR ? (struct datalink *)(d) : NULL)
+
+extern struct datalink *datalink_Create(const char *name, struct bundle *, int);
+extern struct datalink *datalink_Clone(struct datalink *, const char *);
+extern struct datalink *iov2datalink(struct bundle *, struct iovec *, int *,
+ int, int);
+extern int datalink2iov(struct datalink *, struct iovec *, int *, int);
+extern struct datalink *datalink_Destroy(struct datalink *);
+extern void datalink_GotAuthname(struct datalink *, const char *, int);
+extern void datalink_Up(struct datalink *, int, int);
+extern void datalink_Close(struct datalink *, int);
+extern void datalink_Down(struct datalink *, int);
+extern void datalink_StayDown(struct datalink *);
+extern void datalink_AuthOk(struct datalink *);
+extern void datalink_AuthNotOk(struct datalink *);
+extern int datalink_Show(struct cmdargs const *);
+extern int datalink_SetRedial(struct cmdargs const *);
+extern int datalink_SetReconnect(struct cmdargs const *);
+extern const char *datalink_State(struct datalink *);
+extern void datalink_Rename(struct datalink *, const char *);
+extern char *datalink_NextName(struct datalink *);
+extern int datalink_RemoveFromSet(struct datalink *, fd_set *, fd_set *,
+ fd_set *);
+extern int datalink_SetMode(struct datalink *, int);
diff --git a/usr.sbin/ppp/deflate.c b/usr.sbin/ppp/deflate.c
index f3e6d17ff917..08e5f85f0265 100644
--- a/usr.sbin/ppp/deflate.c
+++ b/usr.sbin/ppp/deflate.c
@@ -23,67 +23,64 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: deflate.c,v 1.6 1998/01/10 01:55:09 brian Exp $
+ * $Id: deflate.c,v 1.6.4.16 1998/05/15 18:21:03 brian Exp $
*/
-#include <sys/param.h>
-#include <netinet/in.h>
+#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
-#include "defs.h"
-#include "loadalias.h"
-#include "vars.h"
+#include "timer.h"
+#include "lqr.h"
#include "hdlc.h"
+#include "fsm.h"
#include "lcp.h"
#include "ccp.h"
-#include "lcpproto.h"
-#include "timer.h"
-#include "fsm.h"
#include "deflate.h"
/* Our state */
struct deflate_state {
u_short seqno;
int uncomp_rec;
+ int winsize;
z_stream cx;
};
-static int iWindowSize = 15;
-static int oWindowSize = 15;
-static struct deflate_state InputState, OutputState;
static char garbage[10];
static u_char EMPTY_BLOCK[4] = { 0x00, 0x00, 0xff, 0xff };
#define DEFLATE_CHUNK_LEN 1024 /* Allocate mbufs this size */
static void
-DeflateResetOutput(void)
+DeflateResetOutput(void *v)
{
- OutputState.seqno = 0;
- OutputState.uncomp_rec = 0;
- deflateReset(&OutputState.cx);
- LogPrintf(LogCCP, "Deflate: Output channel reset\n");
+ struct deflate_state *state = (struct deflate_state *)v;
+
+ state->seqno = 0;
+ state->uncomp_rec = 0;
+ deflateReset(&state->cx);
+ log_Printf(LogCCP, "Deflate: Output channel reset\n");
}
static int
-DeflateOutput(int pri, u_short proto, struct mbuf *mp)
+DeflateOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short proto,
+ struct mbuf *mp)
{
+ struct deflate_state *state = (struct deflate_state *)v;
u_char *wp, *rp;
int olen, ilen, len, res, flush;
struct mbuf *mo_head, *mo, *mi_head, *mi;
- ilen = plength(mp);
- LogPrintf(LogDEBUG, "DeflateOutput: Proto %02x (%d bytes)\n", proto, ilen);
- LogDumpBp(LogDEBUG, "DeflateOutput: Compress packet:", mp);
+ ilen = mbuf_Length(mp);
+ log_Printf(LogDEBUG, "DeflateOutput: Proto %02x (%d bytes)\n", proto, ilen);
+ log_DumpBp(LogDEBUG, "DeflateOutput: Compress packet:", mp);
/* Stuff the protocol in front of the input */
- mi_head = mi = mballoc(2, MB_HDLCOUT);
+ mi_head = mi = mbuf_Alloc(2, MB_HDLCOUT);
mi->next = mp;
rp = MBUF_CTOP(mi);
if (proto < 0x100) { /* Compress the protocol */
@@ -96,74 +93,73 @@ DeflateOutput(int pri, u_short proto, struct mbuf *mp)
}
/* Allocate the initial output mbuf */
- mo_head = mo = mballoc(DEFLATE_CHUNK_LEN, MB_HDLCOUT);
+ mo_head = mo = mbuf_Alloc(DEFLATE_CHUNK_LEN, MB_HDLCOUT);
mo->cnt = 2;
wp = MBUF_CTOP(mo);
- *wp++ = OutputState.seqno >> 8;
- *wp++ = OutputState.seqno & 0377;
- LogPrintf(LogDEBUG, "DeflateOutput: Seq %d\n", OutputState.seqno);
- OutputState.seqno++;
+ *wp++ = state->seqno >> 8;
+ *wp++ = state->seqno & 0377;
+ log_Printf(LogDEBUG, "DeflateOutput: Seq %d\n", state->seqno);
+ state->seqno++;
/* Set up the deflation context */
- OutputState.cx.next_out = wp;
- OutputState.cx.avail_out = DEFLATE_CHUNK_LEN - 2;
- OutputState.cx.next_in = MBUF_CTOP(mi);
- OutputState.cx.avail_in = mi->cnt;
+ state->cx.next_out = wp;
+ state->cx.avail_out = DEFLATE_CHUNK_LEN - 2;
+ state->cx.next_in = MBUF_CTOP(mi);
+ state->cx.avail_in = mi->cnt;
flush = Z_NO_FLUSH;
olen = 0;
while (1) {
- if ((res = deflate(&OutputState.cx, flush)) != Z_OK) {
+ if ((res = deflate(&state->cx, flush)) != Z_OK) {
if (res == Z_STREAM_END)
break; /* Done */
- LogPrintf(LogERROR, "DeflateOutput: deflate returned %d (%s)\n",
- res, OutputState.cx.msg ? OutputState.cx.msg : "");
- pfree(mo_head);
- mbfree(mi_head);
- OutputState.seqno--;
+ log_Printf(LogERROR, "DeflateOutput: deflate returned %d (%s)\n",
+ res, state->cx.msg ? state->cx.msg : "");
+ mbuf_Free(mo_head);
+ mbuf_FreeSeg(mi_head);
+ state->seqno--;
return 1; /* packet dropped */
}
- if (flush == Z_SYNC_FLUSH && OutputState.cx.avail_out != 0)
+ if (flush == Z_SYNC_FLUSH && state->cx.avail_out != 0)
break;
- if (OutputState.cx.avail_in == 0 && mi->next != NULL) {
+ if (state->cx.avail_in == 0 && mi->next != NULL) {
mi = mi->next;
- OutputState.cx.next_in = MBUF_CTOP(mi);
- OutputState.cx.avail_in = mi->cnt;
+ state->cx.next_in = MBUF_CTOP(mi);
+ state->cx.avail_in = mi->cnt;
if (mi->next == NULL)
flush = Z_SYNC_FLUSH;
}
- if (OutputState.cx.avail_out == 0) {
- mo->next = mballoc(DEFLATE_CHUNK_LEN, MB_HDLCOUT);
+ if (state->cx.avail_out == 0) {
+ mo->next = mbuf_Alloc(DEFLATE_CHUNK_LEN, MB_HDLCOUT);
olen += (mo->cnt = DEFLATE_CHUNK_LEN);
mo = mo->next;
mo->cnt = 0;
- OutputState.cx.next_out = MBUF_CTOP(mo);
- OutputState.cx.avail_out = DEFLATE_CHUNK_LEN;
+ state->cx.next_out = MBUF_CTOP(mo);
+ state->cx.avail_out = DEFLATE_CHUNK_LEN;
}
}
- olen += (mo->cnt = DEFLATE_CHUNK_LEN - OutputState.cx.avail_out);
+ olen += (mo->cnt = DEFLATE_CHUNK_LEN - state->cx.avail_out);
olen -= 4; /* exclude the trailing EMPTY_BLOCK */
/*
* If the output packet (including seqno and excluding the EMPTY_BLOCK)
- * got bigger, send the original - returning 0 to HdlcOutput() will
- * continue to send ``mp''.
+ * got bigger, send the original.
*/
if (olen >= ilen) {
- pfree(mo_head);
- mbfree(mi_head);
- LogPrintf(LogDEBUG, "DeflateOutput: %d => %d: Uncompressible (0x%04x)\n",
+ mbuf_Free(mo_head);
+ mbuf_FreeSeg(mi_head);
+ log_Printf(LogDEBUG, "DeflateOutput: %d => %d: Uncompressible (0x%04x)\n",
ilen, olen, proto);
- CcpInfo.uncompout += ilen;
- CcpInfo.compout += ilen; /* We measure this stuff too */
+ ccp->uncompout += ilen;
+ ccp->compout += ilen; /* We measure this stuff too */
return 0;
}
- pfree(mi_head);
+ mbuf_Free(mi_head);
/*
* Lose the last four bytes of our output.
@@ -174,66 +170,69 @@ DeflateOutput(int pri, u_short proto, struct mbuf *mp)
;
mo->cnt -= len - olen;
if (mo->next != NULL) {
- pfree(mo->next);
+ mbuf_Free(mo->next);
mo->next = NULL;
}
- CcpInfo.uncompout += ilen;
- CcpInfo.compout += olen;
+ ccp->uncompout += ilen;
+ ccp->compout += olen;
- LogPrintf(LogDEBUG, "DeflateOutput: %d => %d bytes, proto 0x%04x\n",
+ log_Printf(LogDEBUG, "DeflateOutput: %d => %d bytes, proto 0x%04x\n",
ilen, olen, proto);
- HdlcOutput(PRI_NORMAL, PROTO_COMPD, mo_head);
+ hdlc_Output(l, PRI_NORMAL, ccp_Proto(ccp), mo_head);
return 1;
}
static void
-DeflateResetInput(void)
+DeflateResetInput(void *v)
{
- InputState.seqno = 0;
- InputState.uncomp_rec = 0;
- inflateReset(&InputState.cx);
- LogPrintf(LogCCP, "Deflate: Input channel reset\n");
+ struct deflate_state *state = (struct deflate_state *)v;
+
+ state->seqno = 0;
+ state->uncomp_rec = 0;
+ inflateReset(&state->cx);
+ log_Printf(LogCCP, "Deflate: Input channel reset\n");
}
static struct mbuf *
-DeflateInput(u_short *proto, struct mbuf *mi)
+DeflateInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mi)
{
+ struct deflate_state *state = (struct deflate_state *)v;
struct mbuf *mo, *mo_head, *mi_head;
u_char *wp;
int ilen, olen;
int seq, flush, res, first;
u_char hdr[2];
- LogDumpBp(LogDEBUG, "DeflateInput: Decompress packet:", mi);
- mi_head = mi = mbread(mi, hdr, 2);
+ log_DumpBp(LogDEBUG, "DeflateInput: Decompress packet:", mi);
+ mi_head = mi = mbuf_Read(mi, hdr, 2);
ilen = 2;
/* Check the sequence number. */
seq = (hdr[0] << 8) + hdr[1];
- LogPrintf(LogDEBUG, "DeflateInput: Seq %d\n", seq);
- if (seq != InputState.seqno) {
- if (seq <= InputState.uncomp_rec)
+ log_Printf(LogDEBUG, "DeflateInput: Seq %d\n", seq);
+ if (seq != state->seqno) {
+ if (seq <= state->uncomp_rec)
/*
* So the peer's started at zero again - fine ! If we're wrong,
* inflate() will fail. This is better than getting into a loop
* trying to get a ResetReq to a busy sender.
*/
- InputState.seqno = seq;
+ state->seqno = seq;
else {
- LogPrintf(LogERROR, "DeflateInput: Seq error: Got %d, expected %d\n",
- seq, InputState.seqno);
- pfree(mi_head);
- CcpSendResetReq(&CcpFsm);
+ log_Printf(LogERROR, "DeflateInput: Seq error: Got %d, expected %d\n",
+ seq, state->seqno);
+ mbuf_Free(mi_head);
+ ccp_SendResetReq(&ccp->fsm);
return NULL;
}
}
- InputState.seqno++;
- InputState.uncomp_rec = 0;
+ state->seqno++;
+ state->uncomp_rec = 0;
/* Allocate an output mbuf */
- mo_head = mo = mballoc(DEFLATE_CHUNK_LEN, MB_IPIN);
+ mo_head = mo = mbuf_Alloc(DEFLATE_CHUNK_LEN, MB_IPIN);
/* Our proto starts with 0 if it's compressed */
wp = MBUF_CTOP(mo);
@@ -244,10 +243,10 @@ DeflateInput(u_short *proto, struct mbuf *mi)
* byte of the output and decide whether we have a compressed
* proto field.
*/
- InputState.cx.next_in = MBUF_CTOP(mi);
- InputState.cx.avail_in = mi->cnt;
- InputState.cx.next_out = wp + 1;
- InputState.cx.avail_out = 1;
+ state->cx.next_in = MBUF_CTOP(mi);
+ state->cx.avail_in = mi->cnt;
+ state->cx.next_out = wp + 1;
+ state->cx.avail_out = 1;
ilen += mi->cnt;
flush = mi->next ? Z_NO_FLUSH : Z_SYNC_FLUSH;
@@ -255,102 +254,103 @@ DeflateInput(u_short *proto, struct mbuf *mi)
olen = 0;
while (1) {
- if ((res = inflate(&InputState.cx, flush)) != Z_OK) {
+ if ((res = inflate(&state->cx, flush)) != Z_OK) {
if (res == Z_STREAM_END)
break; /* Done */
- LogPrintf(LogERROR, "DeflateInput: inflate returned %d (%s)\n",
- res, InputState.cx.msg ? InputState.cx.msg : "");
- pfree(mo_head);
- pfree(mi);
- CcpSendResetReq(&CcpFsm);
+ log_Printf(LogERROR, "DeflateInput: inflate returned %d (%s)\n",
+ res, state->cx.msg ? state->cx.msg : "");
+ mbuf_Free(mo_head);
+ mbuf_Free(mi);
+ ccp_SendResetReq(&ccp->fsm);
return NULL;
}
- if (flush == Z_SYNC_FLUSH && InputState.cx.avail_out != 0)
+ if (flush == Z_SYNC_FLUSH && state->cx.avail_out != 0)
break;
- if (InputState.cx.avail_in == 0 && mi && (mi = mbfree(mi)) != NULL) {
+ if (state->cx.avail_in == 0 && mi && (mi = mbuf_FreeSeg(mi)) != NULL) {
/* underflow */
- InputState.cx.next_in = MBUF_CTOP(mi);
- ilen += (InputState.cx.avail_in = mi->cnt);
+ state->cx.next_in = MBUF_CTOP(mi);
+ ilen += (state->cx.avail_in = mi->cnt);
if (mi->next == NULL)
flush = Z_SYNC_FLUSH;
}
- if (InputState.cx.avail_out == 0) {
+ if (state->cx.avail_out == 0) {
/* overflow */
if (first) {
if (!(wp[1] & 1)) {
/* 2 byte proto, shuffle it back in output */
wp[0] = wp[1];
- InputState.cx.next_out--;
- InputState.cx.avail_out = DEFLATE_CHUNK_LEN-1;
+ state->cx.next_out--;
+ state->cx.avail_out = DEFLATE_CHUNK_LEN-1;
} else
- InputState.cx.avail_out = DEFLATE_CHUNK_LEN-2;
+ state->cx.avail_out = DEFLATE_CHUNK_LEN-2;
first = 0;
} else {
olen += (mo->cnt = DEFLATE_CHUNK_LEN);
- mo->next = mballoc(DEFLATE_CHUNK_LEN, MB_IPIN);
+ mo->next = mbuf_Alloc(DEFLATE_CHUNK_LEN, MB_IPIN);
mo = mo->next;
- InputState.cx.next_out = MBUF_CTOP(mo);
- InputState.cx.avail_out = DEFLATE_CHUNK_LEN;
+ state->cx.next_out = MBUF_CTOP(mo);
+ state->cx.avail_out = DEFLATE_CHUNK_LEN;
}
}
}
if (mi != NULL)
- pfree(mi);
+ mbuf_Free(mi);
if (first) {
- LogPrintf(LogERROR, "DeflateInput: Length error\n");
- pfree(mo_head);
- CcpSendResetReq(&CcpFsm);
+ log_Printf(LogERROR, "DeflateInput: Length error\n");
+ mbuf_Free(mo_head);
+ ccp_SendResetReq(&ccp->fsm);
return NULL;
}
- olen += (mo->cnt = DEFLATE_CHUNK_LEN - InputState.cx.avail_out);
+ olen += (mo->cnt = DEFLATE_CHUNK_LEN - state->cx.avail_out);
*proto = ((u_short)wp[0] << 8) | wp[1];
mo_head->offset += 2;
mo_head->cnt -= 2;
olen -= 2;
- CcpInfo.compin += ilen;
- CcpInfo.uncompin += olen;
+ ccp->compin += ilen;
+ ccp->uncompin += olen;
- LogPrintf(LogDEBUG, "DeflateInput: %d => %d bytes, proto 0x%04x\n",
+ log_Printf(LogDEBUG, "DeflateInput: %d => %d bytes, proto 0x%04x\n",
ilen, olen, *proto);
/*
* Simulate an EMPTY_BLOCK so that our dictionary stays in sync.
* The peer will have silently removed this!
*/
- InputState.cx.next_out = garbage;
- InputState.cx.avail_out = sizeof garbage;
- InputState.cx.next_in = EMPTY_BLOCK;
- InputState.cx.avail_in = sizeof EMPTY_BLOCK;
- inflate(&InputState.cx, Z_SYNC_FLUSH);
+ state->cx.next_out = garbage;
+ state->cx.avail_out = sizeof garbage;
+ state->cx.next_in = EMPTY_BLOCK;
+ state->cx.avail_in = sizeof EMPTY_BLOCK;
+ inflate(&state->cx, Z_SYNC_FLUSH);
return mo_head;
}
static void
-DeflateDictSetup(u_short proto, struct mbuf *mi)
+DeflateDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi)
{
+ struct deflate_state *state = (struct deflate_state *)v;
int res, flush, expect_error;
u_char *rp;
struct mbuf *mi_head;
short len;
- LogPrintf(LogDEBUG, "DeflateDictSetup: Got seq %d\n", InputState.seqno);
+ log_Printf(LogDEBUG, "DeflateDictSetup: Got seq %d\n", state->seqno);
/*
* Stuff an ``uncompressed data'' block header followed by the
* protocol in front of the input
*/
- mi_head = mballoc(7, MB_HDLCOUT);
+ mi_head = mbuf_Alloc(7, MB_HDLCOUT);
mi_head->next = mi;
- len = plength(mi);
+ len = mbuf_Length(mi);
mi = mi_head;
rp = MBUF_CTOP(mi);
if (proto < 0x100) { /* Compress the protocol */
@@ -369,41 +369,41 @@ DeflateDictSetup(u_short proto, struct mbuf *mi)
rp[3] = (~len) & 0377; /* One's compliment of the length */
rp[4] = (~len) >> 8;
- InputState.cx.next_in = rp;
- InputState.cx.avail_in = mi->cnt;
- InputState.cx.next_out = garbage;
- InputState.cx.avail_out = sizeof garbage;
+ state->cx.next_in = rp;
+ state->cx.avail_in = mi->cnt;
+ state->cx.next_out = garbage;
+ state->cx.avail_out = sizeof garbage;
flush = Z_NO_FLUSH;
expect_error = 0;
while (1) {
- if ((res = inflate(&InputState.cx, flush)) != Z_OK) {
+ if ((res = inflate(&state->cx, flush)) != Z_OK) {
if (res == Z_STREAM_END)
break; /* Done */
if (expect_error && res == Z_BUF_ERROR)
break;
- LogPrintf(LogERROR, "DeflateDictSetup: inflate returned %d (%s)\n",
- res, InputState.cx.msg ? InputState.cx.msg : "");
- LogPrintf(LogERROR, "DeflateDictSetup: avail_in %d, avail_out %d\n",
- InputState.cx.avail_in, InputState.cx.avail_out);
- CcpSendResetReq(&CcpFsm);
- mbfree(mi_head); /* lose our allocated ``head'' buf */
+ log_Printf(LogERROR, "DeflateDictSetup: inflate returned %d (%s)\n",
+ res, state->cx.msg ? state->cx.msg : "");
+ log_Printf(LogERROR, "DeflateDictSetup: avail_in %d, avail_out %d\n",
+ state->cx.avail_in, state->cx.avail_out);
+ ccp_SendResetReq(&ccp->fsm);
+ mbuf_FreeSeg(mi_head); /* lose our allocated ``head'' buf */
return;
}
- if (flush == Z_SYNC_FLUSH && InputState.cx.avail_out != 0)
+ if (flush == Z_SYNC_FLUSH && state->cx.avail_out != 0)
break;
- if (InputState.cx.avail_in == 0 && mi && (mi = mi->next) != NULL) {
+ if (state->cx.avail_in == 0 && mi && (mi = mi->next) != NULL) {
/* underflow */
- InputState.cx.next_in = MBUF_CTOP(mi);
- InputState.cx.avail_in = mi->cnt;
+ state->cx.next_in = MBUF_CTOP(mi);
+ state->cx.avail_in = mi->cnt;
if (mi->next == NULL)
flush = Z_SYNC_FLUSH;
}
- if (InputState.cx.avail_out == 0) {
- if (InputState.cx.avail_in == 0)
+ if (state->cx.avail_out == 0) {
+ if (state->cx.avail_in == 0)
/*
* This seems to be a bug in libz ! If inflate() finished
* with 0 avail_in and 0 avail_out *and* this is the end of
@@ -417,17 +417,17 @@ DeflateDictSetup(u_short proto, struct mbuf *mi)
*/
expect_error = 1;
/* overflow */
- InputState.cx.next_out = garbage;
- InputState.cx.avail_out = sizeof garbage;
+ state->cx.next_out = garbage;
+ state->cx.avail_out = sizeof garbage;
}
}
- CcpInfo.compin += len;
- CcpInfo.uncompin += len;
+ ccp->compin += len;
+ ccp->uncompin += len;
- InputState.seqno++;
- InputState.uncomp_rec++;
- mbfree(mi_head); /* lose our allocated ``head'' buf */
+ state->seqno++;
+ state->uncomp_rec++;
+ mbuf_FreeSeg(mi_head); /* lose our allocated ``head'' buf */
}
static const char *
@@ -440,144 +440,119 @@ DeflateDispOpts(struct lcp_opt *o)
}
static void
-DeflateGetInputOpts(struct lcp_opt *o)
+DeflateInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
{
- o->id = TY_DEFLATE;
o->len = 4;
- o->data[0] = ((iWindowSize-8)<<4)+8;
+ o->data[0] = ((cfg->deflate.out.winsize - 8) << 4) + 8;
o->data[1] = '\0';
}
-static void
-DeflateGetOutputOpts(struct lcp_opt *o)
+static int
+DeflateSetOptsOutput(struct lcp_opt *o)
{
- o->id = TY_DEFLATE;
- o->len = 4;
- o->data[0] = ((oWindowSize-8)<<4)+8;
- o->data[1] = '\0';
-}
+ if (o->len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0')
+ return MODE_REJ;
-static void
-PppdDeflateGetInputOpts(struct lcp_opt *o)
-{
- o->id = TY_PPPD_DEFLATE;
- o->len = 4;
- o->data[0] = ((iWindowSize-8)<<4)+8;
- o->data[1] = '\0';
-}
+ if ((o->data[0] >> 4) + 8 > 15) {
+ o->data[0] = ((15 - 8) << 4) + 8;
+ return MODE_NAK;
+ }
-static void
-PppdDeflateGetOutputOpts(struct lcp_opt *o)
-{
- o->id = TY_PPPD_DEFLATE;
- o->len = 4;
- o->data[0] = ((oWindowSize-8)<<4)+8;
- o->data[1] = '\0';
+ return MODE_ACK;
}
static int
-DeflateSetOpts(struct lcp_opt *o, int *sz)
+DeflateSetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
{
- if (o->len != 4 || (o->data[0]&15) != 8 || o->data[1] != '\0') {
+ int want;
+
+ if (o->len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0')
return MODE_REJ;
- }
- *sz = (o->data[0] >> 4) + 8;
- if (*sz > 15) {
- *sz = 15;
+
+ want = (o->data[0] >> 4) + 8;
+ if (cfg->deflate.in.winsize == 0) {
+ if (want < 8 || want > 15) {
+ o->data[0] = ((15 - 8) << 4) + 8;
+ }
+ } else if (want != cfg->deflate.in.winsize) {
+ o->data[0] = ((cfg->deflate.in.winsize - 8) << 4) + 8;
return MODE_NAK;
}
return MODE_ACK;
}
-static int
-DeflateSetInputOpts(struct lcp_opt *o)
+static void *
+DeflateInitInput(struct lcp_opt *o)
{
- int res;
- res = DeflateSetOpts(o, &iWindowSize);
- if (res != MODE_ACK)
- DeflateGetInputOpts(o);
- return res;
-}
+ struct deflate_state *state;
+
+ state = (struct deflate_state *)malloc(sizeof(struct deflate_state));
+ if (state != NULL) {
+ state->winsize = (o->data[0] >> 4) + 8;
+ state->cx.zalloc = NULL;
+ state->cx.opaque = NULL;
+ state->cx.zfree = NULL;
+ state->cx.next_out = NULL;
+ if (inflateInit2(&state->cx, -state->winsize) == Z_OK)
+ DeflateResetInput(state);
+ else {
+ free(state);
+ state = NULL;
+ }
+ }
-static int
-DeflateSetOutputOpts(struct lcp_opt *o)
-{
- int res;
- res = DeflateSetOpts(o, &oWindowSize);
- if (res != MODE_ACK)
- DeflateGetOutputOpts(o);
- return res;
+ return state;
}
-static int
-PppdDeflateSetInputOpts(struct lcp_opt *o)
+static void *
+DeflateInitOutput(struct lcp_opt *o)
{
- int res;
- res = DeflateSetOpts(o, &iWindowSize);
- if (res != MODE_ACK)
- PppdDeflateGetInputOpts(o);
- return res;
-}
+ struct deflate_state *state;
+
+ state = (struct deflate_state *)malloc(sizeof(struct deflate_state));
+ if (state != NULL) {
+ state->winsize = (o->data[0] >> 4) + 8;
+ state->cx.zalloc = NULL;
+ state->cx.opaque = NULL;
+ state->cx.zfree = NULL;
+ state->cx.next_in = NULL;
+ if (deflateInit2(&state->cx, Z_DEFAULT_COMPRESSION, 8,
+ -state->winsize, 8, Z_DEFAULT_STRATEGY) == Z_OK)
+ DeflateResetOutput(state);
+ else {
+ free(state);
+ state = NULL;
+ }
+ }
-static int
-PppdDeflateSetOutputOpts(struct lcp_opt *o)
-{
- int res;
- res = DeflateSetOpts(o, &oWindowSize);
- if (res != MODE_ACK)
- PppdDeflateGetOutputOpts(o);
- return res;
+ return state;
}
-static int
-DeflateInitInput(void)
+static void
+DeflateTermInput(void *v)
{
- InputState.cx.zalloc = NULL;
- InputState.cx.opaque = NULL;
- InputState.cx.zfree = NULL;
- InputState.cx.next_out = NULL;
- if (inflateInit2(&InputState.cx, -iWindowSize) != Z_OK)
- return 0;
- DeflateResetInput();
- return 1;
-}
+ struct deflate_state *state = (struct deflate_state *)v;
-static int
-DeflateInitOutput(void)
-{
- OutputState.cx.zalloc = NULL;
- OutputState.cx.opaque = NULL;
- OutputState.cx.zfree = NULL;
- OutputState.cx.next_in = NULL;
- if (deflateInit2(&OutputState.cx, Z_DEFAULT_COMPRESSION, 8,
- -oWindowSize, 8, Z_DEFAULT_STRATEGY) != Z_OK)
- return 0;
- DeflateResetOutput();
- return 1;
+ inflateEnd(&state->cx);
+ free(state);
}
static void
-DeflateTermInput(void)
+DeflateTermOutput(void *v)
{
- iWindowSize = 15;
- inflateEnd(&InputState.cx);
-}
+ struct deflate_state *state = (struct deflate_state *)v;
-static void
-DeflateTermOutput(void)
-{
- oWindowSize = 15;
- deflateEnd(&OutputState.cx);
+ deflateEnd(&state->cx);
+ free(state);
}
const struct ccp_algorithm PppdDeflateAlgorithm = {
TY_PPPD_DEFLATE, /* pppd (wrongly) expects this ``type'' field */
- ConfPppdDeflate,
+ CCP_NEG_DEFLATE24,
DeflateDispOpts,
{
- PppdDeflateGetInputOpts,
- PppdDeflateSetInputOpts,
+ DeflateSetOptsInput,
DeflateInitInput,
DeflateTermInput,
DeflateResetInput,
@@ -585,8 +560,8 @@ const struct ccp_algorithm PppdDeflateAlgorithm = {
DeflateDictSetup
},
{
- PppdDeflateGetOutputOpts,
- PppdDeflateSetOutputOpts,
+ DeflateInitOptsOutput,
+ DeflateSetOptsOutput,
DeflateInitOutput,
DeflateTermOutput,
DeflateResetOutput,
@@ -596,11 +571,10 @@ const struct ccp_algorithm PppdDeflateAlgorithm = {
const struct ccp_algorithm DeflateAlgorithm = {
TY_DEFLATE, /* rfc 1979 */
- ConfDeflate,
+ CCP_NEG_DEFLATE,
DeflateDispOpts,
{
- DeflateGetInputOpts,
- DeflateSetInputOpts,
+ DeflateSetOptsInput,
DeflateInitInput,
DeflateTermInput,
DeflateResetInput,
@@ -608,8 +582,8 @@ const struct ccp_algorithm DeflateAlgorithm = {
DeflateDictSetup
},
{
- DeflateGetOutputOpts,
- DeflateSetOutputOpts,
+ DeflateInitOptsOutput,
+ DeflateSetOptsOutput,
DeflateInitOutput,
DeflateTermOutput,
DeflateResetOutput,
diff --git a/usr.sbin/ppp/defs.c b/usr.sbin/ppp/defs.c
index e66c7b55bf3b..7c444655cc9a 100644
--- a/usr.sbin/ppp/defs.c
+++ b/usr.sbin/ppp/defs.c
@@ -23,54 +23,22 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: defs.c,v 1.11 1998/01/21 02:15:14 brian Exp $
+ * $Id: defs.c,v 1.11.4.12 1998/05/15 23:58:21 brian Exp $
*/
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/errno.h>
#include <time.h>
#include <unistd.h>
#include "defs.h"
-#include "command.h"
-#include "mbuf.h"
-#include "log.h"
-#include "loadalias.h"
-#include "vars.h"
-
-int mode = MODE_INTER;
-int BGFiledes[2] = { -1, -1 };
-int modem = -1;
-int tun_in = -1;
-int tun_out = -1;
-int netfd = -1;
-
-static char dstsystem[50];
-
-void
-SetLabel(const char *label)
-{
- if (label)
- strncpy(dstsystem, label, sizeof dstsystem - 1);
- else
- *dstsystem = '\0';
-}
-
-const char *
-GetLabel()
-{
- return *dstsystem ? dstsystem : NULL;
-}
void
randinit()
{
-#if __FreeBSD__ >= 3
+#if __FreeBSD__ >= 2
static int initdone;
if (!initdone) {
@@ -78,40 +46,69 @@ randinit()
srandomdev();
}
#else
- srandom(time(NULL)^getpid());
+ srandom((time(NULL)^getpid())+random());
#endif
}
-
-int
-GetShortHost()
+ssize_t
+fullread(int fd, void *v, size_t n)
{
- char *p;
+ size_t got, total;
+
+ for (total = 0; total < n; total += got)
+ switch ((got = read(fd, (char *)v + total, n - total))) {
+ case 0:
+ return total;
+ case -1:
+ if (errno == EINTR)
+ got = 0;
+ else
+ return -1;
+ }
+ return total;
+}
- if (gethostname(VarShortHost, sizeof VarShortHost)) {
- LogPrintf(LogERROR, "GetShortHost: gethostname: %s\n", strerror(errno));
- return 0;
- }
+static struct {
+ int mode;
+ const char *name;
+} modes[] = {
+ { PHYS_MANUAL, "interactive" },
+ { PHYS_DEMAND, "auto" },
+ { PHYS_DIRECT, "direct" },
+ { PHYS_DEDICATED, "dedicated" },
+ { PHYS_PERM, "ddial" },
+ { PHYS_1OFF, "background" },
+ { PHYS_ALL, "*" },
+ { 0, 0 }
+};
+
+const char *
+mode2Nam(int mode)
+{
+ int m;
- if ((p = strchr(VarShortHost, '.')))
- *p = '\0';
+ for (m = 0; modes[m].mode; m++)
+ if (modes[m].mode == mode)
+ return modes[m].name;
- return 1;
+ return "unknown";
}
-void
-DropClient(int verbose)
+int
+Nam2mode(const char *name)
{
- FILE *oVarTerm;
-
- if (VarTerm && !(mode & MODE_INTER)) {
- oVarTerm = VarTerm;
- VarTerm = 0;
- if (oVarTerm)
- fclose(oVarTerm);
- close(netfd);
- netfd = -1;
- if (verbose)
- LogPrintf(LogPHASE, "Client connection dropped.\n");
- }
+ int m, got, len;
+
+ len = strlen(name);
+ got = -1;
+ for (m = 0; modes[m].mode; m++)
+ if (!strncasecmp(name, modes[m].name, len)) {
+ if (modes[m].name[len] == '\0')
+ return modes[m].mode;
+ if (got != -1)
+ return 0;
+ got = m;
+ }
+
+ return got == -1 ? 0 : modes[got].mode;
}
diff --git a/usr.sbin/ppp/defs.h b/usr.sbin/ppp/defs.h
index da6422944a2b..6f39ad63729b 100644
--- a/usr.sbin/ppp/defs.h
+++ b/usr.sbin/ppp/defs.h
@@ -15,57 +15,47 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: defs.h,v 1.28 1997/11/22 03:37:29 brian Exp $
+ * $Id: defs.h,v 1.29.2.18 1998/05/15 23:58:22 brian Exp $
*
* TODO:
*/
-/*
- * Check following definitions for your machine environment
- */
+/* Check the following definitions for your machine environment */
#ifdef __FreeBSD__
-# define MODEM_DEV "/dev/cuaa1" /* name of tty device */
-# define BASE_MODEM_DEV "cuaa1" /* name of base tty device */
+# define MODEM_LIST "/dev/cuaa1, /dev/cuaa0" /* name of tty device */
#else
# ifdef __OpenBSD__
-# define MODEM_DEV "/dev/cua01" /* name of tty device */
-# define BASE_MODEM_DEV "cua01" /* name of base tty device */
+# define MODEM_LIST "/dev/cua01, /dev/cua00" /* name of tty device */
# else
-# define MODEM_DEV "/dev/tty01" /* name of tty device */
-# define BASE_MODEM_DEV "tty01" /* name of base tty device */
+# define MODEM_LIST "/dev/tty01, /dev/tty00" /* name of tty device */
# endif
#endif
+#define _PATH_PPP "/etc/ppp"
+
+#define TUN_PREFIX "/dev/tun" /* tunnel device prefix */
+#define CATPROG "/bin/cat" /* Multilink pipe program name */
+
#define MODEM_SPEED B38400 /* tty speed */
#define SERVER_PORT 3000 /* Base server port no. */
#define MODEM_CTSRTS 1 /* Default (true): use CTS/RTS signals */
-#define RECONNECT_TIMER 3 /* Default timer for carrier loss */
-#define RECONNECT_TRIES 0 /* Default retries on carrier loss */
-#define REDIAL_PERIOD 30 /* Default Hold time to redial */
-#define NEXT_REDIAL_PERIOD 3 /* Default Hold time to next number redial */
+#define RECONNECT_TIMEOUT 3 /* Default timer for carrier loss */
+#define DIAL_TIMEOUT 30 /* Default and Max random time to redial */
+#define DIAL_NEXT_TIMEOUT 3 /* Default Hold time to next number redial */
#define SCRIPT_LEN 512 /* Size of login scripts */
#define LINE_LEN SCRIPT_LEN /* Size of login scripts */
#define MAXARGS 40 /* How many args per config line */
+#define NCP_IDLE_TIMEOUT 180 /* Drop all links */
+
+#define LINK_MINWEIGHT 20
+#define DEF_LQRPERIOD 30 /* LQR frequency */
+#define DEF_FSMRETRY 3 /* FSM retry frequency */
#define CONFFILE "ppp.conf"
#define LINKUPFILE "ppp.linkup"
#define LINKDOWNFILE "ppp.linkdown"
#define SECRETFILE "ppp.secret"
-/*
- * Definition of working mode
- */
-#define MODE_INTER 1 /* Interactive mode */
-#define MODE_AUTO 2 /* Auto calling mode */
-#define MODE_DIRECT 4 /* Direct connection mode */
-#define MODE_DEDICATED 8 /* Dedicated line mode */
-#define MODE_DDIAL 16 /* Dedicated dialing line mode */
-#define MODE_ALIAS 32 /* Packet aliasing (masquerading) */
-#define MODE_BACKGROUND 64 /* Background mode. */
-
-#define MODE_DAEMON (2|4|8|16|64)
-#define MODE_OUTGOING_DAEMON (2|8|16|64)
-
#define EX_SIG -1
#define EX_NORMAL 0
#define EX_START 1
@@ -81,15 +71,17 @@
#define EX_NODIAL 12
#define EX_NOLOGIN 13
-extern int mode;
-extern int BGFiledes[2];
-extern int modem;
-extern int tun_in;
-extern int tun_out;
-extern int netfd;
+/* physical::type values (OR'd in bundle::phys_type) */
+#define PHYS_NONE 0
+#define PHYS_MANUAL 1 /* Manual link */
+#define PHYS_DEMAND 2 /* Dial-on-demand link (-auto) */
+#define PHYS_DIRECT 4 /* Incoming link (-direct) */
+#define PHYS_DEDICATED 8 /* Dedicated link (-dedicated) */
+#define PHYS_PERM 16 /* Dial immediately, stay connected (-ddial) */
+#define PHYS_1OFF 32 /* Dial immediately, delete when done. (-background) */
+#define PHYS_ALL 63
-extern void SetLabel(const char *);
-extern const char *GetLabel(void);
extern void randinit(void);
-extern int GetShortHost(void);
-extern void DropClient(int);
+extern ssize_t fullread(int, void *, size_t);
+extern const char *mode2Nam(int);
+extern int Nam2mode(const char *);
diff --git a/usr.sbin/ppp/pathnames.h b/usr.sbin/ppp/descriptor.h
index a88aaa853943..c0672b81dc9c 100644
--- a/usr.sbin/ppp/pathnames.h
+++ b/usr.sbin/ppp/descriptor.h
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 1989 The Regents of the University of California.
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,18 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -30,14 +23,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- *
- * $Id: pathnames.h,v 1.7 1997/09/10 02:20:33 brian Exp $
- *
- * @(#)pathnames.h 5.2 (Berkeley) 6/1/90
+ * $Id: descriptor.h,v 1.1.2.10 1998/04/28 01:25:13 brian Exp $
*/
-#if defined(__FreeBSD__) || defined(__OpenBSD__)
-#define _PATH_PPP "/etc/ppp"
-#else
-#define _PATH_PPP "/etc"
-#endif
+#define PHYSICAL_DESCRIPTOR (1)
+#define SERVER_DESCRIPTOR (2)
+#define PROMPT_DESCRIPTOR (3)
+#define CHAT_DESCRIPTOR (4)
+#define DATALINK_DESCRIPTOR (5)
+#define BUNDLE_DESCRIPTOR (6)
+#define MPSERVER_DESCRIPTOR (7)
+
+struct bundle;
+
+struct descriptor {
+ int type;
+ struct descriptor *next;
+
+ int (*UpdateSet)(struct descriptor *, fd_set *, fd_set *, fd_set *, int *);
+ int (*IsSet)(struct descriptor *, const fd_set *);
+ void (*Read)(struct descriptor *, struct bundle *, const fd_set *);
+ void (*Write)(struct descriptor *, struct bundle *, const fd_set *);
+};
+
+#define descriptor_UpdateSet(d, r, w, e, n) ((*(d)->UpdateSet)(d, r, w, e, n))
+#define descriptor_IsSet(d, s) ((*(d)->IsSet)(d, s))
+#define descriptor_Read(d, b, f) ((*(d)->Read)(d, b, f))
+#define descriptor_Write(d, b, f) ((*(d)->Write)(d, b, f))
diff --git a/usr.sbin/ppp/filter.c b/usr.sbin/ppp/filter.c
index b426e31ffc47..133048068183 100644
--- a/usr.sbin/ppp/filter.c
+++ b/usr.sbin/ppp/filter.c
@@ -17,37 +17,49 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: filter.c,v 1.21 1997/12/24 09:28:57 brian Exp $
+ * $Id: filter.c,v 1.22.2.19 1998/05/01 19:24:28 brian Exp $
*
* TODO: Shoud send ICMP error message when we discard packets.
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
+#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
-#include "loadalias.h"
#include "defs.h"
-#include "vars.h"
+#include "iplist.h"
+#include "timer.h"
+#include "throughput.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "slcompress.h"
#include "ipcp.h"
#include "filter.h"
+#include "descriptor.h"
+#include "prompt.h"
+#include "mp.h"
+#include "bundle.h"
-struct filterent ifilters[MAXFILTERS]; /* incoming packet filter */
-struct filterent ofilters[MAXFILTERS]; /* outgoing packet filter */
-struct filterent dfilters[MAXFILTERS]; /* dial-out packet filter */
-struct filterent afilters[MAXFILTERS]; /* keep-alive packet filter */
+static int filter_Nam2Proto(int, char const *const *);
+static int filter_Nam2Op(const char *);
-static struct filterent filterdata;
-
-static u_long netmasks[33] = {
+static const u_long netmasks[33] = {
0x00000000,
0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,
@@ -60,52 +72,51 @@ static u_long netmasks[33] = {
};
int
-ParseAddr(int argc,
- char const *const *argv,
- struct in_addr * paddr,
- struct in_addr * pmask,
- int *pwidth)
+ParseAddr(struct ipcp *ipcp, int argc, char const *const *argv,
+ struct in_addr *paddr, struct in_addr *pmask, int *pwidth)
{
int bits, len;
char *wp;
const char *cp;
if (argc < 1) {
- LogPrintf(LogWARN, "ParseAddr: address/mask is expected.\n");
+ log_Printf(LogWARN, "ParseAddr: address/mask is expected.\n");
return (0);
}
if (pmask)
- pmask->s_addr = 0xffffffff; /* Assume 255.255.255.255 as default */
+ pmask->s_addr = INADDR_BROADCAST; /* Assume 255.255.255.255 as default */
cp = pmask || pwidth ? strchr(*argv, '/') : NULL;
len = cp ? cp - *argv : strlen(*argv);
if (strncasecmp(*argv, "HISADDR", len) == 0)
- *paddr = IpcpInfo.his_ipaddr;
+ *paddr = ipcp->peer_ip;
else if (strncasecmp(*argv, "MYADDR", len) == 0)
- *paddr = IpcpInfo.want_ipaddr;
+ *paddr = ipcp->my_ip;
else if (len > 15)
- LogPrintf(LogWARN, "ParseAddr: %s: Bad address\n", *argv);
+ log_Printf(LogWARN, "ParseAddr: %s: Bad address\n", *argv);
else {
char s[16];
strncpy(s, *argv, len);
s[len] = '\0';
if (inet_aton(s, paddr) == 0) {
- LogPrintf(LogWARN, "ParseAddr: %s: Bad address\n", s);
+ log_Printf(LogWARN, "ParseAddr: %s: Bad address\n", s);
return (0);
}
}
if (cp && *++cp) {
bits = strtol(cp, &wp, 0);
if (cp == wp || bits < 0 || bits > 32) {
- LogPrintf(LogWARN, "ParseAddr: bad mask width.\n");
+ log_Printf(LogWARN, "ParseAddr: bad mask width.\n");
return (0);
}
- } else {
- /* if width is not given, assume whole 32 bits are meaningfull */
+ } else if (paddr->s_addr == INADDR_ANY)
+ /* An IP of 0.0.0.0 without a width is anything */
+ bits = 0;
+ else
+ /* If a valid IP is given without a width, assume 32 bits */
bits = 32;
- }
if (pwidth)
*pwidth = bits;
@@ -117,25 +128,6 @@ ParseAddr(int argc,
}
static int
-ParseProto(int argc, char const *const *argv)
-{
- int proto;
-
- if (argc < 1)
- return (P_NONE);
-
- if (!strcmp(*argv, "tcp"))
- proto = P_TCP;
- else if (!strcmp(*argv, "udp"))
- proto = P_UDP;
- else if (!strcmp(*argv, "icmp"))
- proto = P_ICMP;
- else
- proto = P_NONE;
- return (proto);
-}
-
-static int
ParsePort(const char *service, int proto)
{
const char *protocol_name;
@@ -160,7 +152,7 @@ ParsePort(const char *service, int proto)
port = strtol(service, &cp, 0);
if (cp == service) {
- LogPrintf(LogWARN, "ParsePort: %s is not a port name or number.\n",
+ log_Printf(LogWARN, "ParsePort: %s is not a port name or number.\n",
service);
return (0);
}
@@ -171,7 +163,7 @@ ParsePort(const char *service, int proto)
* ICMP Syntax: src eq icmp_message_type
*/
static int
-ParseIcmp(int argc, char const *const *argv)
+ParseIcmp(int argc, char const *const *argv, struct filterent *tgt)
{
int type;
char *cp;
@@ -179,108 +171,96 @@ ParseIcmp(int argc, char const *const *argv)
switch (argc) {
case 0:
/* permit/deny all ICMP types */
- filterdata.opt.srcop = OP_NONE;
+ tgt->opt.srcop = OP_NONE;
break;
- default:
- LogPrintf(LogWARN, "ParseIcmp: bad icmp syntax.\n");
- return (0);
+
case 3:
if (!strcmp(*argv, "src") && !strcmp(argv[1], "eq")) {
type = strtol(argv[2], &cp, 0);
if (cp == argv[2]) {
- LogPrintf(LogWARN, "ParseIcmp: type is expected.\n");
+ log_Printf(LogWARN, "ParseIcmp: type is expected.\n");
return (0);
}
- filterdata.opt.srcop = OP_EQ;
- filterdata.opt.srcport = type;
+ tgt->opt.srcop = OP_EQ;
+ tgt->opt.srcport = type;
}
break;
+
+ default:
+ log_Printf(LogWARN, "ParseIcmp: bad icmp syntax.\n");
+ return (0);
}
return (1);
}
-static int
-ParseOp(const char *cp)
-{
- int op = OP_NONE;
-
- if (!strcmp(cp, "eq"))
- op = OP_EQ;
- else if (!strcmp(cp, "gt"))
- op = OP_GT;
- else if (!strcmp(cp, "lt"))
- op = OP_LT;
- return (op);
-}
-
/*
* UDP Syntax: [src op port] [dst op port]
*/
static int
-ParseUdpOrTcp(int argc, char const *const *argv, int proto)
+ParseUdpOrTcp(int argc, char const *const *argv, int proto,
+ struct filterent *tgt)
{
- filterdata.opt.srcop = filterdata.opt.dstop = OP_NONE;
- filterdata.opt.estab = 0;
-
- if (argc == 0) {
- /* permit/deny all tcp traffic */
- return (1);
- }
+ tgt->opt.srcop = tgt->opt.dstop = OP_NONE;
+ tgt->opt.estab = tgt->opt.syn = tgt->opt.finrst = 0;
if (argc >= 3 && !strcmp(*argv, "src")) {
- filterdata.opt.srcop = ParseOp(argv[1]);
- if (filterdata.opt.srcop == OP_NONE) {
- LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n");
+ tgt->opt.srcop = filter_Nam2Op(argv[1]);
+ if (tgt->opt.srcop == OP_NONE) {
+ log_Printf(LogWARN, "ParseUdpOrTcp: bad operation\n");
return (0);
}
- filterdata.opt.srcport = ParsePort(argv[2], proto);
- if (filterdata.opt.srcport == 0)
+ tgt->opt.srcport = ParsePort(argv[2], proto);
+ if (tgt->opt.srcport == 0)
return (0);
argc -= 3;
argv += 3;
- if (argc == 0)
- return (1);
}
+
if (argc >= 3 && !strcmp(argv[0], "dst")) {
- filterdata.opt.dstop = ParseOp(argv[1]);
- if (filterdata.opt.dstop == OP_NONE) {
- LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n");
+ tgt->opt.dstop = filter_Nam2Op(argv[1]);
+ if (tgt->opt.dstop == OP_NONE) {
+ log_Printf(LogWARN, "ParseUdpOrTcp: bad operation\n");
return (0);
}
- filterdata.opt.dstport = ParsePort(argv[2], proto);
- if (filterdata.opt.dstport == 0)
+ tgt->opt.dstport = ParsePort(argv[2], proto);
+ if (tgt->opt.dstport == 0)
return (0);
argc -= 3;
argv += 3;
- if (argc == 0)
- return (1);
}
- if (argc == 1 && proto == P_TCP) {
- if (!strcmp(*argv, "estab")) {
- filterdata.opt.estab = 1;
- return (1);
- }
- LogPrintf(LogWARN, "ParseUdpOrTcp: estab is expected: %s\n", *argv);
- return (0);
+
+ if (proto == P_TCP) {
+ for (; argc > 0; argc--, argv++)
+ if (!strcmp(*argv, "estab"))
+ tgt->opt.estab = 1;
+ else if (!strcmp(*argv, "syn"))
+ tgt->opt.syn = 1;
+ else if (!strcmp(*argv, "finrst"))
+ tgt->opt.finrst = 1;
+ else
+ break;
}
- if (argc > 0)
- LogPrintf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv);
- return (0);
-}
-static const char *opname[] = {"none", "eq", "gt", NULL, "lt"};
+ if (argc > 0) {
+ log_Printf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv);
+ return 0;
+ }
+
+ return 1;
+}
static int
-Parse(int argc, char const *const *argv, struct filterent * ofp)
+Parse(struct ipcp *ipcp, int argc, char const *const *argv,
+ struct filterent *ofp)
{
int action, proto;
int val;
char *wp;
- struct filterent *fp = &filterdata;
+ struct filterent filterdata;
val = strtol(*argv, &wp, 0);
if (*argv == wp || val > MAXFILTERS) {
- LogPrintf(LogWARN, "Parse: invalid filter number.\n");
+ log_Printf(LogWARN, "Parse: invalid filter number.\n");
return (0);
}
if (val < 0) {
@@ -288,13 +268,13 @@ Parse(int argc, char const *const *argv, struct filterent * ofp)
ofp->action = A_NONE;
ofp++;
}
- LogPrintf(LogWARN, "Parse: filter cleared.\n");
+ log_Printf(LogWARN, "Parse: filter cleared.\n");
return (1);
}
ofp += val;
if (--argc == 0) {
- LogPrintf(LogWARN, "Parse: missing action.\n");
+ log_Printf(LogWARN, "Parse: missing action.\n");
return (0);
}
argv++;
@@ -310,37 +290,39 @@ Parse(int argc, char const *const *argv, struct filterent * ofp)
ofp->action = A_NONE;
return (1);
} else {
- LogPrintf(LogWARN, "Parse: bad action: %s\n", *argv);
+ log_Printf(LogWARN, "Parse: bad action: %s\n", *argv);
return (0);
}
- fp->action = action;
+ filterdata.action = action;
argc--;
argv++;
- if (fp->action == A_DENY) {
+ if (filterdata.action == A_DENY) {
if (!strcmp(*argv, "host")) {
- fp->action |= A_UHOST;
+ filterdata.action |= A_UHOST;
argc--;
argv++;
} else if (!strcmp(*argv, "port")) {
- fp->action |= A_UPORT;
+ filterdata.action |= A_UPORT;
argc--;
argv++;
}
}
- proto = ParseProto(argc, argv);
+ proto = filter_Nam2Proto(argc, argv);
if (proto == P_NONE) {
- if (ParseAddr(argc, argv, &fp->saddr, &fp->smask, &fp->swidth)) {
+ if (ParseAddr(ipcp, argc, argv, &filterdata.saddr, &filterdata.smask,
+ &filterdata.swidth)) {
argc--;
argv++;
- proto = ParseProto(argc, argv);
+ proto = filter_Nam2Proto(argc, argv);
if (proto == P_NONE) {
- if (ParseAddr(argc, argv, &fp->daddr, &fp->dmask, &fp->dwidth)) {
+ if (ParseAddr(ipcp, argc, argv, &filterdata.daddr, &filterdata.dmask,
+ &filterdata.dwidth)) {
argc--;
argv++;
}
- proto = ParseProto(argc, argv);
+ proto = filter_Nam2Proto(argc, argv);
if (proto != P_NONE) {
argc--;
argv++;
@@ -350,7 +332,7 @@ Parse(int argc, char const *const *argv, struct filterent * ofp)
argv++;
}
} else {
- LogPrintf(LogWARN, "Parse: Address/protocol expected.\n");
+ log_Printf(LogWARN, "Parse: Address/protocol expected.\n");
return (0);
}
} else {
@@ -359,141 +341,193 @@ Parse(int argc, char const *const *argv, struct filterent * ofp)
}
val = 1;
- fp->proto = proto;
+ filterdata.proto = proto;
switch (proto) {
case P_TCP:
- val = ParseUdpOrTcp(argc, argv, P_TCP);
+ val = ParseUdpOrTcp(argc, argv, P_TCP, &filterdata);
break;
case P_UDP:
- val = ParseUdpOrTcp(argc, argv, P_UDP);
+ val = ParseUdpOrTcp(argc, argv, P_UDP, &filterdata);
break;
case P_ICMP:
- val = ParseIcmp(argc, argv);
+ val = ParseIcmp(argc, argv, &filterdata);
break;
}
- LogPrintf(LogDEBUG, "Parse: Src: %s\n", inet_ntoa(fp->saddr));
- LogPrintf(LogDEBUG, "Parse: Src mask: %s\n", inet_ntoa(fp->smask));
- LogPrintf(LogDEBUG, "Parse: Dst: %s\n", inet_ntoa(fp->daddr));
- LogPrintf(LogDEBUG, "Parse: Dst mask: %s\n", inet_ntoa(fp->dmask));
- LogPrintf(LogDEBUG, "Parse: Proto = %d\n", proto);
+ log_Printf(LogDEBUG, "Parse: Src: %s\n", inet_ntoa(filterdata.saddr));
+ log_Printf(LogDEBUG, "Parse: Src mask: %s\n", inet_ntoa(filterdata.smask));
+ log_Printf(LogDEBUG, "Parse: Dst: %s\n", inet_ntoa(filterdata.daddr));
+ log_Printf(LogDEBUG, "Parse: Dst mask: %s\n", inet_ntoa(filterdata.dmask));
+ log_Printf(LogDEBUG, "Parse: Proto = %d\n", proto);
- LogPrintf(LogDEBUG, "Parse: src: %s (%d)\n", opname[fp->opt.srcop],
- fp->opt.srcport);
- LogPrintf(LogDEBUG, "Parse: dst: %s (%d)\n", opname[fp->opt.dstop],
- fp->opt.dstport);
- LogPrintf(LogDEBUG, "Parse: estab: %d\n", fp->opt.estab);
+ log_Printf(LogDEBUG, "Parse: src: %s (%d)\n",
+ filter_Op2Nam(filterdata.opt.srcop), filterdata.opt.srcport);
+ log_Printf(LogDEBUG, "Parse: dst: %s (%d)\n",
+ filter_Op2Nam(filterdata.opt.dstop), filterdata.opt.dstport);
+ log_Printf(LogDEBUG, "Parse: estab: %u\n", filterdata.opt.estab);
+ log_Printf(LogDEBUG, "Parse: syn: %u\n", filterdata.opt.syn);
+ log_Printf(LogDEBUG, "Parse: finrst: %u\n", filterdata.opt.finrst);
if (val)
- *ofp = *fp;
+ *ofp = filterdata;
return (val);
}
int
-SetIfilter(struct cmdargs const *arg)
-{
- if (arg->argc > 0) {
- Parse(arg->argc, arg->argv, ifilters);
- return 0;
- }
- return -1;
-}
-
-int
-SetOfilter(struct cmdargs const *arg)
+filter_Set(struct cmdargs const *arg)
{
- if (arg->argc > 0) {
- (void) Parse(arg->argc, arg->argv, ofilters);
- return 0;
+ struct filter *filter;
+
+ if (arg->argc < arg->argn+2)
+ return -1;
+
+ if (!strcmp(arg->argv[arg->argn], "in"))
+ filter = &arg->bundle->filter.in;
+ else if (!strcmp(arg->argv[arg->argn], "out"))
+ filter = &arg->bundle->filter.out;
+ else if (!strcmp(arg->argv[arg->argn], "dial"))
+ filter = &arg->bundle->filter.dial;
+ else if (!strcmp(arg->argv[arg->argn], "alive"))
+ filter = &arg->bundle->filter.alive;
+ else {
+ log_Printf(LogWARN, "filter_Set: %s: Invalid filter name.\n",
+ arg->argv[arg->argn]);
+ return -1;
}
- return -1;
-}
-int
-SetDfilter(struct cmdargs const *arg)
-{
- if (arg->argc > 0) {
- (void) Parse(arg->argc, arg->argv, dfilters);
- return 0;
- }
- return -1;
+ Parse(&arg->bundle->ncp.ipcp, arg->argc - arg->argn - 1,
+ arg->argv + arg->argn + 1, filter->rule);
+ return 0;
}
-int
-SetAfilter(struct cmdargs const *arg)
+const char *
+filter_Action2Nam(int act)
{
- if (arg->argc > 0) {
- (void) Parse(arg->argc, arg->argv, afilters);
- return 0;
- }
- return -1;
+ static const char *actname[] = { "none ", "permit ", "deny " };
+ return actname[act & (A_PERMIT|A_DENY)];
}
-static const char *protoname[] = { "none", "tcp", "udp", "icmp" };
-static const char *actname[] = { "none ", "permit ", "deny " };
-
static void
-ShowFilter(struct filterent * fp)
+doShowFilter(struct filterent *fp, struct prompt *prompt)
{
int n;
- if (!VarTerm)
- return;
-
for (n = 0; n < MAXFILTERS; n++, fp++) {
if (fp->action != A_NONE) {
- fprintf(VarTerm, "%2d %s", n, actname[fp->action & (A_PERMIT|A_DENY)]);
+ prompt_Printf(prompt, " %2d %s", n, filter_Action2Nam(fp->action));
if (fp->action & A_UHOST)
- fprintf(VarTerm, "host ");
+ prompt_Printf(prompt, "host ");
else if (fp->action & A_UPORT)
- fprintf(VarTerm, "port ");
+ prompt_Printf(prompt, "port ");
else
- fprintf(VarTerm, " ");
- fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->saddr), fp->swidth);
- fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->daddr), fp->dwidth);
+ prompt_Printf(prompt, " ");
+ prompt_Printf(prompt, "%s/%d ", inet_ntoa(fp->saddr), fp->swidth);
+ prompt_Printf(prompt, "%s/%d ", inet_ntoa(fp->daddr), fp->dwidth);
if (fp->proto) {
- fprintf(VarTerm, "%s", protoname[fp->proto]);
+ prompt_Printf(prompt, "%s", filter_Proto2Nam(fp->proto));
if (fp->opt.srcop)
- fprintf(VarTerm, " src %s %d", opname[fp->opt.srcop],
+ prompt_Printf(prompt, " src %s %d", filter_Op2Nam(fp->opt.srcop),
fp->opt.srcport);
if (fp->opt.dstop)
- fprintf(VarTerm, " dst %s %d", opname[fp->opt.dstop],
+ prompt_Printf(prompt, " dst %s %d", filter_Op2Nam(fp->opt.dstop),
fp->opt.dstport);
if (fp->opt.estab)
- fprintf(VarTerm, " estab");
-
+ prompt_Printf(prompt, " estab");
+ if (fp->opt.syn)
+ prompt_Printf(prompt, " syn");
+ if (fp->opt.finrst)
+ prompt_Printf(prompt, " finrst");
}
- fprintf(VarTerm, "\n");
+ prompt_Printf(prompt, "\n");
}
}
}
int
-ShowIfilter(struct cmdargs const *arg)
+filter_Show(struct cmdargs const *arg)
{
- ShowFilter(ifilters);
+ if (arg->argc > arg->argn+1)
+ return -1;
+
+ if (arg->argc == arg->argn+1) {
+ struct filter *filter;
+
+ if (!strcmp(arg->argv[arg->argn], "in"))
+ filter = &arg->bundle->filter.in;
+ else if (!strcmp(arg->argv[arg->argn], "out"))
+ filter = &arg->bundle->filter.out;
+ else if (!strcmp(arg->argv[arg->argn], "dial"))
+ filter = &arg->bundle->filter.dial;
+ else if (!strcmp(arg->argv[arg->argn], "alive"))
+ filter = &arg->bundle->filter.alive;
+ else
+ return -1;
+ doShowFilter(filter->rule, arg->prompt);
+ } else {
+ struct filter *filter[4];
+ int f;
+
+ filter[0] = &arg->bundle->filter.in;
+ filter[1] = &arg->bundle->filter.out;
+ filter[2] = &arg->bundle->filter.dial;
+ filter[3] = &arg->bundle->filter.alive;
+ for (f = 0; f < 4; f++) {
+ if (f)
+ prompt_Printf(arg->prompt, "\n");
+ prompt_Printf(arg->prompt, "%s:\n", filter[f]->name);
+ doShowFilter(filter[f]->rule, arg->prompt);
+ }
+ }
+
return 0;
}
-int
-ShowOfilter(struct cmdargs const *arg)
+static const char *protoname[] = { "none", "tcp", "udp", "icmp" };
+
+const char *
+filter_Proto2Nam(int proto)
{
- ShowFilter(ofilters);
- return 0;
+ if (proto >= sizeof protoname / sizeof protoname[0])
+ return "unknown";
+ return protoname[proto];
}
-int
-ShowDfilter(struct cmdargs const *arg)
+static int
+filter_Nam2Proto(int argc, char const *const *argv)
{
- ShowFilter(dfilters);
- return 0;
+ int proto;
+
+ if (argc == 0)
+ proto = 0;
+ else
+ for (proto = sizeof protoname / sizeof protoname[0] - 1; proto; proto--)
+ if (!strcasecmp(*argv, protoname[proto]))
+ break;
+
+ return proto;
}
-int
-ShowAfilter(struct cmdargs const *arg)
+static const char *opname[] = {"none", "eq", "gt", "unknown", "lt"};
+
+const char *
+filter_Op2Nam(int op)
{
- ShowFilter(afilters);
- return 0;
+ if (op >= sizeof opname / sizeof opname[0])
+ return "unknown";
+ return opname[op];
+
+}
+
+static int
+filter_Nam2Op(const char *cp)
+{
+ int op;
+
+ for (op = sizeof opname / sizeof opname[0] - 1; op; op--)
+ if (!strcasecmp(cp, opname[op]))
+ break;
+
+ return op;
}
diff --git a/usr.sbin/ppp/filter.h b/usr.sbin/ppp/filter.h
index 1342a996664f..f96af409ada6 100644
--- a/usr.sbin/ppp/filter.h
+++ b/usr.sbin/ppp/filter.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: filter.h,v 1.10 1997/10/26 01:02:35 brian Exp $
+ * $Id: filter.h,v 1.11.2.7 1998/05/01 19:24:30 brian Exp $
*
* TODO:
*/
@@ -60,28 +60,33 @@ struct filterent {
u_short srcport;
short dstop;
u_short dstport;
- int estab;
+ unsigned estab : 1;
+ unsigned syn : 1;
+ unsigned finrst : 1;
} opt;
};
-#define MAXFILTERS 20
+#define MAXFILTERS 20 /* in each filter set */
+
+struct filter {
+ struct filterent rule[MAXFILTERS]; /* incoming packet filter */
+ const char *name;
+ unsigned fragok : 1;
+ unsigned logok : 1;
+};
#define FL_IN 0
#define FL_OUT 1
#define FL_DIAL 2
#define FL_KEEP 3
-extern struct filterent ifilters[MAXFILTERS]; /* incoming packet filter */
-extern struct filterent ofilters[MAXFILTERS]; /* outgoing packet filter */
-extern struct filterent dfilters[MAXFILTERS]; /* dial-out packet filter */
-extern struct filterent afilters[MAXFILTERS]; /* keep-alive packet filter */
+struct ipcp;
+struct cmdargs;
-extern int ParseAddr(int, char const *const *, struct in_addr *, struct in_addr *, int *);
-extern int ShowIfilter(struct cmdargs const *);
-extern int ShowOfilter(struct cmdargs const *);
-extern int ShowDfilter(struct cmdargs const *);
-extern int ShowAfilter(struct cmdargs const *);
-extern int SetIfilter(struct cmdargs const *);
-extern int SetOfilter(struct cmdargs const *);
-extern int SetDfilter(struct cmdargs const *);
-extern int SetAfilter(struct cmdargs const *);
+extern int ParseAddr(struct ipcp *, int, char const *const *, struct in_addr *,
+ struct in_addr *, int *);
+extern int filter_Show(struct cmdargs const *);
+extern int filter_Set(struct cmdargs const *);
+extern const char * filter_Action2Nam(int);
+extern const char *filter_Proto2Nam(int);
+extern const char *filter_Op2Nam(int);
diff --git a/usr.sbin/ppp/fsm.c b/usr.sbin/ppp/fsm.c
index a3a50d2245cf..1e0f6cb7f7f9 100644
--- a/usr.sbin/ppp/fsm.c
+++ b/usr.sbin/ppp/fsm.c
@@ -17,114 +17,193 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: fsm.c,v 1.26 1998/01/10 01:55:09 brian Exp $
+ * $Id: fsm.c,v 1.27.2.35 1998/05/01 19:24:32 brian Exp $
*
* TODO:
- * o Refer loglevel for log output
- * o Better option log display
*/
-#include <sys/param.h>
+
+#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
-#include <stdio.h>
#include <string.h>
#include <termios.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
-#include "hdlc.h"
+#include "iplist.h"
#include "lqr.h"
-#include "lcpproto.h"
+#include "hdlc.h"
+#include "throughput.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
#include "lcp.h"
#include "ccp.h"
-#include "modem.h"
-#include "loadalias.h"
-#include "vars.h"
-
-u_char AckBuff[200];
-u_char NakBuff[200];
-u_char RejBuff[100];
-u_char ReqBuff[200];
-u_char *ackp = NULL;
-u_char *nakp = NULL;
-u_char *rejp = NULL;
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
+#include "async.h"
+#include "physical.h"
+#include "lcpproto.h"
static void FsmSendConfigReq(struct fsm *);
static void FsmSendTerminateReq(struct fsm *);
static void FsmInitRestartCounter(struct fsm *);
-char const *StateNames[] = {
- "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
- "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
+typedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *);
+static recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak,
+ FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck,
+ FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq,
+ FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent,
+ FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck;
+
+static const struct fsmcodedesc {
+ recvfn *recv;
+ unsigned check_reqid : 1;
+ unsigned inc_reqid : 1;
+ const char *name;
+} FsmCodes[] = {
+ { FsmRecvConfigReq, 0, 0, "ConfigReq" },
+ { FsmRecvConfigAck, 1, 1, "ConfigAck" },
+ { FsmRecvConfigNak, 1, 1, "ConfigNak" },
+ { FsmRecvConfigRej, 1, 1, "ConfigRej" },
+ { FsmRecvTermReq, 0, 0, "TerminateReq" },
+ { FsmRecvTermAck, 1, 1, "TerminateAck" },
+ { FsmRecvCodeRej, 0, 0, "CodeRej" },
+ { FsmRecvProtoRej, 0, 0, "ProtocolRej" },
+ { FsmRecvEchoReq, 0, 0, "EchoRequest" },
+ { FsmRecvEchoRep, 0, 0, "EchoReply" },
+ { FsmRecvDiscReq, 0, 0, "DiscardReq" },
+ { FsmRecvIdent, 0, 0, "Ident" },
+ { FsmRecvTimeRemain,0, 0, "TimeRemain" },
+ { FsmRecvResetReq, 0, 0, "ResetReqt" },
+ { FsmRecvResetAck, 0, 1, "ResetAck" }
};
+static const char *
+Code2Nam(u_int code)
+{
+ if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0])
+ return "Unknown";
+ return FsmCodes[code-1].name;
+}
+
+const char *
+State2Nam(u_int state)
+{
+ static const char *StateNames[] = {
+ "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
+ "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
+ };
+
+ if (state >= sizeof StateNames / sizeof StateNames[0])
+ return "unknown";
+ return StateNames[state];
+}
+
static void
StoppedTimeout(void *v)
{
struct fsm *fp = (struct fsm *)v;
- LogPrintf(fp->LogLevel, "Stopped timer expired\n");
+ log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name);
if (fp->OpenTimer.state == TIMER_RUNNING) {
- LogPrintf(LogWARN, "%s: aborting open delay due to stopped timer\n",
- fp->name);
- StopTimer(&fp->OpenTimer);
+ log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n",
+ fp->link->name, fp->name);
+ timer_Stop(&fp->OpenTimer);
+ }
+ if (fp->state == ST_STOPPED) {
+ /* Force ourselves back to initial */
+ fsm_Down(fp);
+ fsm_Close(fp);
}
- if (modem != -1)
- DownConnection();
- else
- FsmDown(fp);
}
void
-FsmInit(struct fsm * fp)
-{
- LogPrintf(LogDEBUG, "FsmInit\n");
- fp->state = ST_INITIAL;
+fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode,
+ int maxcode, int maxcfg, int LogLevel, struct bundle *bundle,
+ struct link *l, const struct fsm_parent *parent,
+ struct fsm_callbacks *fn, const char *timer_names[3])
+{
+ fp->name = name;
+ fp->proto = proto;
+ fp->min_code = mincode;
+ fp->max_code = maxcode;
+ fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL;
fp->reqid = 1;
fp->restart = 1;
- fp->maxconfig = 3;
+ fp->maxconfig = maxcfg;
+ memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer);
+ memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer);
+ memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer);
+ fp->LogLevel = LogLevel;
+ fp->link = l;
+ fp->bundle = bundle;
+ fp->parent = parent;
+ fp->fn = fn;
+ fp->FsmTimer.name = timer_names[0];
+ fp->OpenTimer.name = timer_names[1];
+ fp->StoppedTimer.name = timer_names[2];
}
static void
NewState(struct fsm * fp, int new)
{
- LogPrintf(fp->LogLevel, "State change %s --> %s\n",
- StateNames[fp->state], StateNames[new]);
+ log_Printf(fp->LogLevel, "%s: State change %s --> %s\n",
+ fp->link->name, State2Nam(fp->state), State2Nam(new));
if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
- StopTimer(&fp->StoppedTimer);
+ timer_Stop(&fp->StoppedTimer);
fp->state = new;
if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
- StopTimer(&fp->FsmTimer);
+ timer_Stop(&fp->FsmTimer);
if (new == ST_STOPPED && fp->StoppedTimer.load) {
- fp->StoppedTimer.state = TIMER_STOPPED;
+ timer_Stop(&fp->StoppedTimer);
fp->StoppedTimer.func = StoppedTimeout;
fp->StoppedTimer.arg = (void *) fp;
- StartTimer(&fp->StoppedTimer);
+ timer_Start(&fp->StoppedTimer);
}
}
}
void
-FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count)
+fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count)
{
int plen;
struct fsmheader lh;
struct mbuf *bp;
+ if (log_IsKept(fp->LogLevel)) {
+ log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n",
+ fp->link->name, Code2Nam(code), id, State2Nam(fp->state));
+ switch (code) {
+ case CODE_CONFIGREQ:
+ case CODE_CONFIGACK:
+ case CODE_CONFIGREJ:
+ case CODE_CONFIGNAK:
+ (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL);
+ if (count < sizeof(struct fsmconfig))
+ log_Printf(fp->LogLevel, " [EMPTY]\n");
+ break;
+ }
+ }
+
plen = sizeof(struct fsmheader) + count;
lh.code = code;
lh.id = id;
lh.length = htons(plen);
- bp = mballoc(plen, MB_FSM);
+ bp = mbuf_Alloc(plen, MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
if (count)
memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
- LogDumpBp(LogDEBUG, "FsmOutput", bp);
- HdlcOutput(PRI_LINK, fp->proto, bp);
+ log_DumpBp(LogDEBUG, "fsm_Output", bp);
+ hdlc_Output(fp->link, PRI_LINK, fp->proto, bp);
}
static void
@@ -132,7 +211,7 @@ FsmOpenNow(void *v)
{
struct fsm *fp = (struct fsm *)v;
- StopTimer(&fp->OpenTimer);
+ timer_Stop(&fp->OpenTimer);
if (fp->state <= ST_STOPPED) {
FsmInitRestartCounter(fp);
FsmSendConfigReq(fp);
@@ -141,28 +220,27 @@ FsmOpenNow(void *v)
}
void
-FsmOpen(struct fsm * fp)
+fsm_Open(struct fsm * fp)
{
switch (fp->state) {
- case ST_INITIAL:
- (fp->LayerStart) (fp);
+ case ST_INITIAL:
NewState(fp, ST_STARTING);
- break;
- case ST_STARTING:
+ (*fp->fn->LayerStart)(fp);
+ (*fp->parent->LayerStart)(fp->parent->object, fp);
break;
case ST_CLOSED:
if (fp->open_mode == OPEN_PASSIVE) {
NewState(fp, ST_STOPPED);
} else if (fp->open_mode > 0) {
if (fp->open_mode > 1)
- LogPrintf(LogPHASE, "Entering STOPPED state for %d seconds\n",
- fp->open_mode);
+ log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n",
+ fp->link->name, fp->open_mode);
NewState(fp, ST_STOPPED);
- fp->OpenTimer.state = TIMER_STOPPED;
+ timer_Stop(&fp->OpenTimer);
fp->OpenTimer.load = fp->open_mode * SECTICKS;
fp->OpenTimer.func = FsmOpenNow;
fp->OpenTimer.arg = (void *)fp;
- StartTimer(&fp->OpenTimer);
+ timer_Start(&fp->OpenTimer);
} else
FsmOpenNow(fp);
break;
@@ -180,10 +258,12 @@ FsmOpen(struct fsm * fp)
}
void
-FsmUp(struct fsm * fp)
+fsm_Up(struct fsm * fp)
{
switch (fp->state) {
case ST_INITIAL:
+ log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n",
+ fp->link->name);
NewState(fp, ST_CLOSED);
break;
case ST_STARTING:
@@ -192,22 +272,29 @@ FsmUp(struct fsm * fp)
NewState(fp, ST_REQSENT);
break;
default:
- LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]);
+ log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n",
+ fp->link->name, State2Nam(fp->state));
break;
}
}
void
-FsmDown(struct fsm * fp)
+fsm_Down(struct fsm *fp)
{
switch (fp->state) {
- case ST_CLOSED:
- case ST_CLOSING:
+ case ST_CLOSED:
+ NewState(fp, ST_INITIAL);
+ break;
+ case ST_CLOSING:
+ (*fp->fn->LayerFinish)(fp);
NewState(fp, ST_INITIAL);
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
break;
case ST_STOPPED:
- (fp->LayerStart) (fp);
- /* Fall into.. */
+ NewState(fp, ST_STARTING);
+ (*fp->fn->LayerStart)(fp);
+ (*fp->parent->LayerStart)(fp->parent->object, fp);
+ break;
case ST_STOPPING:
case ST_REQSENT:
case ST_ACKRCVD:
@@ -215,18 +302,21 @@ FsmDown(struct fsm * fp)
NewState(fp, ST_STARTING);
break;
case ST_OPENED:
- (fp->LayerDown) (fp);
+ (*fp->fn->LayerDown)(fp);
NewState(fp, ST_STARTING);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
break;
}
}
void
-FsmClose(struct fsm * fp)
+fsm_Close(struct fsm *fp)
{
switch (fp->state) {
- case ST_STARTING:
+ case ST_STARTING:
+ (*fp->fn->LayerFinish)(fp);
NewState(fp, ST_INITIAL);
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
break;
case ST_STOPPED:
NewState(fp, ST_CLOSED);
@@ -235,8 +325,12 @@ FsmClose(struct fsm * fp)
NewState(fp, ST_CLOSING);
break;
case ST_OPENED:
- (fp->LayerDown) (fp);
- /* Fall down */
+ (*fp->fn->LayerDown)(fp);
+ FsmInitRestartCounter(fp);
+ FsmSendTerminateReq(fp);
+ NewState(fp, ST_CLOSING);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
+ break;
case ST_REQSENT:
case ST_ACKRCVD:
case ST_ACKSENT:
@@ -254,57 +348,23 @@ static void
FsmSendConfigReq(struct fsm * fp)
{
if (--fp->maxconfig > 0) {
- (fp->SendConfigReq) (fp);
- StartTimer(&fp->FsmTimer); /* Start restart timer */
+ (*fp->fn->SendConfigReq)(fp);
+ timer_Start(&fp->FsmTimer); /* Start restart timer */
fp->restart--; /* Decrement restart counter */
} else {
- FsmClose(fp);
+ fsm_Close(fp);
}
}
static void
-FsmSendTerminateReq(struct fsm * fp)
+FsmSendTerminateReq(struct fsm *fp)
{
- LogPrintf(fp->LogLevel, "SendTerminateReq.\n");
- FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
- (fp->SendTerminateReq) (fp);
- StartTimer(&fp->FsmTimer); /* Start restart timer */
+ fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0);
+ (*fp->fn->SentTerminateReq)(fp);
+ timer_Start(&fp->FsmTimer); /* Start restart timer */
fp->restart--; /* Decrement restart counter */
}
-static void
-FsmSendConfigAck(struct fsm * fp,
- struct fsmheader * lhp,
- u_char * option,
- int count)
-{
- LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]);
- (fp->DecodeConfig) (option, count, MODE_NOP);
- FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
-}
-
-static void
-FsmSendConfigRej(struct fsm * fp,
- struct fsmheader * lhp,
- u_char * option,
- int count)
-{
- LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]);
- (fp->DecodeConfig) (option, count, MODE_NOP);
- FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
-}
-
-static void
-FsmSendConfigNak(struct fsm * fp,
- struct fsmheader * lhp,
- u_char * option,
- int count)
-{
- LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]);
- (fp->DecodeConfig) (option, count, MODE_NOP);
- FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
-}
-
/*
* Timeout actions
*/
@@ -315,8 +375,8 @@ FsmTimeout(void *v)
if (fp->restart) {
switch (fp->state) {
- case ST_CLOSING:
- case ST_STOPPING:
+ case ST_CLOSING:
+ case ST_STOPPING:
FsmSendTerminateReq(fp);
break;
case ST_REQSENT:
@@ -328,22 +388,25 @@ FsmTimeout(void *v)
NewState(fp, ST_REQSENT);
break;
}
- StartTimer(&fp->FsmTimer);
+ timer_Start(&fp->FsmTimer);
} else {
switch (fp->state) {
case ST_CLOSING:
+ (*fp->fn->LayerFinish)(fp);
NewState(fp, ST_CLOSED);
- (fp->LayerFinish) (fp);
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
break;
case ST_STOPPING:
+ (*fp->fn->LayerFinish)(fp);
NewState(fp, ST_STOPPED);
- (fp->LayerFinish) (fp);
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
break;
case ST_REQSENT: /* XXX: 3p */
case ST_ACKSENT:
case ST_ACKRCVD:
+ (*fp->fn->LayerFinish)(fp);
NewState(fp, ST_STOPPED);
- (fp->LayerFinish) (fp);
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
break;
}
}
@@ -352,29 +415,29 @@ FsmTimeout(void *v)
static void
FsmInitRestartCounter(struct fsm * fp)
{
- StopTimer(&fp->FsmTimer);
- fp->FsmTimer.state = TIMER_STOPPED;
+ timer_Stop(&fp->FsmTimer);
fp->FsmTimer.func = FsmTimeout;
fp->FsmTimer.arg = (void *) fp;
- (fp->InitRestartCounter) (fp);
+ (*fp->fn->InitRestartCounter)(fp);
}
/*
* Actions when receive packets
*/
static void
-FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
/* RCR */
{
+ struct fsm_decode dec;
int plen, flen;
int ackaction = 0;
- plen = plength(bp);
+ plen = mbuf_Length(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
- LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n",
- plen, flen);
- pfree(bp);
+ log_Printf(LogERROR, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
+ fp->link->name, plen, flen);
+ mbuf_Free(bp);
return;
}
@@ -384,30 +447,37 @@ FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
switch (fp->state) {
case ST_INITIAL:
case ST_STARTING:
- LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]);
- pfree(bp);
+ log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n",
+ fp->link->name, State2Nam(fp->state));
+ mbuf_Free(bp);
return;
case ST_CLOSED:
- (fp->SendTerminateAck) (fp);
- pfree(bp);
+ (*fp->fn->SendTerminateAck)(fp, lhp->id);
+ mbuf_Free(bp);
return;
case ST_CLOSING:
- LogPrintf(fp->LogLevel, "Error: Got ConfigReq while state = %d\n",
- fp->state);
+ log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n",
+ fp->link->name, State2Nam(fp->state));
case ST_STOPPING:
- pfree(bp);
+ mbuf_Free(bp);
return;
}
- (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REQ);
+ dec.ackend = dec.ack;
+ dec.nakend = dec.nak;
+ dec.rejend = dec.rej;
+ (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec);
+ if (flen < sizeof(struct fsmconfig))
+ log_Printf(fp->LogLevel, " [EMPTY]\n");
- if (nakp == NakBuff && rejp == RejBuff)
+ if (dec.nakend == dec.nak && dec.rejend == dec.rej)
ackaction = 1;
switch (fp->state) {
case ST_OPENED:
- (fp->LayerDown) (fp);
+ (*fp->fn->LayerDown)(fp);
FsmSendConfigReq(fp);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
break;
case ST_STOPPED:
FsmInitRestartCounter(fp);
@@ -415,16 +485,16 @@ FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
break;
}
- if (rejp != RejBuff)
- FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
- if (nakp != NakBuff)
- FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
+ if (dec.rejend != dec.rej)
+ fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej);
+ if (dec.nakend != dec.nak)
+ fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak);
if (ackaction)
- FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
+ fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack);
switch (fp->state) {
- case ST_STOPPED:
case ST_OPENED:
+ case ST_STOPPED:
if (ackaction)
NewState(fp, ST_ACKSENT);
else
@@ -437,7 +507,14 @@ FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
case ST_ACKRCVD:
if (ackaction) {
NewState(fp, ST_OPENED);
- (fp->LayerUp) (fp);
+ if ((*fp->fn->LayerUp)(fp))
+ (*fp->parent->LayerUp)(fp->parent->object, fp);
+ else {
+ (*fp->fn->LayerDown)(fp);
+ FsmInitRestartCounter(fp);
+ FsmSendTerminateReq(fp);
+ NewState(fp, ST_CLOSING);
+ }
}
break;
case ST_ACKSENT:
@@ -445,17 +522,17 @@ FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
NewState(fp, ST_REQSENT);
break;
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
/* RCA */
{
switch (fp->state) {
case ST_CLOSED:
case ST_STOPPED:
- (fp->SendTerminateAck) (fp);
+ (*fp->fn->SendTerminateAck)(fp, lhp->id);
break;
case ST_CLOSING:
case ST_STOPPING:
@@ -471,27 +548,36 @@ FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
case ST_ACKSENT:
FsmInitRestartCounter(fp);
NewState(fp, ST_OPENED);
- (fp->LayerUp) (fp);
+ if ((*fp->fn->LayerUp)(fp))
+ (*fp->parent->LayerUp)(fp->parent->object, fp);
+ else {
+ (*fp->fn->LayerDown)(fp);
+ FsmInitRestartCounter(fp);
+ FsmSendTerminateReq(fp);
+ NewState(fp, ST_CLOSING);
+ }
break;
case ST_OPENED:
- (fp->LayerDown) (fp);
+ (*fp->fn->LayerDown)(fp);
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
break;
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
/* RCN */
{
+ struct fsm_decode dec;
int plen, flen;
- plen = plength(bp);
+ plen = mbuf_Length(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
- pfree(bp);
+ mbuf_Free(bp);
return;
}
@@ -501,21 +587,27 @@ FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
switch (fp->state) {
case ST_INITIAL:
case ST_STARTING:
- LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]);
- pfree(bp);
+ log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n",
+ fp->link->name, State2Nam(fp->state));
+ mbuf_Free(bp);
return;
case ST_CLOSED:
case ST_STOPPED:
- (fp->SendTerminateAck) (fp);
- pfree(bp);
+ (*fp->fn->SendTerminateAck)(fp, lhp->id);
+ mbuf_Free(bp);
return;
case ST_CLOSING:
case ST_STOPPING:
- pfree(bp);
+ mbuf_Free(bp);
return;
}
- (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_NAK);
+ dec.ackend = dec.ack;
+ dec.nakend = dec.nak;
+ dec.rejend = dec.rej;
+ (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec);
+ if (flen < sizeof(struct fsmconfig))
+ log_Printf(fp->LogLevel, " [EMPTY]\n");
switch (fp->state) {
case ST_REQSENT:
@@ -524,47 +616,52 @@ FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
FsmSendConfigReq(fp);
break;
case ST_OPENED:
- (fp->LayerDown) (fp);
- /* Fall down */
+ (*fp->fn->LayerDown)(fp);
+ FsmSendConfigReq(fp);
+ NewState(fp, ST_REQSENT);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
+ break;
case ST_ACKRCVD:
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvTermReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
/* RTR */
{
switch (fp->state) {
- case ST_INITIAL:
- case ST_STARTING:
- LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]);
+ case ST_INITIAL:
+ case ST_STARTING:
+ log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n",
+ fp->link->name, State2Nam(fp->state));
break;
case ST_CLOSED:
case ST_STOPPED:
case ST_CLOSING:
case ST_STOPPING:
case ST_REQSENT:
- (fp->SendTerminateAck) (fp);
+ (*fp->fn->SendTerminateAck)(fp, lhp->id);
break;
case ST_ACKRCVD:
case ST_ACKSENT:
- (fp->SendTerminateAck) (fp);
+ (*fp->fn->SendTerminateAck)(fp, lhp->id);
NewState(fp, ST_REQSENT);
break;
case ST_OPENED:
- (fp->LayerDown) (fp);
- (fp->SendTerminateAck) (fp);
- StartTimer(&fp->FsmTimer); /* Start restart timer */
+ (*fp->fn->LayerDown)(fp);
+ (*fp->fn->SendTerminateAck)(fp, lhp->id);
+ timer_Start(&fp->FsmTimer); /* Start restart timer */
fp->restart = 0;
NewState(fp, ST_STOPPING);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
break;
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
@@ -572,39 +669,42 @@ FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
/* RTA */
{
switch (fp->state) {
- case ST_CLOSING:
+ case ST_CLOSING:
+ (*fp->fn->LayerFinish)(fp);
NewState(fp, ST_CLOSED);
- (fp->LayerFinish) (fp);
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
break;
case ST_STOPPING:
+ (*fp->fn->LayerFinish)(fp);
NewState(fp, ST_STOPPED);
- (fp->LayerFinish) (fp);
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
break;
case ST_ACKRCVD:
NewState(fp, ST_REQSENT);
break;
case ST_OPENED:
- (fp->LayerDown) (fp);
+ (*fp->fn->LayerDown)(fp);
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
break;
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
/* RCJ */
{
+ struct fsm_decode dec;
int plen, flen;
- plen = plength(bp);
+ plen = mbuf_Length(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
- pfree(bp);
+ mbuf_Free(bp);
return;
}
- LogPrintf(fp->LogLevel, "RecvConfigRej.\n");
/*
* Check and process easy case
@@ -612,21 +712,27 @@ FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
switch (fp->state) {
case ST_INITIAL:
case ST_STARTING:
- LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]);
- pfree(bp);
+ log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n",
+ fp->link->name, State2Nam(fp->state));
+ mbuf_Free(bp);
return;
case ST_CLOSED:
case ST_STOPPED:
- (fp->SendTerminateAck) (fp);
- pfree(bp);
+ (*fp->fn->SendTerminateAck)(fp, lhp->id);
+ mbuf_Free(bp);
return;
case ST_CLOSING:
case ST_STOPPING:
- pfree(bp);
+ mbuf_Free(bp);
return;
}
- (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REJ);
+ dec.ackend = dec.ack;
+ dec.nakend = dec.nak;
+ dec.rejend = dec.rej;
+ (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec);
+ if (flen < sizeof(struct fsmconfig))
+ log_Printf(fp->LogLevel, " [EMPTY]\n");
switch (fp->state) {
case ST_REQSENT:
@@ -635,186 +741,220 @@ FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
FsmSendConfigReq(fp);
break;
case ST_OPENED:
- (fp->LayerDown) (fp);
- /* Fall down */
+ (*fp->fn->LayerDown)(fp);
+ FsmSendConfigReq(fp);
+ NewState(fp, ST_REQSENT);
+ (*fp->parent->LayerDown)(fp->parent->object, fp);
+ break;
case ST_ACKRCVD:
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvCodeRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
{
- LogPrintf(fp->LogLevel, "RecvCodeRej\n");
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvProtoRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
{
+ struct physical *p = link2physical(fp->link);
u_short *sp, proto;
sp = (u_short *) MBUF_CTOP(bp);
proto = ntohs(*sp);
- LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto);
+ log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
+ fp->link->name, proto, hdlc_Protocol2Nam(proto));
switch (proto) {
case PROTO_LQR:
- StopLqr(LQM_LQR);
+ if (p)
+ lqr_Stop(p, LQM_LQR);
+ else
+ log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n",
+ fp->link->name);
break;
case PROTO_CCP:
- fp = &CcpFsm;
- (fp->LayerFinish) (fp);
- switch (fp->state) {
- case ST_CLOSED:
- case ST_CLOSING:
- NewState(fp, ST_CLOSED);
- default:
- NewState(fp, ST_STOPPED);
- break;
+ if (fp->proto == PROTO_LCP) {
+ fp = &fp->link->ccp.fsm;
+ (*fp->fn->LayerFinish)(fp);
+ switch (fp->state) {
+ case ST_CLOSED:
+ case ST_CLOSING:
+ NewState(fp, ST_CLOSED);
+ default:
+ NewState(fp, ST_STOPPED);
+ break;
+ }
+ (*fp->parent->LayerFinish)(fp->parent->object, fp);
+ }
+ break;
+ case PROTO_MP:
+ if (fp->proto == PROTO_LCP) {
+ struct lcp *lcp = fsm2lcp(fp);
+
+ if (lcp->want_mrru && lcp->his_mrru) {
+ log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n",
+ fp->link->name);
+ fsm_Close(fp);
+ }
}
break;
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvEchoReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
{
+ struct lcp *lcp = fsm2lcp(fp);
u_char *cp;
- u_long *lp, magic;
-
- cp = MBUF_CTOP(bp);
- lp = (u_long *) cp;
- magic = ntohl(*lp);
- if (magic != LcpInfo.his_magic) {
- LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n");
- /* XXX: We should send terminate request */
- }
- if (fp->state == ST_OPENED) {
- *lp = htonl(LcpInfo.want_magic); /* Insert local magic number */
- LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]);
- FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
+ u_int32_t magic;
+
+ if (lcp) {
+ cp = MBUF_CTOP(bp);
+ magic = ntohl(*(u_int32_t *)cp);
+ if (magic != lcp->his_magic) {
+ log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n",
+ fp->link->name);
+ /* XXX: We should send terminate request */
+ }
+ if (fp->state == ST_OPENED) {
+ *(u_int32_t *)cp = htonl(lcp->want_magic); /* local magic */
+ fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp));
+ }
}
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvEchoRep(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
-{
- u_long *lp, magic;
-
- lp = (u_long *) MBUF_CTOP(bp);
- magic = ntohl(*lp);
-/*
- * Tolerate echo replies with either magic number
- */
- if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) {
- LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
- LcpInfo.his_magic, magic);
-
- /*
- * XXX: We should send terminate request. But poor implementation may die
- * as a result.
- */
+FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
+{
+ struct lcp *lcp = fsm2lcp(fp);
+ u_int32_t magic;
+
+ if (lcp) {
+ magic = ntohl(*(u_int32_t *)MBUF_CTOP(bp));
+ /* Tolerate echo replies with either magic number */
+ if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) {
+ log_Printf(LogWARN,
+ "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n",
+ fp->link->name, lcp->his_magic, magic);
+ /*
+ * XXX: We should send terminate request. But poor implementations may
+ * die as a result.
+ */
+ }
+ lqr_RecvEcho(fp, bp);
}
- RecvEchoLqr(bp);
- pfree(bp);
+ mbuf_Free(bp);
}
static void
FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
- LogPrintf(fp->LogLevel, "RecvDiscReq\n");
- pfree(bp);
+ mbuf_Free(bp);
}
static void
FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
- LogPrintf(fp->LogLevel, "RecvIdent\n");
- pfree(bp);
+ mbuf_Free(bp);
}
static void
FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
- LogPrintf(fp->LogLevel, "RecvTimeRemain\n");
- pfree(bp);
+ mbuf_Free(bp);
}
static void
-FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
+FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
{
- LogPrintf(fp->LogLevel, "RecvResetReq(%d)\n", lhp->id);
- CcpRecvResetReq(fp);
+ (*fp->fn->RecvResetReq)(fp);
/*
* All sendable compressed packets are queued in the PRI_NORMAL modem
* output queue.... dump 'em to the priority queue so that they arrive
* at the peer before our ResetAck.
*/
- SequenceQueues();
- LogPrintf(fp->LogLevel, "SendResetAck(%d)\n", lhp->id);
- FsmOutput(fp, CODE_RESETACK, lhp->id, NULL, 0);
- pfree(bp);
+ link_SequenceQueue(fp->link);
+ fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0);
+ mbuf_Free(bp);
}
static void
-FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
-{
- LogPrintf(fp->LogLevel, "RecvResetAck(%d)\n", lhp->id);
- CcpResetInput(lhp->id);
- fp->reqid++;
- pfree(bp);
-}
-
-static const struct fsmcodedesc FsmCodes[] = {
- {FsmRecvConfigReq, "Configure Request",},
- {FsmRecvConfigAck, "Configure Ack",},
- {FsmRecvConfigNak, "Configure Nak",},
- {FsmRecvConfigRej, "Configure Reject",},
- {FsmRecvTermReq, "Terminate Request",},
- {FsmRecvTermAck, "Terminate Ack",},
- {FsmRecvCodeRej, "Code Reject",},
- {FsmRecvProtoRej, "Protocol Reject",},
- {FsmRecvEchoReq, "Echo Request",},
- {FsmRecvEchoRep, "Echo Reply",},
- {FsmRecvDiscReq, "Discard Request",},
- {FsmRecvIdent, "Ident",},
- {FsmRecvTimeRemain, "Time Remain",},
- {FsmRecvResetReq, "Reset Request",},
- {FsmRecvResetAck, "Reset Ack",},
-};
+FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
+{
+ (*fp->fn->RecvResetAck)(fp, lhp->id);
+ mbuf_Free(bp);
+}
void
-FsmInput(struct fsm * fp, struct mbuf * bp)
+fsm_Input(struct fsm *fp, struct mbuf *bp)
{
int len;
struct fsmheader *lhp;
const struct fsmcodedesc *codep;
- len = plength(bp);
+ len = mbuf_Length(bp);
if (len < sizeof(struct fsmheader)) {
- pfree(bp);
+ mbuf_Free(bp);
return;
}
lhp = (struct fsmheader *) MBUF_CTOP(bp);
- if (lhp->code == 0 || lhp->code > fp->max_code) {
- pfree(bp); /* XXX: Should send code reject */
+ if (lhp->code < fp->min_code || lhp->code > fp->max_code ||
+ lhp->code > sizeof FsmCodes / sizeof *FsmCodes) {
+ /*
+ * Use a private id. This is really a response-type packet, but we
+ * MUST send a unique id for each REQ....
+ */
+ static u_char id;
+ fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt);
+ mbuf_Free(bp);
return;
}
bp->offset += sizeof(struct fsmheader);
bp->cnt -= sizeof(struct fsmheader);
codep = FsmCodes + lhp->code - 1;
- LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n",
- codep->name, lhp->id, StateNames[fp->state], fp->state);
- if (LogIsKept(LogDEBUG))
- LogMemory();
- (codep->action) (fp, lhp, bp);
- if (LogIsKept(LogDEBUG))
- LogMemory();
+ if (lhp->id != fp->reqid && codep->check_reqid &&
+ Enabled(fp->bundle, OPT_IDCHECK)) {
+ log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n",
+ fp->link->name, codep->name, lhp->id, fp->reqid);
+ return;
+ }
+
+ log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n",
+ fp->link->name, codep->name, lhp->id, State2Nam(fp->state));
+
+ if (log_IsKept(LogDEBUG))
+ mbuf_Log();
+
+ if (codep->inc_reqid && (lhp->id == fp->reqid ||
+ (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid)))
+ fp->reqid++; /* That's the end of that ``exchange''.... */
+
+ (*codep->recv)(fp, lhp, bp);
+
+ if (log_IsKept(LogDEBUG))
+ mbuf_Log();
+}
+
+void
+fsm_NullRecvResetReq(struct fsm *fp)
+{
+ log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n",
+ fp->link->name);
+}
+
+void
+fsm_NullRecvResetAck(struct fsm *fp, u_char id)
+{
+ log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n",
+ fp->link->name);
}
diff --git a/usr.sbin/ppp/fsm.h b/usr.sbin/ppp/fsm.h
index 131c90100eba..8f033fca33aa 100644
--- a/usr.sbin/ppp/fsm.h
+++ b/usr.sbin/ppp/fsm.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: fsm.h,v 1.15 1998/01/20 22:47:37 brian Exp $
+ * $Id: fsm.h,v 1.16.2.16 1998/05/01 19:24:35 brian Exp $
*
* TODO:
*/
@@ -45,15 +45,50 @@
#define OPEN_PASSIVE -1
+struct fsm;
+
+struct fsm_decode {
+ u_char ack[100], *ackend;
+ u_char nak[100], *nakend;
+ u_char rej[100], *rejend;
+};
+
+struct fsm_callbacks {
+ int (*LayerUp) (struct fsm *); /* Layer is now up (tlu) */
+ void (*LayerDown) (struct fsm *); /* About to come down (tld) */
+ void (*LayerStart) (struct fsm *); /* Layer about to start up (tls) */
+ void (*LayerFinish) (struct fsm *); /* Layer now down (tlf) */
+ void (*InitRestartCounter) (struct fsm *); /* Set fsm timer load */
+ void (*SendConfigReq) (struct fsm *); /* Send REQ please */
+ void (*SentTerminateReq) (struct fsm *); /* Term REQ just sent */
+ void (*SendTerminateAck) (struct fsm *, u_char); /* Send Term ACK please */
+ void (*DecodeConfig) (struct fsm *, u_char *, int, int, struct fsm_decode *);
+ /* Deal with incoming data */
+ void (*RecvResetReq) (struct fsm *fp); /* Reset output */
+ void (*RecvResetAck) (struct fsm *fp, u_char); /* Reset input */
+};
+
+struct fsm_parent {
+ void (*LayerStart) (void *, struct fsm *); /* tls */
+ void (*LayerUp) (void *, struct fsm *); /* tlu */
+ void (*LayerDown) (void *, struct fsm *); /* tld */
+ void (*LayerFinish) (void *, struct fsm *); /* tlf */
+ void *object;
+};
+
+struct link;
+struct bundle;
+
struct fsm {
const char *name; /* Name of protocol */
u_short proto; /* Protocol number */
+ u_short min_code;
u_short max_code;
- int open_mode;
+ int open_mode; /* Delay before config REQ (-1 forever) */
int state; /* State of the machine */
u_char reqid; /* Next request id */
int restart; /* Restart counter value */
- int maxconfig;
+ int maxconfig; /* Max config REQ before a close() */
struct pppTimer FsmTimer; /* Restart Timer */
struct pppTimer OpenTimer; /* Delay before opening */
@@ -70,15 +105,14 @@ struct fsm {
struct pppTimer StoppedTimer;
int LogLevel;
- void (*LayerUp) (struct fsm *);
- void (*LayerDown) (struct fsm *);
- void (*LayerStart) (struct fsm *);
- void (*LayerFinish) (struct fsm *);
- void (*InitRestartCounter) (struct fsm *);
- void (*SendConfigReq) (struct fsm *);
- void (*SendTerminateReq) (struct fsm *);
- void (*SendTerminateAck) (struct fsm *);
- void (*DecodeConfig) (u_char *, int, int);
+ /* The link layer active with this FSM (may be our bundle below) */
+ struct link *link;
+
+ /* Our high-level link */
+ struct bundle *bundle;
+
+ const struct fsm_parent *parent;
+ const struct fsm_callbacks *fn;
};
struct fsmheader {
@@ -103,30 +137,21 @@ struct fsmheader {
#define CODE_RESETREQ 14 /* Used in CCP */
#define CODE_RESETACK 15 /* Used in CCP */
-struct fsmcodedesc {
- void (*action) (struct fsm *, struct fsmheader *, struct mbuf *);
- const char *name;
-};
-
+/* Minimum config req size. This struct is *only* used for it's size */
struct fsmconfig {
u_char type;
u_char length;
};
-extern u_char AckBuff[200];
-extern u_char NakBuff[200];
-extern u_char RejBuff[100];
-extern u_char ReqBuff[200];
-extern u_char *ackp;
-extern u_char *nakp;
-extern u_char *rejp;
-
-extern char const *StateNames[];
-
-extern void FsmInit(struct fsm *);
-extern void FsmOutput(struct fsm *, u_int, u_int, u_char *, int);
-extern void FsmOpen(struct fsm *);
-extern void FsmUp(struct fsm *);
-extern void FsmDown(struct fsm *);
-extern void FsmInput(struct fsm *, struct mbuf *);
-extern void FsmClose(struct fsm *);
+extern void fsm_Init(struct fsm *, const char *, u_short, int, int, int, int,
+ struct bundle *, struct link *, const struct fsm_parent *,
+ struct fsm_callbacks *, const char *[3]);
+extern void fsm_Output(struct fsm *, u_int, u_int, u_char *, int);
+extern void fsm_Open(struct fsm *);
+extern void fsm_Up(struct fsm *);
+extern void fsm_Down(struct fsm *);
+extern void fsm_Input(struct fsm *, struct mbuf *);
+extern void fsm_Close(struct fsm *);
+extern void fsm_NullRecvResetReq(struct fsm *fp);
+extern void fsm_NullRecvResetAck(struct fsm *fp, u_char);
+extern const char *State2Nam(u_int);
diff --git a/usr.sbin/ppp/hdlc.c b/usr.sbin/ppp/hdlc.c
index 4854811543de..a6f1c25133ae 100644
--- a/usr.sbin/ppp/hdlc.c
+++ b/usr.sbin/ppp/hdlc.c
@@ -17,12 +17,15 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: hdlc.c,v 1.29 1998/03/12 02:23:38 brian Exp $
+ * $Id: hdlc.c,v 1.28.2.37 1998/05/21 01:26:07 brian Exp $
*
* TODO:
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <stdio.h>
#include <string.h>
@@ -34,50 +37,30 @@
#include "defs.h"
#include "timer.h"
#include "fsm.h"
+#include "lqr.h"
#include "hdlc.h"
#include "lcpproto.h"
+#include "iplist.h"
+#include "throughput.h"
+#include "slcompress.h"
#include "ipcp.h"
#include "ip.h"
#include "vjcomp.h"
+#include "auth.h"
#include "pap.h"
#include "chap.h"
#include "lcp.h"
#include "async.h"
-#include "lqr.h"
-#include "loadalias.h"
-#include "vars.h"
-#include "modem.h"
#include "ccp.h"
-
-static struct hdlcstat {
- int badfcs;
- int badaddr;
- int badcommand;
- int unknownproto;
-} HdlcStat;
-
-static u_int32_t ifOutPackets;
-static u_int32_t ifOutOctets;
-static u_int32_t ifOutLQRs;
-
-static struct protostat {
- u_short number;
- const char *name;
- u_long in_count;
- u_long out_count;
-} ProtocolStat[] = {
- { PROTO_IP, "IP" },
- { PROTO_VJUNCOMP, "VJ_UNCOMP" },
- { PROTO_VJCOMP, "VJ_COMP" },
- { PROTO_COMPD, "COMPD" },
- { PROTO_LCP, "LCP" },
- { PROTO_IPCP, "IPCP" },
- { PROTO_CCP, "CCP" },
- { PROTO_PAP, "PAP" },
- { PROTO_LQR, "LQR" },
- { PROTO_CHAP, "CHAP" },
- { 0, "Others" }
-};
+#include "link.h"
+#include "descriptor.h"
+#include "physical.h"
+#include "prompt.h"
+#include "chat.h"
+#include "mp.h"
+#include "datalink.h"
+#include "filter.h"
+#include "bundle.h"
static u_short const fcstab[256] = {
/* 00 */ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
@@ -114,14 +97,11 @@ static u_short const fcstab[256] = {
/* f8 */ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
-u_char EscMap[33];
-
void
-HdlcInit()
+hdlc_Init(struct hdlc *hdlc, struct lcp *lcp)
{
- ifOutOctets = 0;
- ifOutPackets = 0;
- ifOutLQRs = 0;
+ memset(hdlc, '\0', sizeof(struct hdlc));
+ hdlc->lqm.owner = lcp;
}
/*
@@ -129,7 +109,7 @@ HdlcInit()
* 2.27 for further details.
*/
inline u_short
-HdlcFcs(u_short fcs, u_char * cp, int len)
+hdlc_Fcs(u_short fcs, u_char * cp, int len)
{
while (len--)
fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];
@@ -142,7 +122,7 @@ HdlcFcsBuf(u_short fcs, struct mbuf *m)
int len;
u_char *pos, *end;
- len = plength(m);
+ len = mbuf_Length(m);
pos = MBUF_CTOP(m);
end = pos + m->cnt;
while (len--) {
@@ -157,28 +137,22 @@ HdlcFcsBuf(u_short fcs, struct mbuf *m)
}
void
-HdlcOutput(int pri, u_short proto, struct mbuf * bp)
+hdlc_Output(struct link *l, int pri, u_short proto, struct mbuf *bp)
{
+ struct physical *p = link2physical(l);
struct mbuf *mhp, *mfcs;
- struct protostat *statp;
- struct lqrdata *lqr;
u_char *cp;
u_short fcs;
- if ((proto & 0xfff1) == 0x21) /* Network Layer protocol */
- if (CcpFsm.state == ST_OPENED)
- if (CcpOutput(pri, proto, bp))
- return;
-
- if (DEV_IS_SYNC)
+ if (!p || physical_IsSync(p))
mfcs = NULL;
else
- mfcs = mballoc(2, MB_HDLCOUT);
+ mfcs = mbuf_Alloc(2, MB_HDLCOUT);
- mhp = mballoc(4, MB_HDLCOUT);
+ mhp = mbuf_Alloc(4, MB_HDLCOUT);
mhp->cnt = 0;
cp = MBUF_CTOP(mhp);
- if (proto == PROTO_LCP || LcpInfo.his_acfcomp == 0) {
+ if (p && (proto == PROTO_LCP || l->lcp.his_acfcomp == 0)) {
*cp++ = HDLC_ADDR;
*cp++ = HDLC_UI;
mhp->cnt += 2;
@@ -187,7 +161,7 @@ HdlcOutput(int pri, u_short proto, struct mbuf * bp)
/*
* If possible, compress protocol field.
*/
- if (LcpInfo.his_protocomp && (proto & 0xff00) == 0) {
+ if (l->lcp.his_protocomp && (proto & 0xff00) == 0) {
*cp++ = proto;
mhp->cnt++;
} else {
@@ -195,41 +169,60 @@ HdlcOutput(int pri, u_short proto, struct mbuf * bp)
*cp = proto & 0377;
mhp->cnt += 2;
}
+
mhp->next = bp;
+
+ if (!p) {
+ /*
+ * This is where we multiplex the data over our available physical
+ * links. We don't frame our logical link data. Instead we wait
+ * for the logical link implementation to chop our data up and pile
+ * it into the physical links by re-calling this function with the
+ * encapsulated fragments.
+ */
+ link_Output(l, pri, mhp);
+ return;
+ }
+
+ /* Tack mfcs onto the end, then set bp back to the start of the data */
while (bp->next != NULL)
bp = bp->next;
bp->next = mfcs;
bp = mhp->next;
- lqr = &MyLqrData;
- lqr->PeerOutPackets = ifOutPackets++;
- ifOutOctets += plength(mhp) + 1;
- lqr->PeerOutOctets = ifOutOctets;
+ p->hdlc.lqm.OutOctets += mbuf_Length(mhp) + 1;
+ p->hdlc.lqm.OutPackets++;
if (proto == PROTO_LQR) {
- lqr->MagicNumber = LcpInfo.want_magic;
- lqr->LastOutLQRs = HisLqrData.PeerOutLQRs;
- lqr->LastOutPackets = HisLqrData.PeerOutPackets;
- lqr->LastOutOctets = HisLqrData.PeerOutOctets;
- lqr->PeerInLQRs = HisLqrSave.SaveInLQRs;
- lqr->PeerInPackets = HisLqrSave.SaveInPackets;
- lqr->PeerInDiscards = HisLqrSave.SaveInDiscards;
- lqr->PeerInErrors = HisLqrSave.SaveInErrors;
- lqr->PeerInOctets = HisLqrSave.SaveInOctets;
- if (HisLqrData.LastOutLQRs == ifOutLQRs) {
+ /* Overwrite the entire packet */
+ struct lqrdata lqr;
+
+ lqr.MagicNumber = p->link.lcp.want_magic;
+ lqr.LastOutLQRs = p->hdlc.lqm.lqr.peer.PeerOutLQRs;
+ lqr.LastOutPackets = p->hdlc.lqm.lqr.peer.PeerOutPackets;
+ lqr.LastOutOctets = p->hdlc.lqm.lqr.peer.PeerOutOctets;
+ lqr.PeerInLQRs = p->hdlc.lqm.lqr.SaveInLQRs;
+ lqr.PeerInPackets = p->hdlc.lqm.SaveInPackets;
+ lqr.PeerInDiscards = p->hdlc.lqm.SaveInDiscards;
+ lqr.PeerInErrors = p->hdlc.lqm.SaveInErrors;
+ lqr.PeerInOctets = p->hdlc.lqm.SaveInOctets;
+ lqr.PeerOutPackets = p->hdlc.lqm.OutPackets;
+ lqr.PeerOutOctets = p->hdlc.lqm.OutOctets;
+ if (p->hdlc.lqm.lqr.peer.LastOutLQRs == p->hdlc.lqm.lqr.OutLQRs) {
/*
* only increment if it's the first time or we've got a reply
* from the last one
*/
- lqr->PeerOutLQRs = ++ifOutLQRs;
- LqrDump("LqrOutput", lqr);
+ lqr.PeerOutLQRs = ++p->hdlc.lqm.lqr.OutLQRs;
+ lqr_Dump(l->name, "Output", &lqr);
} else {
- lqr->PeerOutLQRs = ifOutLQRs;
- LqrDump("LqrOutput (again)", lqr);
+ lqr.PeerOutLQRs = p->hdlc.lqm.lqr.OutLQRs;
+ lqr_Dump(l->name, "Output (again)", &lqr);
}
- LqrChangeOrder(lqr, (struct lqrdata *) (MBUF_CTOP(bp)));
+ lqr_ChangeOrder(&lqr, (struct lqrdata *)MBUF_CTOP(bp));
}
- if (!DEV_IS_SYNC) {
+
+ if (mfcs) {
mfcs->cnt = 0;
fcs = HdlcFcsBuf(INITFCS, mhp);
fcs = ~fcs;
@@ -238,18 +231,16 @@ HdlcOutput(int pri, u_short proto, struct mbuf * bp)
*cp++ = fcs >> 8;
mfcs->cnt = 2;
}
- LogDumpBp(LogHDLC, "HdlcOutput", mhp);
- for (statp = ProtocolStat; statp->number; statp++)
- if (statp->number == proto)
- break;
- statp->out_count++;
- LogPrintf(LogDEBUG, "HdlcOutput: proto = 0x%04x\n", proto);
+ log_DumpBp(LogHDLC, "hdlc_Output", mhp);
+
+ link_ProtocolRecord(l, proto, PROTO_OUT);
+ log_Printf(LogDEBUG, "hdlc_Output: proto = 0x%04x\n", proto);
- if (DEV_IS_SYNC)
- ModemOutput(pri, mhp);
+ if (physical_IsSync(p))
+ link_Output(l, pri, mhp); /* Send it raw */
else
- AsyncOutput(pri, mhp, proto);
+ async_Output(pri, mhp, proto, p);
}
/* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
@@ -365,8 +356,8 @@ static struct {
#define NPROTOCOLS (sizeof protocols/sizeof protocols[0])
-static const char *
-Protocol2Nam(u_short proto)
+const char *
+hdlc_Protocol2Nam(u_short proto)
{
int f;
@@ -378,209 +369,260 @@ Protocol2Nam(u_short proto)
return "unrecognised protocol";
}
-static void
-DecodePacket(u_short proto, struct mbuf * bp)
+void
+hdlc_DecodePacket(struct bundle *bundle, u_short proto, struct mbuf * bp,
+ struct link *l)
{
+ struct physical *p = link2physical(l);
u_char *cp;
- LogPrintf(LogDEBUG, "DecodePacket: proto = 0x%04x\n", proto);
+ log_Printf(LogDEBUG, "DecodePacket: proto = 0x%04x\n", proto);
- /*
- * If proto isn't PROTO_COMPD, we still want to pass it to the
- * decompression routines so that the dictionary's updated
- */
- if (CcpFsm.state == ST_OPENED) {
- if (proto == PROTO_COMPD) {
- if ((bp = CompdInput(&proto, bp)) == NULL)
- return;
- } else if ((proto & 0xfff1) == 0x21) /* Network Layer protocol */
- CcpDictSetup(proto, bp);
- }
+ /* decompress everything. CCP needs uncompressed data too */
+ if ((bp = ccp_Decompress(&l->ccp, &proto, bp)) == NULL)
+ return;
switch (proto) {
case PROTO_LCP:
- LcpInput(bp);
+ lcp_Input(&l->lcp, bp);
break;
case PROTO_PAP:
- PapInput(bp);
+ if (p)
+ pap_Input(bundle, bp, p);
+ else {
+ log_Printf(LogERROR, "DecodePacket: PAP: Not a physical link !\n");
+ mbuf_Free(bp);
+ }
break;
case PROTO_LQR:
- HisLqrSave.SaveInLQRs++;
- LqrInput(bp);
+ if (p) {
+ p->hdlc.lqm.lqr.SaveInLQRs++;
+ lqr_Input(p, bp);
+ } else {
+ log_Printf(LogERROR, "DecodePacket: LQR: Not a physical link !\n");
+ mbuf_Free(bp);
+ }
break;
case PROTO_CHAP:
- ChapInput(bp);
+ if (p)
+ chap_Input(bundle, bp, p);
+ else {
+ log_Printf(LogERROR, "DecodePacket: CHAP: Not a physical link !\n");
+ mbuf_Free(bp);
+ }
break;
case PROTO_VJUNCOMP:
case PROTO_VJCOMP:
- bp = VjCompInput(bp, proto);
- if (bp == NULL) {
+ bp = vj_Input(&bundle->ncp.ipcp, bp, proto);
+ if (bp == NULL)
break;
- }
/* fall down */
case PROTO_IP:
- IpInput(bp);
+ ip_Input(bundle, bp);
break;
case PROTO_IPCP:
- IpcpInput(bp);
+ ipcp_Input(&bundle->ncp.ipcp, bundle, bp);
break;
case PROTO_CCP:
- CcpInput(bp);
+ ccp_Input(&l->ccp, bundle, bp);
break;
+ case PROTO_MP:
+ if (bundle->ncp.mp.active) {
+ if (p)
+ mp_Input(&bundle->ncp.mp, bp, p);
+ else {
+ log_Printf(LogERROR, "DecodePacket: MP inside MP ?!\n");
+ mbuf_Free(bp);
+ }
+ break;
+ }
+ /* Fall through */
default:
- LogPrintf(LogPHASE, "Unknown protocol 0x%04x (%s)\n",
- proto, Protocol2Nam(proto));
+ log_Printf(LogPHASE, "%s protocol 0x%04x (%s)\n",
+ proto == PROTO_MP ? "Unexpected" : "Unknown",
+ proto, hdlc_Protocol2Nam(proto));
bp->offset -= 2;
bp->cnt += 2;
cp = MBUF_CTOP(bp);
- LcpSendProtoRej(cp, bp->cnt);
- HisLqrSave.SaveInDiscards++;
- HdlcStat.unknownproto++;
- pfree(bp);
- break;
- }
-}
-
-int
-ReportProtStatus(struct cmdargs const *arg)
-{
- struct protostat *statp;
- int cnt;
-
- statp = ProtocolStat;
- statp--;
- cnt = 0;
- fprintf(VarTerm, " Protocol in out Protocol in out\n");
- do {
- statp++;
- fprintf(VarTerm, " %-9s: %8lu, %8lu",
- statp->name, statp->in_count, statp->out_count);
- if (++cnt == 2) {
- fprintf(VarTerm, "\n");
- cnt = 0;
+ lcp_SendProtoRej(&l->lcp, cp, bp->cnt);
+ if (p) {
+ p->hdlc.lqm.SaveInDiscards++;
+ p->hdlc.stats.unknownproto++;
}
- } while (statp->number);
- if (cnt)
- fprintf(VarTerm, "\n");
- return (0);
-}
-
-int
-ReportHdlcStatus(struct cmdargs const *arg)
-{
- struct hdlcstat *hp = &HdlcStat;
-
- if (VarTerm) {
- fprintf(VarTerm, "HDLC level errors\n\n");
- fprintf(VarTerm, "FCS: %u ADDR: %u COMMAND: %u PROTO: %u\n",
- hp->badfcs, hp->badaddr, hp->badcommand, hp->unknownproto);
+ mbuf_Free(bp);
+ break;
}
- return 0;
}
-static struct hdlcstat laststat;
-
-void
-HdlcErrorCheck()
+static int
+hdlc_GetProto(const u_char *cp, u_short *proto)
{
- struct hdlcstat *hp = &HdlcStat;
- struct hdlcstat *op = &laststat;
-
- if (memcmp(hp, op, sizeof laststat)) {
- LogPrintf(LogPHASE, "HDLC errors -> FCS: %u ADDR: %u COMD: %u PROTO: %u\n",
- hp->badfcs - op->badfcs, hp->badaddr - op->badaddr,
- hp->badcommand - op->badcommand, hp->unknownproto - op->unknownproto);
+ *proto = *cp;
+ if (!(*proto & 1)) {
+ *proto = (*proto << 8) | cp[1];
+ return 2;
}
- laststat = HdlcStat;
+ return 1;
}
void
-HdlcInput(struct mbuf * bp)
+hdlc_Input(struct bundle *bundle, struct mbuf * bp, struct physical *physical)
{
u_short fcs, proto;
u_char *cp, addr, ctrl;
- struct protostat *statp;
+ int n;
- LogDumpBp(LogHDLC, "HdlcInput:", bp);
- if (DEV_IS_SYNC)
+ log_DumpBp(LogHDLC, "hdlc_Input:", bp);
+ if (physical_IsSync(physical))
fcs = GOODFCS;
else
- fcs = HdlcFcs(INITFCS, MBUF_CTOP(bp), bp->cnt);
- HisLqrSave.SaveInOctets += bp->cnt + 1;
+ fcs = hdlc_Fcs(INITFCS, MBUF_CTOP(bp), bp->cnt);
+ physical->hdlc.lqm.SaveInOctets += bp->cnt + 1;
- LogPrintf(LogDEBUG, "HdlcInput: fcs = %04x (%s)\n",
- fcs, (fcs == GOODFCS) ? "good" : "bad");
+ log_Printf(LogDEBUG, "%s: hdlc_Input: fcs = %04x (%s)\n",
+ physical->link.name, fcs, (fcs == GOODFCS) ? "good" : "BAD!");
if (fcs != GOODFCS) {
- HisLqrSave.SaveInErrors++;
- LogPrintf(LogDEBUG, "HdlcInput: Bad FCS\n");
- HdlcStat.badfcs++;
- pfree(bp);
+ physical->hdlc.lqm.SaveInErrors++;
+ physical->hdlc.stats.badfcs++;
+ mbuf_Free(bp);
return;
}
- if (!DEV_IS_SYNC)
+ if (!physical_IsSync(physical))
bp->cnt -= 2; /* discard FCS part */
if (bp->cnt < 2) { /* XXX: raise this bar ? */
- pfree(bp);
+ mbuf_Free(bp);
return;
}
cp = MBUF_CTOP(bp);
- if (!LcpInfo.want_acfcomp) {
-
- /*
- * We expect that packet is not compressed.
- */
+ if (!physical->link.lcp.want_acfcomp) {
+ /* We expect the packet not to be compressed */
addr = *cp++;
if (addr != HDLC_ADDR) {
- HisLqrSave.SaveInErrors++;
- HdlcStat.badaddr++;
- LogPrintf(LogDEBUG, "HdlcInput: addr %02x\n", *cp);
- pfree(bp);
+ physical->hdlc.lqm.SaveInErrors++;
+ physical->hdlc.stats.badaddr++;
+ log_Printf(LogDEBUG, "hdlc_Input: addr %02x\n", *cp);
+ mbuf_Free(bp);
return;
}
ctrl = *cp++;
if (ctrl != HDLC_UI) {
- HisLqrSave.SaveInErrors++;
- HdlcStat.badcommand++;
- LogPrintf(LogDEBUG, "HdlcInput: %02x\n", *cp);
- pfree(bp);
+ physical->hdlc.lqm.SaveInErrors++;
+ physical->hdlc.stats.badcommand++;
+ log_Printf(LogDEBUG, "hdlc_Input: %02x\n", *cp);
+ mbuf_Free(bp);
return;
}
bp->offset += 2;
bp->cnt -= 2;
} else if (cp[0] == HDLC_ADDR && cp[1] == HDLC_UI) {
-
/*
- * We can receive compressed packet, but peer still send uncompressed
- * packet to me.
+ * We can receive compressed packets, but the peer still sends
+ * uncompressed packets !
*/
cp += 2;
bp->offset += 2;
bp->cnt -= 2;
}
- if (LcpInfo.want_protocomp) {
- proto = 0;
- cp--;
- do {
- cp++;
- bp->offset++;
- bp->cnt--;
- proto = proto << 8;
- proto += *cp;
- } while (!(proto & 1));
- } else {
- proto = *cp++ << 8;
- proto |= *cp++;
- bp->offset += 2;
- bp->cnt -= 2;
- }
- for (statp = ProtocolStat; statp->number; statp++)
- if (statp->number == proto)
+ n = hdlc_GetProto(cp, &proto);
+ bp->offset += n;
+ bp->cnt -= n;
+ if (!physical->link.lcp.want_protocomp && n == 1)
+ log_Printf(LogHDLC, "%s: Warning: received a proto-compressed packet !\n",
+ physical->link.name);
+
+ link_ProtocolRecord(&physical->link, proto, PROTO_IN);
+ physical->hdlc.lqm.SaveInPackets++;
+
+ hdlc_DecodePacket(bundle, proto, bp, &physical->link);
+}
+
+/*
+ * Detect a HDLC frame
+ */
+
+static const char *FrameHeaders[] = {
+ "\176\377\003\300\041",
+ "\176\377\175\043\300\041",
+ "\176\177\175\043\100\041",
+ "\176\175\337\175\043\300\041",
+ "\176\175\137\175\043\100\041",
+ NULL,
+};
+
+u_char *
+hdlc_Detect(struct physical *physical, u_char *cp, int n)
+{
+ const char *fp, **hp;
+ char *ptr;
+
+ cp[n] = '\0'; /* be sure to null terminate */
+ ptr = NULL;
+ for (hp = FrameHeaders; *hp; hp++) {
+ fp = *hp;
+ if (physical_IsSync(physical))
+ fp++;
+ ptr = strstr((char *)cp, fp); /* XXX: cp may have embedded NULs */
+ if (ptr)
break;
- statp->in_count++;
- HisLqrSave.SaveInPackets++;
+ }
+ return (u_char *)ptr;
+}
- DecodePacket(proto, bp);
+int
+hdlc_ReportStatus(struct cmdargs const *arg)
+{
+ struct hdlc *hdlc = &arg->cx->physical->hdlc;
+
+ prompt_Printf(arg->prompt, "%s HDLC level errors:\n", arg->cx->name);
+ prompt_Printf(arg->prompt, " Bad Frame Check Sequence fields: %u\n",
+ hdlc->stats.badfcs);
+ prompt_Printf(arg->prompt, " Bad address (!= 0x%02x) fields: %u\n",
+ HDLC_ADDR, hdlc->stats.badaddr);
+ prompt_Printf(arg->prompt, " Bad command (!= 0x%02x) fields: %u\n",
+ HDLC_UI, hdlc->stats.badcommand);
+ prompt_Printf(arg->prompt, " Unrecognised protocol fields: %u\n",
+ hdlc->stats.unknownproto);
+ return 0;
+}
+
+static void
+hdlc_ReportTime(void *v)
+{
+ /* Moan about HDLC errors */
+ struct hdlc *hdlc = (struct hdlc *)v;
+
+ timer_Stop(&hdlc->ReportTimer);
+
+ if (memcmp(&hdlc->laststats, &hdlc->stats, sizeof hdlc->stats)) {
+ log_Printf(LogPHASE,
+ "%s: HDLC errors -> FCS: %u, ADDR: %u, COMD: %u, PROTO: %u\n",
+ hdlc->lqm.owner->fsm.link->name,
+ hdlc->stats.badfcs - hdlc->laststats.badfcs,
+ hdlc->stats.badaddr - hdlc->laststats.badaddr,
+ hdlc->stats.badcommand - hdlc->laststats.badcommand,
+ hdlc->stats.unknownproto - hdlc->laststats.unknownproto);
+ hdlc->laststats = hdlc->stats;
+ }
+
+ timer_Start(&hdlc->ReportTimer);
+}
+
+void
+hdlc_StartTimer(struct hdlc *hdlc)
+{
+ timer_Stop(&hdlc->ReportTimer);
+ hdlc->ReportTimer.load = 60 * SECTICKS;
+ hdlc->ReportTimer.arg = hdlc;
+ hdlc->ReportTimer.func = hdlc_ReportTime;
+ hdlc->ReportTimer.name = "hdlc";
+ timer_Start(&hdlc->ReportTimer);
+}
+
+void
+hdlc_StopTimer(struct hdlc *hdlc)
+{
+ timer_Stop(&hdlc->ReportTimer);
}
diff --git a/usr.sbin/ppp/hdlc.h b/usr.sbin/ppp/hdlc.h
index caf991fa4006..14864ced60bb 100644
--- a/usr.sbin/ppp/hdlc.h
+++ b/usr.sbin/ppp/hdlc.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: hdlc.h,v 1.13 1997/12/03 10:23:48 brian Exp $
+ * $Id: hdlc.h,v 1.14.2.12 1998/05/01 19:24:39 brian Exp $
*
* TODO:
*/
@@ -54,13 +54,62 @@
#define PRI_NORMAL 0 /* Normal priority */
#define PRI_FAST 1 /* Fast (interractive) */
#define PRI_LINK 1 /* Urgent (LQR packets) */
+#define PRI_MAX 1
-extern u_char EscMap[33];
+struct physical;
+struct link;
+struct lcp;
+struct bundle;
+struct mbuf;
+struct cmdargs;
-extern void HdlcInit(void);
-extern void HdlcErrorCheck(void);
-extern void HdlcInput(struct mbuf *);
-extern void HdlcOutput(int, u_short, struct mbuf *bp);
-extern u_short HdlcFcs(u_short, u_char *, int);
-extern int ReportHdlcStatus(struct cmdargs const *);
-extern int ReportProtStatus(struct cmdargs const *);
+struct hdlc {
+ struct pppTimer ReportTimer;
+
+ struct {
+ int badfcs;
+ int badaddr;
+ int badcommand;
+ int unknownproto;
+ } laststats, stats;
+
+ struct {
+ struct lcp *owner; /* parent LCP */
+ struct pppTimer timer; /* When to send */
+ int method; /* bit-mask for LQM_* from lqr.h */
+
+ u_int32_t OutPackets; /* Packets sent by me */
+ u_int32_t OutOctets; /* Octets sent by me */
+ u_int32_t SaveInPackets; /* Packets received from peer */
+ u_int32_t SaveInDiscards; /* Discards */
+ u_int32_t SaveInErrors; /* Errors */
+ u_int32_t SaveInOctets; /* Octets received from peer */
+
+ struct {
+ u_int32_t OutLQRs; /* LQRs sent by me */
+ u_int32_t SaveInLQRs; /* LQRs received from peer */
+ struct lqrdata peer; /* Last LQR from peer */
+ int peer_timeout; /* peers max lqr timeout */
+ int resent; /* Resent last packet `resent' times */
+ } lqr;
+
+ struct {
+ u_int32_t seq_sent; /* last echo sent */
+ u_int32_t seq_recv; /* last echo received */
+ } echo;
+ } lqm;
+};
+
+
+extern void hdlc_Init(struct hdlc *, struct lcp *);
+extern void hdlc_StartTimer(struct hdlc *);
+extern void hdlc_StopTimer(struct hdlc *);
+extern int hdlc_ReportStatus(struct cmdargs const *);
+extern const char *hdlc_Protocol2Nam(u_short);
+extern void hdlc_DecodePacket(struct bundle *, u_short, struct mbuf *,
+ struct link *);
+
+extern void hdlc_Input(struct bundle *, struct mbuf *, struct physical *);
+extern void hdlc_Output(struct link *, int, u_short, struct mbuf *bp);
+extern u_short hdlc_Fcs(u_short, u_char *, int);
+extern u_char *hdlc_Detect(struct physical *, u_char *, int);
diff --git a/usr.sbin/ppp/id.c b/usr.sbin/ppp/id.c
index b6ff63ffff74..2e4072cdc5f3 100644
--- a/usr.sbin/ppp/id.c
+++ b/usr.sbin/ppp/id.c
@@ -23,14 +23,16 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: id.c,v 1.6 1998/01/21 02:15:16 brian Exp $
+ * $Id: id.c,v 1.6.4.10 1998/05/01 19:24:41 brian Exp $
*/
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <sys/ioctl.h>
#include <fcntl.h>
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
@@ -42,8 +44,6 @@
#endif
#include <utmp.h>
-#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "main.h"
#include "id.h"
@@ -62,8 +62,8 @@ static void
ID0setuser(void)
{
if (seteuid(uid) == -1) {
- LogPrintf(LogERROR, "ID0setuser: Unable to seteuid!\n");
- Cleanup(EX_NOPERM);
+ log_Printf(LogERROR, "ID0setuser: Unable to seteuid!\n");
+ AbortProgram(EX_NOPERM);
}
}
@@ -77,8 +77,8 @@ static void
ID0set0(void)
{
if (seteuid(euid) == -1) {
- LogPrintf(LogERROR, "ID0set0: Unable to seteuid!\n");
- Cleanup(EX_NOPERM);
+ log_Printf(LogERROR, "ID0set0: Unable to seteuid!\n");
+ AbortProgram(EX_NOPERM);
}
}
@@ -89,7 +89,7 @@ ID0ioctl(int fd, unsigned long req, void *arg)
ID0set0();
ret = ioctl(fd, req, arg);
- LogPrintf(LogID0, "%d = ioctl(%d, %d, %p)\n", ret, fd, req, arg);
+ log_Printf(LogID0, "%d = ioctl(%d, %lu, %p)\n", ret, fd, req, arg);
ID0setuser();
return ret;
}
@@ -101,7 +101,7 @@ ID0unlink(const char *name)
ID0set0();
ret = unlink(name);
- LogPrintf(LogID0, "%d = unlink(\"%s\")\n", ret, name);
+ log_Printf(LogID0, "%d = unlink(\"%s\")\n", ret, name);
ID0setuser();
return ret;
}
@@ -113,7 +113,7 @@ ID0socket(int domain, int type, int protocol)
ID0set0();
ret = socket(domain, type, protocol);
- LogPrintf(LogID0, "%d = socket(%d, %d, %d)\n", ret, domain, type, protocol);
+ log_Printf(LogID0, "%d = socket(%d, %d, %d)\n", ret, domain, type, protocol);
ID0setuser();
return ret;
}
@@ -125,20 +125,23 @@ ID0fopen(const char *path, const char *mode)
ID0set0();
ret = fopen(path, mode);
- LogPrintf(LogID0, "%p = fopen(\"%s\", \"%s\")\n", ret, path, mode);
+ log_Printf(LogID0, "%p = fopen(\"%s\", \"%s\")\n", ret, path, mode);
ID0setuser();
return ret;
}
int
-ID0open(const char *path, int flags)
+ID0open(const char *path, int flags, ...)
{
int ret;
+ va_list ap;
+ va_start(ap, flags);
ID0set0();
- ret = open(path, flags);
- LogPrintf(LogID0, "%d = open(\"%s\", %d)\n", ret, path, flags);
+ ret = open(path, flags, va_arg(ap, int));
+ log_Printf(LogID0, "%d = open(\"%s\", %d)\n", ret, path, flags);
ID0setuser();
+ va_end(ap);
return ret;
}
@@ -149,7 +152,7 @@ ID0write(int fd, const void *data, size_t len)
ID0set0();
ret = write(fd, data, len);
- LogPrintf(LogID0, "%d = write(%d, data, %d)\n", ret, fd, len);
+ log_Printf(LogID0, "%d = write(%d, data, %d)\n", ret, fd, len);
ID0setuser();
return ret;
}
@@ -161,7 +164,7 @@ ID0uu_lock(const char *basettyname)
ID0set0();
ret = uu_lock(basettyname);
- LogPrintf(LogID0, "%d = uu_lock(\"%s\")\n", ret, basettyname);
+ log_Printf(LogID0, "%d = uu_lock(\"%s\")\n", ret, basettyname);
ID0setuser();
return ret;
}
@@ -173,7 +176,7 @@ ID0uu_unlock(const char *basettyname)
ID0set0();
ret = uu_unlock(basettyname);
- LogPrintf(LogID0, "%d = uu_unlock(\"%s\")\n", ret, basettyname);
+ log_Printf(LogID0, "%d = uu_unlock(\"%s\")\n", ret, basettyname);
ID0setuser();
return ret;
}
@@ -183,13 +186,13 @@ ID0login(struct utmp *ut)
{
ID0set0();
if (logout(ut->ut_line)) {
- LogPrintf(LogID0, "logout(\"%s\")\n", ut->ut_line);
+ log_Printf(LogID0, "logout(\"%s\")\n", ut->ut_line);
logwtmp(ut->ut_line, "", "");
- LogPrintf(LogID0, "logwtmp(\"%s\", \"\", \"\")\n", ut->ut_line);
+ log_Printf(LogID0, "logwtmp(\"%s\", \"\", \"\")\n", ut->ut_line);
}
login(ut);
- LogPrintf(LogID0, "login(\"%s\", \"%.*s\")\n",
- ut->ut_line, sizeof ut->ut_name, ut->ut_name);
+ log_Printf(LogID0, "login(\"%s\", \"%.*s\")\n",
+ ut->ut_line, (int)(sizeof ut->ut_name), ut->ut_name);
ID0setuser();
}
@@ -203,10 +206,36 @@ ID0logout(const char *device)
ID0set0();
if (logout(ut.ut_line)) {
- LogPrintf(LogID0, "logout(\"%s\")\n", ut.ut_line);
+ log_Printf(LogID0, "logout(\"%s\")\n", ut.ut_line);
logwtmp(ut.ut_line, "", "");
- LogPrintf(LogID0, "logwtmp(\"%s\", \"\", \"\")\n", ut.ut_line);
+ log_Printf(LogID0, "logwtmp(\"%s\", \"\", \"\")\n", ut.ut_line);
} else
- LogPrintf(LogERROR, "ID0logout: No longer logged in on %s\n", ut.ut_line);
+ log_Printf(LogERROR, "ID0logout: No longer logged in on %s\n", ut.ut_line);
ID0setuser();
}
+
+int
+ID0bind_un(int s, const struct sockaddr_un *name)
+{
+ int result;
+
+ ID0set0();
+ result = bind(s, (const struct sockaddr *)name, sizeof *name);
+ log_Printf(LogID0, "%d = bind(%d, \"%s\", %d)\n",
+ result, s, name->sun_path, sizeof *name);
+ ID0setuser();
+ return result;
+}
+
+int
+ID0connect_un(int s, const struct sockaddr_un *name)
+{
+ int result;
+
+ ID0set0();
+ result = connect(s, (const struct sockaddr *)name, sizeof *name);
+ log_Printf(LogID0, "%d = connect(%d, \"%s\", %d)\n",
+ result, s, name->sun_path, sizeof *name);
+ ID0setuser();
+ return result;
+}
diff --git a/usr.sbin/ppp/id.h b/usr.sbin/ppp/id.h
index 6dba7b89d9bc..af55d580e5b4 100644
--- a/usr.sbin/ppp/id.h
+++ b/usr.sbin/ppp/id.h
@@ -23,10 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: id.h,v 1.3 1997/12/27 19:23:13 brian Exp $
+ * $Id: id.h,v 1.3.4.4 1998/04/30 23:53:40 brian Exp $
*/
struct utmp;
+struct sockaddr_un;
extern void ID0init(void);
extern uid_t ID0realuid(void);
@@ -34,9 +35,11 @@ extern int ID0ioctl(int, unsigned long, void *);
extern int ID0unlink(const char *);
extern int ID0socket(int, int, int);
extern FILE *ID0fopen(const char *, const char *);
-extern int ID0open(const char *, int);
+extern int ID0open(const char *, int, ...);
extern int ID0write(int, const void *, size_t);
extern int ID0uu_lock(const char *);
extern int ID0uu_unlock(const char *);
extern void ID0login(struct utmp *);
extern void ID0logout(const char *);
+extern int ID0bind_un(int, const struct sockaddr_un *);
+extern int ID0connect_un(int, const struct sockaddr_un *);
diff --git a/usr.sbin/ppp/ip.c b/usr.sbin/ppp/ip.c
index e9546e037daa..7a889e03de13 100644
--- a/usr.sbin/ppp/ip.c
+++ b/usr.sbin/ppp/ip.c
@@ -17,17 +17,14 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ip.c,v 1.39 1998/03/13 01:36:09 brian Exp $
+ * $Id: ip.c,v 1.38.2.26 1998/05/06 23:50:11 brian Exp $
*
* TODO:
* o Return ICMP message for filterd packet
* and optionaly record it into log.
*/
-#include <sys/param.h>
-#include <sys/time.h>
+#include <sys/types.h>
#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_tun.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -35,6 +32,8 @@
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
+#include <net/if_tun.h>
+#include <sys/un.h>
#ifndef NOALIAS
#include <alias.h>
@@ -43,91 +42,31 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
#include <unistd.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
+#include "lqr.h"
#include "hdlc.h"
#include "loadalias.h"
-#include "vars.h"
-#include "filter.h"
-#include "os.h"
+#include "throughput.h"
+#include "iplist.h"
+#include "slcompress.h"
#include "ipcp.h"
-#include "vjcomp.h"
+#include "filter.h"
+#include "descriptor.h"
#include "lcp.h"
-#include "modem.h"
+#include "ccp.h"
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
+#include "vjcomp.h"
#include "tun.h"
#include "ip.h"
-static struct pppTimer IdleTimer;
-
-static void
-IdleTimeout(void *v)
-{
- LogPrintf(LogPHASE, "Idle timer expired.\n");
- reconnect(RECON_FALSE);
- LcpClose();
-}
-
-/*
- * Start Idle timer. If timeout is reached, we call LcpClose() to
- * close LCP and link.
- */
-void
-StartIdleTimer()
-{
- static time_t IdleStarted;
-
- if (!(mode & (MODE_DEDICATED | MODE_DDIAL))) {
- StopTimer(&IdleTimer);
- IdleTimer.func = IdleTimeout;
- IdleTimer.load = VarIdleTimeout * SECTICKS;
- IdleTimer.state = TIMER_STOPPED;
- time(&IdleStarted);
- IdleTimer.arg = (void *)&IdleStarted;
- StartTimer(&IdleTimer);
- }
-}
-
-void
-UpdateIdleTimer()
-{
- if (OsLinkIsUp())
- StartIdleTimer();
-}
-
-void
-StopIdleTimer()
-{
- StopTimer(&IdleTimer);
-}
-
-int
-RemainingIdleTime()
-{
- if (VarIdleTimeout == 0 || IdleTimer.state != TIMER_RUNNING ||
- IdleTimer.arg == NULL)
- return -1;
- return VarIdleTimeout - (time(NULL) - *(time_t *)IdleTimer.arg);
-}
-
-/*
- * If any IP layer traffic is detected, refresh IdleTimer.
- */
-static void
-RestartIdleTimer(void)
-{
- if (!(mode & (MODE_DEDICATED | MODE_DDIAL)) && ipKeepAlive) {
- time((time_t *)IdleTimer.arg);
- StartTimer(&IdleTimer);
- }
-}
-
static const u_short interactive_ports[32] = {
544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
@@ -137,9 +76,6 @@ static const u_short interactive_ports[32] = {
static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
-static const char *Direction[] = {"INP", "OUT", "OUT", "IN/OUT"};
-static struct filterent *Filters[] = {ifilters, ofilters, dfilters, afilters};
-
static int
PortMatch(int op, u_short pport, u_short rport)
{
@@ -159,27 +95,30 @@ PortMatch(int op, u_short pport, u_short rport)
* Check a packet against with defined filters
*/
static int
-FilterCheck(struct ip * pip, int direction)
+FilterCheck(struct ip *pip, struct filter *filter)
{
- struct filterent *fp = Filters[direction];
- int gotinfo, cproto, estab, n;
+ int gotinfo, cproto, estab, syn, finrst, n, len, didname;
struct tcphdr *th;
struct udphdr *uh;
struct icmp *ih;
char *ptop;
u_short sport, dport;
+ struct filterent *fp = filter->rule;
+ char dbuff[100];
if (fp->action) {
- cproto = gotinfo = estab = 0;
+ cproto = gotinfo = estab = syn = finrst = didname = 0;
sport = dport = 0;
for (n = 0; n < MAXFILTERS; n++) {
if (fp->action) {
/* permit fragments on in and out filter */
- if ((direction == FL_IN || direction == FL_OUT) &&
- (ntohs(pip->ip_off) & IP_OFFMASK) != 0) {
+ if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
return (A_PERMIT);
- }
- LogPrintf(LogDEBUG, "rule = %d\n", n);
+
+ if (!didname)
+ log_Printf(LogDEBUG, "%s filter:\n", filter->name);
+ didname = 1;
+
if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
(fp->saddr.s_addr & fp->smask.s_addr) &&
(pip->ip_dst.s_addr & fp->dmask.s_addr) ==
@@ -193,14 +132,19 @@ FilterCheck(struct ip * pip, int direction)
cproto = P_ICMP;
ih = (struct icmp *) ptop;
sport = ih->icmp_type;
- estab = 1;
+ estab = syn = finrst = -1;
+ if (log_IsKept(LogDEBUG))
+ snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
break;
case IPPROTO_UDP:
cproto = P_UDP;
uh = (struct udphdr *) ptop;
sport = ntohs(uh->uh_sport);
dport = ntohs(uh->uh_dport);
- estab = 1;
+ estab = syn = finrst = -1;
+ if (log_IsKept(LogDEBUG))
+ snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
+ sport, dport);
break;
case IPPROTO_TCP:
cproto = P_TCP;
@@ -208,39 +152,67 @@ FilterCheck(struct ip * pip, int direction)
sport = ntohs(th->th_sport);
dport = ntohs(th->th_dport);
estab = (th->th_flags & TH_ACK);
- if (estab == 0)
- LogPrintf(LogDEBUG, "flag = %02x, sport = %d, dport = %d\n",
- th->th_flags, sport, dport);
+ syn = (th->th_flags & TH_SYN);
+ finrst = (th->th_flags & (TH_FIN|TH_RST));
+ if (log_IsKept(LogDEBUG) && !estab)
+ snprintf(dbuff, sizeof dbuff,
+ "flags = %02x, sport = %d, dport = %d",
+ th->th_flags, sport, dport);
break;
default:
- return (A_DENY);/* We'll block unknown type of packet */
+ return (A_DENY); /* We'll block unknown type of packet */
}
+ if (log_IsKept(LogDEBUG)) {
+ if (estab != -1) {
+ len = strlen(dbuff);
+ snprintf(dbuff + len, sizeof dbuff - len,
+ ", estab = %d, syn = %d, finrst = %d",
+ estab, syn, finrst);
+ }
+ log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
+ filter_Proto2Nam(cproto), dbuff);
+ }
gotinfo = 1;
- LogPrintf(LogDEBUG, "dir = %d, proto = %d, srcop = %d,"
- " dstop = %d, estab = %d\n", direction, cproto,
- fp->opt.srcop, fp->opt.dstop, estab);
}
- LogPrintf(LogDEBUG, "check0: rule = %d, proto = %d, sport = %d,"
- " dport = %d\n", n, cproto, sport, dport);
- LogPrintf(LogDEBUG, "check0: action = %d\n", fp->action);
+ if (log_IsKept(LogDEBUG)) {
+ if (fp->opt.srcop != OP_NONE) {
+ snprintf(dbuff, sizeof dbuff, ", src %s %d",
+ filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
+ len = strlen(dbuff);
+ } else
+ len = 0;
+ if (fp->opt.dstop != OP_NONE) {
+ snprintf(dbuff + len, sizeof dbuff - len,
+ ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
+ fp->opt.dstport);
+ } else if (!len)
+ *dbuff = '\0';
+
+ log_Printf(LogDEBUG, " rule = %d: Address match, "
+ "check against proto %s%s, action = %s\n",
+ n, filter_Proto2Nam(fp->proto),
+ dbuff, filter_Action2Nam(fp->action));
+ }
if (cproto == fp->proto) {
if ((fp->opt.srcop == OP_NONE ||
- PortMatch(fp->opt.srcop, sport, fp->opt.srcport))
- &&
+ PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
(fp->opt.dstop == OP_NONE ||
- PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
- &&
- (fp->opt.estab == 0 || estab)) {
+ PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
+ (fp->opt.estab == 0 || estab) &&
+ (fp->opt.syn == 0 || syn) &&
+ (fp->opt.finrst == 0 || finrst)) {
return (fp->action);
}
}
} else {
/* Address is mached. Make a decision. */
- LogPrintf(LogDEBUG, "check1: action = %d\n", fp->action);
+ log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
+ filter_Action2Nam(fp->action));
return (fp->action);
}
- }
+ } else
+ log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
}
fp++;
}
@@ -249,27 +221,26 @@ FilterCheck(struct ip * pip, int direction)
return (A_PERMIT); /* No rule is given. Permit this packet */
}
+#ifdef notdef
static void
IcmpError(struct ip * pip, int code)
{
-#ifdef notdef
struct mbuf *bp;
if (pip->ip_p != IPPROTO_ICMP) {
- bp = mballoc(cnt, MB_IPIN);
+ bp = mbuf_Alloc(cnt, MB_IPIN);
memcpy(MBUF_CTOP(bp), ptr, cnt);
- SendPppFrame(bp);
- RestartIdleTimer();
- IpcpAddOutOctets(cnt);
+ vj_SendFrame(bp);
+ ipcp_AddOutOctets(cnt);
}
-#endif
}
+#endif
/*
* For debugging aid.
*/
int
-PacketCheck(char *cp, int nb, int direction)
+PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
{
struct ip *pip;
struct tcphdr *th;
@@ -281,14 +252,13 @@ PacketCheck(char *cp, int nb, int direction)
int logit, loglen;
static char logbuf[200];
- logit = LogIsKept(LogTCPIP) && direction != FL_DIAL;
+ logit = log_IsKept(LogTCPIP) && filter->logok;
loglen = 0;
pip = (struct ip *) cp;
if (logit && loglen < sizeof logbuf) {
- snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ",
- Direction[direction]);
+ snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
loglen += strlen(logbuf + loglen);
}
ptop = (cp + (pip->ip_hl << 2));
@@ -359,42 +329,43 @@ PacketCheck(char *cp, int nb, int direction)
break;
}
- if ((FilterCheck(pip, direction) & A_DENY)) {
+ if ((FilterCheck(pip, filter) & A_DENY)) {
if (logit)
- LogPrintf(LogTCPIP, "%s - BLOCKED\n", logbuf);
+ log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
+#ifdef notdef
if (direction == 0)
IcmpError(pip, pri);
+#endif
return (-1);
} else {
- if (FilterCheck(pip, FL_KEEP) & A_DENY) { /* Check Keep Alive filter */
- if (logit)
- LogPrintf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
- ipKeepAlive = 0;
- } else {
- if (logit)
- LogPrintf(LogTCPIP, "%s\n", logbuf);
- ipKeepAlive = 1;
+ /* Check Keep Alive filter */
+ if (logit) {
+ if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
+ log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
+ else
+ log_Printf(LogTCPIP, "%s\n", logbuf);
}
return (pri);
}
}
void
-IpInput(struct mbuf * bp)
-{ /* IN: Pointer to IP pakcet */
+ip_Input(struct bundle *bundle, struct mbuf * bp)
+{
u_char *cp;
struct mbuf *wp;
int nb, nw;
struct tun_data tun;
+ struct ip *pip = (struct ip *)tun.data;
tun_fill_header(tun, AF_INET);
cp = tun.data;
nb = 0;
for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */
if (sizeof tun.data - (cp - tun.data) < wp->cnt) {
- LogPrintf(LogERROR, "IpInput: Packet too large (%d) - dropped\n",
- plength(bp));
- pfree(bp);
+ log_Printf(LogERROR, "ip_Input: Packet too large (%d) - dropped\n",
+ mbuf_Length(bp));
+ mbuf_Free(bp);
return;
}
memcpy(cp, MBUF_CTOP(wp), wp->cnt);
@@ -403,52 +374,56 @@ IpInput(struct mbuf * bp)
}
#ifndef NOALIAS
- if (mode & MODE_ALIAS) {
+ if (alias_IsEnabled()) {
struct tun_data *frag;
int iresult;
char *fptr;
- iresult = VarPacketAliasIn(tun.data, sizeof tun.data);
+ iresult = (*PacketAlias.In)(tun.data, sizeof tun.data);
nb = ntohs(((struct ip *) tun.data)->ip_len);
if (nb > MAX_MRU) {
- LogPrintf(LogERROR, "IpInput: Problem with IP header length\n");
- pfree(bp);
+ log_Printf(LogERROR, "ip_Input: Problem with IP header length\n");
+ mbuf_Free(bp);
return;
}
if (iresult == PKT_ALIAS_OK
|| iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
- if (PacketCheck(tun.data, nb, FL_IN) < 0) {
- pfree(bp);
+ if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
+ mbuf_Free(bp);
return;
}
- IpcpAddInOctets(nb);
+
+ if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
+ bundle_StartIdleTimer(bundle);
+
+ ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
nb = ntohs(((struct ip *) tun.data)->ip_len);
nb += sizeof tun - sizeof tun.data;
- nw = write(tun_out, &tun, nb);
+ nw = write(bundle->dev.fd, &tun, nb);
if (nw != nb) {
if (nw == -1)
- LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb,
+ log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
strerror(errno));
else
- LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
+ log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
}
if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
- while ((fptr = VarPacketAliasGetFragment(tun.data)) != NULL) {
- VarPacketAliasFragmentIn(tun.data, fptr);
+ while ((fptr = (*PacketAlias.GetFragment)(tun.data)) != NULL) {
+ (*PacketAlias.FragmentIn)(tun.data, fptr);
nb = ntohs(((struct ip *) fptr)->ip_len);
frag = (struct tun_data *)
((char *)fptr - sizeof tun + sizeof tun.data);
nb += sizeof tun - sizeof tun.data;
- nw = write(tun_out, frag, nb);
+ nw = write(bundle->dev.fd, frag, nb);
if (nw != nb) {
if (nw == -1)
- LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb,
+ log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
strerror(errno));
else
- LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
+ log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
}
free(frag);
}
@@ -458,83 +433,86 @@ IpInput(struct mbuf * bp)
nb += sizeof tun - sizeof tun.data;
frag = (struct tun_data *)malloc(nb);
if (frag == NULL)
- LogPrintf(LogALERT, "IpInput: Cannot allocate memory for fragment\n");
+ log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n");
else {
tun_fill_header(*frag, AF_INET);
memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data);
- VarPacketAliasSaveFragment(frag->data);
+ (*PacketAlias.SaveFragment)(frag->data);
}
}
} else
#endif /* #ifndef NOALIAS */
{ /* no aliasing */
- if (PacketCheck(tun.data, nb, FL_IN) < 0) {
- pfree(bp);
+ if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
+ mbuf_Free(bp);
return;
}
- IpcpAddInOctets(nb);
+
+ if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
+ bundle_StartIdleTimer(bundle);
+
+ ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
+
nb += sizeof tun - sizeof tun.data;
- nw = write(tun_out, &tun, nb);
+ nw = write(bundle->dev.fd, &tun, nb);
if (nw != nb) {
if (nw == -1)
- LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, strerror(errno));
+ log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno));
else
- LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
+ log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
}
}
- pfree(bp);
-
- RestartIdleTimer();
+ mbuf_Free(bp);
}
static struct mqueue IpOutputQueues[PRI_FAST + 1];
void
-IpEnqueue(int pri, char *ptr, int count)
+ip_Enqueue(int pri, char *ptr, int count)
{
struct mbuf *bp;
- bp = mballoc(count, MB_IPQ);
+ bp = mbuf_Alloc(count, MB_IPQ);
memcpy(MBUF_CTOP(bp), ptr, count);
- Enqueue(&IpOutputQueues[pri], bp);
+ mbuf_Enqueue(&IpOutputQueues[pri], bp);
}
-#if 0
int
-IsIpEnqueued()
+ip_QueueLen()
{
struct mqueue *queue;
- int exist = 0;
+ int result = 0;
- for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) {
- if (queue->qlen > 0) {
- exist = 1;
- break;
- }
- }
- return (exist);
+ for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--)
+ result += queue->qlen;
+
+ return result;
}
-#endif
-void
-IpStartOutput()
+int
+ip_FlushPacket(struct link *l, struct bundle *bundle)
{
struct mqueue *queue;
struct mbuf *bp;
int cnt;
- if (IpcpFsm.state != ST_OPENED)
- return;
- for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) {
+ if (bundle->ncp.ipcp.fsm.state != ST_OPENED)
+ return 0;
+
+ for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--)
if (queue->top) {
- bp = Dequeue(queue);
+ bp = mbuf_Dequeue(queue);
if (bp) {
- cnt = plength(bp);
- SendPppFrame(bp);
- RestartIdleTimer();
- IpcpAddOutOctets(cnt);
- break;
+ struct ip *pip = (struct ip *)MBUF_CTOP(bp);
+
+ cnt = mbuf_Length(bp);
+ vj_SendFrame(l, bp, bundle);
+ if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
+ bundle_StartIdleTimer(bundle);
+ ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt);
+ return 1;
}
}
- }
+
+ return 0;
}
diff --git a/usr.sbin/ppp/ip.h b/usr.sbin/ppp/ip.h
index 2f3d992d839b..968fd34e7248 100644
--- a/usr.sbin/ppp/ip.h
+++ b/usr.sbin/ppp/ip.h
@@ -17,15 +17,17 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ip.h,v 1.7 1997/10/26 12:42:11 brian Exp $
+ * $Id: ip.h,v 1.8.2.9 1998/05/01 19:24:46 brian Exp $
*
*/
-extern void IpStartOutput(void);
-extern int PacketCheck(char *, int, int);
-extern void IpEnqueue(int, char *, int);
-extern void IpInput(struct mbuf *);
-extern void StartIdleTimer(void);
-extern void StopIdleTimer(void);
-extern void UpdateIdleTimer(void);
-extern int RemainingIdleTime(void);
+struct mbuf;
+struct filter;
+struct link;
+struct bundle;
+
+extern int ip_FlushPacket(struct link *, struct bundle *);
+extern int PacketCheck(struct bundle *, char *, int, struct filter *);
+extern void ip_Enqueue(int, char *, int);
+extern void ip_Input(struct bundle *, struct mbuf *);
+extern int ip_QueueLen(void);
diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c
index 72c8eb1b7229..015da503c04e 100644
--- a/usr.sbin/ppp/ipcp.c
+++ b/usr.sbin/ppp/ipcp.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ipcp.c,v 1.49 1998/01/20 22:47:38 brian Exp $
+ * $Id: ipcp.c,v 1.50.2.54 1998/05/21 01:26:08 brian Exp $
*
* TODO:
* o More RFC1772 backwoard compatibility
@@ -29,10 +29,16 @@
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
+#include <net/if.h>
+#include <sys/sockio.h>
+#include <sys/un.h>
-#include <stdio.h>
+#include <fcntl.h>
+#include <resolv.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/errno.h>
+#include <termios.h>
#include <unistd.h>
#include "command.h"
@@ -44,62 +50,61 @@
#include "lcpproto.h"
#include "lcp.h"
#include "iplist.h"
-#include "ipcp.h"
+#include "throughput.h"
#include "slcompress.h"
-#include "os.h"
-#include "phase.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
#include "loadalias.h"
-#include "vars.h"
#include "vjcomp.h"
-#include "ip.h"
-#include "throughput.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "async.h"
+#include "ccp.h"
+#include "link.h"
+#include "physical.h"
+#include "mp.h"
+#include "bundle.h"
+#include "id.h"
+#include "arp.h"
+#include "systems.h"
+#include "prompt.h"
#include "route.h"
-#include "filter.h"
-#ifndef NOMSEXT
-struct in_addr ns_entries[2];
-struct in_addr nbns_entries[2];
-#endif
+#undef REJECTED
+#define REJECTED(p, x) ((p)->peer_reject & (1<<(x)))
+#define issep(ch) ((ch) == ' ' || (ch) == '\t')
+#define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
-struct ipcpstate IpcpInfo;
-struct in_range DefMyAddress;
-struct in_range DefHisAddress;
-struct iplist DefHisChoice;
-struct in_addr TriggerAddress;
-int HaveTriggerAddress;
+struct compreq {
+ u_short proto;
+ u_char slots;
+ u_char compcid;
+};
-static void IpcpSendConfigReq(struct fsm *);
-static void IpcpSendTerminateAck(struct fsm *);
-static void IpcpSendTerminateReq(struct fsm *);
-static void IpcpDecodeConfig(u_char *, int, int);
+static int IpcpLayerUp(struct fsm *);
+static void IpcpLayerDown(struct fsm *);
static void IpcpLayerStart(struct fsm *);
static void IpcpLayerFinish(struct fsm *);
-static void IpcpLayerUp(struct fsm *);
-static void IpcpLayerDown(struct fsm *);
static void IpcpInitRestartCounter(struct fsm *);
+static void IpcpSendConfigReq(struct fsm *);
+static void IpcpSentTerminateReq(struct fsm *);
+static void IpcpSendTerminateAck(struct fsm *, u_char);
+static void IpcpDecodeConfig(struct fsm *, u_char *, int, int,
+ struct fsm_decode *);
-struct fsm IpcpFsm = {
- "IPCP",
- PROTO_IPCP,
- IPCP_MAXCODE,
- 0,
- ST_INITIAL,
- 0, 0, 0,
-
- {0, 0, 0, NULL, NULL, NULL}, /* FSM timer */
- {0, 0, 0, NULL, NULL, NULL}, /* Open timer */
- {0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */
- LogIPCP,
-
+static struct fsm_callbacks ipcp_Callbacks = {
IpcpLayerUp,
IpcpLayerDown,
IpcpLayerStart,
IpcpLayerFinish,
IpcpInitRestartCounter,
IpcpSendConfigReq,
- IpcpSendTerminateReq,
+ IpcpSentTerminateReq,
IpcpSendTerminateAck,
IpcpDecodeConfig,
+ fsm_NullRecvResetReq,
+ fsm_NullRecvResetAck
};
static const char *cftypes[] = {
@@ -123,93 +128,200 @@ static const char *cftypes128[] = {
#define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0])
-static struct pppThroughput throughput;
-
void
-IpcpAddInOctets(int n)
+ipcp_AddInOctets(struct ipcp *ipcp, int n)
{
- throughput_addin(&throughput, n);
+ throughput_addin(&ipcp->throughput, n);
}
void
-IpcpAddOutOctets(int n)
+ipcp_AddOutOctets(struct ipcp *ipcp, int n)
{
- throughput_addout(&throughput, n);
+ throughput_addout(&ipcp->throughput, n);
}
-int
-ReportIpcpStatus(struct cmdargs const *arg)
+static void
+getdns(struct ipcp *ipcp, struct in_addr addr[2])
{
- struct fsm *fp = &IpcpFsm;
-
- if (!VarTerm)
- return 1;
- fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
- if (IpcpFsm.state == ST_OPENED) {
- fprintf(VarTerm, " his side: %s, %s\n",
- inet_ntoa(IpcpInfo.his_ipaddr), vj2asc(IpcpInfo.his_compproto));
- fprintf(VarTerm, " my side: %s, %s\n",
- inet_ntoa(IpcpInfo.want_ipaddr), vj2asc(IpcpInfo.want_compproto));
- }
-
- fprintf(VarTerm, "Defaults:\n");
- fprintf(VarTerm, " My Address: %s/%d\n",
- inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
- if (iplist_isvalid(&DefHisChoice))
- fprintf(VarTerm, " His Address: %s\n", DefHisChoice.src);
- else
- fprintf(VarTerm, " His Address: %s/%d\n",
- inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
- if (HaveTriggerAddress)
- fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress));
- else
- fprintf(VarTerm, " Negotiation(trigger): MYADDR\n");
+ FILE *fp;
- fprintf(VarTerm, "\n");
- throughput_disp(&throughput, VarTerm);
+ addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ char buf[LINE_LEN], *cp, *end;
+ int n;
- return 0;
+ n = 0;
+ buf[sizeof buf - 1] = '\0';
+ while (fgets(buf, sizeof buf - 1, fp)) {
+ if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) {
+ for (cp = buf + 11; issep(*cp); cp++)
+ ;
+ for (end = cp; isip(*end); end++)
+ ;
+ *end = '\0';
+ if (inet_aton(cp, addr+n) && ++n == 2)
+ break;
+ }
+ }
+ if (n == 1)
+ addr[1] = addr[0];
+ fclose(fp);
+ }
}
-void
-IpcpDefAddress()
+static int
+setdns(struct ipcp *ipcp, struct in_addr addr[2])
{
- struct hostent *hp;
- char name[200];
+ FILE *fp;
+ char wbuf[LINE_LEN + 54];
+ int wlen;
- memset(&DefMyAddress, '\0', sizeof DefMyAddress);
- memset(&DefHisAddress, '\0', sizeof DefHisAddress);
- TriggerAddress.s_addr = 0;
- HaveTriggerAddress = 0;
- if (gethostname(name, sizeof name) == 0) {
- hp = gethostbyname(name);
- if (hp && hp->h_addrtype == AF_INET) {
- memcpy(&DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length);
+ if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) {
+ struct in_addr old[2];
+
+ getdns(ipcp, old);
+ if (addr[0].s_addr == INADDR_ANY)
+ addr[0] = old[0];
+ if (addr[1].s_addr == INADDR_ANY)
+ addr[1] = old[1];
+ }
+
+ if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) {
+ log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n",
+ _PATH_RESCONF);
+ return 0;
+ }
+
+ wlen = 0;
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ char buf[LINE_LEN];
+ int len;
+
+ buf[sizeof buf - 1] = '\0';
+ while (fgets(buf, sizeof buf - 1, fp)) {
+ if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) {
+ len = strlen(buf);
+ if (len > sizeof wbuf - wlen) {
+ log_Printf(LogWARN, "%s: Can only cope with max file size %d\n",
+ _PATH_RESCONF, LINE_LEN);
+ fclose(fp);
+ return 0;
+ }
+ memcpy(wbuf + wlen, buf, len);
+ wlen += len;
+ }
+ }
+ fclose(fp);
+ }
+
+ if (addr[0].s_addr != INADDR_ANY) {
+ snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
+ inet_ntoa(addr[0]));
+ log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11);
+ wlen += strlen(wbuf + wlen);
+ }
+
+ if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) {
+ snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
+ inet_ntoa(addr[1]));
+ log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11);
+ wlen += strlen(wbuf + wlen);
+ }
+
+ if (wlen) {
+ int fd;
+
+ if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) {
+ if (write(fd, wbuf, wlen) != wlen) {
+ log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno));
+ close(fd);
+ return 0;
+ }
+ if (ftruncate(fd, wlen) == -1) {
+ log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno));
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ } else {
+ log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno));
+ return 0;
}
}
+
+ return 1;
}
-static int VJInitSlots = MAX_STATES;
-static int VJInitComp = 1;
+int
+ipcp_Show(struct cmdargs const *arg)
+{
+ struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
+
+ prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
+ State2Nam(ipcp->fsm.state));
+ if (ipcp->fsm.state == ST_OPENED) {
+ prompt_Printf(arg->prompt, " His side: %s, %s\n",
+ inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
+ prompt_Printf(arg->prompt, " My side: %s, %s\n",
+ inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
+ }
+
+ if (ipcp->route) {
+ prompt_Printf(arg->prompt, "\n");
+ route_ShowSticky(arg->prompt, ipcp->route);
+ }
+
+ prompt_Printf(arg->prompt, "\nDefaults:\n");
+ prompt_Printf(arg->prompt, " My Address: %s/%d",
+ inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width);
+
+ if (ipcp->cfg.HaveTriggerAddress)
+ prompt_Printf(arg->prompt, " (trigger with %s)",
+ inet_ntoa(ipcp->cfg.TriggerAddress));
+ prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot "
+ "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg),
+ ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without");
+
+ if (iplist_isvalid(&ipcp->cfg.peer_list))
+ prompt_Printf(arg->prompt, " His Address: %s\n",
+ ipcp->cfg.peer_list.src);
+ else
+ prompt_Printf(arg->prompt, " His Address: %s/%d\n",
+ inet_ntoa(ipcp->cfg.peer_range.ipaddr),
+ ipcp->cfg.peer_range.width);
+
+ prompt_Printf(arg->prompt, " DNS: %s, ",
+ inet_ntoa(ipcp->cfg.ns.dns[0]));
+ prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]),
+ command_ShowNegval(ipcp->cfg.ns.dns_neg));
+ prompt_Printf(arg->prompt, " NetBIOS NS: %s, ",
+ inet_ntoa(ipcp->cfg.ns.nbns[0]));
+ prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1]));
+
+ prompt_Printf(arg->prompt, "\n");
+ throughput_disp(&ipcp->throughput, arg->prompt);
+
+ return 0;
+}
int
-SetInitVJ(struct cmdargs const *args)
+ipcp_vjset(struct cmdargs const *arg)
{
- if (args->argc != 2)
+ if (arg->argc != arg->argn+2)
return -1;
- if (!strcasecmp(args->argv[0], "slots")) {
+ if (!strcasecmp(arg->argv[arg->argn], "slots")) {
int slots;
- slots = atoi(args->argv[1]);
+ slots = atoi(arg->argv[arg->argn+1]);
if (slots < 4 || slots > 16)
return 1;
- VJInitSlots = slots;
+ arg->bundle->ncp.ipcp.cfg.vj.slots = slots;
return 0;
- } else if (!strcasecmp(args->argv[0], "slotcomp")) {
- if (!strcasecmp(args->argv[1], "on"))
- VJInitComp = 1;
- else if (!strcasecmp(args->argv[1], "off"))
- VJInitComp = 0;
+ } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) {
+ if (!strcasecmp(arg->argv[arg->argn+1], "on"))
+ arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1;
+ else if (!strcasecmp(arg->argv[arg->argn+1], "off"))
+ arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0;
else
return 2;
return 0;
@@ -217,199 +329,453 @@ SetInitVJ(struct cmdargs const *args)
return -1;
}
-int
-ShowInitVJ(struct cmdargs const *args)
+void
+ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
+ const struct fsm_parent *parent)
{
- if (VarTerm) {
- fprintf(VarTerm, "Initial slots: %d\n", VJInitSlots);
- fprintf(VarTerm, "Initial compression: %s\n", VJInitComp ? "on" : "off");
+ struct hostent *hp;
+ char name[MAXHOSTNAMELEN];
+ static const char *timer_names[] =
+ {"IPCP restart", "IPCP openmode", "IPCP stopped"};
+
+ fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP,
+ bundle, l, parent, &ipcp_Callbacks, timer_names);
+
+ ipcp->route = NULL;
+ ipcp->cfg.vj.slots = DEF_VJ_STATES;
+ ipcp->cfg.vj.slotcomp = 1;
+ memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
+ if (gethostname(name, sizeof name) == 0) {
+ hp = gethostbyname(name);
+ if (hp && hp->h_addrtype == AF_INET) {
+ memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
+ ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
+ ipcp->cfg.peer_range.width = 32;
+ }
}
- return 0;
+ ipcp->cfg.netmask.s_addr = INADDR_ANY;
+ memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
+ iplist_setsrc(&ipcp->cfg.peer_list, "");
+ ipcp->cfg.HaveTriggerAddress = 0;
+
+ ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY;
+ ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY;
+ ipcp->cfg.ns.dns_neg = 0;
+ ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
+ ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
+
+ ipcp->cfg.fsmretry = DEF_FSMRETRY;
+ ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED;
+
+ memset(&ipcp->vj, '\0', sizeof ipcp->vj);
+
+ ipcp->my_ifip.s_addr = INADDR_ANY;
+ ipcp->peer_ifip.s_addr = INADDR_ANY;
+
+ throughput_init(&ipcp->throughput);
+ ipcp_Setup(ipcp);
}
void
-IpcpInit()
+ipcp_SetLink(struct ipcp *ipcp, struct link *l)
{
- if (iplist_isvalid(&DefHisChoice))
- iplist_setrandpos(&DefHisChoice);
- FsmInit(&IpcpFsm);
- memset(&IpcpInfo, '\0', sizeof IpcpInfo);
- if ((mode & MODE_DEDICATED) && !GetLabel()) {
- IpcpInfo.want_ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr = 0;
- } else {
- IpcpInfo.want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
- IpcpInfo.his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
+ ipcp->fsm.link = l;
+}
+
+void
+ipcp_Setup(struct ipcp *ipcp)
+{
+ int pos;
+
+ ipcp->fsm.open_mode = 0;
+ ipcp->fsm.maxconfig = 10;
+
+ if (iplist_isvalid(&ipcp->cfg.peer_list)) {
+ if (ipcp->my_ifip.s_addr != INADDR_ANY &&
+ (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1)
+ ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos);
+ else
+ ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
+ ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
+ ipcp->cfg.peer_range.width = 32;
}
- /*
- * Some implementations of PPP require that we send a
- * *special* value as our address, even though the rfc specifies
- * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
- */
- if (HaveTriggerAddress) {
- IpcpInfo.want_ipaddr.s_addr = TriggerAddress.s_addr;
- LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress));
+ ipcp->heis1172 = 0;
+
+ ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr;
+ ipcp->peer_compproto = 0;
+
+ if (ipcp->cfg.HaveTriggerAddress) {
+ /*
+ * Some implementations of PPP require that we send a
+ * *special* value as our address, even though the rfc specifies
+ * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
+ */
+ ipcp->my_ip = ipcp->cfg.TriggerAddress;
+ log_Printf(LogIPCP, "Using trigger address %s\n",
+ inet_ntoa(ipcp->cfg.TriggerAddress));
+ } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
+ (ipcp->cfg.my_range.ipaddr.s_addr &
+ ipcp->cfg.my_range.mask.s_addr))
+ /*
+ * Otherwise, if we've been assigned an IP number before, we really
+ * want to keep the same IP number so that we can keep any existing
+ * connections that are bound to that IP.
+ */
+ ipcp->my_ip = ipcp->my_ifip;
+ else
+ ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
+
+ if (IsEnabled(ipcp->cfg.vj.neg))
+ ipcp->my_compproto = (PROTO_VJCOMP << 16) +
+ ((ipcp->cfg.vj.slots - 1) << 8) +
+ ipcp->cfg.vj.slotcomp;
+ else
+ ipcp->my_compproto = 0;
+ sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1);
+
+ ipcp->peer_reject = 0;
+ ipcp->my_reject = 0;
+
+ throughput_stop(&ipcp->throughput);
+ throughput_init(&ipcp->throughput);
+}
+
+static int
+ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
+ struct in_addr hisaddr, int silent)
+{
+ struct sockaddr_in *sock_in;
+ int s;
+ u_long mask, addr;
+ struct ifaliasreq ifra;
+
+ /* If given addresses are alreay set, then ignore this request */
+ if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr &&
+ bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr)
+ return 0;
+
+ ipcp_CleanInterface(&bundle->ncp.ipcp);
+
+ s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno));
+ return (-1);
}
- if (Enabled(ConfVjcomp))
- IpcpInfo.want_compproto = (PROTO_VJCOMP << 16) | ((VJInitSlots - 1) << 8) |
- VJInitComp;
+
+ memset(&ifra, '\0', sizeof ifra);
+ strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1);
+ ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
+
+ /* Set interface address */
+ sock_in = (struct sockaddr_in *)&ifra.ifra_addr;
+ sock_in->sin_family = AF_INET;
+ sock_in->sin_addr = myaddr;
+ sock_in->sin_len = sizeof *sock_in;
+
+ /* Set destination address */
+ sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr;
+ sock_in->sin_family = AF_INET;
+ sock_in->sin_addr = hisaddr;
+ sock_in->sin_len = sizeof *sock_in;
+
+ addr = ntohl(myaddr.s_addr);
+ if (IN_CLASSA(addr))
+ mask = IN_CLASSA_NET;
+ else if (IN_CLASSB(addr))
+ mask = IN_CLASSB_NET;
else
- IpcpInfo.want_compproto = 0;
- IpcpInfo.heis1172 = 0;
- IpcpFsm.maxconfig = 10;
- throughput_init(&throughput);
+ mask = IN_CLASSC_NET;
+
+ /* if subnet mask is given, use it instead of class mask */
+ if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY &&
+ (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask)
+ mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr);
+
+ sock_in = (struct sockaddr_in *)&ifra.ifra_mask;
+ sock_in->sin_family = AF_INET;
+ sock_in->sin_addr.s_addr = htonl(mask);
+ sock_in->sin_len = sizeof *sock_in;
+
+ if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) {
+ if (!silent)
+ log_Printf(LogERROR, "SetIpDevice: ioctl(SIOCAIFADDR): %s\n",
+ strerror(errno));
+ close(s);
+ return (-1);
+ }
+
+ if (Enabled(bundle, OPT_SROUTES))
+ route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr);
+
+ bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr;
+ bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr;
+
+ if (Enabled(bundle, OPT_PROXY))
+ arp_SetProxy(bundle, bundle->ncp.ipcp.peer_ifip, s);
+
+ close(s);
+ return (0);
+}
+
+static struct in_addr
+ChooseHisAddr(struct bundle *bundle, const struct in_addr gw)
+{
+ struct in_addr try;
+ int f;
+
+ for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) {
+ try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
+ log_Printf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n",
+ f, inet_ntoa(try));
+ if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) {
+ log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
+ break;
+ }
+ }
+
+ if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) {
+ log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
+ try.s_addr = INADDR_ANY;
+ }
+
+ return try;
}
static void
IpcpInitRestartCounter(struct fsm * fp)
{
- fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
+ /* Set fsm timer load */
+ struct ipcp *ipcp = fsm2ipcp(fp);
+
+ fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS;
fp->restart = 5;
}
static void
-IpcpSendConfigReq(struct fsm * fp)
+IpcpSendConfigReq(struct fsm *fp)
{
- u_char *cp;
- struct lcp_opt o;
-
- cp = ReqBuff;
- LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
- if (!DEV_IS_SYNC || !REJECTED(&IpcpInfo, TY_IPADDR)) {
- o.id = TY_IPADDR;
- o.len = 6;
- *(u_long *)o.data = IpcpInfo.want_ipaddr.s_addr;
- cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id],
- inet_ntoa(IpcpInfo.want_ipaddr));
+ /* Send config REQ please */
+ struct physical *p = link2physical(fp->link);
+ struct ipcp *ipcp = fsm2ipcp(fp);
+ u_char buff[24];
+ struct lcp_opt *o;
+
+ o = (struct lcp_opt *)buff;
+
+ if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
+ *(u_int32_t *)o->data = ipcp->my_ip.s_addr;
+ INC_LCP_OPT(TY_IPADDR, 6, o);
}
- if (IpcpInfo.want_compproto && !REJECTED(&IpcpInfo, TY_COMPPROTO)) {
- const char *args;
- o.id = TY_COMPPROTO;
- if (IpcpInfo.heis1172) {
- o.len = 4;
- *(u_short *)o.data = htons(PROTO_VJCOMP);
- args = "";
+ if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
+ if (ipcp->heis1172) {
+ *(u_short *)o->data = htons(PROTO_VJCOMP);
+ INC_LCP_OPT(TY_COMPPROTO, 4, o);
} else {
- o.len = 6;
- *(u_long *)o.data = htonl(IpcpInfo.want_compproto);
- args = vj2asc(IpcpInfo.want_compproto);
+ *(u_long *)o->data = htonl(ipcp->my_compproto);
+ INC_LCP_OPT(TY_COMPPROTO, 6, o);
}
- cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], args);
}
- FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
+
+ if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
+ !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) &&
+ !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
+ struct in_addr dns[2];
+ getdns(ipcp, dns);
+ *(u_int32_t *)o->data = dns[0].s_addr;
+ INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
+ *(u_int32_t *)o->data = dns[1].s_addr;
+ INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
+ }
+
+ fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff);
}
static void
-IpcpSendTerminateReq(struct fsm * fp)
+IpcpSentTerminateReq(struct fsm * fp)
{
- /* XXX: No code yet */
+ /* Term REQ just sent by FSM */
}
static void
-IpcpSendTerminateAck(struct fsm * fp)
+IpcpSendTerminateAck(struct fsm *fp, u_char id)
{
- LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
- FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
+ /* Send Term ACK please */
+ fsm_Output(fp, CODE_TERMACK, id, NULL, 0);
}
static void
IpcpLayerStart(struct fsm * fp)
{
- LogPrintf(LogIPCP, "IpcpLayerStart.\n");
+ /* We're about to start up ! */
+ log_Printf(LogIPCP, "%s: IpcpLayerStart.\n", fp->link->name);
+
+ /* This is where we should be setting up the interface in DEMAND mode */
}
static void
-IpcpLayerFinish(struct fsm * fp)
+IpcpLayerFinish(struct fsm *fp)
{
- LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
- reconnect(RECON_FALSE);
- LcpClose();
- NewPhase(PHASE_TERMINATE);
+ /* We're now down */
+ log_Printf(LogIPCP, "%s: IpcpLayerFinish.\n", fp->link->name);
}
-static void
-IpcpLayerDown(struct fsm * fp)
+void
+ipcp_CleanInterface(struct ipcp *ipcp)
{
- LogPrintf(LogIPCP, "IpcpLayerDown.\n");
- throughput_stop(&throughput);
- throughput_log(&throughput, LogIPCP, NULL);
+ struct ifaliasreq ifra;
+ struct sockaddr_in *me, *peer;
+ int s;
+
+ s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", strerror(errno));
+ return;
+ }
+
+ route_Clean(ipcp->fsm.bundle, ipcp->route);
+
+ if (Enabled(ipcp->fsm.bundle, OPT_PROXY))
+ arp_ClearProxy(ipcp->fsm.bundle, ipcp->peer_ifip, s);
+
+ if (ipcp->my_ifip.s_addr != INADDR_ANY ||
+ ipcp->peer_ifip.s_addr != INADDR_ANY) {
+ memset(&ifra, '\0', sizeof ifra);
+ strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifp.Name,
+ sizeof ifra.ifra_name - 1);
+ ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
+ me = (struct sockaddr_in *)&ifra.ifra_addr;
+ peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
+ me->sin_family = peer->sin_family = AF_INET;
+ me->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
+ me->sin_addr = ipcp->my_ifip;
+ peer->sin_addr = ipcp->peer_ifip;
+ if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0)
+ log_Printf(LogERROR, "ipcp_CleanInterface: ioctl(SIOCDIFADDR): %s\n",
+ strerror(errno));
+ ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY;
+ }
+
+ close(s);
}
-/*
- * Called when IPCP has reached to OPEN state
- */
static void
-IpcpLayerUp(struct fsm * fp)
+IpcpLayerDown(struct fsm *fp)
{
- char tbuff[100];
+ /* About to come down */
+ struct ipcp *ipcp = fsm2ipcp(fp);
+ const char *s;
- Prompt();
- LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
- snprintf(tbuff, sizeof tbuff, "myaddr = %s ",
- inet_ntoa(IpcpInfo.want_ipaddr));
+ s = inet_ntoa(ipcp->peer_ifip);
+ log_Printf(LogIPCP, "%s: IpcpLayerDown: %s\n", fp->link->name, s);
- if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP)
- VjInit((IpcpInfo.his_compproto >> 8) & 255);
+ throughput_stop(&ipcp->throughput);
+ throughput_log(&ipcp->throughput, LogIPCP, NULL);
+ /*
+ * XXX this stuff should really live in the FSM. Our config should
+ * associate executable sections in files with events.
+ */
+ if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL) < 0) {
+ if (bundle_GetLabel(fp->bundle)) {
+ if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
+ LINKDOWNFILE, NULL) < 0)
+ system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL);
+ } else
+ system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL);
+ }
- LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
- tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
- if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr) < 0) {
- if (VarTerm)
- LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
- return;
+ if (!(ipcp->fsm.bundle->phys_type & PHYS_DEMAND))
+ ipcp_CleanInterface(ipcp);
+}
+
+int
+ipcp_InterfaceUp(struct ipcp *ipcp)
+{
+ if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) {
+ log_Printf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
+ return 0;
}
+
#ifndef NOALIAS
- if (mode & MODE_ALIAS)
- VarPacketAliasSetAddress(IpcpInfo.want_ipaddr);
+ if (alias_IsEnabled())
+ (*PacketAlias.SetAddress)(ipcp->my_ip);
#endif
- OsLinkup();
- throughput_start(&throughput);
- StartIdleTimer();
-}
-void
-IpcpUp()
-{
- FsmUp(&IpcpFsm);
- LogPrintf(LogIPCP, "IPCP Up event!!\n");
+ return 1;
}
-void
-IpcpOpen()
+static int
+IpcpLayerUp(struct fsm *fp)
{
- FsmOpen(&IpcpFsm);
+ /* We're now up */
+ struct ipcp *ipcp = fsm2ipcp(fp);
+ char tbuff[100];
+
+ log_Printf(LogIPCP, "%s: IpcpLayerUp.\n", fp->link->name);
+ snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip));
+ log_Printf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip));
+
+ if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
+ sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
+
+ if (!ipcp_InterfaceUp(ipcp))
+ return 0;
+
+ /*
+ * XXX this stuff should really live in the FSM. Our config should
+ * associate executable sections in files with events.
+ */
+ if (system_Select(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE, NULL)
+ < 0) {
+ if (bundle_GetLabel(fp->bundle)) {
+ if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
+ LINKUPFILE, NULL) < 0)
+ system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL);
+ } else
+ system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL);
+ }
+
+ throughput_start(&ipcp->throughput, "IPCP throughput",
+ Enabled(fp->bundle, OPT_THROUGHPUT));
+ bundle_DisplayPrompt(fp->bundle);
+ return 1;
}
static int
-AcceptableAddr(struct in_range * prange, struct in_addr ipaddr)
+AcceptableAddr(struct in_range *prange, struct in_addr ipaddr)
{
- LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr));
- LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr));
- LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
- LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
- mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
+ /* Is the given IP in the given range ? */
return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
(ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
}
static void
-IpcpDecodeConfig(u_char * cp, int plen, int mode_type)
+IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
+ struct fsm_decode *dec)
{
+ /* Deal with incoming PROTO_IPCP */
+ struct ipcp *ipcp = fsm2ipcp(fp);
int type, length;
- u_long *lp, compproto;
+ u_int32_t compproto;
struct compreq *pcomp;
- struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
- char tbuff[100];
- char tbuff2[100];
+ struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2];
+ char tbuff[100], tbuff2[100];
+ int gotdns, gotdnsnak;
- ackp = AckBuff;
- nakp = NakBuff;
- rejp = RejBuff;
+ gotdns = 0;
+ gotdnsnak = 0;
+ dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY;
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
+
+ if (length == 0) {
+ log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);
+ break;
+ }
+
if (type < NCFTYPES)
snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length);
else if (type > 128 && type < 128 + NCFTYPES128)
@@ -419,288 +785,328 @@ IpcpDecodeConfig(u_char * cp, int plen, int mode_type)
switch (type) {
case TY_IPADDR: /* RFC1332 */
- lp = (u_long *) (cp + 2);
- ipaddr.s_addr = *lp;
- LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
+ ipaddr.s_addr = *(u_int32_t *)(cp + 2);
+ log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
switch (mode_type) {
case MODE_REQ:
- if (iplist_isvalid(&DefHisChoice)) {
+ if (iplist_isvalid(&ipcp->cfg.peer_list)) {
if (ipaddr.s_addr == INADDR_ANY ||
- iplist_ip2pos(&DefHisChoice, ipaddr) < 0 ||
- OsTrySetIpaddress(DefMyAddress.ipaddr, ipaddr) != 0) {
- LogPrintf(LogIPCP, "%s: Address invalid or already in use\n",
+ iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 ||
+ ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr,
+ ipaddr, 1)) {
+ log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
inet_ntoa(ipaddr));
- IpcpInfo.his_ipaddr = ChooseHisAddr(DefMyAddress.ipaddr);
- if (IpcpInfo.his_ipaddr.s_addr == INADDR_ANY) {
- memcpy(rejp, cp, length);
- rejp += length;
+ if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0)
+ /*
+ * If we've already got a valid address configured for the peer
+ * (in DEMAND mode), try NAKing with that so that we don't
+ * have to upset things too much.
+ */
+ ipcp->peer_ip = ipcp->peer_ifip;
+ else
+ /* Just pick an IP number from our list */
+ ipcp->peer_ip = ChooseHisAddr
+ (fp->bundle, ipcp->cfg.my_range.ipaddr);
+
+ if (ipcp->peer_ip.s_addr == INADDR_ANY) {
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
} else {
- memcpy(nakp, cp, 2);
- memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length - 2);
- nakp += length;
+ memcpy(dec->nakend, cp, 2);
+ memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2);
+ dec->nakend += length;
}
break;
}
- } else if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
+ } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) {
/*
- * If destination address is not acceptable, insist to use what we
+ * If destination address is not acceptable, NAK with what we
* want to use.
*/
- memcpy(nakp, cp, 2);
- memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length - 2);
- nakp += length;
+ memcpy(dec->nakend, cp, 2);
+ if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) ==
+ (ipcp->cfg.peer_range.ipaddr.s_addr &
+ ipcp->cfg.peer_range.mask.s_addr))
+ /* We prefer the already-configured address */
+ memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2);
+ else
+ memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2);
+ dec->nakend += length;
break;
}
- IpcpInfo.his_ipaddr = ipaddr;
- memcpy(ackp, cp, length);
- ackp += length;
+ ipcp->peer_ip = ipaddr;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
break;
case MODE_NAK:
- if (AcceptableAddr(&DefMyAddress, ipaddr)) {
+ if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
/* Use address suggested by peer */
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
- inet_ntoa(IpcpInfo.want_ipaddr));
- LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
- IpcpInfo.want_ipaddr = ipaddr;
+ inet_ntoa(ipcp->my_ip));
+ log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
+ ipcp->my_ip = ipaddr;
} else {
- LogPrintf(LogIPCP, "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
- FsmClose(&IpcpFsm);
+ log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
+ "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
+ fsm_Close(&ipcp->fsm);
}
break;
case MODE_REJ:
- IpcpInfo.his_reject |= (1 << type);
+ ipcp->peer_reject |= (1 << type);
break;
}
break;
case TY_COMPPROTO:
- lp = (u_long *) (cp + 2);
- compproto = htonl(*lp);
- LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
+ compproto = htonl(*(u_int32_t *)(cp + 2));
+ log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
switch (mode_type) {
case MODE_REQ:
- if (!Acceptable(ConfVjcomp)) {
- memcpy(rejp, cp, length);
- rejp += length;
+ if (!IsAccepted(ipcp->cfg.vj.neg)) {
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
} else {
pcomp = (struct compreq *) (cp + 2);
switch (length) {
case 4: /* RFC1172 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
- LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
- IpcpInfo.heis1172 = 1;
- IpcpInfo.his_compproto = compproto;
- memcpy(ackp, cp, length);
- ackp += length;
+ log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
+ ipcp->heis1172 = 1;
+ ipcp->peer_compproto = compproto;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
} else {
- memcpy(nakp, cp, 2);
+ memcpy(dec->nakend, cp, 2);
pcomp->proto = htons(PROTO_VJCOMP);
- memcpy(nakp+2, &pcomp, 2);
- nakp += length;
+ memcpy(dec->nakend+2, &pcomp, 2);
+ dec->nakend += length;
}
break;
case 6: /* RFC1332 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP
- && pcomp->slots < MAX_STATES && pcomp->slots > 2) {
- IpcpInfo.his_compproto = compproto;
- IpcpInfo.heis1172 = 0;
- memcpy(ackp, cp, length);
- ackp += length;
+ && pcomp->slots <= MAX_VJ_STATES
+ && pcomp->slots >= MIN_VJ_STATES) {
+ ipcp->peer_compproto = compproto;
+ ipcp->heis1172 = 0;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
} else {
- memcpy(nakp, cp, 2);
+ memcpy(dec->nakend, cp, 2);
pcomp->proto = htons(PROTO_VJCOMP);
- pcomp->slots = MAX_STATES - 1;
+ pcomp->slots = DEF_VJ_STATES;
pcomp->compcid = 0;
- memcpy(nakp+2, &pcomp, sizeof pcomp);
- nakp += length;
+ memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
+ dec->nakend += length;
}
break;
default:
- memcpy(rejp, cp, length);
- rejp += length;
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
break;
}
}
break;
case MODE_NAK:
- LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
- tbuff, IpcpInfo.want_compproto, compproto);
- IpcpInfo.want_compproto = compproto;
+ log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
+ tbuff, ipcp->my_compproto, compproto);
+ ipcp->my_compproto = compproto;
break;
case MODE_REJ:
- IpcpInfo.his_reject |= (1 << type);
+ ipcp->peer_reject |= (1 << type);
break;
}
break;
case TY_IPADDRS: /* RFC1172 */
- lp = (u_long *) (cp + 2);
- ipaddr.s_addr = *lp;
- lp = (u_long *) (cp + 6);
- dstipaddr.s_addr = *lp;
+ ipaddr.s_addr = *(u_int32_t *)(cp + 2);
+ dstipaddr.s_addr = *(u_int32_t *)(cp + 6);
snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
- LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
+ log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
switch (mode_type) {
case MODE_REQ:
- IpcpInfo.his_ipaddr = ipaddr;
- IpcpInfo.want_ipaddr = dstipaddr;
- memcpy(ackp, cp, length);
- ackp += length;
+ ipcp->peer_ip = ipaddr;
+ ipcp->my_ip = dstipaddr;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
break;
case MODE_NAK:
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff,
- inet_ntoa(IpcpInfo.want_ipaddr));
- LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
- IpcpInfo.want_ipaddr = ipaddr;
- IpcpInfo.his_ipaddr = dstipaddr;
+ inet_ntoa(ipcp->my_ip));
+ log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
+ ipcp->my_ip = ipaddr;
+ ipcp->peer_ip = dstipaddr;
break;
case MODE_REJ:
- IpcpInfo.his_reject |= (1 << type);
+ ipcp->peer_reject |= (1 << type);
break;
}
break;
- /*
- * MS extensions for MS's PPP
- */
-
-#ifndef NOMSEXT
- case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */
+ case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */
case TY_SECONDARY_DNS:
- if (!Enabled(ConfMSExt)) {
- LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
- IpcpInfo.my_reject |= (1 << type);
- memcpy(rejp, cp, length);
- rejp += length;
- break;
- }
+ ipaddr.s_addr = *(u_int32_t *)(cp + 2);
+ log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
+
switch (mode_type) {
case MODE_REQ:
- lp = (u_long *) (cp + 2);
- dnsstuff.s_addr = *lp;
- ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS) ? 1 : 0)].s_addr;
- if (dnsstuff.s_addr != ms_info_req.s_addr) {
+ if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
+ ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
+ break;
+ }
+ if (!gotdns) {
+ dns[0] = ipcp->cfg.ns.dns[0];
+ dns[1] = ipcp->cfg.ns.dns[1];
+ if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY)
+ getdns(ipcp, dns);
+ gotdns = 1;
+ }
+ have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1];
+ if (ipaddr.s_addr != have_ip.s_addr) {
/*
- * So the client has got the DNS stuff wrong (first request) so
+ * The client has got the DNS stuff wrong (first request) so
* we'll tell 'em how it is
*/
- memcpy(nakp, cp, 2); /* copy first two (type/length) */
- LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n",
- type,
- inet_ntoa(dnsstuff),
- inet_ntoa(ms_info_req));
- memcpy(nakp+2, &ms_info_req, length);
- nakp += length;
- break;
- }
-
- /*
- * Otherwise they have it right (this time) so we send a ack packet
- * back confirming it... end of story
- */
- LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n",
- type,
- inet_ntoa(ms_info_req));
- memcpy(ackp, cp, length);
- ackp += length;
+ memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */
+ memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);
+ dec->nakend += length;
+ } else {
+ /*
+ * Otherwise they have it right (this time) so we send a ack packet
+ * back confirming it... end of story
+ */
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
+ }
break;
case MODE_NAK: /* what does this mean?? */
- LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type);
+ if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
+ gotdnsnak = 1;
+ dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr =
+ *(u_int32_t *)(cp + 2);
+ }
break;
- case MODE_REJ: /* confused?? me to :) */
- LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type);
+ case MODE_REJ: /* Can't do much, stop asking */
+ ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
break;
}
break;
- case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */
+ case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */
case TY_SECONDARY_NBNS:
- if (!Enabled(ConfMSExt)) {
- LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n");
- IpcpInfo.my_reject |= (1 << type);
- memcpy(rejp, cp, length);
- rejp += length;
- break;
- }
+ ipaddr.s_addr = *(u_int32_t *)(cp + 2);
+ log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
+
switch (mode_type) {
case MODE_REQ:
- lp = (u_long *) (cp + 2);
- dnsstuff.s_addr = *lp;
- ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS) ? 1 : 0)].s_addr;
- if (dnsstuff.s_addr != ms_info_req.s_addr) {
- memcpy(nakp, cp, 2);
- memcpy(nakp+2, &ms_info_req.s_addr, length);
- LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
- type,
- inet_ntoa(dnsstuff),
- inet_ntoa(ms_info_req));
- nakp += length;
+ have_ip.s_addr =
+ ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
+
+ if (have_ip.s_addr == INADDR_ANY) {
+ log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
+ ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
break;
- }
- LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
- type,
- inet_ntoa(ms_info_req));
- memcpy(ackp, cp, length);
- ackp += length;
+ }
+
+ if (ipaddr.s_addr != have_ip.s_addr) {
+ memcpy(dec->nakend, cp, 2);
+ memcpy(dec->nakend+2, &have_ip.s_addr, length);
+ dec->nakend += length;
+ } else {
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
+ }
break;
case MODE_NAK:
- LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
+ log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
break;
case MODE_REJ:
- LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
+ log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
break;
}
break;
-#endif
-
default:
- IpcpInfo.my_reject |= (1 << type);
- memcpy(rejp, cp, length);
- rejp += length;
+ if (mode_type != MODE_NOP) {
+ ipcp->my_reject |= (1 << type);
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
+ }
break;
}
plen -= length;
cp += length;
}
+
+ if (gotdnsnak)
+ if (!setdns(ipcp, dnsnak)) {
+ ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
+ ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
+ }
+
+ if (mode_type != MODE_NOP) {
+ if (dec->rejend != dec->rej) {
+ /* rejects are preferred */
+ dec->ackend = dec->ack;
+ dec->nakend = dec->nak;
+ } else if (dec->nakend != dec->nak)
+ /* then NAKs */
+ dec->ackend = dec->ack;
+ }
}
void
-IpcpInput(struct mbuf * bp)
+ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp)
{
- FsmInput(&IpcpFsm, bp);
+ /* Got PROTO_IPCP from link */
+ if (bundle_Phase(bundle) == PHASE_NETWORK)
+ fsm_Input(&ipcp->fsm, bp);
+ else {
+ if (bundle_Phase(bundle) < PHASE_NETWORK)
+ log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n",
+ ipcp->fsm.link->name, bundle_PhaseName(bundle));
+ mbuf_Free(bp);
+ }
}
int
-UseHisaddr(const char *hisaddr, int setaddr)
+ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
{
- memset(&DefHisAddress, '\0', sizeof DefHisAddress);
- iplist_reset(&DefHisChoice);
+ struct ipcp *ipcp = &bundle->ncp.ipcp;
+
+ /* Use `hisaddr' for the peers address (set iface if `setaddr') */
+ memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
+ iplist_reset(&ipcp->cfg.peer_list);
if (strpbrk(hisaddr, ",-")) {
- iplist_setsrc(&DefHisChoice, hisaddr);
- if (iplist_isvalid(&DefHisChoice)) {
- iplist_setrandpos(&DefHisChoice);
- IpcpInfo.his_ipaddr = ChooseHisAddr(IpcpInfo.want_ipaddr);
- if (IpcpInfo.his_ipaddr.s_addr == INADDR_ANY) {
- LogPrintf(LogWARN, "%s: None available !\n", DefHisChoice.src);
+ iplist_setsrc(&ipcp->cfg.peer_list, hisaddr);
+ if (iplist_isvalid(&ipcp->cfg.peer_list)) {
+ iplist_setrandpos(&ipcp->cfg.peer_list);
+ ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip);
+ if (ipcp->peer_ip.s_addr == INADDR_ANY) {
+ log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
return(0);
}
- DefHisAddress.ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr;
- DefHisAddress.mask.s_addr = 0xffffffff;
- DefHisAddress.width = 32;
+ ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr;
+ ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
+ ipcp->cfg.peer_range.width = 32;
} else {
- LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr);
+ log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
return 0;
}
- } else if (ParseAddr(1, &hisaddr, &DefHisAddress.ipaddr,
- &DefHisAddress.mask, &DefHisAddress.width) != 0) {
- IpcpInfo.his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
+ } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr,
+ &ipcp->cfg.peer_range.mask,
+ &ipcp->cfg.peer_range.width) != 0) {
+ ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
- if (setaddr && OsSetIpaddress
- (DefMyAddress.ipaddr, DefHisAddress.ipaddr) < 0) {
- DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
+ if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
+ ipcp->cfg.peer_range.ipaddr, 0) < 0) {
+ ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY;
+ ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY;
return 0;
}
} else
diff --git a/usr.sbin/ppp/ipcp.h b/usr.sbin/ppp/ipcp.h
index 5570f67695c0..410dda53cd2d 100644
--- a/usr.sbin/ppp/ipcp.h
+++ b/usr.sbin/ppp/ipcp.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ipcp.h,v 1.17 1998/01/11 17:50:33 brian Exp $
+ * $Id: ipcp.h,v 1.18.2.28 1998/05/21 01:26:10 brian Exp $
*
* TODO:
*/
@@ -26,35 +26,15 @@
#define TY_COMPPROTO 2
#define TY_IPADDR 3
-/* MS PPP NameServer and NetBIOS NameServer stuff */
+/* Domain NameServer and NetBIOS NameServer options */
-#ifndef NOMSEXT
#define TY_PRIMARY_DNS 129
#define TY_PRIMARY_NBNS 130
#define TY_SECONDARY_DNS 131
#define TY_SECONDARY_NBNS 132
+#define TY_ADJUST_NS 119 /* subtract from NS val for REJECT bit */
-extern struct in_addr ns_entries[2];
-extern struct in_addr nbns_entries[2];
-#endif
-
-struct ipcpstate {
- struct in_addr his_ipaddr; /* IP address he is willing to use */
- u_int32_t his_compproto;
-
- struct in_addr want_ipaddr; /* IP address I'm willing to use */
- u_int32_t want_compproto;
-
- u_int32_t his_reject; /* Request codes rejected by peer */
- u_int32_t my_reject; /* Request codes I have rejected */
- int heis1172; /* True if he is speaking rfc1172 */
-};
-
-struct compreq {
- u_short proto;
- u_char slots;
- u_char compcid;
-};
+struct sticky_route;
struct in_range {
struct in_addr ipaddr;
@@ -62,22 +42,73 @@ struct in_range {
int width;
};
-extern struct ipcpstate IpcpInfo;
-extern struct in_range DefMyAddress;
-extern struct in_range DefHisAddress;
-extern struct iplist DefHisChoice;
-extern struct in_addr TriggerAddress;
-extern int HaveTriggerAddress;
-extern struct fsm IpcpFsm;
-
-extern void IpcpInit(void);
-extern void IpcpDefAddress(void);
-extern void IpcpUp(void);
-extern void IpcpOpen(void);
-extern int ReportIpcpStatus(struct cmdargs const *);
-extern void IpcpInput(struct mbuf *);
-extern void IpcpAddInOctets(int);
-extern void IpcpAddOutOctets(int);
-extern int UseHisaddr(const char *, int);
-extern int SetInitVJ(struct cmdargs const *);
-extern int ShowInitVJ(struct cmdargs const *);
+struct ipcp {
+ struct fsm fsm; /* The finite state machine */
+
+ struct {
+ struct {
+ int slots; /* Maximum VJ slots */
+ unsigned slotcomp : 1; /* Slot compression */
+ unsigned neg : 2; /* VJ negotiation */
+ } vj;
+
+ struct in_range my_range; /* MYADDR spec */
+ struct in_addr netmask; /* netmask (unused by most OSs) */
+ struct in_range peer_range; /* HISADDR spec */
+ struct iplist peer_list; /* Ranges of HISADDR values */
+
+ struct in_addr TriggerAddress; /* Address to suggest in REQ */
+ unsigned HaveTriggerAddress : 1; /* Trigger address specified */
+
+ struct {
+ struct in_addr dns[2]; /* DNS addresses offered */
+ unsigned dns_neg : 2; /* dns negotiation */
+ struct in_addr nbns[2]; /* NetBIOS NS addresses offered */
+ } ns;
+
+ u_int fsmretry; /* FSM retry frequency */
+ } cfg;
+
+ struct {
+ struct slcompress cslc; /* VJ state */
+ struct slstat slstat; /* VJ statistics */
+ } vj;
+
+ struct sticky_route *route; /* List of dynamic routes */
+
+ unsigned heis1172 : 1; /* True if he is speaking rfc1172 */
+
+ struct in_addr peer_ip; /* IP address he's willing to use */
+ u_int32_t peer_compproto; /* VJ params he's willing to use */
+
+ struct in_addr my_ip; /* IP address I'm willing to use */
+ u_int32_t my_compproto; /* VJ params I'm willing to use */
+
+ u_int32_t peer_reject; /* Request codes rejected by peer */
+ u_int32_t my_reject; /* Request codes I have rejected */
+
+ struct in_addr my_ifip; /* My configured interface address */
+ struct in_addr peer_ifip; /* My congigured destination address */
+
+ struct pppThroughput throughput; /* throughput statistics */
+};
+
+#define fsm2ipcp(fp) (fp->proto == PROTO_IPCP ? (struct ipcp *)fp : NULL)
+
+struct bundle;
+struct link;
+struct cmdargs;
+
+extern void ipcp_Init(struct ipcp *, struct bundle *, struct link *,
+ const struct fsm_parent *);
+extern void ipcp_Setup(struct ipcp *);
+extern void ipcp_SetLink(struct ipcp *, struct link *);
+
+extern int ipcp_Show(struct cmdargs const *);
+extern void ipcp_Input(struct ipcp *, struct bundle *, struct mbuf *);
+extern void ipcp_AddInOctets(struct ipcp *, int);
+extern void ipcp_AddOutOctets(struct ipcp *, int);
+extern int ipcp_UseHisaddr(struct bundle *, const char *, int);
+extern int ipcp_vjset(struct cmdargs const *);
+extern void ipcp_CleanInterface(struct ipcp *);
+extern int ipcp_InterfaceUp(struct ipcp *);
diff --git a/usr.sbin/ppp/iplist.c b/usr.sbin/ppp/iplist.c
index 6e6ecd1f25d9..319f13088534 100644
--- a/usr.sbin/ppp/iplist.c
+++ b/usr.sbin/ppp/iplist.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: iplist.c,v 1.3 1997/12/23 22:38:54 brian Exp $
+ * $Id: iplist.c,v 1.4.4.3 1998/05/01 19:24:54 brian Exp $
*/
#include <sys/types.h>
@@ -33,8 +33,6 @@
#include <stdlib.h>
#include <string.h>
-#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "iplist.h"
@@ -45,7 +43,7 @@ do_inet_aton(const char *start, const char *end, struct in_addr *ip)
static char ipstr[16];
if (end - start > 15) {
- LogPrintf(LogWARN, "%.*s: Invalid IP address\n", end-start, start);
+ log_Printf(LogWARN, "%.*s: Invalid IP address\n", end-start, start);
return 0;
}
strncpy(ipstr, start, end-start);
@@ -112,7 +110,7 @@ iplist_nextrange(struct iplist *list)
end = ptr + strlen(ptr);
if (end == ptr)
return 0;
- LogPrintf(LogWARN, "%.*s: Invalid IP range (skipping)\n", end - ptr, ptr);
+ log_Printf(LogWARN, "%.*s: Invalid IP range (skipping)\n", end - ptr, ptr);
to = ptr;
do
*to = *end++;
diff --git a/usr.sbin/ppp/lcp.c b/usr.sbin/ppp/lcp.c
index 010187473a19..6fc31ef7a622 100644
--- a/usr.sbin/ppp/lcp.c
+++ b/usr.sbin/ppp/lcp.c
@@ -17,26 +17,21 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: lcp.c,v 1.55 1998/01/21 02:15:18 brian Exp $
+ * $Id: lcp.c,v 1.55.2.54 1998/05/15 23:58:24 brian Exp $
*
* TODO:
- * o Validate magic number received from peer.
* o Limit data field length by MRU
*/
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_tun.h>
+
+#include <sys/types.h>
#include <netinet/in.h>
-#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <signal.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
@@ -46,24 +41,27 @@
#include "defs.h"
#include "timer.h"
#include "fsm.h"
+#include "iplist.h"
#include "lcp.h"
-#include "ipcp.h"
+#include "throughput.h"
#include "lcpproto.h"
-#include "os.h"
+#include "descriptor.h"
+#include "lqr.h"
#include "hdlc.h"
#include "ccp.h"
-#include "lqr.h"
-#include "phase.h"
-#include "loadalias.h"
-#include "vars.h"
+#include "async.h"
+#include "link.h"
+#include "physical.h"
+#include "prompt.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "mp.h"
+#include "chat.h"
#include "auth.h"
-#include "pap.h"
#include "chap.h"
-#include "async.h"
-#include "main.h"
-#include "ip.h"
-#include "modem.h"
-#include "tun.h"
+#include "datalink.h"
+#include "bundle.h"
/* for received LQRs */
struct lqrreq {
@@ -73,17 +71,33 @@ struct lqrreq {
u_long period; /* Reporting interval */
};
-struct lcpstate LcpInfo;
-
-static void LcpSendConfigReq(struct fsm *);
-static void LcpSendTerminateReq(struct fsm *);
-static void LcpSendTerminateAck(struct fsm *);
-static void LcpDecodeConfig(u_char *, int, int);
-static void LcpInitRestartCounter(struct fsm *);
-static void LcpLayerUp(struct fsm *);
+static int LcpLayerUp(struct fsm *);
static void LcpLayerDown(struct fsm *);
static void LcpLayerStart(struct fsm *);
static void LcpLayerFinish(struct fsm *);
+static void LcpInitRestartCounter(struct fsm *);
+static void LcpSendConfigReq(struct fsm *);
+static void LcpSentTerminateReq(struct fsm *);
+static void LcpSendTerminateAck(struct fsm *, u_char);
+static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
+ struct fsm_decode *);
+
+static struct fsm_callbacks lcp_Callbacks = {
+ LcpLayerUp,
+ LcpLayerDown,
+ LcpLayerStart,
+ LcpLayerFinish,
+ LcpInitRestartCounter,
+ LcpSendConfigReq,
+ LcpSentTerminateReq,
+ LcpSendTerminateAck,
+ LcpDecodeConfig,
+ fsm_NullRecvResetReq,
+ fsm_NullRecvResetAck
+};
+
+static const char *lcp_TimerNames[] =
+ {"LCP restart", "LCP openmode", "LCP stopped"};
static const char *cftypes[] = {
/* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
@@ -104,9 +118,9 @@ static const char *cftypes[] = {
"CONTIME", /* 14: Connect-Time */
"COMPFRAME", /* 15: Compound-Frames */
"NDE", /* 16: Nominal-Data-Encapsulation */
- "MULTIMRRU", /* 17: Multilink-MRRU */
- "MULTISSNH", /* 18: Multilink-Short-Sequence-Number-Header */
- "MULTIED", /* 19: Multilink-Endpoint-Descriminator */
+ "MRRU", /* 17: Multilink-MRRU */
+ "SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */
+ "ENDDISC", /* 19: Multilink-Endpoint-Descriminator */
"PROPRIETRY", /* 20: Proprietary */
"DCEID", /* 21: DCE-Identifier */
"MULTIPP", /* 22: Multi-Link-Plus-Procedure */
@@ -115,437 +129,422 @@ static const char *cftypes[] = {
#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
-struct fsm LcpFsm = {
- "LCP", /* Name of protocol */
- PROTO_LCP, /* Protocol Number */
- LCP_MAXCODE,
- 1, /* Open mode delay */
- ST_INITIAL, /* State of machine */
- 0, 0, 0,
- {0, 0, 0, NULL, NULL, NULL}, /* FSM timer */
- {0, 0, 0, NULL, NULL, NULL}, /* Open timer */
- {0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */
- LogLCP,
-
- LcpLayerUp,
- LcpLayerDown,
- LcpLayerStart,
- LcpLayerFinish,
- LcpInitRestartCounter,
- LcpSendConfigReq,
- LcpSendTerminateReq,
- LcpSendTerminateAck,
- LcpDecodeConfig,
-};
-
-static struct pppTimer LcpReportTimer;
-static int LcpFailedMagic;
-
-static void
-LcpReportTime(void *data)
-{
- if (LogIsKept(LogDEBUG)) {
- time_t t;
-
- time(&t);
- LogPrintf(LogDEBUG, "LcpReportTime: %s\n", ctime(&t));
- }
- StopTimer(&LcpReportTimer);
- LcpReportTimer.state = TIMER_STOPPED;
- StartTimer(&LcpReportTimer);
- HdlcErrorCheck();
-}
-
int
-ReportLcpStatus(struct cmdargs const *arg)
+lcp_ReportStatus(struct cmdargs const *arg)
{
- struct lcpstate *lcp = &LcpInfo;
- struct fsm *fp = &LcpFsm;
-
- if (!VarTerm)
- return 1;
-
- fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
- fprintf(VarTerm,
- " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d,\n"
- " MAGIC %08lx, REJECT %04x\n",
- lcp->his_mru, (u_long)lcp->his_accmap, lcp->his_protocomp,
- lcp->his_acfcomp, (u_long)lcp->his_magic, lcp->his_reject);
- fprintf(VarTerm,
- " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d,\n"
- " MAGIC %08lx, REJECT %04x\n",
- lcp->want_mru, (u_long)lcp->want_accmap, lcp->want_protocomp,
- lcp->want_acfcomp, (u_long)lcp->want_magic, lcp->my_reject);
- fprintf(VarTerm, "\nDefaults: MRU = %d, ACCMAP = %08lx\t",
- VarMRU, (u_long)VarAccmap);
- fprintf(VarTerm, "Open Mode: %s",
- (VarOpenMode == OPEN_PASSIVE) ? "passive" : "active");
- if (VarOpenMode > 0)
- fprintf(VarTerm, " (delay %d)", VarOpenMode);
- fputc('\n', VarTerm);
+ struct link *l;
+ struct lcp *lcp;
+
+ if (!(l = command_ChooseLink(arg)))
+ return -1;
+ lcp = &l->lcp;
+
+ prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
+ State2Nam(lcp->fsm.state));
+ prompt_Printf(arg->prompt,
+ " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
+ " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
+ lcp->his_mru, (u_long)lcp->his_accmap,
+ lcp->his_protocomp ? "on" : "off",
+ lcp->his_acfcomp ? "on" : "off",
+ (u_long)lcp->his_magic, lcp->his_mrru,
+ lcp->his_shortseq ? "on" : "off", lcp->his_reject);
+ prompt_Printf(arg->prompt,
+ " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
+ " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
+ lcp->want_mru, (u_long)lcp->want_accmap,
+ lcp->want_protocomp ? "on" : "off",
+ lcp->want_acfcomp ? "on" : "off",
+ (u_long)lcp->want_magic, lcp->want_mrru,
+ lcp->want_shortseq ? "on" : "off", lcp->my_reject);
+
+ prompt_Printf(arg->prompt, "\n Defaults: MRU = %d, ", lcp->cfg.mru);
+ prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
+ prompt_Printf(arg->prompt, " LQR period = %us, ",
+ lcp->cfg.lqrperiod);
+ prompt_Printf(arg->prompt, "Open Mode = %s",
+ lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
+ if (lcp->cfg.openmode > 0)
+ prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
+ prompt_Printf(arg->prompt, "\n FSM retry = %us\n",
+ lcp->cfg.fsmretry);
+ prompt_Printf(arg->prompt, "\n Negotiation:\n");
+ prompt_Printf(arg->prompt, " ACFCOMP = %s\n",
+ command_ShowNegval(lcp->cfg.acfcomp));
+ prompt_Printf(arg->prompt, " CHAP = %s\n",
+ command_ShowNegval(lcp->cfg.chap));
+ prompt_Printf(arg->prompt, " LQR = %s\n",
+ command_ShowNegval(lcp->cfg.lqr));
+ prompt_Printf(arg->prompt, " PAP = %s\n",
+ command_ShowNegval(lcp->cfg.pap));
+ prompt_Printf(arg->prompt, " PROTOCOMP = %s\n",
+ command_ShowNegval(lcp->cfg.protocomp));
+
return 0;
}
-/*
- * Generate random number which will be used as magic number.
- */
static u_int32_t
GenerateMagic(void)
{
+ /* Generate random number which will be used as magic number */
randinit();
- return (random());
+ return random();
}
void
-LcpInit()
+lcp_SetupCallbacks(struct lcp *lcp)
{
- struct lcpstate *lcp = &LcpInfo;
+ lcp->fsm.fn = &lcp_Callbacks;
+ lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
+ lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
+ lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
+}
- FsmInit(&LcpFsm);
- HdlcInit();
+void
+lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
+ const struct fsm_parent *parent)
+{
+ /* Initialise ourselves */
+ int mincode = parent ? 1 : LCP_MINMPCODE;
- memset(lcp, '\0', sizeof(struct lcpstate));
- lcp->want_mru = VarMRU;
- lcp->his_mru = DEF_MRU;
- lcp->his_accmap = 0xffffffff;
- lcp->want_accmap = VarAccmap;
- lcp->want_magic = GenerateMagic();
- lcp->want_auth = lcp->his_auth = 0;
- if (Enabled(ConfChap))
- lcp->want_auth = PROTO_CHAP;
- else if (Enabled(ConfPap))
- lcp->want_auth = PROTO_PAP;
- if (Enabled(ConfLqr))
- lcp->want_lqrperiod = VarLqrTimeout * 100;
- if (Enabled(ConfAcfcomp))
- lcp->want_acfcomp = 1;
- if (Enabled(ConfProtocomp))
- lcp->want_protocomp = 1;
- LcpFsm.maxconfig = 10;
+ fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, 10, LogLCP,
+ bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
+
+ lcp->cfg.mru = DEF_MRU;
+ lcp->cfg.accmap = 0;
+ lcp->cfg.openmode = 1;
+ lcp->cfg.lqrperiod = DEF_LQRPERIOD;
+ lcp->cfg.fsmretry = DEF_FSMRETRY;
+
+ lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
+ lcp->cfg.chap = NEG_ACCEPTED;
+ lcp->cfg.lqr = NEG_ACCEPTED;
+ lcp->cfg.pap = NEG_ACCEPTED;
+ lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
+
+ lcp_Setup(lcp, lcp->cfg.openmode);
}
-static void
-LcpInitRestartCounter(struct fsm * fp)
+void
+lcp_Setup(struct lcp *lcp, int openmode)
{
- fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
- fp->restart = 5;
+ lcp->fsm.open_mode = openmode;
+ lcp->fsm.maxconfig = 10;
+
+ lcp->his_mru = DEF_MRU;
+ lcp->his_mrru = 0;
+ lcp->his_magic = 0;
+ lcp->his_lqrperiod = 0;
+ lcp->his_acfcomp = 0;
+ lcp->his_auth = 0;
+ lcp->his_shortseq = 0;
+
+ lcp->want_mru = lcp->cfg.mru;
+ lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
+ lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
+ lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
+
+ if (lcp->fsm.parent) {
+ lcp->his_accmap = 0xffffffff;
+ lcp->want_accmap = lcp->cfg.accmap;
+ lcp->his_protocomp = 0;
+ lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
+ lcp->want_magic = GenerateMagic();
+ lcp->want_auth = IsEnabled(lcp->cfg.chap) ? PROTO_CHAP :
+ IsEnabled(lcp->cfg.pap) ? PROTO_PAP : 0;
+ lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
+ lcp->cfg.lqrperiod * 100 : 0;
+ } else {
+ lcp->his_accmap = lcp->want_accmap = 0;
+ lcp->his_protocomp = lcp->want_protocomp = 1;
+ lcp->want_magic = 0;
+ lcp->want_auth = 0;
+ lcp->want_lqrperiod = 0;
+ }
+
+ lcp->his_reject = lcp->my_reject = 0;
+ lcp->auth_iwait = lcp->auth_ineed = 0;
+ lcp->LcpFailedMagic = 0;
}
-int
-LcpPutConf(int log, u_char *tgt, const struct lcp_opt *o, const char *nm,
- const char *arg, ...)
+static void
+LcpInitRestartCounter(struct fsm * fp)
{
- va_list ap;
- char buf[30];
-
- va_start(ap, arg);
- memcpy(tgt, o, o->len);
- if (arg == NULL || *arg == '\0')
- LogPrintf(log, " %s[%d]\n", nm, o->len);
- else {
- vsnprintf(buf, sizeof buf, arg, ap);
- LogPrintf(log, " %s[%d] %s\n", nm, o->len, buf);
- }
- va_end(ap);
+ /* Set fsm timer load */
+ struct lcp *lcp = fsm2lcp(fp);
- return o->len;
+ fp->FsmTimer.load = lcp->cfg.fsmretry * SECTICKS;
+ fp->restart = 5;
}
-#define PUTN(ty) \
-do { \
- o.id = ty; \
- o.len = 2; \
- cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], NULL); \
-} while (0)
-
-#define PUTHEX32(ty, arg) \
-do { \
- o.id = ty; \
- o.len = 6; \
- *(u_long *)o.data = htonl(arg); \
- cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], "0x%08lx", (u_long)arg);\
-} while (0)
-
-#define PUTACCMAP(arg) PUTHEX32(TY_ACCMAP, arg)
-#define PUTMAGIC(arg) PUTHEX32(TY_MAGICNUM, arg)
-
-#define PUTMRU(arg) \
-do { \
- o.id = TY_MRU; \
- o.len = 4; \
- *(u_short *)o.data = htons(arg); \
- cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], "%u", arg); \
-} while (0)
-
-#define PUTLQR(period) \
-do { \
- o.id = TY_QUALPROTO; \
- o.len = 8; \
- *(u_short *)o.data = htons(PROTO_LQR); \
- *(u_long *)(o.data+2) = htonl(period); \
- cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \
- "period %ld", (u_long)period); \
-} while (0)
-
-#define PUTPAP() \
-do { \
- o.id = TY_AUTHPROTO; \
- o.len = 4; \
- *(u_short *)o.data = htons(PROTO_PAP); \
- cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \
- "0x%04x (PAP)", PROTO_PAP); \
-} while (0)
-
-#define PUTCHAP(val) \
-do { \
- o.id = TY_AUTHPROTO; \
- o.len = 5; \
- *(u_short *)o.data = htons(PROTO_CHAP); \
- o.data[2] = val; \
- cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \
- "0x%04x (CHAP 0x%02x)", PROTO_CHAP, val); \
-} while (0)
-
-#define PUTMD5CHAP() PUTCHAP(0x05)
-#define PUTMSCHAP() PUTCHAP(0x80)
-
static void
-LcpSendConfigReq(struct fsm * fp)
+LcpSendConfigReq(struct fsm *fp)
{
- u_char *cp;
- struct lcpstate *lcp = &LcpInfo;
- struct lcp_opt o;
+ /* Send config REQ please */
+ struct physical *p = link2physical(fp->link);
+ struct lcp *lcp = fsm2lcp(fp);
+ u_char buff[200];
+ struct lcp_opt *o;
+ struct mp *mp;
+
+ if (!p) {
+ log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
+ fp->link->name);
+ return;
+ }
- LogPrintf(LogLCP, "LcpSendConfigReq\n");
- cp = ReqBuff;
- if (!DEV_IS_SYNC) {
+ o = (struct lcp_opt *)buff;
+ if (!physical_IsSync(p)) {
if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
- PUTN(TY_ACFCOMP);
+ INC_LCP_OPT(TY_ACFCOMP, 2, o);
if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
- PUTN(TY_PROTOCOMP);
+ INC_LCP_OPT(TY_PROTOCOMP, 2, o);
- if (!REJECTED(lcp, TY_ACCMAP))
- PUTACCMAP(lcp->want_accmap);
+ if (!REJECTED(lcp, TY_ACCMAP)) {
+ *(u_int32_t *)o->data = htonl(lcp->want_accmap);
+ INC_LCP_OPT(TY_ACCMAP, 6, o);
+ }
}
- if (!REJECTED(lcp, TY_MRU))
- PUTMRU(lcp->want_mru);
+ if (!REJECTED(lcp, TY_MRU)) {
+ *(u_short *)o->data = htons(lcp->want_mru);
+ INC_LCP_OPT(TY_MRU, 4, o);
+ }
- if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM))
- PUTMAGIC(lcp->want_magic);
+ if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
+ *(u_int32_t *)o->data = htonl(lcp->want_magic);
+ INC_LCP_OPT(TY_MAGICNUM, 6, o);
+ }
- if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO))
- PUTLQR(lcp->want_lqrperiod);
+ if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
+ *(u_short *)o->data = htons(PROTO_LQR);
+ *(u_long *)(o->data + 2) = htonl(lcp->want_lqrperiod);
+ INC_LCP_OPT(TY_QUALPROTO, 8, o);
+ }
switch (lcp->want_auth) {
case PROTO_PAP:
- PUTPAP();
+ *(u_short *)o->data = htons(PROTO_PAP);
+ INC_LCP_OPT(TY_AUTHPROTO, 4, o);
break;
case PROTO_CHAP:
-#ifdef HAVE_DES
- if (VarMSChap)
- PUTMSCHAP(); /* Use MSChap */
- else
-#endif
- PUTMD5CHAP(); /* Use MD5 */
+ *(u_short *)o->data = htons(PROTO_CHAP);
+ o->data[2] = 0x05;
+ INC_LCP_OPT(TY_AUTHPROTO, 5, o);
break;
}
- FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
-}
-void
-LcpSendProtoRej(u_char * option, int count)
-{
- struct fsm *fp = &LcpFsm;
+ if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
+ *(u_short *)o->data = htons(lcp->want_mrru);
+ INC_LCP_OPT(TY_MRRU, 4, o);
- LogPrintf(LogLCP, "LcpSendProtoRej\n");
- FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count);
-}
+ if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
+ INC_LCP_OPT(TY_SHORTSEQ, 2, o);
+ }
-static void
-LcpSendTerminateReq(struct fsm * fp)
-{
- /* Most thins are done in fsm layer. Nothing to to. */
-}
+ mp = &lcp->fsm.bundle->ncp.mp;
+ if (mp->cfg.enddisc.class != 0 && !REJECTED(lcp, TY_ENDDISC)) {
+ *o->data = mp->cfg.enddisc.class;
+ memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
+ INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
+ }
-static void
-LcpSendTerminateAck(struct fsm * fp)
-{
- LogPrintf(LogLCP, "LcpSendTerminateAck.\n");
- FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
+ fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff);
}
-static void
-LcpLayerStart(struct fsm * fp)
+void
+lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
{
- LogPrintf(LogLCP, "LcpLayerStart\n");
- NewPhase(PHASE_ESTABLISH);
+ /* Don't understand `option' */
+ fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count);
}
static void
-StopAllTimers(void)
+LcpSentTerminateReq(struct fsm * fp)
{
- StopTimer(&LcpReportTimer);
- StopIdleTimer();
- StopTimer(&AuthPapInfo.authtimer);
- StopTimer(&AuthChapInfo.authtimer);
- StopLqrTimer();
+ /* Term REQ just sent by FSM */
}
static void
-LcpLayerFinish(struct fsm * fp)
+LcpSendTerminateAck(struct fsm *fp, u_char id)
{
- LogPrintf(LogLCP, "LcpLayerFinish\n");
- HangupModem(0);
- StopAllTimers();
- /* We're down at last. Lets tell background and direct mode to get out */
- NewPhase(PHASE_DEAD);
- LcpInit();
- IpcpInit();
- CcpInit();
- Prompt();
+ /* Send Term ACK please */
+ fsm_Output(fp, CODE_TERMACK, id, NULL, 0);
}
static void
-LcpLayerUp(struct fsm * fp)
+LcpLayerStart(struct fsm *fp)
{
- LogPrintf(LogLCP, "LcpLayerUp\n");
- tun_configure(LcpInfo.his_mru, ModemSpeed());
- SetLinkParams(&LcpInfo);
-
- NewPhase(PHASE_AUTHENTICATE);
-
- StartLqm();
- StopTimer(&LcpReportTimer);
- LcpReportTimer.state = TIMER_STOPPED;
- LcpReportTimer.load = 60 * SECTICKS;
- LcpReportTimer.func = LcpReportTime;
- StartTimer(&LcpReportTimer);
+ /* We're about to start up ! */
+ struct lcp *lcp = fsm2lcp(fp);
+
+ log_Printf(LogLCP, "%s: LcpLayerStart\n", fp->link->name);
+ lcp->LcpFailedMagic = 0;
}
static void
-LcpLayerDown(struct fsm * fp)
+LcpLayerFinish(struct fsm *fp)
{
- StopAllTimers();
- OsLinkdown();
- LogPrintf(LogLCP, "LcpLayerDown\n");
- /*
- * OsLinkdown() brings CCP & IPCP down, then waits 'till we go from
- * STOPPING to STOPPED. At this point, the FSM gives us a LayerFinish
- */
+ /* We're now down */
+ log_Printf(LogLCP, "%s: LcpLayerFinish\n", fp->link->name);
}
-void
-LcpUp()
+static int
+LcpLayerUp(struct fsm *fp)
{
- FsmUp(&LcpFsm);
- LcpFailedMagic = 0;
+ /* We're now up */
+ struct physical *p = link2physical(fp->link);
+ struct lcp *lcp = fsm2lcp(fp);
+
+ log_Printf(LogLCP, "%s: LcpLayerUp\n", fp->link->name);
+ async_SetLinkParams(&p->async, lcp);
+ lqr_Start(lcp);
+ hdlc_StartTimer(&p->hdlc);
+ return 1;
}
-void
-LcpDown()
-{ /* Sudden death */
- LcpFailedMagic = 0;
- FsmDown(&LcpFsm);
- /* FsmDown() results in a LcpLayerDown() if we're currently open. */
- LcpLayerFinish(&LcpFsm);
-}
-
-void
-LcpOpen(int open_mode)
+static void
+LcpLayerDown(struct fsm *fp)
{
- LcpFsm.open_mode = open_mode;
- LcpFailedMagic = 0;
- FsmOpen(&LcpFsm);
-}
+ /* About to come down */
+ struct physical *p = link2physical(fp->link);
-void
-LcpClose()
-{
- NewPhase(PHASE_TERMINATE);
- OsInterfaceDown(0);
- FsmClose(&LcpFsm);
- LcpFailedMagic = 0;
+ log_Printf(LogLCP, "%s: LcpLayerDown\n", fp->link->name);
+ hdlc_StopTimer(&p->hdlc);
+ lqr_StopTimer(p);
}
-/*
- * XXX: Should validate option length
- */
static void
-LcpDecodeConfig(u_char *cp, int plen, int mode_type)
+LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
+ struct fsm_decode *dec)
{
+ /* Deal with incoming PROTO_LCP */
+ struct lcp *lcp = fsm2lcp(fp);
int type, length, sz, pos;
- u_int32_t *lp, magic, accmap;
+ u_int32_t magic, accmap;
u_short mtu, mru, *sp, proto;
struct lqrreq *req;
char request[20], desc[22];
-
- ackp = AckBuff;
- nakp = NakBuff;
- rejp = RejBuff;
+ struct mp *mp;
+ struct physical *p = link2physical(fp->link);
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
+ if (length == 0) {
+ log_Printf(LogLCP, "%s: LCP size zero\n", fp->link->name);
+ break;
+ }
+
if (type < 0 || type >= NCFTYPES)
snprintf(request, sizeof request, " <%d>[%d]", type, length);
else
snprintf(request, sizeof request, " %s[%d]", cftypes[type], length);
switch (type) {
+ case TY_MRRU:
+ mp = &lcp->fsm.bundle->ncp.mp;
+ sp = (u_short *)(cp + 2);
+ mru = htons(*sp);
+ log_Printf(LogLCP, "%s %u\n", request, mru);
+
+ switch (mode_type) {
+ case MODE_REQ:
+ if (mp->cfg.mrru) {
+ if (REJECTED(lcp, TY_MRRU))
+ /* Ignore his previous reject so that we REQ next time */
+ lcp->his_reject &= ~(1 << type);
+
+ mtu = lcp->fsm.bundle->cfg.mtu;
+ if (mru < MIN_MRU || mru < mtu) {
+ /* Push him up to MTU or MIN_MRU */
+ lcp->his_mrru = mru < mtu ? mtu : MIN_MRU;
+ *sp = htons((u_short)lcp->his_mrru);
+ memcpy(dec->nakend, cp, 4);
+ dec->nakend += 4;
+ } else {
+ lcp->his_mrru = mtu ? mtu : mru;
+ memcpy(dec->ackend, cp, 4);
+ dec->ackend += 4;
+ }
+ break;
+ } else
+ goto reqreject;
+ break;
+ case MODE_NAK:
+ if (mp->cfg.mrru) {
+ if (REJECTED(lcp, TY_MRRU))
+ /* Must have changed his mind ! */
+ lcp->his_reject &= ~(1 << type);
+
+ if (mru > MAX_MRU)
+ lcp->want_mrru = MAX_MRU;
+ else if (mru < MIN_MRU)
+ lcp->want_mrru = MIN_MRU;
+ else
+ lcp->want_mrru = mru;
+ }
+ /* else we honour our config and don't send the suggested REQ */
+ break;
+ case MODE_REJ:
+ lcp->his_reject |= (1 << type);
+ lcp->want_mrru = 0; /* Ah well, no multilink :-( */
+ break;
+ }
+ break;
+
case TY_MRU:
sp = (u_short *) (cp + 2);
mru = htons(*sp);
- LogPrintf(LogLCP, "%s %d\n", request, mru);
+ log_Printf(LogLCP, "%s %d\n", request, mru);
switch (mode_type) {
case MODE_REQ:
- mtu = VarPrefMTU;
- if (mtu == 0)
- mtu = MAX_MTU;
- if (mru > mtu) {
- *sp = htons(mtu);
- memcpy(nakp, cp, 4);
- nakp += 4;
- } else if (mru < MIN_MRU) {
- *sp = htons(MIN_MRU);
- memcpy(nakp, cp, 4);
- nakp += 4;
- } else {
- LcpInfo.his_mru = mru;
- memcpy(ackp, cp, 4);
- ackp += 4;
- }
+ mtu = lcp->fsm.bundle->cfg.mtu;
+ if (mru < MIN_MRU || (!lcp->want_mrru && mru < mtu)) {
+ /* Push him up to MTU or MIN_MRU */
+ lcp->his_mru = mru < mtu ? mtu : MIN_MRU;
+ *sp = htons((u_short)lcp->his_mru);
+ memcpy(dec->nakend, cp, 4);
+ dec->nakend += 4;
+ } else {
+ lcp->his_mru = mtu ? mtu : mru;
+ memcpy(dec->ackend, cp, 4);
+ dec->ackend += 4;
+ }
break;
case MODE_NAK:
- if (mru >= MIN_MRU || mru <= MAX_MRU)
- LcpInfo.want_mru = mru;
+ if (mru > MAX_MRU)
+ lcp->want_mru = MAX_MRU;
+ else if (mru < MIN_MRU)
+ lcp->want_mru = MIN_MRU;
+ else
+ lcp->want_mru = mru;
break;
case MODE_REJ:
- LcpInfo.his_reject |= (1 << type);
+ lcp->his_reject |= (1 << type);
break;
}
break;
case TY_ACCMAP:
- lp = (u_int32_t *) (cp + 2);
- accmap = htonl(*lp);
- LogPrintf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
+ accmap = htonl(*(u_int32_t *)(cp + 2));
+ log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
switch (mode_type) {
case MODE_REQ:
- LcpInfo.his_accmap = accmap;
- memcpy(ackp, cp, 6);
- ackp += 6;
+ lcp->his_accmap = accmap;
+ memcpy(dec->ackend, cp, 6);
+ dec->ackend += 6;
break;
case MODE_NAK:
- LcpInfo.want_accmap = accmap;
+ lcp->want_accmap = accmap;
break;
case MODE_REJ:
- LcpInfo.his_reject |= (1 << type);
+ lcp->his_reject |= (1 << type);
break;
}
break;
@@ -555,13 +554,13 @@ LcpDecodeConfig(u_char *cp, int plen, int mode_type)
proto = ntohs(*sp);
switch (proto) {
case PROTO_PAP:
- LogPrintf(LogLCP, "%s 0x%04x (PAP)\n", request, proto);
+ log_Printf(LogLCP, "%s 0x%04x (PAP)\n", request, proto);
break;
case PROTO_CHAP:
- LogPrintf(LogLCP, "%s 0x%04x (CHAP 0x%02x)\n", request, proto, cp[4]);
+ log_Printf(LogLCP, "%s 0x%04x (CHAP 0x%02x)\n", request, proto, cp[4]);
break;
default:
- LogPrintf(LogLCP, "%s 0x%04x\n", request, proto);
+ log_Printf(LogLCP, "%s 0x%04x\n", request, proto);
break;
}
@@ -570,228 +569,278 @@ LcpDecodeConfig(u_char *cp, int plen, int mode_type)
switch (proto) {
case PROTO_PAP:
if (length != 4) {
- LogPrintf(LogLCP, " Bad length!\n");
+ log_Printf(LogLCP, " Bad length!\n");
goto reqreject;
}
- if (Acceptable(ConfPap)) {
- LcpInfo.his_auth = proto;
- memcpy(ackp, cp, length);
- ackp += length;
- } else if (Acceptable(ConfChap)) {
- *nakp++ = *cp;
- *nakp++ = 5;
- *nakp++ = (unsigned char) (PROTO_CHAP >> 8);
- *nakp++ = (unsigned char) PROTO_CHAP;
-#ifdef HAVE_DES
- if (VarMSChap)
- *nakp++ = 0x80;
- else
-#endif
- *nakp++ = 5;
+ if (IsAccepted(lcp->cfg.pap)) {
+ lcp->his_auth = proto;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
+ } else if (IsAccepted(lcp->cfg.chap)) {
+ *dec->nakend++ = *cp;
+ *dec->nakend++ = 5;
+ *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
+ *dec->nakend++ = (unsigned char) PROTO_CHAP;
+ *dec->nakend++ = 0x05;
} else
goto reqreject;
break;
case PROTO_CHAP:
if (length < 5) {
- LogPrintf(LogLCP, " Bad length!\n");
+ log_Printf(LogLCP, " Bad length!\n");
goto reqreject;
}
#ifdef HAVE_DES
- if (Acceptable(ConfChap) && (cp[4] == 5 || cp[4] == 0x80))
+ if (IsAccepted(lcp->cfg.chap) && (cp[4] == 0x05 || cp[4] == 0x80))
#else
- if (Acceptable(ConfChap) && cp[4] == 5)
+ if (IsAccepted(lcp->cfg.chap) && cp[4] == 0x05)
#endif
{
- LcpInfo.his_auth = proto;
- memcpy(ackp, cp, length);
- ackp += length;
+ lcp->his_auth = proto;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
#ifdef HAVE_DES
- VarMSChap = cp[4] == 0x80;
+ link2physical(fp->link)->dl->chap.using_MSChap = cp[4] == 0x80;
#endif
- } else if (Acceptable(ConfPap)) {
- *nakp++ = *cp;
- *nakp++ = 4;
- *nakp++ = (unsigned char) (PROTO_PAP >> 8);
- *nakp++ = (unsigned char) PROTO_PAP;
+ } else if (IsAccepted(lcp->cfg.pap)) {
+ *dec->nakend++ = *cp;
+ *dec->nakend++ = 4;
+ *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
+ *dec->nakend++ = (unsigned char) PROTO_PAP;
} else
goto reqreject;
break;
default:
- LogPrintf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
+ log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
request, proto);
- memcpy(nakp, cp, length);
- nakp += length;
+ memcpy(dec->nakend, cp, length);
+ dec->nakend += length;
break;
}
break;
case MODE_NAK:
switch (proto) {
case PROTO_PAP:
- if (Enabled(ConfPap))
- LcpInfo.want_auth = PROTO_PAP;
+ if (IsEnabled(lcp->cfg.pap))
+ lcp->want_auth = PROTO_PAP;
else {
- LogPrintf(LogLCP, "Peer will only send PAP (not enabled)\n");
- LcpInfo.his_reject |= (1 << type);
+ log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
+ lcp->his_reject |= (1 << type);
}
break;
case PROTO_CHAP:
- if (Enabled(ConfChap))
- LcpInfo.want_auth = PROTO_CHAP;
+ if (IsEnabled(lcp->cfg.chap))
+ lcp->want_auth = PROTO_CHAP;
else {
- LogPrintf(LogLCP, "Peer will only send CHAP (not enabled)\n");
- LcpInfo.his_reject |= (1 << type);
+ log_Printf(LogLCP, "Peer will only send CHAP (not enabled)\n");
+ lcp->his_reject |= (1 << type);
}
break;
default:
/* We've been NAK'd with something we don't understand :-( */
- LcpInfo.his_reject |= (1 << type);
+ lcp->his_reject |= (1 << type);
break;
}
break;
case MODE_REJ:
- LcpInfo.his_reject |= (1 << type);
+ lcp->his_reject |= (1 << type);
break;
}
break;
case TY_QUALPROTO:
- req = (struct lqrreq *) cp;
- LogPrintf(LogLCP, "%s proto %x, interval %dms\n",
- request, ntohs(req->proto), ntohl(req->period) * 10);
+ req = (struct lqrreq *)cp;
+ log_Printf(LogLCP, "%s proto %x, interval %ldms\n",
+ request, ntohs(req->proto), (long)ntohl(req->period) * 10);
switch (mode_type) {
case MODE_REQ:
- if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr))
+ if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
goto reqreject;
else {
- LcpInfo.his_lqrperiod = ntohl(req->period);
- if (LcpInfo.his_lqrperiod < 500)
- LcpInfo.his_lqrperiod = 500;
- req->period = htonl(LcpInfo.his_lqrperiod);
- memcpy(ackp, cp, length);
- ackp += length;
+ lcp->his_lqrperiod = ntohl(req->period);
+ if (lcp->his_lqrperiod < 500)
+ lcp->his_lqrperiod = 500;
+ req->period = htonl(lcp->his_lqrperiod);
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
}
break;
case MODE_NAK:
break;
case MODE_REJ:
- LcpInfo.his_reject |= (1 << type);
+ lcp->his_reject |= (1 << type);
break;
}
break;
case TY_MAGICNUM:
- lp = (u_int32_t *) (cp + 2);
- magic = ntohl(*lp);
- LogPrintf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
+ magic = ntohl(*(u_int32_t *)(cp + 2));
+ log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
switch (mode_type) {
case MODE_REQ:
- if (LcpInfo.want_magic) {
+ if (lcp->want_magic) {
/* Validate magic number */
- if (magic == LcpInfo.want_magic) {
- LogPrintf(LogLCP, "Magic is same (%08lx) - %d times\n",
- (u_long)magic, ++LcpFailedMagic);
- LcpInfo.want_magic = GenerateMagic();
- memcpy(nakp, cp, 6);
- nakp += 6;
- ualarm(TICKUNIT * (4 + 4 * LcpFailedMagic), 0);
+ if (magic == lcp->want_magic) {
+ log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
+ (u_long)magic, ++lcp->LcpFailedMagic);
+ lcp->want_magic = GenerateMagic();
+ memcpy(dec->nakend, cp, 6);
+ dec->nakend += 6;
+ ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
sigpause(0);
} else {
- LcpInfo.his_magic = magic;
- memcpy(ackp, cp, length);
- ackp += length;
- LcpFailedMagic = 0;
+ lcp->his_magic = magic;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
+ lcp->LcpFailedMagic = 0;
}
} else {
- LcpInfo.my_reject |= (1 << type);
goto reqreject;
}
break;
case MODE_NAK:
- LogPrintf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
- LcpInfo.want_magic = GenerateMagic();
+ log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
+ lcp->want_magic = GenerateMagic();
break;
case MODE_REJ:
- LogPrintf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
- LcpInfo.want_magic = 0;
- LcpInfo.his_reject |= (1 << type);
+ log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
+ lcp->want_magic = 0;
+ lcp->his_reject |= (1 << type);
break;
}
break;
case TY_PROTOCOMP:
- LogPrintf(LogLCP, "%s\n", request);
+ log_Printf(LogLCP, "%s\n", request);
switch (mode_type) {
case MODE_REQ:
- if (Acceptable(ConfProtocomp)) {
- LcpInfo.his_protocomp = 1;
- memcpy(ackp, cp, 2);
- ackp += 2;
+ if (IsAccepted(lcp->cfg.protocomp)) {
+ lcp->his_protocomp = 1;
+ memcpy(dec->ackend, cp, 2);
+ dec->ackend += 2;
} else {
#ifdef OLDMST
/*
* MorningStar before v1.3 needs NAK
*/
- memcpy(nakp, cp, 2);
- nakp += 2;
+ memcpy(dec->nakend, cp, 2);
+ dec->nakend += 2;
#else
- memcpy(rejp, cp, 2);
- rejp += 2;
- LcpInfo.my_reject |= (1 << type);
+ goto reqreject;
#endif
}
break;
case MODE_NAK:
case MODE_REJ:
- LcpInfo.want_protocomp = 0;
- LcpInfo.his_reject |= (1 << type);
+ lcp->want_protocomp = 0;
+ lcp->his_reject |= (1 << type);
break;
}
break;
case TY_ACFCOMP:
- LogPrintf(LogLCP, "%s\n", request);
+ log_Printf(LogLCP, "%s\n", request);
switch (mode_type) {
case MODE_REQ:
- if (Acceptable(ConfAcfcomp)) {
- LcpInfo.his_acfcomp = 1;
- memcpy(ackp, cp, 2);
- ackp += 2;
+ if (IsAccepted(lcp->cfg.acfcomp)) {
+ lcp->his_acfcomp = 1;
+ memcpy(dec->ackend, cp, 2);
+ dec->ackend += 2;
} else {
#ifdef OLDMST
/*
* MorningStar before v1.3 needs NAK
*/
- memcpy(nakp, cp, 2);
- nakp += 2;
+ memcpy(dec->nakend, cp, 2);
+ dec->nakend += 2;
#else
- memcpy(rejp, cp, 2);
- rejp += 2;
- LcpInfo.my_reject |= (1 << type);
+ goto reqreject;
#endif
}
break;
case MODE_NAK:
case MODE_REJ:
- LcpInfo.want_acfcomp = 0;
- LcpInfo.his_reject |= (1 << type);
+ lcp->want_acfcomp = 0;
+ lcp->his_reject |= (1 << type);
break;
}
break;
case TY_SDP:
- LogPrintf(LogLCP, "%s\n", request);
+ log_Printf(LogLCP, "%s\n", request);
+ switch (mode_type) {
+ case MODE_REQ:
+ case MODE_NAK:
+ case MODE_REJ:
+ break;
+ }
+ break;
+
+ case TY_SHORTSEQ:
+ mp = &lcp->fsm.bundle->ncp.mp;
+ log_Printf(LogLCP, "%s\n", request);
+
switch (mode_type) {
case MODE_REQ:
+ if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
+ lcp->his_shortseq = 1;
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
+ } else
+ goto reqreject;
+ break;
case MODE_NAK:
+ /*
+ * He's trying to get us to ask for short sequence numbers.
+ * We ignore the NAK and honour our configuration file instead.
+ */
+ break;
case MODE_REJ:
+ lcp->his_reject |= (1 << type);
+ lcp->want_shortseq = 0; /* For when we hit MP */
break;
}
break;
+ case TY_ENDDISC:
+ log_Printf(LogLCP, "%s %s\n", request,
+ mp_Enddisc(cp[2], cp + 3, length - 3));
+ switch (mode_type) {
+ case MODE_REQ:
+ if (!p) {
+ log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
+ goto reqreject;
+ } else if (length-3 < sizeof p->dl->peer.enddisc.address &&
+ cp[2] <= MAX_ENDDISC_CLASS) {
+ p->dl->peer.enddisc.class = cp[2];
+ p->dl->peer.enddisc.len = length-3;
+ memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
+ p->dl->peer.enddisc.address[length - 3] = '\0';
+ /* XXX: If mp->active, compare and NAK with mp->peer ? */
+ memcpy(dec->ackend, cp, length);
+ dec->ackend += length;
+ } else {
+ if (cp[2] > MAX_ENDDISC_CLASS)
+ log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
+ cp[2]);
+ else
+ log_Printf(LogLCP, " ENDDISC rejected - local max length is %d\n",
+ sizeof p->dl->peer.enddisc.address - 1);
+ goto reqreject;
+ }
+ break;
+
+ case MODE_NAK: /* Treat this as a REJ, we don't vary or disc */
+ case MODE_REJ:
+ lcp->his_reject |= (1 << type);
+ break;
+ }
+ break;
+
default:
sz = (sizeof desc - 2) / 2;
if (sz > length - 2)
@@ -801,35 +850,41 @@ LcpDecodeConfig(u_char *cp, int plen, int mode_type)
for (pos = 0; sz--; pos++)
sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
- LogPrintf(LogLCP, "%s%s\n", request, desc);
+ log_Printf(LogLCP, "%s%s\n", request, desc);
if (mode_type == MODE_REQ) {
reqreject:
- if (length > sizeof RejBuff - (rejp - RejBuff)) {
- length = sizeof RejBuff - (rejp - RejBuff);
- LogPrintf(LogLCP, "Can't REJ length %d - trunating to %d\n",
+ if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
+ length = sizeof dec->rej - (dec->rejend - dec->rej);
+ log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
cp[1], length);
}
- memcpy(rejp, cp, length);
- rejp += length;
- LcpInfo.my_reject |= (1 << type);
+ memcpy(dec->rejend, cp, length);
+ dec->rejend += length;
+ lcp->my_reject |= (1 << type);
if (length != cp[1])
- return;
+ length = 0; /* force our way out of the loop */
}
break;
}
- /* to avoid inf. loop */
- if (length == 0) {
- LogPrintf(LogLCP, "LCP size zero\n");
- break;
- }
plen -= length;
cp += length;
}
+
+ if (mode_type != MODE_NOP) {
+ if (dec->rejend != dec->rej) {
+ /* rejects are preferred */
+ dec->ackend = dec->ack;
+ dec->nakend = dec->nak;
+ } else if (dec->nakend != dec->nak)
+ /* then NAKs */
+ dec->ackend = dec->ack;
+ }
}
void
-LcpInput(struct mbuf * bp)
+lcp_Input(struct lcp *lcp, struct mbuf * bp)
{
- FsmInput(&LcpFsm, bp);
+ /* Got PROTO_LCP from link */
+ fsm_Input(&lcp->fsm, bp);
}
diff --git a/usr.sbin/ppp/lcp.h b/usr.sbin/ppp/lcp.h
index 5c594f8a6e28..69ef41c8207a 100644
--- a/usr.sbin/ppp/lcp.h
+++ b/usr.sbin/ppp/lcp.h
@@ -15,38 +15,60 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: lcp.h,v 1.15 1997/12/04 18:49:28 brian Exp $
+ * $Id: lcp.h,v 1.16.2.23 1998/05/01 19:24:57 brian Exp $
*
* TODO:
*/
#define REJECTED(p, x) ((p)->his_reject & (1<<(x)))
-struct lcpstate {
- u_int16_t his_mru;
- u_int32_t his_accmap;
- u_int32_t his_magic;
- u_int32_t his_lqrperiod;
- u_char his_protocomp;
- u_char his_acfcomp;
- u_short his_auth;
-
- u_short want_mru;
- u_int32_t want_accmap;
- u_int32_t want_magic;
- u_int32_t want_lqrperiod;
- u_char want_protocomp;
- u_char want_acfcomp;
- u_short want_auth;
+struct lcp {
+ struct fsm fsm; /* The finite state machine */
+ u_int16_t his_mru; /* Peers maximum packet size */
+ u_int16_t his_mrru; /* Peers maximum reassembled packet size (MP) */
+ u_int32_t his_accmap; /* Peeers async char control map */
+ u_int32_t his_magic; /* Peers magic number */
+ u_int32_t his_lqrperiod; /* Peers LQR frequency */
+ u_short his_auth; /* Peer wants this type of authentication */
+ unsigned his_shortseq : 1; /* Peer would like only 12bit seqs (MP) */
+ unsigned his_protocomp : 1; /* Does peer do Protocol field compression */
+ unsigned his_acfcomp : 1; /* Does peer do addr & cntrl fld compression */
+
+ u_short want_mru; /* Our maximum packet size */
+ u_short want_mrru; /* Our maximum reassembled packet size (MP) */
+ u_int32_t want_accmap; /* Our async char control map */
+ u_int32_t want_magic; /* Our magic number */
+ u_int32_t want_lqrperiod; /* Our LQR frequency */
+ u_short want_auth; /* We want this type of authentication */
+ unsigned want_shortseq : 1; /* I'd like only 12bit seqs (MP) */
+ unsigned want_protocomp : 1; /* Do we do protocol field compression */
+ unsigned want_acfcomp : 1; /* Do we do addr & cntrl fld compression */
u_int32_t his_reject; /* Request codes rejected by peer */
u_int32_t my_reject; /* Request codes I have rejected */
- u_short auth_iwait;
- u_short auth_ineed;
+ u_short auth_iwait; /* I must authenticate to the peer */
+ u_short auth_ineed; /* I require that the peer authenticates */
+
+ int LcpFailedMagic; /* Number of `magic is same' errors */
+
+ struct {
+ u_short mru; /* Preferred MRU value */
+ u_int32_t accmap; /* Initial ACCMAP value */
+ int openmode; /* when to start CFG REQs */
+ u_int lqrperiod; /* LQR frequency */
+ u_int fsmretry; /* FSM retry frequency */
+
+ unsigned acfcomp : 2; /* Address & Control Field Compression neg */
+ unsigned chap : 2; /* Challenge Handshake Authentication proto */
+ unsigned lqr : 2; /* Link Quality Report */
+ unsigned pap : 2; /* Password Authentication protocol */
+ unsigned protocomp : 2; /* Protocol field compression */
+ } cfg;
};
#define LCP_MAXCODE CODE_DISCREQ
+#define LCP_MINMPCODE CODE_CODEREJ
#define TY_MRU 1 /* Maximum-Receive-Unit */
#define TY_ACCMAP 2 /* Async-Control-Character-Map */
@@ -58,6 +80,9 @@ struct lcpstate {
#define TY_ACFCOMP 8 /* Address-and-Control-Field-Compression */
#define TY_FCSALT 9 /* FCS-Alternatives */
#define TY_SDP 10 /* Self-Describing-Padding */
+#define TY_MRRU 17 /* Max Reconstructed Receive Unit (MP) */
+#define TY_SHORTSEQ 18 /* Want short seqs (12bit) please (see mp.h) */
+#define TY_ENDDISC 19 /* Endpoint discriminator */
#define MAX_LCP_OPT_LEN 10
struct lcp_opt {
@@ -66,17 +91,26 @@ struct lcp_opt {
u_char data[MAX_LCP_OPT_LEN-2];
};
+#define INC_LCP_OPT(ty, length, o) \
+ do { \
+ (o)->id = (ty); \
+ (o)->len = (length); \
+ (o) = (struct lcp_opt *)((char *)(o) + (length)); \
+ } while (0)
+
+struct mbuf;
+struct link;
+struct physical;
+struct bundle;
+struct cmdargs;
+
+#define fsm2lcp(fp) (fp->proto == PROTO_LCP ? (struct lcp *)fp : NULL)
-extern struct lcpstate LcpInfo;
-extern struct fsm LcpFsm;
+extern void lcp_Init(struct lcp *, struct bundle *, struct link *,
+ const struct fsm_parent *);
+extern void lcp_Setup(struct lcp *, int);
-extern void LcpInit(void);
-extern void LcpUp(void);
-extern void LcpSendProtoRej(u_char *, int);
-extern void LcpOpen(int);
-extern void LcpClose(void);
-extern void LcpDown(void);
-extern int LcpPutConf(int, u_char *, const struct lcp_opt *, const char *,
- const char *, ...);
-extern int ReportLcpStatus(struct cmdargs const *);
-extern void LcpInput(struct mbuf *);
+extern void lcp_SendProtoRej(struct lcp *, u_char *, int);
+extern int lcp_ReportStatus(struct cmdargs const *);
+extern void lcp_Input(struct lcp *, struct mbuf *);
+extern void lcp_SetupCallbacks(struct lcp *);
diff --git a/usr.sbin/ppp/lcpproto.h b/usr.sbin/ppp/lcpproto.h
index 74c5d4d51577..8f15fe6c6c8e 100644
--- a/usr.sbin/ppp/lcpproto.h
+++ b/usr.sbin/ppp/lcpproto.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: lcpproto.h,v 1.9 1997/10/26 01:02:59 brian Exp $
+ * $Id: lcpproto.h,v 1.10.2.2 1998/05/15 18:21:07 brian Exp $
*
* TODO:
*/
@@ -26,9 +26,12 @@
#define PROTO_IP 0x0021 /* IP */
#define PROTO_VJUNCOMP 0x002f /* VJ Uncompressed */
#define PROTO_VJCOMP 0x002d /* VJ Compressed */
+#define PROTO_MP 0x003d /* Multilink fragment */
#define PROTO_ICOMPD 0x00fb /* Individual link compressed */
#define PROTO_COMPD 0x00fd /* Compressed datagram */
+#define PROTO_COMPRESSIBLE(p) (((p) & 0xffe1) == 0x21)
+
#define PROTO_IPCP 0x8021
#define PROTO_ICCP 0x80fb
#define PROTO_CCP 0x80fd
diff --git a/usr.sbin/ppp/link.c b/usr.sbin/ppp/link.c
new file mode 100644
index 000000000000..ead0e142d255
--- /dev/null
+++ b/usr.sbin/ppp/link.c
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: link.c,v 1.1.2.20 1998/05/01 19:24:59 brian Exp $
+ *
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <termios.h>
+
+#include "mbuf.h"
+#include "log.h"
+#include "timer.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "throughput.h"
+#include "lcpproto.h"
+#include "fsm.h"
+#include "descriptor.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "prompt.h"
+
+void
+link_AddInOctets(struct link *l, int n)
+{
+ throughput_addin(&l->throughput, n);
+}
+
+void
+link_AddOutOctets(struct link *l, int n)
+{
+ throughput_addout(&l->throughput, n);
+}
+
+void
+link_SequenceQueue(struct link *l)
+{
+ log_Printf(LogDEBUG, "link_SequenceQueue\n");
+ while (l->Queue[PRI_NORMAL].qlen)
+ mbuf_Enqueue(l->Queue + PRI_LINK, mbuf_Dequeue(l->Queue + PRI_NORMAL));
+}
+
+int
+link_QueueLen(struct link *l)
+{
+ int i, len;
+
+ for (i = 0, len = 0; i < LINK_QUEUES; i++)
+ len += l->Queue[i].qlen;
+
+ return len;
+}
+
+int
+link_QueueBytes(struct link *l)
+{
+ int i, len, bytes;
+ struct mbuf *m;
+
+ bytes = 0;
+ for (i = 0, len = 0; i < LINK_QUEUES; i++) {
+ len = l->Queue[i].qlen;
+ m = l->Queue[i].top;
+ while (len--) {
+ bytes += mbuf_Length(m);
+ m = m->pnext;
+ }
+ }
+
+ return bytes;
+}
+
+struct mbuf *
+link_Dequeue(struct link *l)
+{
+ int pri;
+ struct mbuf *bp;
+
+ for (bp = (struct mbuf *)0, pri = LINK_QUEUES - 1; pri >= 0; pri--)
+ if (l->Queue[pri].qlen) {
+ bp = mbuf_Dequeue(l->Queue + pri);
+ log_Printf(LogDEBUG, "link_Dequeue: Dequeued from queue %d,"
+ " containing %d more packets\n", pri, l->Queue[pri].qlen);
+ break;
+ }
+
+ return bp;
+}
+
+/*
+ * Write to the link. Actualy, requested packets are queued, and go out
+ * at some later time depending on the physical link implementation.
+ */
+void
+link_Write(struct link *l, int pri, const char *ptr, int count)
+{
+ struct mbuf *bp;
+
+ if(pri < 0 || pri >= LINK_QUEUES)
+ pri = 0;
+
+ bp = mbuf_Alloc(count, MB_LINK);
+ memcpy(MBUF_CTOP(bp), ptr, count);
+
+ mbuf_Enqueue(l->Queue + pri, bp);
+}
+
+void
+link_Output(struct link *l, int pri, struct mbuf *bp)
+{
+ struct mbuf *wp;
+ int len;
+
+ if(pri < 0 || pri >= LINK_QUEUES)
+ pri = 0;
+
+ len = mbuf_Length(bp);
+ wp = mbuf_Alloc(len, MB_LINK);
+ mbuf_Read(bp, MBUF_CTOP(wp), len);
+ mbuf_Enqueue(l->Queue + pri, wp);
+}
+
+static struct protostatheader {
+ u_short number;
+ const char *name;
+} ProtocolStat[NPROTOSTAT] = {
+ { PROTO_IP, "IP" },
+ { PROTO_VJUNCOMP, "VJ_UNCOMP" },
+ { PROTO_VJCOMP, "VJ_COMP" },
+ { PROTO_COMPD, "COMPD" },
+ { PROTO_ICOMPD, "ICOMPD" },
+ { PROTO_LCP, "LCP" },
+ { PROTO_IPCP, "IPCP" },
+ { PROTO_CCP, "CCP" },
+ { PROTO_PAP, "PAP" },
+ { PROTO_LQR, "LQR" },
+ { PROTO_CHAP, "CHAP" },
+ { PROTO_MP, "MULTILINK" },
+ { 0, "Others" }
+};
+
+void
+link_ProtocolRecord(struct link *l, u_short proto, int type)
+{
+ int i;
+
+ for (i = 0; i < NPROTOSTAT; i++)
+ if (ProtocolStat[i].number == proto)
+ break;
+
+ if (type == PROTO_IN)
+ l->proto_in[i]++;
+ else
+ l->proto_out[i]++;
+}
+
+void
+link_ReportProtocolStatus(struct link *l, struct prompt *prompt)
+{
+ int i;
+
+ prompt_Printf(prompt, " Protocol in out "
+ "Protocol in out\n");
+ for (i = 0; i < NPROTOSTAT; i++) {
+ prompt_Printf(prompt, " %-9s: %8lu, %8lu",
+ ProtocolStat[i].name, l->proto_in[i], l->proto_out[i]);
+ if ((i % 2) == 0)
+ prompt_Printf(prompt, "\n");
+ }
+ if (!(i % 2))
+ prompt_Printf(prompt, "\n");
+}
diff --git a/usr.sbin/ppp/link.h b/usr.sbin/ppp/link.h
new file mode 100644
index 000000000000..5186b00e7a60
--- /dev/null
+++ b/usr.sbin/ppp/link.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: link.h,v 1.1.2.11 1998/04/24 19:15:26 brian Exp $
+ *
+ */
+
+
+#define PHYSICAL_LINK 1
+#define MP_LINK 2
+
+#define LINK_QUEUES (PRI_MAX + 1)
+#define NPROTOSTAT 13
+
+struct bundle;
+struct prompt;
+
+struct link {
+ int type; /* _LINK type */
+ const char *name; /* unique id per link type */
+ int len; /* full size of parent struct */
+ struct pppThroughput throughput; /* Link throughput statistics */
+ struct mqueue Queue[LINK_QUEUES]; /* Our output queue of mbufs */
+
+ u_long proto_in[NPROTOSTAT]; /* outgoing protocol stats */
+ u_long proto_out[NPROTOSTAT]; /* incoming protocol stats */
+
+ struct lcp lcp; /* Our line control FSM */
+ struct ccp ccp; /* Our compression FSM */
+};
+
+extern void link_AddInOctets(struct link *, int);
+extern void link_AddOutOctets(struct link *, int);
+
+extern void link_SequenceQueue(struct link *);
+extern int link_QueueLen(struct link *);
+extern int link_QueueBytes(struct link *);
+extern struct mbuf *link_Dequeue(struct link *);
+extern void link_Write(struct link *, int, const char *, int);
+extern void link_StartOutput(struct link *, struct bundle *);
+extern void link_Output(struct link *, int, struct mbuf *);
+
+#define PROTO_IN 1 /* third arg to link_ProtocolRecord */
+#define PROTO_OUT 2
+extern void link_ProtocolRecord(struct link *, u_short, int);
+extern void link_ReportProtocolStatus(struct link *, struct prompt *);
diff --git a/usr.sbin/ppp/loadalias.c b/usr.sbin/ppp/loadalias.c
index 6834a7b3cf34..f6d306f2ffb0 100644
--- a/usr.sbin/ppp/loadalias.c
+++ b/usr.sbin/ppp/loadalias.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: loadalias.c,v 1.14 1998/01/19 22:59:57 brian Exp $
+ * $Id: loadalias.c,v 1.14.2.5 1998/05/01 19:25:01 brian Exp $
*/
#include <sys/param.h>
@@ -34,22 +34,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/socket.h>
#include <unistd.h>
-#include "command.h"
-#include "mbuf.h"
#include "log.h"
-#include "systems.h"
#include "id.h"
#include "loadalias.h"
-#include "defs.h"
-#include "vars.h"
#define _PATH_ALIAS_PREFIX "/usr/lib/libalias.so.2."
#define off(item) ((int)&(((struct aliasHandlers *)0)->item))
-#define entry(a) { off(a), "_" #a }
+#define entry(a) { off(a), "_PacketAlias" #a }
#ifndef RTLD_NOW
#define RTLD_NOW 1 /* really RTLD_LAZY */
@@ -59,48 +53,51 @@ static struct {
int offset;
const char *name;
} map[] = {
- entry(PacketAliasGetFragment),
- entry(PacketAliasInit),
- entry(PacketAliasIn),
- entry(PacketAliasOut),
- entry(PacketAliasRedirectAddr),
- entry(PacketAliasRedirectPort),
- entry(PacketAliasSaveFragment),
- entry(PacketAliasSetAddress),
- entry(PacketAliasSetMode),
- entry(PacketAliasFragmentIn),
+ entry(GetFragment),
+ entry(Init),
+ entry(In),
+ entry(Out),
+ entry(RedirectAddr),
+ entry(RedirectPort),
+ entry(SaveFragment),
+ entry(SetAddress),
+ entry(SetMode),
+ entry(FragmentIn),
{ 0, 0 }
};
-static void *dl;
+struct aliasHandlers PacketAlias;
int
-loadAliasHandlers(struct aliasHandlers * h)
+alias_Load()
{
const char *path;
const char *env;
int i;
+ if (PacketAlias.dl)
+ return 0;
+
path = _PATH_ALIAS_PREFIX;
env = getenv("_PATH_ALIAS_PREFIX");
if (env) {
if (ID0realuid() == 0)
path = env;
else
- LogPrintf(LogALERT, "Ignoring environment _PATH_ALIAS_PREFIX"
+ log_Printf(LogALERT, "Ignoring environment _PATH_ALIAS_PREFIX"
" value (%s)\n", env);
}
- dl = dlopen(path, RTLD_NOW);
- if (dl == (void *) 0) {
+ PacketAlias.dl = dlopen(path, RTLD_NOW);
+ if (PacketAlias.dl == (void *) 0) {
/* Look for _PATH_ALIAS_PREFIX with any number appended */
int plen;
plen = strlen(path);
if (plen && plen < MAXPATHLEN - 1 && path[plen-1] == '.') {
DIR *d;
- char p[MAXPATHLEN], *fix;
- char *file, *dir;
+ char p[MAXPATHLEN], *fix, *file;
+ const char *dir;
strcpy(p, path);
if ((file = strrchr(p, '/')) != NULL) {
@@ -134,37 +131,37 @@ loadAliasHandlers(struct aliasHandlers * h)
if (maxver > -1) {
sprintf(p + plen, "%ld", maxver);
- dl = dlopen(p, RTLD_NOW);
+ PacketAlias.dl = dlopen(p, RTLD_NOW);
}
}
}
- if (dl == (void *) 0) {
- LogPrintf(LogWARN, "_PATH_ALIAS_PREFIX (%s*): Invalid lib: %s\n",
+ if (PacketAlias.dl == (void *) 0) {
+ log_Printf(LogWARN, "_PATH_ALIAS_PREFIX (%s*): Invalid lib: %s\n",
path, dlerror());
return -1;
}
}
for (i = 0; map[i].name; i++) {
- *(void **) ((char *) h + map[i].offset) = dlsym(dl, map[i].name);
- if (*(void **) ((char *) h + map[i].offset) == (void *) 0) {
- LogPrintf(LogWARN, "_PATH_ALIAS (%s*): %s: %s\n", path,
+ *(void **)((char *)&PacketAlias + map[i].offset) =
+ dlsym(PacketAlias.dl, map[i].name);
+ if (*(void **)((char *)&PacketAlias + map[i].offset) == (void *)0) {
+ log_Printf(LogWARN, "_PATH_ALIAS (%s*): %s: %s\n", path,
map[i].name, dlerror());
- (void) dlclose(dl);
- dl = (void *) 0;
+ alias_Unload();
return -1;
}
}
- VarPacketAliasInit();
+ (*PacketAlias.Init)();
return 0;
}
void
-unloadAliasHandlers()
+alias_Unload()
{
- if (dl) {
- dlclose(dl);
- dl = (void *) 0;
+ if (PacketAlias.dl) {
+ dlclose(PacketAlias.dl);
+ memset(&PacketAlias, '\0', sizeof PacketAlias);
}
}
diff --git a/usr.sbin/ppp/loadalias.h b/usr.sbin/ppp/loadalias.h
index 0fec74ea97aa..c30346f6946f 100644
--- a/usr.sbin/ppp/loadalias.h
+++ b/usr.sbin/ppp/loadalias.h
@@ -23,23 +23,27 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: loadalias.h,v 1.4.2.3 1998/05/01 19:25:03 brian Exp $
*/
struct aliasHandlers {
- char *(*PacketAliasGetFragment)(char *);
- void (*PacketAliasInit)(void);
- int (*PacketAliasIn)(char *, int);
- int (*PacketAliasOut)(char *, int);
- struct alias_link *(*PacketAliasRedirectAddr)(struct in_addr, struct in_addr);
- struct alias_link *(*PacketAliasRedirectPort)
- (struct in_addr, u_short, struct in_addr, u_short,
- struct in_addr, u_short, u_char);
- int (*PacketAliasSaveFragment)(char *);
- void (*PacketAliasSetAddress)(struct in_addr);
- unsigned (*PacketAliasSetMode)(unsigned, unsigned);
- void (*PacketAliasFragmentIn)(char *, char *);
+ void *dl;
+
+ char *(*GetFragment)(char *);
+ void (*Init)(void);
+ int (*In)(char *, int);
+ int (*Out)(char *, int);
+ struct alias_link *(*RedirectAddr)(struct in_addr, struct in_addr);
+ struct alias_link *(*RedirectPort)(struct in_addr, u_short, struct in_addr,
+ u_short, struct in_addr, u_short, u_char);
+ int (*SaveFragment)(char *);
+ void (*SetAddress)(struct in_addr);
+ unsigned (*SetMode)(unsigned, unsigned);
+ void (*FragmentIn)(char *, char *);
};
-extern int loadAliasHandlers(struct aliasHandlers *);
-extern void unloadAliasHandlers(void);
+extern struct aliasHandlers PacketAlias;
+
+#define alias_IsEnabled() (PacketAlias.dl ? 1 : 0)
+extern int alias_Load(void);
+extern void alias_Unload(void);
diff --git a/usr.sbin/ppp/log.c b/usr.sbin/ppp/log.c
index 77729dd4e76a..0522059cd883 100644
--- a/usr.sbin/ppp/log.c
+++ b/usr.sbin/ppp/log.c
@@ -23,27 +23,25 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: log.c,v 1.25 1998/01/21 02:15:18 brian Exp $
+ * $Id: log.c,v 1.25.2.14 1998/05/01 22:39:35 brian Exp $
*/
-#include <sys/param.h>
-#include <netinet/in.h>
+#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
+#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
-#include "loadalias.h"
-#include "defs.h"
-#include "vars.h"
+#include "descriptor.h"
+#include "prompt.h"
static const char *LogNames[] = {
"Async",
- "Carrier",
"CCP",
"Chat",
"Command",
@@ -53,10 +51,10 @@ static const char *LogNames[] = {
"ID0",
"IPCP",
"LCP",
- "Link",
"LQM",
"Phase",
"TCP/IP",
+ "Timer",
"Tun",
"Warning",
"Error",
@@ -65,15 +63,54 @@ static const char *LogNames[] = {
#define MSK(n) (1<<((n)-1))
-static u_long LogMask = MSK(LogLINK) | MSK(LogCARRIER) | MSK(LogPHASE);
+static u_long LogMask = MSK(LogPHASE);
static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
static int LogTunno = -1;
+static struct prompt *logprompt; /* Where to log local stuff */
+
+void
+log_RegisterPrompt(struct prompt *prompt)
+{
+ if (prompt) {
+ prompt->lognext = logprompt;
+ logprompt = prompt;
+ LogMaskLocal |= prompt->logmask;
+ }
+}
+
+static void
+LogSetMaskLocal(void)
+{
+ struct prompt *p;
+
+ LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
+ for (p = logprompt; p; p = p->lognext)
+ LogMaskLocal |= p->logmask;
+}
+
+void
+log_UnRegisterPrompt(struct prompt *prompt)
+{
+ if (prompt) {
+ struct prompt **p;
+
+ for (p = &logprompt; *p; p = &(*p)->lognext)
+ if (*p == prompt) {
+ *p = prompt->lognext;
+ prompt->lognext = NULL;
+ break;
+ }
+ LogSetMaskLocal();
+ }
+}
static int
syslogLevel(int lev)
{
switch (lev) {
- case LogDEBUG:return LOG_DEBUG;
+ case LogDEBUG:
+ case LogTIMER:
+ return LOG_DEBUG;
case LogWARN:
return LOG_WARNING;
case LogERROR:
@@ -85,53 +122,58 @@ syslogLevel(int lev)
}
const char *
-LogName(int id)
+log_Name(int id)
{
return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
}
void
-LogKeep(int id)
+log_Keep(int id)
{
if (id >= LogMIN && id <= LogMAXCONF)
LogMask |= MSK(id);
}
void
-LogKeepLocal(int id)
+log_KeepLocal(int id, u_long *mask)
{
- if (id >= LogMIN && id <= LogMAXCONF)
+ if (id >= LogMIN && id <= LogMAXCONF) {
LogMaskLocal |= MSK(id);
+ *mask |= MSK(id);
+ }
}
void
-LogDiscard(int id)
+log_Discard(int id)
{
if (id >= LogMIN && id <= LogMAXCONF)
LogMask &= ~MSK(id);
}
void
-LogDiscardLocal(int id)
+log_DiscardLocal(int id, u_long *mask)
{
- if (id >= LogMIN && id <= LogMAXCONF)
- LogMaskLocal &= ~MSK(id);
+ if (id >= LogMIN && id <= LogMAXCONF) {
+ *mask &= ~MSK(id);
+ LogSetMaskLocal();
+ }
}
void
-LogDiscardAll()
+log_DiscardAll()
{
LogMask = 0;
}
void
-LogDiscardAllLocal()
+log_DiscardAllLocal(u_long *mask)
{
- LogMaskLocal = 0;
+ *mask = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
+ LogSetMaskLocal();
}
int
-LogIsKept(int id)
+log_IsKept(int id)
{
if (id < LogMIN || id > LogMAX)
return 0;
@@ -142,50 +184,65 @@ LogIsKept(int id)
((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
}
+int
+log_IsKeptLocal(int id, u_long mask)
+{
+ if (id < LogMIN || id > LogMAX)
+ return 0;
+ if (id > LogMAXCONF)
+ return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
+
+ return ((mask & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
+ ((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
+}
+
void
-LogOpen(const char *Name)
+log_Open(const char *Name)
{
openlog(Name, LOG_PID, LOG_DAEMON);
}
void
-LogSetTun(int tunno)
+log_SetTun(int tunno)
{
LogTunno = tunno;
}
void
-LogClose()
+log_Close()
{
closelog();
LogTunno = -1;
}
void
-LogPrintf(int lev, const char *fmt,...)
+log_Printf(int lev, const char *fmt,...)
{
va_list ap;
+ struct prompt *prompt;
va_start(ap, fmt);
- if (LogIsKept(lev)) {
+ if (log_IsKept(lev)) {
static char nfmt[200];
- if ((LogIsKept(lev) & LOG_KEPT_LOCAL) && VarTerm) {
- if ((LogIsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
+ if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && logprompt) {
+ if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s",
- LogTunno, LogName(lev), fmt);
+ LogTunno, log_Name(lev), fmt);
else
- snprintf(nfmt, sizeof nfmt, "%s: %s", LogName(lev), fmt);
- vfprintf(VarTerm, nfmt, ap);
- fflush(VarTerm);
+ snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
+
+ for (prompt = logprompt; prompt; prompt = prompt->lognext)
+ if (lev > LogMAXCONF || (prompt->logmask & MSK(lev)))
+ prompt_vPrintf(prompt, nfmt, ap);
}
- if ((LogIsKept(lev) & LOG_KEPT_SYSLOG) && (lev != LogWARN || !VarTerm)) {
- if ((LogIsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
+ if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) && (lev != LogWARN || !logprompt)) {
+ if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s",
- LogTunno, LogName(lev), fmt);
+ LogTunno, log_Name(lev), fmt);
else
- snprintf(nfmt, sizeof nfmt, "%s: %s", LogName(lev), fmt);
+ snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt);
vsyslog(syslogLevel(lev), nfmt, ap);
}
}
@@ -193,16 +250,16 @@ LogPrintf(int lev, const char *fmt,...)
}
void
-LogDumpBp(int lev, const char *hdr, const struct mbuf * bp)
+log_DumpBp(int lev, const char *hdr, const struct mbuf * bp)
{
- if (LogIsKept(lev)) {
+ if (log_IsKept(lev)) {
char buf[50];
char *b;
u_char *ptr;
int f;
if (hdr && *hdr)
- LogPrintf(lev, "%s\n", hdr);
+ log_Printf(lev, "%s\n", hdr);
b = buf;
do {
@@ -213,7 +270,7 @@ LogDumpBp(int lev, const char *hdr, const struct mbuf * bp)
b += 3;
if (b == buf + sizeof buf - 2) {
strcpy(b, "\n");
- LogPrintf(lev, buf);
+ log_Printf(lev, buf);
b = buf;
}
}
@@ -221,26 +278,116 @@ LogDumpBp(int lev, const char *hdr, const struct mbuf * bp)
if (b > buf) {
strcpy(b, "\n");
- LogPrintf(lev, buf);
+ log_Printf(lev, buf);
}
}
}
void
-LogDumpBuff(int lev, const char *hdr, const u_char * ptr, int n)
+log_DumpBuff(int lev, const char *hdr, const u_char * ptr, int n)
{
- if (LogIsKept(lev)) {
+ if (log_IsKept(lev)) {
char buf[50];
char *b;
if (hdr && *hdr)
- LogPrintf(lev, "%s\n", hdr);
+ log_Printf(lev, "%s\n", hdr);
while (n > 0) {
b = buf;
for (b = buf; b != buf + sizeof buf - 2 && n--; b += 3)
sprintf(b, " %02x", (int) *ptr++);
strcpy(b, "\n");
- LogPrintf(lev, buf);
+ log_Printf(lev, buf);
}
}
}
+
+int
+log_ShowLevel(struct cmdargs const *arg)
+{
+ int i;
+
+ prompt_Printf(arg->prompt, "Log: ");
+ for (i = LogMIN; i <= LogMAX; i++)
+ if (log_IsKept(i) & LOG_KEPT_SYSLOG)
+ prompt_Printf(arg->prompt, " %s", log_Name(i));
+
+ prompt_Printf(arg->prompt, "\nLocal:");
+ for (i = LogMIN; i <= LogMAX; i++)
+ if (log_IsKeptLocal(i, arg->prompt->logmask) & LOG_KEPT_LOCAL)
+ prompt_Printf(arg->prompt, " %s", log_Name(i));
+
+ prompt_Printf(arg->prompt, "\n");
+
+ return 0;
+}
+
+int
+log_SetLevel(struct cmdargs const *arg)
+{
+ int i, res, argc, local;
+ char const *const *argv, *argp;
+
+ argc = arg->argc - arg->argn;
+ argv = arg->argv + arg->argn;
+ res = 0;
+
+ if (argc == 0 || strcasecmp(argv[0], "local"))
+ local = 0;
+ else {
+ if (arg->prompt == NULL) {
+ log_Printf(LogWARN, "set log local: Only available on the command line\n");
+ return 1;
+ }
+ argc--;
+ argv++;
+ local = 1;
+ }
+
+ if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-')) {
+ if (local)
+ log_DiscardAllLocal(&arg->prompt->logmask);
+ else
+ log_DiscardAll();
+ }
+
+ while (argc--) {
+ argp = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
+ for (i = LogMIN; i <= LogMAX; i++)
+ if (strcasecmp(argp, log_Name(i)) == 0) {
+ if (**argv == '-') {
+ if (local)
+ log_DiscardLocal(i, &arg->prompt->logmask);
+ else
+ log_Discard(i);
+ } else if (local)
+ log_KeepLocal(i, &arg->prompt->logmask);
+ else
+ log_Keep(i);
+ break;
+ }
+ if (i > LogMAX) {
+ log_Printf(LogWARN, "%s: Invalid log value\n", argp);
+ res = -1;
+ }
+ argv++;
+ }
+ return res;
+}
+
+int
+log_ShowWho(struct cmdargs const *arg)
+{
+ struct prompt *p;
+
+ for (p = logprompt; p; p = p->lognext) {
+ prompt_Printf(arg->prompt, "%s (%s)", p->src.type, p->src.from);
+ if (p == arg->prompt)
+ prompt_Printf(arg->prompt, " *");
+ if (!p->active)
+ prompt_Printf(arg->prompt, " ^Z");
+ prompt_Printf(arg->prompt, "\n");
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/ppp/log.h b/usr.sbin/ppp/log.h
index 875159ed20b6..4e34ee1eb75e 100644
--- a/usr.sbin/ppp/log.h
+++ b/usr.sbin/ppp/log.h
@@ -23,46 +23,60 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: log.h,v 1.18.2.8 1998/05/01 22:39:37 brian Exp $
*/
#define LogMIN (1)
#define LogASYNC (1) /* syslog(LOG_INFO, ....) */
-#define LogCARRIER (2)
-#define LogCCP (3)
-#define LogCHAT (4)
-#define LogCOMMAND (5)
-#define LogCONNECT (6)
-#define LogDEBUG (7) /* syslog(LOG_DEBUG, ....) */
-#define LogHDLC (8)
-#define LogID0 (9)
-#define LogIPCP (10)
-#define LogLCP (11)
-#define LogLINK (12)
-#define LogLQM (13)
-#define LogPHASE (14)
-#define LogTCPIP (15)
-#define LogTUN (16) /* If set, tun%d is output with each message */
-#define LogMAXCONF (16)
-#define LogWARN (17) /* Sent to VarTerm else syslog(LOG_WARNING, ) */
-#define LogERROR (18) /* syslog(LOG_ERR, ....), + sent to VarTerm */
-#define LogALERT (19) /* syslog(LOG_ALERT, ....) */
-#define LogMAX (19)
+#define LogCCP (2)
+#define LogCHAT (3)
+#define LogCOMMAND (4)
+#define LogCONNECT (5)
+#define LogDEBUG (6) /* syslog(LOG_DEBUG, ....) */
+#define LogHDLC (7)
+#define LogID0 (8)
+#define LogIPCP (9)
+#define LogLCP (10)
+#define LogLQM (11)
+#define LogPHASE (12)
+#define LogTCPIP (13)
+#define LogTIMER (14) /* syslog(LOG_DEBUG, ....) */
+#define LogTUN (15) /* If set, tun%d is output with each message */
+#define LogMAXCONF (15)
+#define LogWARN (16) /* Sent to VarTerm else syslog(LOG_WARNING, ) */
+#define LogERROR (17) /* syslog(LOG_ERR, ....), + sent to VarTerm */
+#define LogALERT (18) /* syslog(LOG_ALERT, ....) */
+#define LogMAX (18)
+
+struct mbuf;
+struct cmdargs;
+struct prompt;
/* The first int arg for all of the following is one of the above values */
-extern const char *LogName(int);
-extern void LogKeep(int);
-extern void LogKeepLocal(int);
-extern void LogDiscard(int);
-extern void LogDiscardLocal(int);
-extern void LogDiscardAll(void);
-extern void LogDiscardAllLocal(void);
-#define LOG_KEPT_SYSLOG (1) /* Results of LogIsKept() */
-#define LOG_KEPT_LOCAL (2) /* Results of LogIsKept() */
-extern int LogIsKept(int);
-extern void LogOpen(const char *);
-extern void LogSetTun(int);
-extern void LogClose(void);
-extern void LogPrintf(int, const char *,...);
-extern void LogDumpBp(int, const char *, const struct mbuf *);
-extern void LogDumpBuff(int, const char *, const u_char *, int);
+extern const char *log_Name(int);
+extern void log_Keep(int);
+extern void log_KeepLocal(int, u_long *);
+extern void log_Discard(int);
+extern void log_DiscardLocal(int, u_long *);
+extern void log_DiscardAll(void);
+extern void log_DiscardAllLocal(u_long *);
+#define LOG_KEPT_SYSLOG (1) /* Results of log_IsKept() */
+#define LOG_KEPT_LOCAL (2) /* Results of log_IsKept() */
+extern int log_IsKept(int);
+extern int log_IsKeptLocal(int, u_long);
+extern void log_Open(const char *);
+extern void log_SetTun(int);
+extern void log_Close(void);
+#ifdef __GNUC__
+extern void log_Printf(int, const char *,...)
+ __attribute__ ((format (printf, 2, 3)));
+#else
+extern void log_Printf(int, const char *,...);
+#endif
+extern void log_DumpBp(int, const char *, const struct mbuf *);
+extern void log_DumpBuff(int, const char *, const u_char *, int);
+extern void log_RegisterPrompt(struct prompt *);
+extern void log_UnRegisterPrompt(struct prompt *);
+extern int log_ShowLevel(struct cmdargs const *);
+extern int log_SetLevel(struct cmdargs const *);
+extern int log_ShowWho(struct cmdargs const *);
diff --git a/usr.sbin/ppp/lqr.c b/usr.sbin/ppp/lqr.c
index d83c6c511078..0d633229257a 100644
--- a/usr.sbin/ppp/lqr.c
+++ b/usr.sbin/ppp/lqr.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: lqr.c,v 1.23 1998/03/12 02:23:40 brian Exp $
+ * $Id: lqr.c,v 1.22.2.30 1998/05/08 01:15:08 brian Exp $
*
* o LQR based on RFC1333
*
@@ -25,36 +25,34 @@
* o LQM policy
* o Allow user to configure LQM method and interval.
*/
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <stdio.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
#include <string.h>
+#include <termios.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "lcpproto.h"
+#include "lcp.h"
#include "lqr.h"
#include "hdlc.h"
-#include "lcp.h"
-#include "loadalias.h"
-#include "vars.h"
-
-struct lqrdata MyLqrData, HisLqrData;
-struct lqrsave HisLqrSave;
-
-static struct pppTimer LqrTimer;
-
-static u_long lastpeerin = (u_long) - 1;
-
-static int lqmmethod;
-static u_int32_t echoseq;
-static u_int32_t gotseq;
-static int lqrsendcnt;
+#include "async.h"
+#include "throughput.h"
+#include "ccp.h"
+#include "link.h"
+#include "descriptor.h"
+#include "physical.h"
+#include "mp.h"
+#include "chat.h"
+#include "auth.h"
+#include "chap.h"
+#include "command.h"
+#include "datalink.h"
struct echolqr {
u_int32_t magic;
@@ -65,43 +63,44 @@ struct echolqr {
#define SIGNATURE 0x594e4f54
static void
-SendEchoReq(void)
+SendEchoReq(struct lcp *lcp)
{
- struct fsm *fp = &LcpFsm;
- struct echolqr *lqr, lqrdata;
-
- if (fp->state == ST_OPENED) {
- lqr = &lqrdata;
- lqr->magic = htonl(LcpInfo.want_magic);
- lqr->signature = htonl(SIGNATURE);
- LogPrintf(LogLQM, "Send echo LQR [%d]\n", echoseq);
- lqr->sequence = htonl(echoseq++);
- FsmOutput(fp, CODE_ECHOREQ, fp->reqid++,
- (u_char *) lqr, sizeof(struct echolqr));
- }
+ struct hdlc *hdlc = &link2physical(lcp->fsm.link)->hdlc;
+ struct echolqr echo;
+
+ echo.magic = htonl(lcp->want_magic);
+ echo.signature = htonl(SIGNATURE);
+ echo.sequence = htonl(hdlc->lqm.echo.seq_sent);
+ fsm_Output(&lcp->fsm, CODE_ECHOREQ, hdlc->lqm.echo.seq_sent++,
+ (u_char *)&echo, sizeof echo);
}
void
-RecvEchoLqr(struct mbuf * bp)
+lqr_RecvEcho(struct fsm *fp, struct mbuf * bp)
{
+ struct hdlc *hdlc = &link2physical(fp->link)->hdlc;
struct echolqr *lqr;
u_int32_t seq;
- if (plength(bp) == sizeof(struct echolqr)) {
+ if (mbuf_Length(bp) == sizeof(struct echolqr)) {
lqr = (struct echolqr *) MBUF_CTOP(bp);
- if (htonl(lqr->signature) == SIGNATURE) {
+ if (ntohl(lqr->signature) == SIGNATURE) {
seq = ntohl(lqr->sequence);
- LogPrintf(LogLQM, "Got echo LQR [%d]\n", ntohl(lqr->sequence));
- /* careful not to update gotseq with older values */
- if ((gotseq > (u_int32_t)0 - 5 && seq < 5) ||
- (gotseq <= (u_int32_t)0 - 5 && seq > gotseq))
- gotseq = seq;
- }
- }
+ /* careful not to update lqm.echo.seq_recv with older values */
+ if ((hdlc->lqm.echo.seq_recv > (u_int32_t)0 - 5 && seq < 5) ||
+ (hdlc->lqm.echo.seq_recv <= (u_int32_t)0 - 5 &&
+ seq > hdlc->lqm.echo.seq_recv))
+ hdlc->lqm.echo.seq_recv = seq;
+ } else
+ log_Printf(LogERROR, "lqr_RecvEcho: Got sig 0x%08x, expecting 0x%08x !\n",
+ (unsigned)ntohl(lqr->signature), (unsigned)SIGNATURE);
+ } else
+ log_Printf(LogERROR, "lqr_RecvEcho: Got packet size %d, expecting %d !\n",
+ mbuf_Length(bp), sizeof(struct echolqr));
}
void
-LqrChangeOrder(struct lqrdata * src, struct lqrdata * dst)
+lqr_ChangeOrder(struct lqrdata * src, struct lqrdata * dst)
{
u_long *sp, *dp;
int n;
@@ -113,169 +112,207 @@ LqrChangeOrder(struct lqrdata * src, struct lqrdata * dst)
}
static void
-SendLqrReport(void *v)
+SendLqrData(struct lcp *lcp)
{
struct mbuf *bp;
- StopTimer(&LqrTimer);
+ bp = mbuf_Alloc(sizeof(struct lqrdata), MB_LQR);
+ hdlc_Output(lcp->fsm.link, PRI_LINK, PROTO_LQR, bp);
+}
- if (lqmmethod & LQM_LQR) {
- if (lqrsendcnt > 5) {
- /*
- * XXX: Should implement LQM strategy
- */
- LogPrintf(LogPHASE, "** Too many LQR packets lost **\n");
- LogPrintf(LogLQM, "LqrOutput: Too many LQR packets lost\n");
- lqmmethod = 0; /* Prevent recursion via LcpClose() */
- reconnect(RECON_TRUE);
- LcpClose();
+static void
+SendLqrReport(void *v)
+{
+ struct lcp *lcp = (struct lcp *)v;
+ struct physical *p = link2physical(lcp->fsm.link);
+
+ timer_Stop(&p->hdlc.lqm.timer);
+
+ if (p->hdlc.lqm.method & LQM_LQR) {
+ if (p->hdlc.lqm.lqr.resent > 5) {
+ /* XXX: Should implement LQM strategy */
+ log_Printf(LogPHASE, "%s: ** Too many LQR packets lost **\n",
+ lcp->fsm.link->name);
+ log_Printf(LogLQM, "%s: Too many LQR packets lost\n",
+ lcp->fsm.link->name);
+ p->hdlc.lqm.method = 0;
+ datalink_Down(p->dl, 0);
} else {
- bp = mballoc(sizeof(struct lqrdata), MB_LQR);
- HdlcOutput(PRI_LINK, PROTO_LQR, bp);
- lqrsendcnt++;
+ SendLqrData(lcp);
+ p->hdlc.lqm.lqr.resent++;
}
- } else if (lqmmethod & LQM_ECHO) {
- if ((echoseq > 5 && echoseq - 5 > gotseq) ||
- (echoseq <= 5 && echoseq > gotseq + 5)) {
- LogPrintf(LogPHASE, "** Too many ECHO LQR packets lost **\n");
- LogPrintf(LogLQM, "LqrOutput: Too many ECHO LQR packets lost\n");
- lqmmethod = 0; /* Prevent recursion via LcpClose() */
- reconnect(RECON_TRUE);
- LcpClose();
+ } else if (p->hdlc.lqm.method & LQM_ECHO) {
+ if ((p->hdlc.lqm.echo.seq_sent > 5 &&
+ p->hdlc.lqm.echo.seq_sent - 5 > p->hdlc.lqm.echo.seq_recv) ||
+ (p->hdlc.lqm.echo.seq_sent <= 5 &&
+ p->hdlc.lqm.echo.seq_sent > p->hdlc.lqm.echo.seq_recv + 5)) {
+ log_Printf(LogPHASE, "%s: ** Too many ECHO LQR packets lost **\n",
+ lcp->fsm.link->name);
+ log_Printf(LogLQM, "%s: Too many ECHO LQR packets lost\n",
+ lcp->fsm.link->name);
+ p->hdlc.lqm.method = 0;
+ datalink_Down(p->dl, 0);
} else
- SendEchoReq();
+ SendEchoReq(lcp);
}
- if (lqmmethod && LqrTimer.load)
- StartTimer(&LqrTimer);
+ if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load)
+ timer_Start(&p->hdlc.lqm.timer);
}
void
-LqrInput(struct mbuf * bp)
+lqr_Input(struct physical *physical, struct mbuf *bp)
{
int len;
- u_char *cp;
- struct lqrdata *lqr;
- len = plength(bp);
- if (len != sizeof(struct lqrdata)) {
- pfree(bp);
- return;
- }
- if (!Acceptable(ConfLqr)) {
+ len = mbuf_Length(bp);
+ if (len != sizeof(struct lqrdata))
+ log_Printf(LogERROR, "lqr_Input: Got packet size %d, expecting %d !\n",
+ len, sizeof(struct lqrdata));
+ else if (!IsAccepted(physical->link.lcp.cfg.lqr) &&
+ !(physical->hdlc.lqm.method & LQM_LQR)) {
bp->offset -= 2;
bp->cnt += 2;
-
- cp = MBUF_CTOP(bp);
- LcpSendProtoRej(cp, bp->cnt);
+ lcp_SendProtoRej(physical->hdlc.lqm.owner, MBUF_CTOP(bp), bp->cnt);
} else {
- cp = MBUF_CTOP(bp);
- lqr = (struct lqrdata *) cp;
- if (ntohl(lqr->MagicNumber) != LcpInfo.his_magic) {
- LogPrintf(LogERROR, "LqrInput: magic %x != expecting %x\n",
- ntohl(lqr->MagicNumber), LcpInfo.his_magic);
- pfree(bp);
- return;
- }
+ struct lqrdata *lqr;
+ struct lcp *lcp;
+ u_int32_t lastLQR;
- /*
- * Convert byte order and save into our strage
- */
- LqrChangeOrder(lqr, &HisLqrData);
- LqrDump("LqrInput", &HisLqrData);
- lqrsendcnt = 0; /* we have received LQR from peer */
-
- /*
- * Generate an LQR response to peer we're not running LQR timer OR
- * two successive LQR's PeerInLQRs are same OR we're not going to
- * send our next one before the peers max timeout.
- */
- if (LqrTimer.load == 0 || lastpeerin == HisLqrData.PeerInLQRs ||
- (LqrTimer.arg &&
- LqrTimer.rest * 100 / SECTICKS > (u_int32_t)LqrTimer.arg)) {
- lqmmethod |= LQM_LQR;
- SendLqrReport(LqrTimer.arg);
+ lqr = (struct lqrdata *)MBUF_CTOP(bp);
+ lcp = physical->hdlc.lqm.owner;
+ if (ntohl(lqr->MagicNumber) != physical->hdlc.lqm.owner->his_magic)
+ log_Printf(LogERROR, "lqr_Input: magic %x != expecting %x\n",
+ (unsigned)ntohl(lqr->MagicNumber),
+ physical->hdlc.lqm.owner->his_magic);
+ else {
+ /*
+ * Remember our PeerInLQRs, then convert byte order and save
+ */
+ lastLQR = physical->hdlc.lqm.lqr.peer.PeerInLQRs;
+
+ lqr_ChangeOrder(lqr, &physical->hdlc.lqm.lqr.peer);
+ lqr_Dump(physical->link.name, "Input", &physical->hdlc.lqm.lqr.peer);
+ /* we have received an LQR from peer */
+ physical->hdlc.lqm.lqr.resent = 0;
+
+ /*
+ * Generate an LQR response if we're not running an LQR timer OR
+ * two successive LQR's PeerInLQRs are the same OR we're not going to
+ * send our next one before the peers max timeout.
+ */
+ if (physical->hdlc.lqm.timer.load == 0 ||
+ !(physical->hdlc.lqm.method & LQM_LQR) ||
+ (lastLQR && lastLQR == physical->hdlc.lqm.lqr.peer.PeerInLQRs) ||
+ (physical->hdlc.lqm.lqr.peer_timeout &&
+ physical->hdlc.lqm.timer.rest * 100 / SECTICKS >
+ physical->hdlc.lqm.lqr.peer_timeout))
+ SendLqrData(physical->hdlc.lqm.owner);
}
- lastpeerin = HisLqrData.PeerInLQRs;
}
- pfree(bp);
+ mbuf_Free(bp);
}
/*
* When LCP is reached to opened state, We'll start LQM activity.
*/
-void
-StartLqm()
+
+static void
+lqr_Setup(struct lcp *lcp)
{
- struct lcpstate *lcp = &LcpInfo;
+ struct physical *physical = link2physical(lcp->fsm.link);
- lqrsendcnt = 0; /* start waiting all over for ECHOs */
- echoseq = 0;
- gotseq = 0;
- memset(&HisLqrData, '\0', sizeof HisLqrData);
+ physical->hdlc.lqm.lqr.resent = 0;
+ physical->hdlc.lqm.echo.seq_sent = 0;
+ physical->hdlc.lqm.echo.seq_recv = 0;
+ memset(&physical->hdlc.lqm.lqr.peer, '\0',
+ sizeof physical->hdlc.lqm.lqr.peer);
- lqmmethod = LQM_ECHO;
- if (Enabled(ConfLqr) && !REJECTED(lcp, TY_QUALPROTO))
- lqmmethod |= LQM_LQR;
- StopTimer(&LqrTimer);
+ physical->hdlc.lqm.method = LQM_ECHO;
+ if (IsEnabled(lcp->cfg.lqr) && !REJECTED(lcp, TY_QUALPROTO))
+ physical->hdlc.lqm.method |= LQM_LQR;
+ timer_Stop(&physical->hdlc.lqm.timer);
+ physical->hdlc.lqm.lqr.peer_timeout = lcp->his_lqrperiod;
if (lcp->his_lqrperiod)
- LogPrintf(LogLQM, "Expecting LQR every %d.%02d secs\n",
- lcp->his_lqrperiod / 100, lcp->his_lqrperiod % 100);
+ log_Printf(LogLQM, "%s: Expecting LQR every %d.%02d secs\n",
+ physical->link.name, lcp->his_lqrperiod / 100,
+ lcp->his_lqrperiod % 100);
if (lcp->want_lqrperiod) {
- LogPrintf(LogLQM, "Will send %s every %d.%02d secs\n",
- lqmmethod & LQM_LQR ? "LQR" : "ECHO LQR",
- lcp->want_lqrperiod / 100, lcp->want_lqrperiod % 100);
- LqrTimer.state = TIMER_STOPPED;
- LqrTimer.load = lcp->want_lqrperiod * SECTICKS / 100;
- LqrTimer.func = SendLqrReport;
- LqrTimer.arg = (void *)lcp->his_lqrperiod;
- SendLqrReport(LqrTimer.arg);
+ log_Printf(LogLQM, "%s: Will send %s every %d.%02d secs\n",
+ physical->link.name,
+ physical->hdlc.lqm.method & LQM_LQR ? "LQR" : "ECHO LQR",
+ lcp->want_lqrperiod / 100, lcp->want_lqrperiod % 100);
+ physical->hdlc.lqm.timer.load = lcp->want_lqrperiod * SECTICKS / 100;
+ physical->hdlc.lqm.timer.func = SendLqrReport;
+ physical->hdlc.lqm.timer.name = "lqm";
+ physical->hdlc.lqm.timer.arg = lcp;
} else {
- LqrTimer.load = 0;
+ physical->hdlc.lqm.timer.load = 0;
if (!lcp->his_lqrperiod)
- LogPrintf(LogLQM, "LQR/ECHO LQR not negotiated\n");
+ log_Printf(LogLQM, "%s: LQR/ECHO LQR not negotiated\n",
+ physical->link.name);
}
}
void
-StopLqrTimer()
+lqr_Start(struct lcp *lcp)
{
- StopTimer(&LqrTimer);
+ struct physical *p = link2physical(lcp->fsm.link);
+
+ lqr_Setup(lcp);
+ if (p->hdlc.lqm.timer.load)
+ SendLqrReport(lcp);
}
void
-StopLqr(int method)
+lqr_reStart(struct lcp *lcp)
{
- LogPrintf(LogLQM, "StopLqr method = %x\n", method);
+ struct physical *p = link2physical(lcp->fsm.link);
+ lqr_Setup(lcp);
+ if (p->hdlc.lqm.timer.load)
+ timer_Start(&p->hdlc.lqm.timer);
+}
+
+void
+lqr_StopTimer(struct physical *physical)
+{
+ timer_Stop(&physical->hdlc.lqm.timer);
+}
+
+void
+lqr_Stop(struct physical *physical, int method)
+{
if (method == LQM_LQR)
- LogPrintf(LogLQM, "Stop sending LQR, Use LCP ECHO instead.\n");
+ log_Printf(LogLQM, "%s: Stop sending LQR, Use LCP ECHO instead.\n",
+ physical->link.name);
if (method == LQM_ECHO)
- LogPrintf(LogLQM, "Stop sending LCP ECHO.\n");
- lqmmethod &= ~method;
- if (lqmmethod)
- SendLqrReport(LqrTimer.arg);
+ log_Printf(LogLQM, "%s: Stop sending LCP ECHO.\n",
+ physical->link.name);
+ physical->hdlc.lqm.method &= ~method;
+ if (physical->hdlc.lqm.method)
+ SendLqrReport(physical->hdlc.lqm.owner);
else
- StopTimer(&LqrTimer);
+ timer_Stop(&physical->hdlc.lqm.timer);
}
void
-LqrDump(const char *message, const struct lqrdata * lqr)
+lqr_Dump(const char *link, const char *message, const struct lqrdata *lqr)
{
- if (LogIsKept(LogLQM)) {
- LogPrintf(LogLQM, "%s:\n", message);
- LogPrintf(LogLQM, " Magic: %08x LastOutLQRs: %08x\n",
+ if (log_IsKept(LogLQM)) {
+ log_Printf(LogLQM, "%s: %s:\n", link, message);
+ log_Printf(LogLQM, " Magic: %08x LastOutLQRs: %08x\n",
lqr->MagicNumber, lqr->LastOutLQRs);
- LogPrintf(LogLQM, " LastOutPackets: %08x LastOutOctets: %08x\n",
+ log_Printf(LogLQM, " LastOutPackets: %08x LastOutOctets: %08x\n",
lqr->LastOutPackets, lqr->LastOutOctets);
- LogPrintf(LogLQM, " PeerInLQRs: %08x PeerInPackets: %08x\n",
+ log_Printf(LogLQM, " PeerInLQRs: %08x PeerInPackets: %08x\n",
lqr->PeerInLQRs, lqr->PeerInPackets);
- LogPrintf(LogLQM, " PeerInDiscards: %08x PeerInErrors: %08x\n",
+ log_Printf(LogLQM, " PeerInDiscards: %08x PeerInErrors: %08x\n",
lqr->PeerInDiscards, lqr->PeerInErrors);
- LogPrintf(LogLQM, " PeerInOctets: %08x PeerOutLQRs: %08x\n",
+ log_Printf(LogLQM, " PeerInOctets: %08x PeerOutLQRs: %08x\n",
lqr->PeerInOctets, lqr->PeerOutLQRs);
- LogPrintf(LogLQM, " PeerOutPackets: %08x PeerOutOctets: %08x\n",
+ log_Printf(LogLQM, " PeerOutPackets: %08x PeerOutOctets: %08x\n",
lqr->PeerOutPackets, lqr->PeerOutOctets);
}
}
diff --git a/usr.sbin/ppp/lqr.h b/usr.sbin/ppp/lqr.h
index fe85d3e6929f..f562828dde62 100644
--- a/usr.sbin/ppp/lqr.h
+++ b/usr.sbin/ppp/lqr.h
@@ -15,50 +15,45 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: lqr.h,v 1.11 1998/01/11 17:50:42 brian Exp $
+ * $Id: lqr.h,v 1.12.2.6 1998/05/08 01:15:09 brian Exp $
*
* TODO:
*/
/*
- * Structure of LQR packet defined in RFC1333
+ * Structure of LQR packet defined in RFC1989
*/
struct lqrdata {
u_int32_t MagicNumber;
- u_int32_t LastOutLQRs;
- u_int32_t LastOutPackets;
- u_int32_t LastOutOctets;
- u_int32_t PeerInLQRs;
- u_int32_t PeerInPackets;
- u_int32_t PeerInDiscards;
- u_int32_t PeerInErrors;
- u_int32_t PeerInOctets;
- u_int32_t PeerOutLQRs;
- u_int32_t PeerOutPackets;
- u_int32_t PeerOutOctets;
+ u_int32_t LastOutLQRs; /* most recently received PeerOutLQRs */
+ u_int32_t LastOutPackets; /* most recently received PeerOutPackets */
+ u_int32_t LastOutOctets; /* most recently received PeerOutOctets */
+ u_int32_t PeerInLQRs; /* Peers SaveInLQRs */
+ u_int32_t PeerInPackets; /* Peers SaveInPackets */
+ u_int32_t PeerInDiscards; /* Peers SaveInDiscards */
+ u_int32_t PeerInErrors; /* Peers SaveInErrors */
+ u_int32_t PeerInOctets; /* Peers SaveInOctets */
+ u_int32_t PeerOutLQRs; /* Peers OutLQRs (hdlc.h) */
+ u_int32_t PeerOutPackets; /* Peers OutPackets (hdlc.h) */
+ u_int32_t PeerOutOctets; /* Peers OutOctets (hdlc.h) */
};
-struct lqrsave {
- u_int32_t SaveInLQRs;
- u_int32_t SaveInPackets;
- u_int32_t SaveInDiscards;
- u_int32_t SaveInErrors;
- u_int32_t SaveInOctets;
-};
-
-extern struct lqrdata MyLqrData, HisLqrData;
-extern struct lqrsave HisLqrSave;
-
/*
* We support LQR and ECHO as LQM method
*/
#define LQM_LQR 1
#define LQM_ECHO 2
-extern void LqrDump(const char *, const struct lqrdata *);
-extern void LqrChangeOrder(struct lqrdata *, struct lqrdata *);
-extern void StartLqm(void);
-extern void StopLqr(int);
-extern void StopLqrTimer(void);
-extern void RecvEchoLqr(struct mbuf *);
-extern void LqrInput(struct mbuf *);
+struct mbuf;
+struct physical;
+struct lcp;
+struct fsm;
+
+extern void lqr_Dump(const char *, const char *, const struct lqrdata *);
+extern void lqr_ChangeOrder(struct lqrdata *, struct lqrdata *);
+extern void lqr_Start(struct lcp *);
+extern void lqr_reStart(struct lcp *);
+extern void lqr_Stop(struct physical *, int);
+extern void lqr_StopTimer(struct physical *);
+extern void lqr_RecvEcho(struct fsm *, struct mbuf *);
+extern void lqr_Input(struct physical *, struct mbuf *);
diff --git a/usr.sbin/ppp/main.c b/usr.sbin/ppp/main.c
index 3fef84add7f7..96205141c1fc 100644
--- a/usr.sbin/ppp/main.c
+++ b/usr.sbin/ppp/main.c
@@ -17,62 +17,60 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: main.c,v 1.121 1998/01/29 00:42:05 brian Exp $
+ * $Id: main.c,v 1.121.2.60 1998/05/15 18:21:38 brian Exp $
*
* TODO:
- * o Add commands for traffic summary, version display, etc.
- * o Add signal handler for misc controls.
*/
+
#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/select.h>
#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_tun.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#include <arpa/inet.h>
+#include <sys/un.h>
+#include <net/if_tun.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
-#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "id.h"
#include "timer.h"
#include "fsm.h"
-#include "modem.h"
-#include "os.h"
+#include "lqr.h"
#include "hdlc.h"
#include "lcp.h"
#include "ccp.h"
+#include "iplist.h"
+#include "throughput.h"
+#include "slcompress.h"
#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
#include "loadalias.h"
-#include "vars.h"
#include "auth.h"
-#include "filter.h"
#include "systems.h"
#include "ip.h"
#include "sig.h"
-#include "server.h"
#include "main.h"
-#include "vjcomp.h"
-#include "async.h"
-#include "pathnames.h"
#include "tun.h"
-#include "route.h"
+#include "server.h"
+#include "prompt.h"
+#include "chat.h"
+#include "chap.h"
+#include "datalink.h"
#ifndef O_NONBLOCK
#ifdef O_NDELAY
@@ -80,123 +78,32 @@
#endif
#endif
-int TermMode = 0;
-int tunno = 0;
-
-static struct termios oldtio; /* Original tty mode */
-static struct termios comtio; /* Command level tty mode */
-static pid_t BGPid = 0;
static char pid_filename[MAXPATHLEN];
-static int dial_up;
-static void DoLoop(void);
+static void DoLoop(struct bundle *, struct prompt *);
static void TerminalStop(int);
static const char *ex_desc(int);
-static void
-TtyInit(int DontWantInt)
-{
- struct termios newtio;
- int stat;
-
- stat = fcntl(netfd, F_GETFL, 0);
- if (stat > 0) {
- stat |= O_NONBLOCK;
- (void) fcntl(netfd, F_SETFL, stat);
- }
- newtio = oldtio;
- newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
- newtio.c_iflag = 0;
- newtio.c_oflag &= ~OPOST;
- newtio.c_cc[VEOF] = _POSIX_VDISABLE;
- if (DontWantInt)
- newtio.c_cc[VINTR] = _POSIX_VDISABLE;
- newtio.c_cc[VMIN] = 1;
- newtio.c_cc[VTIME] = 0;
- newtio.c_cflag |= CS8;
- tcsetattr(netfd, TCSANOW, &newtio);
- comtio = newtio;
-}
+static struct bundle *SignalBundle;
+static struct prompt *SignalPrompt;
-/*
- * Set tty into command mode. We allow canonical input and echo processing.
- */
-void
-TtyCommandMode(int prompt)
-{
- struct termios newtio;
- int stat;
-
- if (!(mode & MODE_INTER))
- return;
- tcgetattr(netfd, &newtio);
- newtio.c_lflag |= (ECHO | ISIG | ICANON);
- newtio.c_iflag = oldtio.c_iflag;
- newtio.c_oflag |= OPOST;
- tcsetattr(netfd, TCSADRAIN, &newtio);
- stat = fcntl(netfd, F_GETFL, 0);
- if (stat > 0) {
- stat |= O_NONBLOCK;
- (void) fcntl(netfd, F_SETFL, stat);
- }
- TermMode = 0;
- if (prompt)
- Prompt();
-}
-
-/*
- * Set tty into terminal mode which is used while we invoke term command.
- */
void
-TtyTermMode()
-{
- int stat;
-
- tcsetattr(netfd, TCSADRAIN, &comtio);
- stat = fcntl(netfd, F_GETFL, 0);
- if (stat > 0) {
- stat &= ~O_NONBLOCK;
- (void) fcntl(netfd, F_SETFL, stat);
- }
- TermMode = 1;
-}
-
-void
-TtyOldMode()
+Cleanup(int excode)
{
- int stat;
-
- stat = fcntl(netfd, F_GETFL, 0);
- if (stat > 0) {
- stat &= ~O_NONBLOCK;
- (void) fcntl(netfd, F_SETFL, stat);
- }
- tcsetattr(netfd, TCSADRAIN, &oldtio);
+ SignalBundle->CleaningUp = 1;
+ if (bundle_Phase(SignalBundle) != PHASE_DEAD)
+ bundle_Close(SignalBundle, NULL, 1);
}
void
-Cleanup(int excode)
+AbortProgram(int excode)
{
- DropClient(1);
- ServerClose();
- OsInterfaceDown(1);
- HangupModem(1);
- nointr_sleep(1);
- DeleteIfRoutes(1);
+ server_Close(SignalBundle);
ID0unlink(pid_filename);
- if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
- char c = EX_ERRDEAD;
-
- if (write(BGFiledes[1], &c, 1) == 1)
- LogPrintf(LogPHASE, "Parent notified of failure.\n");
- else
- LogPrintf(LogPHASE, "Failed to notify parent of failure.\n");
- close(BGFiledes[1]);
- }
- LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
- TtyOldMode();
- LogClose();
-
+ log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
+ bundle_Close(SignalBundle, NULL, 1);
+ bundle_Destroy(SignalBundle);
+ log_Close();
exit(excode);
}
@@ -204,63 +111,48 @@ static void
CloseConnection(int signo)
{
/* NOTE, these are manual, we've done a setsid() */
- pending_signal(SIGINT, SIG_IGN);
- LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo);
- reconnectState = RECON_FALSE;
- reconnectCount = 0;
- DownConnection();
- dial_up = 0;
- pending_signal(SIGINT, CloseConnection);
+ sig_signal(SIGINT, SIG_IGN);
+ log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo);
+ bundle_Down(SignalBundle);
+ sig_signal(SIGINT, CloseConnection);
}
static void
CloseSession(int signo)
{
- if (BGPid) {
- kill(BGPid, SIGINT);
- exit(EX_TERM);
- }
- LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
- reconnect(RECON_FALSE);
- LcpClose();
+ log_Printf(LogPHASE, "Signal %d, terminate.\n", signo);
Cleanup(EX_TERM);
}
+static pid_t BGPid = 0;
+
static void
-TerminalCont(int signo)
+KillChild(int signo)
{
- pending_signal(SIGCONT, SIG_DFL);
- pending_signal(SIGTSTP, TerminalStop);
- TtyCommandMode(getpgrp() == tcgetpgrp(netfd));
+ log_Printf(LogPHASE, "Parent: Signal %d\n", signo);
+ kill(BGPid, SIGINT);
}
static void
-TerminalStop(int signo)
+TerminalCont(int signo)
{
- pending_signal(SIGCONT, TerminalCont);
- TtyOldMode();
- pending_signal(SIGTSTP, SIG_DFL);
- kill(getpid(), signo);
+ signal(SIGCONT, SIG_DFL);
+ prompt_Continue(SignalPrompt);
}
static void
-SetUpServer(int signo)
+TerminalStop(int signo)
{
- int res;
-
- VarHaveLocalAuthKey = 0;
- LocalAuthInit();
- if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0)
- LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n",
- res, SERVER_PORT + tunno);
+ prompt_Suspend(SignalPrompt);
+ signal(SIGCONT, TerminalCont);
+ raise(SIGSTOP);
}
static void
BringDownServer(int signo)
{
- VarHaveLocalAuthKey = 0;
- LocalAuthInit();
- ServerClose();
+ /* Drops all child prompts too ! */
+ server_Close(SignalBundle);
}
static const char *
@@ -291,38 +183,34 @@ Usage(void)
}
static char *
-ProcessArgs(int argc, char **argv)
+ProcessArgs(int argc, char **argv, int *mode)
{
- int optc;
+ int optc, labelrequired;
char *cp;
- optc = 0;
- mode = MODE_INTER;
+ optc = labelrequired = 0;
+ *mode = PHYS_MANUAL;
while (argc > 0 && **argv == '-') {
cp = *argv + 1;
if (strcmp(cp, "auto") == 0) {
- mode |= MODE_AUTO;
- mode &= ~MODE_INTER;
+ *mode = PHYS_DEMAND;
+ labelrequired = 1;
} else if (strcmp(cp, "background") == 0) {
- mode |= MODE_BACKGROUND;
- mode &= ~MODE_INTER;
- } else if (strcmp(cp, "direct") == 0) {
- mode |= MODE_DIRECT;
- mode &= ~MODE_INTER;
- } else if (strcmp(cp, "dedicated") == 0) {
- mode |= MODE_DEDICATED;
- mode &= ~MODE_INTER;
- } else if (strcmp(cp, "ddial") == 0) {
- mode |= MODE_DDIAL;
- mode &= ~MODE_INTER;
-#ifndef NOALIAS
+ *mode = PHYS_1OFF;
+ labelrequired = 1;
+ } else if (strcmp(cp, "direct") == 0)
+ *mode = PHYS_DIRECT;
+ else if (strcmp(cp, "dedicated") == 0)
+ *mode = PHYS_DEDICATED;
+ else if (strcmp(cp, "ddial") == 0) {
+ *mode = PHYS_PERM;
+ labelrequired = 1;
} else if (strcmp(cp, "alias") == 0) {
- if (loadAliasHandlers(&VarAliasHandlers) == 0)
- mode |= MODE_ALIAS;
- else
- LogPrintf(LogWARN, "Cannot load alias library\n");
- optc--; /* this option isn't exclusive */
+#ifndef NOALIAS
+ if (alias_Load() != 0)
#endif
+ log_Printf(LogWARN, "Cannot load alias library\n");
+ optc--; /* this option isn't exclusive */
} else
Usage();
optc++;
@@ -330,12 +218,18 @@ ProcessArgs(int argc, char **argv)
argc--;
}
if (argc > 1) {
- fprintf(stderr, "specify only one system label.\n");
+ fprintf(stderr, "You may specify only one system label.\n");
exit(EX_START);
}
if (optc > 1) {
- fprintf(stderr, "specify only one mode.\n");
+ fprintf(stderr, "You may specify only one mode.\n");
+ exit(EX_START);
+ }
+
+ if (labelrequired && argc != 1) {
+ fprintf(stderr, "Destination system must be specified in"
+ " auto, background or ddial mode.\n");
exit(EX_START);
}
@@ -347,7 +241,9 @@ main(int argc, char **argv)
{
FILE *lockfile;
char *name, *label;
- int nfds;
+ int nfds, mode;
+ struct bundle *bundle;
+ struct prompt *prompt;
nfds = getdtablesize();
if (nfds >= FD_SETSIZE)
@@ -359,17 +255,53 @@ main(int argc, char **argv)
while (--nfds > 2)
close(nfds);
- VarTerm = 0;
name = strrchr(argv[0], '/');
- LogOpen(name ? name + 1 : argv[0]);
-
- tcgetattr(STDIN_FILENO, &oldtio); /* Save original tty mode */
+ log_Open(name ? name + 1 : argv[0]);
argc--;
argv++;
- label = ProcessArgs(argc, argv);
- if (!(mode & MODE_DIRECT))
- VarTerm = stdout;
+ label = ProcessArgs(argc, argv, &mode);
+
+#ifdef __FreeBSD__
+ /*
+ * A FreeBSD hack to dodge a bug in the tty driver that drops output
+ * occasionally.... I must find the real reason some time. To display
+ * the dodgy behaviour, comment out this bit, make yourself a large
+ * routing table and then run ppp in interactive mode. The `show route'
+ * command will drop chunks of data !!!
+ */
+ if (mode == PHYS_MANUAL) {
+ close(STDIN_FILENO);
+ if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) {
+ fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY);
+ return 2;
+ }
+ }
+#endif
+
+ /* Allow output for the moment (except in direct mode) */
+ if (mode == PHYS_DIRECT)
+ prompt = NULL;
+ else {
+ const char *m;
+
+ SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD);
+ if (mode == PHYS_PERM)
+ m = "direct dial";
+ else if (mode & PHYS_1OFF)
+ m = "background";
+ else if (mode & PHYS_DEMAND)
+ m = "auto";
+ else if (mode & PHYS_DEDICATED)
+ m = "dedicated";
+ else if (mode & PHYS_MANUAL)
+ m = "interactive";
+ else
+ m = NULL;
+
+ if (m)
+ prompt_Printf(prompt, "Working in %s mode\n", m);
+ }
ID0init();
if (ID0realuid() != 0) {
@@ -378,7 +310,7 @@ main(int argc, char **argv)
snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE);
do {
if (!access(conf, W_OK)) {
- LogPrintf(LogALERT, "ppp: Access violation: Please protect %s\n", conf);
+ log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", conf);
return -1;
}
ptr = conf + strlen(conf)-2;
@@ -387,155 +319,129 @@ main(int argc, char **argv)
} while (ptr >= conf);
}
- if (!ValidSystem(label)) {
+ if (!system_IsValid(label, prompt, mode)) {
fprintf(stderr, "You may not use ppp in this mode with this label\n");
- if (mode & MODE_DIRECT) {
+ if (mode == PHYS_DIRECT) {
const char *l;
l = label ? label : "default";
- LogPrintf(LogWARN, "Label %s rejected -direct connection\n", l);
+ log_Printf(LogWARN, "Label %s rejected -direct connection\n", l);
}
- LogClose();
+ log_Close();
return 1;
}
- if (!GetShortHost())
- return 1;
- IsInteractive(1);
- IpcpDefAddress();
-
- if (mode & MODE_INTER)
- VarLocalAuth = LOCAL_AUTH;
-
- if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
- fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
-
- if (OpenTunnel(&tunno) < 0) {
- LogPrintf(LogWARN, "OpenTunnel: %s\n", strerror(errno));
+ if ((bundle = bundle_Create(TUN_PREFIX, prompt, mode)) == NULL) {
+ log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno));
return EX_START;
}
- CleanInterface(IfDevName);
- if ((mode & MODE_OUTGOING_DAEMON) && !(mode & MODE_DEDICATED))
- if (label == NULL) {
- if (VarTerm)
- fprintf(VarTerm, "Destination system must be specified in"
- " auto, background or ddial mode.\n");
- return EX_START;
- }
+ SignalBundle = bundle;
- pending_signal(SIGHUP, CloseSession);
- pending_signal(SIGTERM, CloseSession);
- pending_signal(SIGINT, CloseConnection);
- pending_signal(SIGQUIT, CloseSession);
-#ifdef SIGPIPE
+ if (system_Select(bundle, "default", CONFFILE, prompt) < 0)
+ prompt_Printf(prompt, "Warning: No default entry found in config file.\n");
+
+ sig_signal(SIGHUP, CloseSession);
+ sig_signal(SIGTERM, CloseSession);
+ sig_signal(SIGINT, CloseConnection);
+ sig_signal(SIGQUIT, CloseSession);
+ sig_signal(SIGALRM, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
-#endif
-#ifdef SIGALRM
- pending_signal(SIGALRM, SIG_IGN);
-#endif
- if (mode & MODE_INTER) {
-#ifdef SIGTSTP
- pending_signal(SIGTSTP, TerminalStop);
-#endif
-#ifdef SIGTTIN
- pending_signal(SIGTTIN, TerminalStop);
-#endif
-#ifdef SIGTTOU
- pending_signal(SIGTTOU, SIG_IGN);
-#endif
- }
- if (!(mode & MODE_INTER)) {
-#ifdef SIGUSR1
- pending_signal(SIGUSR1, SetUpServer);
-#endif
-#ifdef SIGUSR2
- pending_signal(SIGUSR2, BringDownServer);
-#endif
- }
+
+ if (mode == PHYS_MANUAL)
+ sig_signal(SIGTSTP, TerminalStop);
+
+ sig_signal(SIGUSR2, BringDownServer);
if (label) {
- if (SelectSystem(label, CONFFILE) < 0) {
- LogPrintf(LogWARN, "Destination system %s not found in conf file.\n",
- GetLabel());
- Cleanup(EX_START);
- }
/*
- * We don't SetLabel() 'till now in case SelectSystem() has an
- * embeded load "otherlabel" command.
+ * Set label both before and after system_Select !
+ * This way, "set enddisc label" works during system_Select, and we
+ * also end up with the correct label if we have embedded load
+ * commands.
*/
- SetLabel(label);
- if (mode & MODE_OUTGOING_DAEMON &&
- DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
- LogPrintf(LogWARN, "You must \"set ifaddr\" in label %s for"
- " auto, background or ddial mode.\n", label);
- Cleanup(EX_START);
+ bundle_SetLabel(bundle, label);
+ if (system_Select(bundle, label, CONFFILE, prompt) < 0) {
+ prompt_Printf(prompt, "Destination system (%s) not found.\n", label);
+ AbortProgram(EX_START);
}
- }
-
- if (mode & MODE_DAEMON) {
- if (mode & MODE_BACKGROUND) {
- if (pipe(BGFiledes)) {
- LogPrintf(LogERROR, "pipe: %s\n", strerror(errno));
- Cleanup(EX_SOCK);
- }
+ bundle_SetLabel(bundle, label);
+ if (mode == PHYS_DEMAND &&
+ bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) {
+ prompt_Printf(prompt, "You must \"set ifaddr\" with a peer address "
+ "in label %s for auto mode.\n", label);
+ AbortProgram(EX_START);
}
+ }
- if (!(mode & MODE_DIRECT)) {
+ if (mode != PHYS_MANUAL) {
+ if (mode != PHYS_DIRECT) {
+ int bgpipe[2];
pid_t bgpid;
+ if (mode == PHYS_1OFF && pipe(bgpipe)) {
+ log_Printf(LogERROR, "pipe: %s\n", strerror(errno));
+ AbortProgram(EX_SOCK);
+ }
+
bgpid = fork();
if (bgpid == -1) {
- LogPrintf(LogERROR, "fork: %s\n", strerror(errno));
- Cleanup(EX_SOCK);
+ log_Printf(LogERROR, "fork: %s\n", strerror(errno));
+ AbortProgram(EX_SOCK);
}
+
if (bgpid) {
char c = EX_NORMAL;
- if (mode & MODE_BACKGROUND) {
- /* Wait for our child to close its pipe before we exit. */
+ if (mode == PHYS_1OFF) {
+ close(bgpipe[1]);
BGPid = bgpid;
- close(BGFiledes[1]);
- if (read(BGFiledes[0], &c, 1) != 1) {
- fprintf(VarTerm, "Child exit, no status.\n");
- LogPrintf(LogPHASE, "Parent: Child exit, no status.\n");
+ /* If we get a signal, kill the child */
+ signal(SIGHUP, KillChild);
+ signal(SIGTERM, KillChild);
+ signal(SIGINT, KillChild);
+ signal(SIGQUIT, KillChild);
+
+ /* Wait for our child to close its pipe before we exit */
+ if (read(bgpipe[0], &c, 1) != 1) {
+ prompt_Printf(prompt, "Child exit, no status.\n");
+ log_Printf(LogPHASE, "Parent: Child exit, no status.\n");
} else if (c == EX_NORMAL) {
- fprintf(VarTerm, "PPP enabled.\n");
- LogPrintf(LogPHASE, "Parent: PPP enabled.\n");
+ prompt_Printf(prompt, "PPP enabled.\n");
+ log_Printf(LogPHASE, "Parent: PPP enabled.\n");
} else {
- fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c));
- LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
+ prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c));
+ log_Printf(LogPHASE, "Parent: Child failed (%s).\n",
ex_desc((int) c));
}
- close(BGFiledes[0]);
+ close(bgpipe[0]);
}
return c;
- } else if (mode & MODE_BACKGROUND)
- close(BGFiledes[0]);
- }
-
- VarTerm = 0; /* We know it's currently stdout */
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
+ } else if (mode == PHYS_1OFF) {
+ close(bgpipe[0]);
+ bundle->notify.fd = bgpipe[1];
+ }
- if (mode & MODE_DIRECT)
- /* STDIN_FILENO gets used by OpenModem in DIRECT mode */
- TtyInit(1);
- else if (mode & MODE_DAEMON) {
- setsid();
+ /* -auto, -dedicated, -ddial & -background */
+ prompt_Destroy(prompt, 0);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
close(STDIN_FILENO);
+ setsid();
+ } else {
+ /* -direct: STDIN_FILENO gets used by modem_Open */
+ prompt_TtyInit(NULL);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
}
} else {
- close(STDIN_FILENO);
- if ((netfd = open(_PATH_TTY, O_RDONLY)) < 0) {
- fprintf(stderr, "Cannot open %s for intput !\n", _PATH_TTY);
- return 2;
- }
+ /* Interactive mode */
close(STDERR_FILENO);
- TtyInit(0);
- TtyCommandMode(1);
+ prompt_TtyInit(prompt);
+ prompt_TtyCommandMode(prompt);
+ prompt_Required(prompt);
}
snprintf(pid_filename, sizeof pid_filename, "%stun%d.pid",
- _PATH_VARRUN, tunno);
+ _PATH_VARRUN, bundle->unit);
lockfile = ID0fopen(pid_filename, "w");
if (lockfile != NULL) {
fprintf(lockfile, "%d\n", (int) getpid());
@@ -543,562 +449,100 @@ main(int argc, char **argv)
}
#ifndef RELEASE_CRUNCH
else
- LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
+ log_Printf(LogALERT, "Warning: Can't create %s: %s\n",
pid_filename, strerror(errno));
#endif
- LogPrintf(LogPHASE, "PPP Started.\n");
-
+ log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode));
+ DoLoop(bundle, prompt);
+ AbortProgram(EX_NORMAL);
- do
- DoLoop();
- while (mode & MODE_DEDICATED);
-
- Cleanup(EX_DONE);
- return 0;
-}
-
-/*
- * Turn into packet mode, where we speak PPP.
- */
-void
-PacketMode(int delay)
-{
- if (RawModem() < 0) {
- LogPrintf(LogWARN, "PacketMode: Not connected.\n");
- return;
- }
- AsyncInit();
- VjInit(15);
- LcpInit();
- IpcpInit();
- CcpInit();
- LcpUp();
-
- LcpOpen(delay);
- if (mode & MODE_INTER)
- TtyCommandMode(1);
- if (VarTerm) {
- fprintf(VarTerm, "Packet mode.\n");
- aft_cmd = 1;
- }
+ return EX_NORMAL;
}
static void
-ShowHelp(void)
-{
- fprintf(stderr, "The following commands are available:\r\n");
- fprintf(stderr, " ~p\tEnter Packet mode\r\n");
- fprintf(stderr, " ~-\tDecrease log level\r\n");
- fprintf(stderr, " ~+\tIncrease log level\r\n");
- fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
- fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
- fprintf(stderr, " ~.\tTerminate program\r\n");
- fprintf(stderr, " ~?\tThis help\r\n");
-}
-
-static void
-ReadTty(void)
-{
- int n;
- char ch;
- static int ttystate;
- char linebuff[LINE_LEN];
-
- LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
- TermMode, netfd, mode);
- if (!TermMode) {
- n = read(netfd, linebuff, sizeof linebuff - 1);
- if (n > 0) {
- aft_cmd = 1;
- if (linebuff[n-1] == '\n')
- linebuff[--n] = '\0';
- else
- linebuff[n] = '\0';
- if (n)
- DecodeCommand(linebuff, n, IsInteractive(0) ? NULL : "Client");
- Prompt();
- } else if (n <= 0) {
- LogPrintf(LogPHASE, "Client connection closed.\n");
- DropClient(0);
- }
- return;
- }
-
- /*
- * We are in terminal mode, decode special sequences
- */
- n = read(netfd, &ch, 1);
- LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
-
- if (n > 0) {
- switch (ttystate) {
- case 0:
- if (ch == '~')
- ttystate++;
- else
- write(modem, &ch, n);
- break;
- case 1:
- switch (ch) {
- case '?':
- ShowHelp();
- break;
- case 'p':
-
- /*
- * XXX: Should check carrier.
- */
- if (LcpFsm.state <= ST_CLOSED)
- PacketMode(0);
- break;
- case '.':
- TermMode = 1;
- aft_cmd = 1;
- TtyCommandMode(1);
- break;
- case 't':
- if (LogIsKept(LogDEBUG)) {
- ShowTimers();
- break;
- }
- case 'm':
- if (LogIsKept(LogDEBUG)) {
- ShowMemMap(NULL);
- break;
- }
- default:
- if (write(modem, &ch, n) < 0)
- LogPrintf(LogERROR, "error writing to modem.\n");
- break;
- }
- ttystate = 0;
- break;
- }
- }
-}
-
-
-/*
- * Here, we'll try to detect HDLC frame
- */
-
-static const char *FrameHeaders[] = {
- "\176\377\003\300\041",
- "\176\377\175\043\300\041",
- "\176\177\175\043\100\041",
- "\176\175\337\175\043\300\041",
- "\176\175\137\175\043\100\041",
- NULL,
-};
-
-static const u_char *
-HdlcDetect(u_char * cp, int n)
-{
- const char *ptr, *fp, **hp;
-
- cp[n] = '\0'; /* be sure to null terminated */
- ptr = NULL;
- for (hp = FrameHeaders; *hp; hp++) {
- fp = *hp;
- if (DEV_IS_SYNC)
- fp++;
- ptr = strstr((char *) cp, fp);
- if (ptr)
- break;
- }
- return ((const u_char *) ptr);
-}
-
-static struct pppTimer RedialTimer;
-
-static void
-RedialTimeout(void *v)
-{
- StopTimer(&RedialTimer);
- LogPrintf(LogPHASE, "Redialing timer expired.\n");
-}
-
-static void
-StartRedialTimer(int Timeout)
-{
- StopTimer(&RedialTimer);
-
- if (Timeout) {
- RedialTimer.state = TIMER_STOPPED;
-
- if (Timeout > 0)
- RedialTimer.load = Timeout * SECTICKS;
- else
- RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
-
- LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
- RedialTimer.load / SECTICKS);
-
- RedialTimer.func = RedialTimeout;
- StartTimer(&RedialTimer);
- }
-}
-
-#define IN_SIZE sizeof(struct sockaddr_in)
-#define UN_SIZE sizeof(struct sockaddr_in)
-#define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
-
-static void
-DoLoop(void)
+DoLoop(struct bundle *bundle, struct prompt *prompt)
{
fd_set rfds, wfds, efds;
- int pri, i, n, wfd, nfds;
- char hisaddr[ADDRSZ];
- struct sockaddr *sa = (struct sockaddr *)hisaddr;
- struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr;
- struct timeval timeout, *tp;
- int ssize = ADDRSZ;
- const u_char *cp;
- int tries;
- int qlen;
- int res;
- struct tun_data tun;
-#define rbuff tun.data
-
- if (mode & MODE_DIRECT) {
- LogPrintf(LogDEBUG, "Opening modem\n");
- if (OpenModem() < 0)
- return;
- LogPrintf(LogPHASE, "Packet mode enabled\n");
- PacketMode(VarOpenMode);
- } else if (mode & MODE_DEDICATED) {
- if (modem < 0)
- while (OpenModem() < 0)
- nointr_sleep(VarReconnectTimer);
- }
- fflush(VarTerm);
-
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- reconnectState = RECON_UNKNOWN;
+ int i, nfds;
- if (mode & MODE_BACKGROUND)
- dial_up = 1; /* Bring the line up */
- else
- dial_up = 0; /* XXXX */
- tries = 0;
- for (;;) {
+ do {
nfds = 0;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
- /*
- * If the link is down and we're in DDIAL mode, bring it back up.
- */
- if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
- dial_up = 1;
-
- /*
- * If we lost carrier and want to re-establish the connection due to the
- * "set reconnect" value, we'd better bring the line back up.
- */
- if (LcpFsm.state <= ST_CLOSED) {
- if (!dial_up && reconnectState == RECON_TRUE) {
- if (++reconnectCount <= VarReconnectTries) {
- LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
- reconnectCount, VarReconnectTries);
- StartRedialTimer(VarReconnectTimer);
- dial_up = 1;
- } else {
- if (VarReconnectTries)
- LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
- VarReconnectTries);
- reconnectCount = 0;
- if (mode & MODE_BACKGROUND)
- Cleanup(EX_DEAD);
- }
- reconnectState = RECON_ENVOKED;
- } else if (mode & MODE_DEDICATED)
- PacketMode(VarOpenMode);
- }
-
- /*
- * If Ip packet for output is enqueued and require dial up, Just do it!
- */
- if (dial_up && RedialTimer.state != TIMER_RUNNING) {
- LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
- if (OpenModem() < 0) {
- tries++;
- if (!(mode & MODE_DDIAL) && VarDialTries)
- LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
- tries, VarDialTries);
- else
- LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
-
- if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
- if (mode & MODE_BACKGROUND)
- Cleanup(EX_DIAL); /* Can't get the modem */
- dial_up = 0;
- reconnectState = RECON_UNKNOWN;
- reconnectCount = 0;
- tries = 0;
- } else
- StartRedialTimer(VarRedialTimeout);
- } else {
- tries++; /* Tries are per number, not per list of
- * numbers. */
- if (!(mode & MODE_DDIAL) && VarDialTries)
- LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
- else
- LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
-
- if ((res = DialModem()) == EX_DONE) {
- ModemTimeout(NULL);
- PacketMode(VarOpenMode);
- dial_up = 0;
- reconnectState = RECON_UNKNOWN;
- tries = 0;
- } else {
- if (mode & MODE_BACKGROUND) {
- if (VarNextPhone == NULL || res == EX_SIG)
- Cleanup(EX_DIAL); /* Tried all numbers - no luck */
- else
- /* Try all numbers in background mode */
- StartRedialTimer(VarRedialNextTimeout);
- } else if (!(mode & MODE_DDIAL) &&
- ((VarDialTries && tries >= VarDialTries) ||
- res == EX_SIG)) {
- /* I give up ! Can't get through :( */
- StartRedialTimer(VarRedialTimeout);
- dial_up = 0;
- reconnectState = RECON_UNKNOWN;
- reconnectCount = 0;
- tries = 0;
- } else if (VarNextPhone == NULL)
- /* Dial failed. Keep quite during redial wait period. */
- StartRedialTimer(VarRedialTimeout);
- else
- StartRedialTimer(VarRedialNextTimeout);
- }
- }
- }
- qlen = ModemQlen();
-
- if (qlen == 0) {
- IpStartOutput();
- qlen = ModemQlen();
- }
-
-#ifdef SIGALRM
- handle_signals();
-#endif
-
- if (modem >= 0) {
- if (modem + 1 > nfds)
- nfds = modem + 1;
- FD_SET(modem, &rfds);
- FD_SET(modem, &efds);
- if (qlen > 0) {
- FD_SET(modem, &wfds);
- }
- }
- if (server >= 0) {
- if (server + 1 > nfds)
- nfds = server + 1;
- FD_SET(server, &rfds);
- }
-
-#ifndef SIGALRM
- /*
- * *** IMPORTANT ***
- * CPU is serviced every TICKUNIT micro seconds. This value must be chosen
- * with great care. If this values is too big, it results in loss of
- * characters from the modem and poor response. If this value is too
- * small, ppp eats too much CPU time.
- */
- usleep(TICKUNIT);
- TimerService();
-#endif
+ sig_Handle();
- /* If there are aren't many packets queued, look for some more. */
- if (qlen < 20 && tun_in >= 0) {
- if (tun_in + 1 > nfds)
- nfds = tun_in + 1;
- FD_SET(tun_in, &rfds);
- }
- if (netfd >= 0) {
- if (netfd + 1 > nfds)
- nfds = netfd + 1;
- FD_SET(netfd, &rfds);
- FD_SET(netfd, &efds);
- }
-#ifndef SIGALRM
+ descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds);
+ descriptor_UpdateSet(&server.desc, &rfds, &wfds, &efds, &nfds);
- /*
- * Normally, select() will not block because modem is writable. In AUTO
- * mode, select will block until we find packet from tun
- */
- tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL;
- i = select(nfds, &rfds, &wfds, &efds, tp);
-#else
+ if (bundle_IsDead(bundle))
+ /* Don't select - we'll be here forever */
+ break;
- /*
- * When SIGALRM timer is running, a select function will be return -1 and
- * EINTR after a Time Service signal hundler is done. If the redial
- * timer is not running and we are trying to dial, poll with a 0 value
- * timer.
- */
- tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
- i = select(nfds, &rfds, &wfds, &efds, tp);
-#endif
+ i = select(nfds, &rfds, &wfds, &efds, NULL);
- if (i == 0) {
+ if (i == 0)
continue;
- }
- if (i < 0) {
- if (errno == EINTR) {
- handle_signals();
- continue;
- }
- LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
- break;
- }
- if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
- LogPrintf(LogALERT, "Exception detected.\n");
- break;
- }
- if (server >= 0 && FD_ISSET(server, &rfds)) {
- wfd = accept(server, sa, &ssize);
- if (wfd < 0) {
- LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno));
+ else if (i < 0) {
+ if (errno == EINTR)
continue;
- }
- switch (sa->sa_family) {
- case AF_LOCAL:
- LogPrintf(LogPHASE, "Connected to local client.\n");
- break;
- case AF_INET:
- if (ntohs(sin->sin_port) < 1024) {
- LogPrintf(LogALERT, "Rejected client connection from %s:%u"
- "(invalid port number) !\n",
- inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
- close(wfd);
- continue;
+ log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
+ if (log_IsKept(LogTIMER)) {
+ struct timeval t;
+
+ for (i = 0; i <= nfds; i++) {
+ if (FD_ISSET(i, &rfds)) {
+ log_Printf(LogTIMER, "Read set contains %d\n", i);
+ FD_CLR(i, &rfds);
+ t.tv_sec = t.tv_usec = 0;
+ if (select(nfds, &rfds, &wfds, &efds, &t) != -1) {
+ log_Printf(LogTIMER, "The culprit !\n");
+ break;
+ }
}
- LogPrintf(LogPHASE, "Connected to client from %s:%u\n",
- inet_ntoa(sin->sin_addr), sin->sin_port);
- break;
- default:
- write(wfd, "Unrecognised access !\n", 22);
- close(wfd);
- continue;
- }
- if (netfd >= 0) {
- write(wfd, "Connection already in use.\n", 27);
- close(wfd);
- continue;
- }
- netfd = wfd;
- VarTerm = fdopen(netfd, "a+");
- LocalAuthInit();
- IsInteractive(1);
- Prompt();
- }
- if (netfd >= 0 && FD_ISSET(netfd, &rfds))
- /* something to read from tty */
- ReadTty();
- if (modem >= 0 && FD_ISSET(modem, &wfds)) {
- /* ready to write into modem */
- ModemStartOutput(modem);
- if (modem < 0)
- dial_up = 1;
- }
- if (modem >= 0 && FD_ISSET(modem, &rfds)) {
- /* something to read from modem */
- if (LcpFsm.state <= ST_CLOSED)
- nointr_usleep(10000);
- n = read(modem, rbuff, sizeof rbuff);
- if ((mode & MODE_DIRECT) && n <= 0) {
- DownConnection();
- } else
- LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
-
- if (LcpFsm.state <= ST_CLOSED) {
- /*
- * In dedicated mode, we just discard input until LCP is started.
- */
- if (!(mode & MODE_DEDICATED)) {
- cp = HdlcDetect(rbuff, n);
- if (cp) {
- /*
- * LCP packet is detected. Turn ourselves into packet mode.
- */
- if (cp != rbuff) {
- write(modem, rbuff, cp - rbuff);
- write(modem, "\r\n", 2);
- }
- PacketMode(0);
- } else
- write(fileno(VarTerm), rbuff, n);
- }
- } else {
- if (n > 0)
- AsyncInput(rbuff, n);
+ if (FD_ISSET(i, &wfds)) {
+ log_Printf(LogTIMER, "Write set contains %d\n", i);
+ FD_CLR(i, &wfds);
+ t.tv_sec = t.tv_usec = 0;
+ if (select(nfds, &rfds, &wfds, &efds, &t) != -1) {
+ log_Printf(LogTIMER, "The culprit !\n");
+ break;
+ }
+ }
+ if (FD_ISSET(i, &efds)) {
+ log_Printf(LogTIMER, "Error set contains %d\n", i);
+ FD_CLR(i, &efds);
+ t.tv_sec = t.tv_usec = 0;
+ if (select(nfds, &rfds, &wfds, &efds, &t) != -1) {
+ log_Printf(LogTIMER, "The culprit !\n");
+ break;
+ }
+ }
+ }
}
+ break;
}
- if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read
- * from tun */
- n = read(tun_in, &tun, sizeof tun);
- if (n < 0) {
- LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno));
- continue;
- }
- n -= sizeof tun - sizeof tun.data;
- if (n <= 0) {
- LogPrintf(LogERROR, "read from tun: Only %d bytes read\n", n);
- continue;
- }
- if (!tun_check_header(tun, AF_INET))
- continue;
- if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) {
- /* we've been asked to send something addressed *to* us :( */
- if (VarLoopback) {
- pri = PacketCheck(rbuff, n, FL_IN);
- if (pri >= 0) {
- struct mbuf *bp;
-#ifndef NOALIAS
- if (mode & MODE_ALIAS) {
- VarPacketAliasIn(rbuff, sizeof rbuff);
- n = ntohs(((struct ip *) rbuff)->ip_len);
- }
-#endif
- bp = mballoc(n, MB_IPIN);
- memcpy(MBUF_CTOP(bp), rbuff, n);
- IpInput(bp);
- LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n");
- }
- continue;
- } else
- LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
+ for (i = 0; i <= nfds; i++)
+ if (FD_ISSET(i, &efds)) {
+ log_Printf(LogALERT, "Exception detected on descriptor %d\n", i);
+ break;
}
- /*
- * Process on-demand dialup. Output packets are queued within tunnel
- * device until IPCP is opened.
- */
- if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO) &&
- (pri = PacketCheck(rbuff, n, FL_DIAL)) >= 0)
- dial_up = 1;
+ if (i <= nfds)
+ break;
- pri = PacketCheck(rbuff, n, FL_OUT);
- if (pri >= 0) {
-#ifndef NOALIAS
- if (mode & MODE_ALIAS) {
- VarPacketAliasOut(rbuff, sizeof rbuff);
- n = ntohs(((struct ip *) rbuff)->ip_len);
- }
-#endif
- IpEnqueue(pri, rbuff, n);
- }
- }
- }
- LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
+ if (descriptor_IsSet(&server.desc, &rfds))
+ descriptor_Read(&server.desc, bundle, &rfds);
+
+ if (descriptor_IsSet(&bundle->desc, &wfds))
+ descriptor_Write(&bundle->desc, bundle, &wfds);
+
+ if (descriptor_IsSet(&bundle->desc, &rfds))
+ descriptor_Read(&bundle->desc, bundle, &rfds);
+ } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle));
+
+ log_Printf(LogDEBUG, "DoLoop done.\n");
}
diff --git a/usr.sbin/ppp/main.h b/usr.sbin/ppp/main.h
index 8e151ddd3d99..8d84cafffa87 100644
--- a/usr.sbin/ppp/main.h
+++ b/usr.sbin/ppp/main.h
@@ -17,15 +17,9 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: main.h,v 1.8 1997/11/22 03:37:39 brian Exp $
+ * $Id: main.h,v 1.9.2.9 1998/04/07 00:54:08 brian Exp $
*
*/
-extern int TermMode;
-extern int tunno;
-
extern void Cleanup(int);
-extern void TtyTermMode(void);
-extern void PacketMode(int);
-extern void TtyOldMode(void);
-extern void TtyCommandMode(int);
+extern void AbortProgram(int);
diff --git a/usr.sbin/ppp/mbuf.c b/usr.sbin/ppp/mbuf.c
index 0b1c2df5c110..fc30aeb09d59 100644
--- a/usr.sbin/ppp/mbuf.c
+++ b/usr.sbin/ppp/mbuf.c
@@ -17,33 +17,33 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: mbuf.c,v 1.12 1997/12/28 02:56:42 brian Exp $
+ * $Id: mbuf.c,v 1.13.2.11 1998/05/01 19:25:19 brian Exp $
*
*/
-#include <sys/param.h>
-#include <netinet/in.h>
+#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
+#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
-#include "defs.h"
-#include "loadalias.h"
-#include "vars.h"
-#include "server.h"
+#include "descriptor.h"
+#include "prompt.h"
+#include "main.h"
static struct memmap {
struct mbuf *queue;
int count;
-} MemMap[MB_MAX + 2];
+} MemMap[MB_MAX + 2];
static int totalalloced;
int
-plength(struct mbuf * bp)
+mbuf_Length(struct mbuf * bp)
{
int len;
@@ -53,25 +53,23 @@ plength(struct mbuf * bp)
}
struct mbuf *
-mballoc(int cnt, int type)
+mbuf_Alloc(int cnt, int type)
{
u_char *p;
struct mbuf *bp;
if (type > MB_MAX)
- LogPrintf(LogERROR, "Bad mbuf type %d\n", type);
+ log_Printf(LogERROR, "Bad mbuf type %d\n", type);
bp = (struct mbuf *) malloc(sizeof(struct mbuf));
if (bp == NULL) {
- LogPrintf(LogALERT, "failed to allocate memory: %u\n", sizeof(struct mbuf));
- ServerClose();
- exit(1);
+ log_Printf(LogALERT, "failed to allocate memory: %u\n", sizeof(struct mbuf));
+ AbortProgram(EX_OSERR);
}
memset(bp, '\0', sizeof(struct mbuf));
p = (u_char *) malloc(cnt);
if (p == NULL) {
- LogPrintf(LogALERT, "failed to allocate memory: %d\n", cnt);
- ServerClose();
- exit(1);
+ log_Printf(LogALERT, "failed to allocate memory: %d\n", cnt);
+ AbortProgram(EX_OSERR);
}
MemMap[type].count += cnt;
totalalloced += cnt;
@@ -83,7 +81,7 @@ mballoc(int cnt, int type)
}
struct mbuf *
-mbfree(struct mbuf * bp)
+mbuf_FreeSeg(struct mbuf * bp)
{
struct mbuf *nbp;
@@ -99,14 +97,14 @@ mbfree(struct mbuf * bp)
}
void
-pfree(struct mbuf * bp)
+mbuf_Free(struct mbuf * bp)
{
while (bp)
- bp = mbfree(bp);
+ bp = mbuf_FreeSeg(bp);
}
struct mbuf *
-mbread(struct mbuf * bp, u_char * ptr, int len)
+mbuf_Read(struct mbuf * bp, u_char * ptr, int len)
{
int nb;
@@ -124,7 +122,7 @@ mbread(struct mbuf * bp, u_char * ptr, int len)
#ifdef notdef
bp = bp->next;
#else
- bp = mbfree(bp);
+ bp = mbuf_FreeSeg(bp);
#endif
}
}
@@ -132,12 +130,12 @@ mbread(struct mbuf * bp, u_char * ptr, int len)
}
void
-mbwrite(struct mbuf * bp, u_char * ptr, int cnt)
+mbuf_Write(struct mbuf * bp, u_char * ptr, int cnt)
{
int plen;
int nb;
- plen = plength(bp);
+ plen = mbuf_Length(bp);
if (plen < cnt)
cnt = plen;
@@ -150,26 +148,65 @@ mbwrite(struct mbuf * bp, u_char * ptr, int cnt)
}
int
-ShowMemMap(struct cmdargs const *arg)
+mbuf_Show(struct cmdargs const *arg)
{
+ /* Watch it - ~m calls us with arg == NULL */
int i;
+ static const char *mbuftype[] = {
+ "async", "fsm", "hdlcout", "ipin", "echo", "lqr", "link", "vjcomp",
+ "ipq", "mp" };
- if (!VarTerm)
- return 1;
+ for (i = 1; i < MB_MAX; i += 2)
+ prompt_Printf(arg->prompt, "%10.10s: %04d\t%10.10s: %04d\n",
+ mbuftype[i-1], MemMap[i].count, mbuftype[i], MemMap[i+1].count);
- for (i = 0; i <= MB_MAX; i += 2)
- fprintf(VarTerm, "%d: %d %d: %d\n",
- i, MemMap[i].count, i + 1, MemMap[i + 1].count);
+ if (i == MB_MAX)
+ prompt_Printf(arg->prompt, "%10.10s: %04d\n",
+ mbuftype[i-1], MemMap[i].count);
return 0;
}
void
-LogMemory()
+mbuf_Log()
{
- LogPrintf(LogDEBUG, "LogMemory: mem alloced: %d\n", totalalloced);
- LogPrintf(LogDEBUG, "LogMemory: 1: %d 2: %d 3: %d 4: %d\n",
+ log_Printf(LogDEBUG, "mbuf_Log: mem alloced: %d\n", totalalloced);
+ log_Printf(LogDEBUG, "mbuf_Log: 1: %d 2: %d 3: %d 4: %d\n",
MemMap[1].count, MemMap[2].count, MemMap[3].count, MemMap[4].count);
- LogPrintf(LogDEBUG, "LogMemory: 5: %d 6: %d 7: %d 8: %d\n",
+ log_Printf(LogDEBUG, "mbuf_Log: 5: %d 6: %d 7: %d 8: %d\n",
MemMap[5].count, MemMap[6].count, MemMap[7].count, MemMap[8].count);
+ log_Printf(LogDEBUG, "mbuf_Log: 9: %d 10: %d\n",
+ MemMap[9].count, MemMap[10].count);
+}
+
+struct mbuf *
+mbuf_Dequeue(struct mqueue *q)
+{
+ struct mbuf *bp;
+
+ log_Printf(LogDEBUG, "mbuf_Dequeue: queue len = %d\n", q->qlen);
+ bp = q->top;
+ if (bp) {
+ q->top = q->top->pnext;
+ q->qlen--;
+ if (q->top == NULL) {
+ q->last = q->top;
+ if (q->qlen)
+ log_Printf(LogERROR, "mbuf_Dequeue: Not zero (%d)!!!\n", q->qlen);
+ }
+ }
+
+ return bp;
+}
+
+void
+mbuf_Enqueue(struct mqueue *queue, struct mbuf *bp)
+{
+ if (queue->last) {
+ queue->last->pnext = bp;
+ queue->last = bp;
+ } else
+ queue->last = queue->top = bp;
+ queue->qlen++;
+ log_Printf(LogDEBUG, "mbuf_Enqueue: len = %d\n", queue->qlen);
}
diff --git a/usr.sbin/ppp/mbuf.h b/usr.sbin/ppp/mbuf.h
index da6255ca04ab..4c7612f313e7 100644
--- a/usr.sbin/ppp/mbuf.h
+++ b/usr.sbin/ppp/mbuf.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: mbuf.h,v 1.10 1997/12/03 10:23:50 brian Exp $
+ * $Id: mbuf.h,v 1.11.2.5 1998/05/01 19:25:24 brian Exp $
*
* TODO:
*/
@@ -44,17 +44,21 @@ struct mqueue {
#define MB_IPIN 4
#define MB_ECHO 5
#define MB_LQR 6
-#define MB_MODEM 7
+#define MB_LINK 7
#define MB_VJCOMP 8
-#define MB_LOG 9
-#define MB_IPQ 10
-#define MB_MAX MB_IPQ
+#define MB_IPQ 9
+#define MB_MP 10
+#define MB_MAX MB_MP
-extern int plength(struct mbuf *);
-extern struct mbuf *mballoc(int, int);
-extern struct mbuf *mbfree(struct mbuf *);
-extern void pfree(struct mbuf *);
-extern void mbwrite(struct mbuf *, u_char *, int);
-extern struct mbuf *mbread(struct mbuf *, u_char *, int);
-extern void LogMemory(void);
-extern int ShowMemMap(struct cmdargs const *);
+struct cmdargs;
+
+extern int mbuf_Length(struct mbuf *);
+extern struct mbuf *mbuf_Alloc(int, int);
+extern struct mbuf *mbuf_FreeSeg(struct mbuf *);
+extern void mbuf_Free(struct mbuf *);
+extern void mbuf_Write(struct mbuf *, u_char *, int);
+extern struct mbuf *mbuf_Read(struct mbuf *, u_char *, int);
+extern void mbuf_Log(void);
+extern int mbuf_Show(struct cmdargs const *);
+extern void mbuf_Enqueue(struct mqueue *, struct mbuf *);
+extern struct mbuf *mbuf_Dequeue(struct mqueue *);
diff --git a/usr.sbin/ppp/modem.c b/usr.sbin/ppp/modem.c
index acdfcacdac81..82bc11315d87 100644
--- a/usr.sbin/ppp/modem.c
+++ b/usr.sbin/ppp/modem.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: modem.c,v 1.79 1998/03/06 00:35:30 brian Exp $
+ * $Id: modem.c,v 1.77.2.71 1998/05/19 21:51:24 brian Exp $
*
* TODO:
*/
@@ -26,6 +26,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <errno.h>
#include <fcntl.h>
@@ -35,8 +38,14 @@
#include <string.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
#include <unistd.h>
-#include <utmp.h>
+#ifdef __OpenBSD__
+#include <util.h>
+#else
+#include <libutil.h>
+#endif
#include "command.h"
#include "mbuf.h"
@@ -45,84 +54,99 @@
#include "id.h"
#include "timer.h"
#include "fsm.h"
+#include "lqr.h"
#include "hdlc.h"
#include "lcp.h"
-#include "ip.h"
#include "modem.h"
-#include "loadalias.h"
-#include "vars.h"
-#include "main.h"
-#include "chat.h"
#include "throughput.h"
-#ifdef __OpenBSD__
-#include <util.h>
-#else
-#include <libutil.h>
-#endif
-
-#ifndef O_NONBLOCK
-#ifdef O_NDELAY
-#define O_NONBLOCK O_NDELAY
-#endif
-#endif
-
-static int mbits; /* Current DCD status */
-static int connect_count;
-static struct pppTimer ModemTimer;
-
-#define Online (mbits & TIOCM_CD)
+#include "async.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "ccp.h"
+#include "link.h"
+#include "physical.h"
+#include "mp.h"
+#include "bundle.h"
+#include "prompt.h"
+#include "chat.h"
+#include "auth.h"
+#include "chap.h"
+#include "datalink.h"
+#include "systems.h"
-static struct mbuf *modemout;
-static struct mqueue OutputQueues[PRI_LINK + 1];
-static int dev_is_modem;
-static struct pppThroughput throughput;
-static void CloseLogicalModem(void);
+static void modem_DescriptorWrite(struct descriptor *, struct bundle *,
+ const fd_set *);
+static void modem_DescriptorRead(struct descriptor *, struct bundle *,
+ const fd_set *);
+static int modem_UpdateSet(struct descriptor *, fd_set *, fd_set *, fd_set *,
+ int *);
-void
-Enqueue(struct mqueue * queue, struct mbuf * bp)
+struct physical *
+modem_Create(struct datalink *dl, int type)
{
- if (queue->last) {
- queue->last->pnext = bp;
- queue->last = bp;
- } else
- queue->last = queue->top = bp;
- queue->qlen++;
- LogPrintf(LogDEBUG, "Enqueue: len = %d\n", queue->qlen);
+ struct physical *p;
+
+ p = (struct physical *)malloc(sizeof(struct physical));
+ if (!p)
+ return NULL;
+
+ p->link.type = PHYSICAL_LINK;
+ p->link.name = dl->name;
+ p->link.len = sizeof *p;
+ throughput_init(&p->link.throughput);
+ memset(&p->Timer, '\0', sizeof p->Timer);
+ memset(p->link.Queue, '\0', sizeof p->link.Queue);
+ memset(p->link.proto_in, '\0', sizeof p->link.proto_in);
+ memset(p->link.proto_out, '\0', sizeof p->link.proto_out);
+
+ p->desc.type = PHYSICAL_DESCRIPTOR;
+ p->desc.UpdateSet = modem_UpdateSet;
+ p->desc.IsSet = physical_IsSet;
+ p->desc.Read = modem_DescriptorRead;
+ p->desc.Write = modem_DescriptorWrite;
+ p->type = type;
+
+ hdlc_Init(&p->hdlc, &p->link.lcp);
+ async_Init(&p->async);
+
+ p->fd = -1;
+ p->mbits = 0;
+ p->dev_is_modem = 0;
+ p->out = NULL;
+ p->connect_count = 0;
+ p->dl = dl;
+
+ *p->name.full = '\0';
+ p->name.base = p->name.full;
+
+ p->Utmp = 0;
+
+ p->cfg.rts_cts = MODEM_CTSRTS;
+ p->cfg.speed = MODEM_SPEED;
+ p->cfg.parity = CS8;
+ strncpy(p->cfg.devlist, MODEM_LIST, sizeof p->cfg.devlist - 1);
+ p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
+
+ lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp);
+ ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp);
+
+ return p;
}
-struct mbuf *
-Dequeue(struct mqueue *queue)
-{
- struct mbuf *bp;
-
- LogPrintf(LogDEBUG, "Dequeue: len = %d\n", queue->qlen);
- bp = queue->top;
- if (bp) {
- queue->top = queue->top->pnext;
- queue->qlen--;
- if (queue->top == NULL) {
- queue->last = queue->top;
- if (queue->qlen)
- LogPrintf(LogERROR, "Dequeue: Not zero (%d)!!!\n", queue->qlen);
- }
- }
- return (bp);
-}
+/* XXX-ML this should probably change when we add support for other
+ types of devices */
+#define Online(modem) ((modem)->mbits & TIOCM_CD)
-void
-SequenceQueues()
-{
- LogPrintf(LogDEBUG, "SequenceQueues\n");
- while (OutputQueues[PRI_NORMAL].qlen)
- Enqueue(OutputQueues + PRI_LINK, Dequeue(OutputQueues + PRI_NORMAL));
-}
+static void modem_LogicalClose(struct physical *);
-static struct speeds {
+static const struct speeds {
int nspeed;
speed_t speed;
-} speeds[] = {
-
+} speeds[] = {
#ifdef B50
{ 50, B50, },
#endif
@@ -203,7 +227,7 @@ static struct speeds {
static int
SpeedToInt(speed_t speed)
{
- struct speeds *sp;
+ const struct speeds *sp;
for (sp = speeds; sp->nspeed; sp++) {
if (sp->speed == speed) {
@@ -216,7 +240,7 @@ SpeedToInt(speed_t speed)
speed_t
IntToSpeed(int nspeed)
{
- struct speeds *sp;
+ const struct speeds *sp;
for (sp = speeds; sp->nspeed; sp++) {
if (sp->nspeed == nspeed) {
@@ -227,79 +251,76 @@ IntToSpeed(int nspeed)
}
static void
-ModemSetDevice(const char *name)
+modem_SetDevice(struct physical *physical, const char *name)
{
- strncpy(VarDevice, name, sizeof VarDevice - 1);
- VarDevice[sizeof VarDevice - 1] = '\0';
- VarBaseDevice = strncmp(VarDevice, "/dev/", 5) ? VarDevice : VarDevice + 5;
-}
+ int len = strlen(_PATH_DEV);
-void
-DownConnection()
-{
- LogPrintf(LogPHASE, "Disconnected!\n");
- LcpDown();
+ strncpy(physical->name.full, name, sizeof physical->name.full - 1);
+ physical->name.full[sizeof physical->name.full - 1] = '\0';
+ physical->name.base = strncmp(physical->name.full, _PATH_DEV, len) ?
+ physical->name.full : physical->name.full + len;
}
/*
- * ModemTimeout() watches DCD signal and notifies if it's status is changed.
+ * modem_Timeout() watches DCD signal and notifies if it's status is changed.
*
*/
-void
-ModemTimeout(void *data)
+static void
+modem_Timeout(void *data)
{
- int ombits = mbits;
+ struct physical *modem = data;
+ int ombits = modem->mbits;
int change;
- StopTimer(&ModemTimer);
- StartTimer(&ModemTimer);
+ timer_Stop(&modem->Timer);
+ timer_Start(&modem->Timer);
- if (dev_is_modem) {
- if (modem >= 0) {
- if (ioctl(modem, TIOCMGET, &mbits) < 0) {
- LogPrintf(LogPHASE, "ioctl error (%s)!\n", strerror(errno));
- DownConnection();
+ if (modem->dev_is_modem) {
+ if (modem->fd >= 0) {
+ if (ioctl(modem->fd, TIOCMGET, &modem->mbits) < 0) {
+ log_Printf(LogPHASE, "%s: ioctl error (%s)!\n", modem->link.name,
+ strerror(errno));
+ datalink_Down(modem->dl, 0);
return;
}
} else
- mbits = 0;
- change = ombits ^ mbits;
+ modem->mbits = 0;
+ change = ombits ^ modem->mbits;
if (change & TIOCM_CD) {
- if (Online) {
- LogPrintf(LogDEBUG, "ModemTimeout: offline -> online\n");
- /*
- * In dedicated mode, start packet mode immediate after we detected
- * carrier.
- */
- if (mode & MODE_DEDICATED)
- PacketMode(VarOpenMode);
- } else {
- LogPrintf(LogDEBUG, "ModemTimeout: online -> offline\n");
- reconnect(RECON_TRUE);
- DownConnection();
+ if (modem->mbits & TIOCM_CD)
+ log_Printf(LogDEBUG, "%s: offline -> online\n", modem->link.name);
+ else {
+ log_Printf(LogDEBUG, "%s: online -> offline\n", modem->link.name);
+ log_Printf(LogPHASE, "%s: Carrier lost\n", modem->link.name);
+ datalink_Down(modem->dl, 0);
}
- }
- else
- LogPrintf(LogDEBUG, "ModemTimeout: Still %sline\n",
- Online ? "on" : "off");
- } else if (!Online) {
- /* mbits was set to zero in OpenModem() */
- mbits = TIOCM_CD;
+ } else
+ log_Printf(LogDEBUG, "%s: Still %sline\n", modem->link.name,
+ Online(modem) ? "on" : "off");
+ } else if (!Online(modem)) {
+ /* mbits was set to zero in modem_Open() */
+ modem->mbits = TIOCM_CD;
}
}
static void
-StartModemTimer(void)
+modem_StartTimer(struct bundle *bundle, struct physical *modem)
{
- StopTimer(&ModemTimer);
- ModemTimer.state = TIMER_STOPPED;
- ModemTimer.load = SECTICKS;
- ModemTimer.func = ModemTimeout;
- LogPrintf(LogDEBUG, "ModemTimer using ModemTimeout() - %p\n", ModemTimeout);
- StartTimer(&ModemTimer);
+ struct pppTimer *ModemTimer;
+
+ ModemTimer = &modem->Timer;
+
+ timer_Stop(ModemTimer);
+ ModemTimer->load = SECTICKS;
+ ModemTimer->func = modem_Timeout;
+ ModemTimer->name = "modem CD";
+ ModemTimer->arg = modem;
+ log_Printf(LogDEBUG, "%s: Using modem_Timeout [%p]\n",
+ modem->link.name, modem_Timeout);
+ timer_Start(ModemTimer);
}
-static struct parity {
+static const struct parity {
const char *name;
const char *name1;
int set;
@@ -313,38 +334,38 @@ static struct parity {
static int
GetParityValue(const char *str)
{
- struct parity *pp;
+ const struct parity *pp;
for (pp = validparity; pp->name; pp++) {
if (strcasecmp(pp->name, str) == 0 ||
strcasecmp(pp->name1, str) == 0) {
- return VarParity = pp->set;
+ return pp->set;
}
}
return (-1);
}
int
-ChangeParity(const char *str)
+modem_SetParity(struct physical *modem, const char *str)
{
struct termios rstio;
int val;
val = GetParityValue(str);
if (val > 0) {
- VarParity = val;
- tcgetattr(modem, &rstio);
+ modem->cfg.parity = val;
+ tcgetattr(modem->fd, &rstio);
rstio.c_cflag &= ~(CSIZE | PARODD | PARENB);
rstio.c_cflag |= val;
- tcsetattr(modem, TCSADRAIN, &rstio);
+ tcsetattr(modem->fd, TCSADRAIN, &rstio);
return 0;
}
- LogPrintf(LogWARN, "ChangeParity: %s: Invalid parity\n", str);
+ log_Printf(LogWARN, "%s: %s: Invalid parity\n", modem->link.name, str);
return -1;
}
static int
-OpenConnection(char *host, char *port)
+OpenConnection(const char *name, char *host, char *port)
{
struct sockaddr_in dest;
int sock;
@@ -358,7 +379,7 @@ OpenConnection(char *host, char *port)
if (hp) {
memcpy(&dest.sin_addr.s_addr, hp->h_addr_list[0], 4);
} else {
- LogPrintf(LogWARN, "OpenConnection: unknown host: %s\n", host);
+ log_Printf(LogWARN, "%s: %s: unknown host\n", name, host);
return (-1);
}
}
@@ -368,45 +389,46 @@ OpenConnection(char *host, char *port)
if (sp) {
dest.sin_port = sp->s_port;
} else {
- LogPrintf(LogWARN, "OpenConnection: unknown service: %s\n", port);
+ log_Printf(LogWARN, "%s: %s: unknown service\n", name, port);
return (-1);
}
}
- LogPrintf(LogPHASE, "Connecting to %s:%s\n", host, port);
+ log_Printf(LogPHASE, "%s: Connecting to %s:%s\n", name, host, port);
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
return (sock);
}
if (connect(sock, (struct sockaddr *)&dest, sizeof dest) < 0) {
- LogPrintf(LogWARN, "OpenConnection: connection failed.\n");
+ log_Printf(LogWARN, "%s: connect: %s\n", name, strerror(errno));
+ close(sock);
return (-1);
}
- LogPrintf(LogDEBUG, "OpenConnection: modem fd is %d.\n", sock);
return (sock);
}
-static char fn[MAXPATHLEN];
-
static int
-LockModem(void)
+modem_lock(struct physical *modem, int tunno)
{
int res;
FILE *lockfile;
+ char fn[MAXPATHLEN];
- if (*VarDevice != '/')
+ if (*modem->name.full != '/')
return 0;
- if (!(mode & MODE_DIRECT) && (res = ID0uu_lock(VarBaseDevice)) != UU_LOCK_OK) {
+ if (modem->type != PHYS_DIRECT &&
+ (res = ID0uu_lock(modem->name.base)) != UU_LOCK_OK) {
if (res == UU_LOCK_INUSE)
- LogPrintf(LogPHASE, "Modem %s is in use\n", VarDevice);
+ log_Printf(LogPHASE, "%s: %s is in use\n",
+ modem->link.name, modem->name.full);
else
- LogPrintf(LogPHASE, "Modem %s is in use: uu_lock: %s\n",
- VarDevice, uu_lockerr(res));
+ log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n",
+ modem->link.name, modem->name.full, uu_lockerr(res));
return (-1);
}
- snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, VarBaseDevice);
+ snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, modem->name.base);
lockfile = ID0fopen(fn, "w");
if (lockfile != NULL) {
fprintf(lockfile, "tun%d\n", tunno);
@@ -414,195 +436,255 @@ LockModem(void)
}
#ifndef RELEASE_CRUNCH
else
- LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", fn, strerror(errno));
+ log_Printf(LogALERT, "%s: Can't create %s: %s\n",
+ modem->link.name, fn, strerror(errno));
#endif
return 0;
}
static void
-UnlockModem(void)
+modem_Unlock(struct physical *modem)
{
- if (*VarDevice != '/')
+ char fn[MAXPATHLEN];
+
+ if (*modem->name.full != '/')
return;
- snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, VarBaseDevice);
+ snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, modem->name.base);
#ifndef RELEASE_CRUNCH
if (ID0unlink(fn) == -1)
- LogPrintf(LogALERT, "Warning: Can't remove %s: %s\n", fn, strerror(errno));
+ log_Printf(LogALERT, "%s: Can't remove %s: %s\n",
+ modem->link.name, fn, strerror(errno));
#else
ID0unlink(fn);
#endif
- if (!(mode & MODE_DIRECT) && ID0uu_unlock(VarBaseDevice) == -1)
- LogPrintf(LogALERT, "Warning: Can't uu_unlock %s\n", fn);
+ if (modem->type != PHYS_DIRECT && ID0uu_unlock(modem->name.base) == -1)
+ log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", modem->link.name, fn);
}
static void
-HaveModem(void)
+modem_Found(struct physical *modem, struct bundle *bundle)
{
- throughput_start(&throughput);
- connect_count++;
- LogPrintf(LogPHASE, "Connected!\n");
+ throughput_start(&modem->link.throughput, "modem throughput",
+ Enabled(bundle, OPT_THROUGHPUT));
+ modem->connect_count++;
+ log_Printf(LogPHASE, "%s: Connected!\n", modem->link.name);
}
-static struct termios modemios;
-
int
-OpenModem()
+modem_Open(struct physical *modem, struct bundle *bundle)
{
struct termios rstio;
int oldflag;
char *host, *port;
char *cp;
- char tmpDeviceList[sizeof VarDeviceList];
+ char tmpDeviceList[sizeof modem->cfg.devlist];
char *tmpDevice;
- if (modem >= 0)
- LogPrintf(LogDEBUG, "OpenModem: Modem is already open!\n");
+ if (modem->fd >= 0)
+ log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", modem->link.name);
/* We're going back into "term" mode */
- else if (mode & MODE_DIRECT) {
+ else if (modem->type == PHYS_DIRECT) {
if (isatty(STDIN_FILENO)) {
- LogPrintf(LogDEBUG, "OpenModem(direct): Modem is a tty\n");
- ModemSetDevice(ttyname(STDIN_FILENO));
- if (LockModem() == -1) {
+ log_Printf(LogDEBUG, "%s: Open(direct): Modem is a tty\n",
+ modem->link.name);
+ modem_SetDevice(modem, ttyname(STDIN_FILENO));
+ if (modem_lock(modem, bundle->unit) == -1) {
close(STDIN_FILENO);
return -1;
}
- modem = STDIN_FILENO;
- HaveModem();
+ modem->fd = STDIN_FILENO;
+ modem_Found(modem, bundle);
} else {
- LogPrintf(LogDEBUG, "OpenModem(direct): Modem is not a tty\n");
- ModemSetDevice("");
- /* We don't call ModemTimeout() with this type of connection */
- HaveModem();
- return modem = STDIN_FILENO;
+ log_Printf(LogDEBUG, "%s: Open(direct): Modem is not a tty\n",
+ modem->link.name);
+ modem_SetDevice(modem, "");
+ /* We don't call modem_Timeout() with this type of connection */
+ modem_Found(modem, bundle);
+ return modem->fd = STDIN_FILENO;
}
} else {
- strncpy(tmpDeviceList, VarDeviceList, sizeof tmpDeviceList - 1);
+ strncpy(tmpDeviceList, modem->cfg.devlist, sizeof tmpDeviceList - 1);
tmpDeviceList[sizeof tmpDeviceList - 1] = '\0';
- for(tmpDevice=strtok(tmpDeviceList, ","); tmpDevice && (modem < 0);
- tmpDevice=strtok(NULL,",")) {
- ModemSetDevice(tmpDevice);
- if (strncmp(VarDevice, "/dev/", 5) == 0) {
- if (LockModem() == -1) {
- modem = -1;
- }
- else {
- modem = ID0open(VarDevice, O_RDWR | O_NONBLOCK);
- if (modem < 0) {
- LogPrintf(LogERROR, "OpenModem failed: %s: %s\n", VarDevice,
- strerror(errno));
- UnlockModem();
- modem = -1;
- }
- else {
- HaveModem();
- LogPrintf(LogDEBUG, "OpenModem: Modem is %s\n", VarDevice);
+ for(tmpDevice=strtok(tmpDeviceList, ", "); tmpDevice && modem->fd < 0;
+ tmpDevice=strtok(NULL,", ")) {
+ modem_SetDevice(modem, tmpDevice);
+
+ if (*modem->name.full == '/') {
+ if (modem_lock(modem, bundle->unit) != -1) {
+ modem->fd = ID0open(modem->name.full, O_RDWR | O_NONBLOCK);
+ if (modem->fd < 0) {
+ log_Printf(LogPHASE, "%s: Open(\"%s\"): %s\n",
+ modem->link.name, modem->name.full, strerror(errno));
+ modem_Unlock(modem);
+ } else {
+ modem_Found(modem, bundle);
+ log_Printf(LogDEBUG, "%s: Opened %s\n",
+ modem->link.name, modem->name.full);
}
}
+ } else if (*modem->name.full == '!') {
+ /* PPP via an external program */
+ /*
+ * XXX: Fix me - this should be another sort of link (similar to a
+ * physical
+ */
+ int fids[2];
+
+ modem->name.base = modem->name.full + 1;
+ if (pipe(fids) < 0)
+ log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
+ strerror(errno));
+ else {
+ int stat;
+ pid_t pid;
+
+ stat = fcntl(fids[0], F_GETFL, 0);
+ if (stat > 0) {
+ stat |= O_NONBLOCK;
+ fcntl(fids[0], F_SETFL, stat);
+ }
+ switch ((pid = fork())) {
+ case -1:
+ log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
+ strerror(errno));
+ break;
+ case 0:
+ close(fids[0]);
+ timer_TermService();
+
+ fids[1] = fcntl(fids[1], F_DUPFD, 3);
+ dup2(fids[1], STDIN_FILENO);
+ dup2(fids[1], STDOUT_FILENO);
+ dup2(fids[1], STDERR_FILENO);
+ setuid(geteuid());
+ if (fork())
+ exit(127);
+ execlp(modem->name.base, modem->name.base, NULL);
+ fprintf(stderr, "execvp failed: %s: %s\n", modem->name.base,
+ strerror(errno));
+ exit(127);
+ break;
+ default:
+ close(fids[1]);
+ modem->fd = fids[0];
+ waitpid(pid, &stat, 0);
+ break;
+ }
+ }
} else {
/* PPP over TCP */
- cp = strchr(VarDevice, ':');
+ /*
+ * XXX: Fix me - this should be another sort of link (similar to a
+ * physical
+ */
+ cp = strchr(modem->name.full, ':');
if (cp) {
*cp = '\0';
- host = VarDevice;
+ host = modem->name.full;
port = cp + 1;
if (*host && *port) {
- modem = OpenConnection(host, port);
- *cp = ':'; /* Don't destroy VarDevice */
- if (modem < 0)
- return (-1);
- HaveModem();
- LogPrintf(LogDEBUG, "OpenModem: Modem is socket %s\n", VarDevice);
+ modem->fd = OpenConnection(modem->link.name, host, port);
+ *cp = ':'; /* Don't destroy name.full */
+ if (modem->fd >= 0) {
+ modem_Found(modem, bundle);
+ log_Printf(LogDEBUG, "%s: Opened socket %s\n", modem->link.name,
+ modem->name.full);
+ }
} else {
- *cp = ':'; /* Don't destroy VarDevice */
- LogPrintf(LogERROR, "Invalid host:port: \"%s\"\n", VarDevice);
- return (-1);
+ *cp = ':'; /* Don't destroy name.full */
+ log_Printf(LogERROR, "%s: Invalid host:port: \"%s\"\n",
+ modem->link.name, modem->name.full);
}
} else {
- LogPrintf(LogERROR,
- "Device (%s) must be in /dev or be a host:port pair\n",
- VarDevice);
- return (-1);
+ log_Printf(LogERROR, "%s: Device (%s) must begin with a '/',"
+ " a '!' or be a host:port pair\n", modem->link.name,
+ modem->name.full);
}
}
}
- if (modem < 0) return modem;
+ if (modem->fd < 0)
+ return modem->fd;
}
/*
* If we are working on tty device, change it's mode into the one desired
- * for further operation. In this implementation, we assume that modem is
- * configuted to use CTS/RTS flow control.
+ * for further operation.
*/
- mbits = 0;
- dev_is_modem = isatty(modem) || DEV_IS_SYNC;
- if (DEV_IS_SYNC)
- nointr_sleep(1);
- if (dev_is_modem && !DEV_IS_SYNC) {
- tcgetattr(modem, &rstio);
- modemios = rstio;
- LogPrintf(LogDEBUG, "OpenModem: modem = %d\n", modem);
- LogPrintf(LogDEBUG, "OpenModem: modem (get): iflag = %x, oflag = %x,"
- " cflag = %x\n", rstio.c_iflag, rstio.c_oflag, rstio.c_cflag);
+ modem->mbits = 0;
+ modem->dev_is_modem = isatty(modem->fd) || physical_IsSync(modem);
+ if (modem->dev_is_modem && !physical_IsSync(modem)) {
+ tcgetattr(modem->fd, &rstio);
+ modem->ios = rstio;
+ log_Printf(LogDEBUG, "%s: Open: modem (get): fd = %d, iflag = %lx, "
+ "oflag = %lx, cflag = %lx\n", modem->link.name, modem->fd,
+ (u_long)rstio.c_iflag, (u_long)rstio.c_oflag,
+ (u_long)rstio.c_cflag);
cfmakeraw(&rstio);
- if (VarCtsRts)
+ if (modem->cfg.rts_cts)
rstio.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
else {
rstio.c_cflag |= CLOCAL;
rstio.c_iflag |= IXOFF;
}
rstio.c_iflag |= IXON;
- if (!(mode & MODE_DEDICATED))
+ if (modem->type != PHYS_DEDICATED)
rstio.c_cflag |= HUPCL;
- if ((mode & MODE_DIRECT) == 0) {
- /*
- * If we are working as direct mode, don't change tty speed.
- */
+ if (modem->type != PHYS_DIRECT) {
+ /* Change tty speed when we're not in -direct mode */
rstio.c_cflag &= ~(CSIZE | PARODD | PARENB);
- rstio.c_cflag |= VarParity;
- if (cfsetspeed(&rstio, IntToSpeed(VarSpeed)) == -1) {
- LogPrintf(LogWARN, "Unable to set modem speed (modem %d to %d)\n",
- modem, VarSpeed);
- }
+ rstio.c_cflag |= modem->cfg.parity;
+ if (cfsetspeed(&rstio, IntToSpeed(modem->cfg.speed)) == -1)
+ log_Printf(LogWARN, "%s: %s: Unable to set speed to %d\n",
+ modem->link.name, modem->name.full, modem->cfg.speed);
}
- tcsetattr(modem, TCSADRAIN, &rstio);
- LogPrintf(LogDEBUG, "modem (put): iflag = %x, oflag = %x, cflag = %x\n",
- rstio.c_iflag, rstio.c_oflag, rstio.c_cflag);
-
- if (!(mode & MODE_DIRECT))
- if (ioctl(modem, TIOCMGET, &mbits)) {
- LogPrintf(LogERROR, "OpenModem: Cannot get modem status: %s\n",
- strerror(errno));
- CloseLogicalModem();
+ tcsetattr(modem->fd, TCSADRAIN, &rstio);
+ log_Printf(LogDEBUG, "%s: modem (put): iflag = %lx, oflag = %lx, "
+ "cflag = %lx\n", modem->link.name, (u_long)rstio.c_iflag,
+ (u_long)rstio.c_oflag, (u_long)rstio.c_cflag);
+
+ if (ioctl(modem->fd, TIOCMGET, &modem->mbits) == -1) {
+ if (modem->type != PHYS_DIRECT) {
+ log_Printf(LogERROR, "%s: Open: Cannot get modem status: %s\n",
+ modem->link.name, strerror(errno));
+ modem_LogicalClose(modem);
return (-1);
- }
- LogPrintf(LogDEBUG, "OpenModem: modem control = %o\n", mbits);
+ } else
+ modem->mbits = TIOCM_CD;
+ }
+ log_Printf(LogDEBUG, "%s: Open: modem control = %o\n",
+ modem->link.name, modem->mbits);
- oldflag = fcntl(modem, F_GETFL, 0);
+ oldflag = fcntl(modem->fd, F_GETFL, 0);
if (oldflag < 0) {
- LogPrintf(LogERROR, "OpenModem: Cannot get modem flags: %s\n",
- strerror(errno));
- CloseLogicalModem();
+ log_Printf(LogERROR, "%s: Open: Cannot get modem flags: %s\n",
+ modem->link.name, strerror(errno));
+ modem_LogicalClose(modem);
return (-1);
}
- (void) fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK);
+ fcntl(modem->fd, F_SETFL, oldflag & ~O_NONBLOCK);
+
+ /* We do the timer only for ttys */
+ modem_StartTimer(bundle, modem);
}
- StartModemTimer();
- return (modem);
+ return modem->fd;
}
int
-ModemSpeed()
+modem_Speed(struct physical *modem)
{
struct termios rstio;
- tcgetattr(modem, &rstio);
+ if (!physical_IsATTY(modem))
+ return 115200;
+
+ tcgetattr(modem->fd, &rstio);
return (SpeedToInt(cfgetispeed(&rstio)));
}
@@ -610,328 +692,377 @@ ModemSpeed()
* Put modem tty line into raw mode which is necessary in packet mode operation
*/
int
-RawModem()
+modem_Raw(struct physical *modem, struct bundle *bundle)
{
struct termios rstio;
int oldflag;
- if (!isatty(modem) || DEV_IS_SYNC)
- return (0);
- if (!(mode & MODE_DIRECT) && modem >= 0 && !Online) {
- LogPrintf(LogDEBUG, "RawModem: mode = %d, modem = %d, mbits = %x\n", mode, modem, mbits);
- }
- tcgetattr(modem, &rstio);
+ log_Printf(LogDEBUG, "%s: Entering modem_Raw\n", modem->link.name);
+
+ if (!isatty(modem->fd) || physical_IsSync(modem))
+ return 0;
+
+ if (modem->type != PHYS_DIRECT && modem->fd >= 0 && !Online(modem))
+ log_Printf(LogDEBUG, "%s: Raw: modem = %d, mbits = %x\n",
+ modem->link.name, modem->fd, modem->mbits);
+
+ tcgetattr(modem->fd, &rstio);
cfmakeraw(&rstio);
- if (VarCtsRts)
+ if (modem->cfg.rts_cts)
rstio.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
else
rstio.c_cflag |= CLOCAL;
- if (!(mode & MODE_DEDICATED))
+ if (modem->type != PHYS_DEDICATED)
rstio.c_cflag |= HUPCL;
- tcsetattr(modem, TCSADRAIN, &rstio);
- oldflag = fcntl(modem, F_GETFL, 0);
+
+ tcsetattr(modem->fd, TCSADRAIN, &rstio);
+ oldflag = fcntl(modem->fd, F_GETFL, 0);
if (oldflag < 0)
return (-1);
- (void) fcntl(modem, F_SETFL, oldflag | O_NONBLOCK);
- return (0);
+ fcntl(modem->fd, F_SETFL, oldflag | O_NONBLOCK);
+
+ if (modem->dev_is_modem && ioctl(modem->fd, TIOCMGET, &modem->mbits) == 0 &&
+ !(modem->mbits & TIOCM_CD)) {
+ log_Printf(LogDEBUG, "%s: Switching off timer - %s doesn't support CD\n",
+ modem->link.name, modem->name.full);
+ timer_Stop(&modem->Timer);
+ } else
+ modem_Timeout(modem);
+
+ return 0;
}
static void
-UnrawModem(void)
+modem_Unraw(struct physical *modem)
{
int oldflag;
- if (isatty(modem) && !DEV_IS_SYNC) {
- tcsetattr(modem, TCSAFLUSH, &modemios);
- oldflag = fcntl(modem, F_GETFL, 0);
+ if (isatty(modem->fd) && !physical_IsSync(modem)) {
+ tcsetattr(modem->fd, TCSAFLUSH, &modem->ios);
+ oldflag = fcntl(modem->fd, F_GETFL, 0);
if (oldflag < 0)
return;
- (void) fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK);
+ (void) fcntl(modem->fd, F_SETFL, oldflag & ~O_NONBLOCK);
}
}
-void
-ModemAddInOctets(int n)
+static void
+modem_PhysicalClose(struct physical *modem)
{
- throughput_addin(&throughput, n);
+ log_Printf(LogDEBUG, "%s: Physical Close\n", modem->link.name);
+ close(modem->fd);
+ modem->fd = -1;
+ timer_Stop(&modem->Timer);
+ bundle_SetTtyCommandMode(modem->dl->bundle, modem->dl);
+ throughput_stop(&modem->link.throughput);
+ throughput_log(&modem->link.throughput, LogPHASE, modem->link.name);
}
void
-ModemAddOutOctets(int n)
+modem_Offline(struct physical *modem)
{
- throughput_addout(&throughput, n);
-}
-
-static void
-ClosePhysicalModem(void)
-{
- LogPrintf(LogDEBUG, "ClosePhysicalModem\n");
- close(modem);
- modem = -1;
- throughput_log(&throughput, LogPHASE, "Modem");
+ if (modem->fd >= 0) {
+ struct termios tio;
+
+ modem->mbits &= ~TIOCM_DTR;
+ if (isatty(modem->fd) && Online(modem)) {
+ tcgetattr(modem->fd, &tio);
+ if (cfsetspeed(&tio, B0) == -1)
+ log_Printf(LogWARN, "%s: Unable to set modem to speed 0\n",
+ modem->link.name);
+ else
+ tcsetattr(modem->fd, TCSANOW, &tio);
+ /* nointr_sleep(1); */
+ }
+ log_Printf(LogPHASE, "%s: Disconnected!\n", modem->link.name);
+ }
}
void
-HangupModem(int flag)
+modem_Close(struct physical *modem)
{
- struct termios tio;
-
- LogPrintf(LogDEBUG, "Hangup modem (%s)\n", modem >= 0 ? "open" : "closed");
-
- if (modem < 0)
+ if (modem->fd < 0)
return;
- StopTimer(&ModemTimer);
- throughput_stop(&throughput);
+ log_Printf(LogDEBUG, "%s: Close\n", modem->link.name);
- if (TermMode) {
- LogPrintf(LogDEBUG, "HangupModem: Not in 'term' mode\n");
+ if (!isatty(modem->fd)) {
+ modem_PhysicalClose(modem);
+ *modem->name.full = '\0';
+ modem->name.base = modem->name.full;
return;
}
- if (!isatty(modem)) {
- mbits &= ~TIOCM_DTR;
- ClosePhysicalModem();
- return;
- }
-
- if (modem >= 0 && Online) {
- mbits &= ~TIOCM_DTR;
- tcgetattr(modem, &tio);
- if (cfsetspeed(&tio, B0) == -1) {
- LogPrintf(LogWARN, "Unable to set modem to speed 0\n");
- }
- tcsetattr(modem, TCSANOW, &tio);
- nointr_sleep(1);
- }
-
- if (modem >= 0) {
- char ScriptBuffer[SCRIPT_LEN];
-
- strncpy(ScriptBuffer, VarHangupScript, sizeof ScriptBuffer - 1);
- ScriptBuffer[sizeof ScriptBuffer - 1] = '\0';
- LogPrintf(LogDEBUG, "HangupModem: Script: %s\n", ScriptBuffer);
- if (flag || !(mode & MODE_DEDICATED)) {
- DoChat(ScriptBuffer);
- tcflush(modem, TCIOFLUSH);
- UnrawModem();
- CloseLogicalModem();
- } else {
- /*
- * If we are working as dedicated mode, never close it until we are
- * directed to quit program.
- */
- mbits |= TIOCM_DTR;
- ioctl(modem, TIOCMSET, &mbits);
- DoChat(ScriptBuffer);
- }
+ if (modem->fd >= 0) {
+ tcflush(modem->fd, TCIOFLUSH);
+ modem_Unraw(modem);
+ modem_LogicalClose(modem);
}
}
-static void
-CloseLogicalModem(void)
-{
- LogPrintf(LogDEBUG, "CloseLogicalModem\n");
- if (modem >= 0) {
- if (Utmp) {
- ID0logout(VarBaseDevice);
- Utmp = 0;
- }
- ClosePhysicalModem();
- UnlockModem();
- }
-}
-
-/*
- * Write to modem. Actualy, requested packets are queued, and goes out
- * to the line when ModemStartOutput() is called.
- */
void
-WriteModem(int pri, const char *ptr, int count)
+modem_Destroy(struct physical *modem)
{
- struct mbuf *bp;
-
- bp = mballoc(count, MB_MODEM);
- memcpy(MBUF_CTOP(bp), ptr, count);
-
- /*
- * Should be NORMAL and LINK only. All IP frames get here marked NORMAL.
- */
- Enqueue(&OutputQueues[pri], bp);
+ modem_Close(modem);
+ free(modem);
}
-void
-ModemOutput(int pri, struct mbuf * bp)
-{
- struct mbuf *wp;
- int len;
-
- len = plength(bp);
- wp = mballoc(len, MB_MODEM);
- mbread(bp, MBUF_CTOP(wp), len);
- Enqueue(&OutputQueues[pri], wp);
- ModemStartOutput(modem);
-}
-
-int
-ModemQlen()
+static void
+modem_LogicalClose(struct physical *modem)
{
- struct mqueue *queue;
- int len = 0;
- int i;
-
- for (i = PRI_NORMAL; i <= PRI_LINK; i++) {
- queue = &OutputQueues[i];
- len += queue->qlen;
+ log_Printf(LogDEBUG, "%s: Logical Close\n", modem->link.name);
+ if (modem->fd >= 0) {
+ physical_Logout(modem);
+ modem_PhysicalClose(modem);
+ modem_Unlock(modem);
}
- return (len);
-
+ *modem->name.full = '\0';
+ modem->name.base = modem->name.full;
}
-void
-ModemStartOutput(int fd)
+static void
+modem_DescriptorWrite(struct descriptor *d, struct bundle *bundle,
+ const fd_set *fdset)
{
- struct mqueue *queue;
+ struct physical *modem = descriptor2physical(d);
int nb, nw;
- int i;
-
- if (modemout == NULL && ModemQlen() == 0)
- IpStartOutput();
- if (modemout == NULL) {
- i = PRI_LINK;
- for (queue = &OutputQueues[PRI_LINK]; queue >= OutputQueues; queue--) {
- if (queue->top) {
- modemout = Dequeue(queue);
- if (LogIsKept(LogDEBUG)) {
- if (i > PRI_NORMAL) {
- struct mqueue *q;
-
- q = &OutputQueues[0];
- LogPrintf(LogDEBUG, "ModemStartOutput: Output from queue %d,"
- " normal has %d\n", i, q->qlen);
- }
- LogPrintf(LogDEBUG, "ModemStartOutput: Dequeued %d\n", i);
- }
- break;
- }
- i--;
- }
- }
- if (modemout) {
- nb = modemout->cnt;
- if (nb > 1600)
- nb = 1600;
- nw = write(fd, MBUF_CTOP(modemout), nb);
- LogPrintf(LogDEBUG, "ModemStartOutput: wrote: %d(%d)\n", nw, nb);
- LogDumpBuff(LogDEBUG, "ModemStartOutput: modem write",
- MBUF_CTOP(modemout), nb);
+
+ if (modem->out == NULL)
+ modem->out = link_Dequeue(&modem->link);
+
+ if (modem->out) {
+ nb = modem->out->cnt;
+ nw = physical_Write(modem, MBUF_CTOP(modem->out), nb);
+ log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%d) to %d\n",
+ modem->link.name, nw, nb, modem->fd);
if (nw > 0) {
- modemout->cnt -= nw;
- modemout->offset += nw;
- if (modemout->cnt == 0) {
- modemout = mbfree(modemout);
- LogPrintf(LogDEBUG, "ModemStartOutput: mbfree\n");
- }
+ modem->out->cnt -= nw;
+ modem->out->offset += nw;
+ if (modem->out->cnt == 0)
+ modem->out = mbuf_FreeSeg(modem->out);
} else if (nw < 0) {
if (errno != EAGAIN) {
- LogPrintf(LogERROR, "modem write (%d): %s\n", modem, strerror(errno));
- reconnect(RECON_TRUE);
- DownConnection();
+ log_Printf(LogPHASE, "%s: write (%d): %s\n", modem->link.name,
+ modem->fd, strerror(errno));
+ datalink_Down(modem->dl, 0);
}
}
}
}
int
-DialModem()
-{
- char ScriptBuffer[SCRIPT_LEN];
- int excode;
-
- strncpy(ScriptBuffer, VarDialScript, sizeof ScriptBuffer - 1);
- ScriptBuffer[sizeof ScriptBuffer - 1] = '\0';
- if ((excode = DoChat(ScriptBuffer)) > 0) {
- if (VarTerm)
- fprintf(VarTerm, "dial OK!\n");
- strncpy(ScriptBuffer, VarLoginScript, sizeof ScriptBuffer - 1);
- if ((excode = DoChat(ScriptBuffer)) > 0) {
- VarAltPhone = NULL;
- if (VarTerm)
- fprintf(VarTerm, "login OK!\n");
- return EX_DONE;
- } else if (excode == -1)
- excode = EX_SIG;
- else {
- LogPrintf(LogWARN, "DialModem: login failed.\n");
- excode = EX_NOLOGIN;
- }
- ModemTimeout(NULL); /* Dummy call to check modem status */
- } else if (excode == -1)
- excode = EX_SIG;
- else {
- LogPrintf(LogWARN, "DialModem: dial failed.\n");
- excode = EX_NODIAL;
- }
- HangupModem(0);
- return (excode);
-}
-
-int
-ShowModemStatus(struct cmdargs const *arg)
+modem_ShowStatus(struct cmdargs const *arg)
{
- const char *dev;
+ struct physical *modem = arg->cx->physical;
#ifdef TIOCOUTQ
int nb;
#endif
- if (!VarTerm)
- return 1;
+ prompt_Printf(arg->prompt, "Name: %s\n", modem->link.name);
+ prompt_Printf(arg->prompt, " State: ");
+ if (modem->fd >= 0) {
+ if (isatty(modem->fd))
+ prompt_Printf(arg->prompt, "open, %s carrier\n",
+ Online(modem) ? "with" : "no");
+ else
+ prompt_Printf(arg->prompt, "open\n");
+ } else
+ prompt_Printf(arg->prompt, "closed\n");
+ prompt_Printf(arg->prompt, " Device: %s\n",
+ *modem->name.full ? modem->name.full :
+ modem->type == PHYS_DIRECT ? "unknown" : "N/A");
+
+ prompt_Printf(arg->prompt, " Link Type: %s\n", mode2Nam(modem->type));
+ prompt_Printf(arg->prompt, " Connect Count: %d\n",
+ modem->connect_count);
+#ifdef TIOCOUTQ
+ if (modem->fd >= 0 && ioctl(modem->fd, TIOCOUTQ, &nb) >= 0)
+ prompt_Printf(arg->prompt, " Physical outq: %d\n", nb);
+#endif
- dev = *VarDevice ? VarDevice : "network";
+ prompt_Printf(arg->prompt, " Queued Packets: %d\n",
+ link_QueueLen(&modem->link));
+ prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen);
- fprintf(VarTerm, "device: %s speed: ", dev);
- if (DEV_IS_SYNC)
- fprintf(VarTerm, "sync\n");
+ prompt_Printf(arg->prompt, "\nDefaults:\n");
+ prompt_Printf(arg->prompt, " Device List: %s\n", modem->cfg.devlist);
+ prompt_Printf(arg->prompt, " Characteristics: ");
+ if (physical_IsSync(arg->cx->physical))
+ prompt_Printf(arg->prompt, "sync");
else
- fprintf(VarTerm, "%d\n", VarSpeed);
+ prompt_Printf(arg->prompt, "%dbps", modem->cfg.speed);
- switch (VarParity & CSIZE) {
+ switch (modem->cfg.parity & CSIZE) {
case CS7:
- fprintf(VarTerm, "cs7, ");
+ prompt_Printf(arg->prompt, ", cs7");
break;
case CS8:
- fprintf(VarTerm, "cs8, ");
+ prompt_Printf(arg->prompt, ", cs8");
break;
}
- if (VarParity & PARENB) {
- if (VarParity & PARODD)
- fprintf(VarTerm, "odd parity, ");
+ if (modem->cfg.parity & PARENB) {
+ if (modem->cfg.parity & PARODD)
+ prompt_Printf(arg->prompt, ", odd parity");
else
- fprintf(VarTerm, "even parity, ");
+ prompt_Printf(arg->prompt, ", even parity");
} else
- fprintf(VarTerm, "no parity, ");
+ prompt_Printf(arg->prompt, ", no parity");
- fprintf(VarTerm, "CTS/RTS %s.\n", (VarCtsRts ? "on" : "off"));
+ prompt_Printf(arg->prompt, ", CTS/RTS %s\n",
+ (modem->cfg.rts_cts ? "on" : "off"));
- if (LogIsKept(LogDEBUG))
- fprintf(VarTerm, "fd = %d, modem control = %o\n", modem, mbits);
- fprintf(VarTerm, "connect count: %d\n", connect_count);
-#ifdef TIOCOUTQ
- if (modem >= 0) {
- if (ioctl(modem, TIOCOUTQ, &nb) >= 0)
- fprintf(VarTerm, "outq: %d\n", nb);
+
+ prompt_Printf(arg->prompt, "\n");
+ throughput_disp(&modem->link.throughput, arg->prompt);
+
+ return 0;
+}
+
+static void
+modem_DescriptorRead(struct descriptor *d, struct bundle *bundle,
+ const fd_set *fdset)
+{
+ struct physical *p = descriptor2physical(d);
+ u_char rbuff[MAX_MRU], *cp;
+ int n;
+
+ /* something to read from modem */
+ n = physical_Read(p, rbuff, sizeof rbuff);
+ log_Printf(LogDEBUG, "%s: DescriptorRead: read %d from %d\n",
+ p->link.name, n, p->fd);
+ if (n <= 0) {
+ if (n < 0)
+ log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd,
+ strerror(errno));
else
- fprintf(VarTerm, "outq: ioctl probe failed: %s\n", strerror(errno));
+ log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n",
+ p->link.name, p->fd);
+ datalink_Down(p->dl, 0);
+ return;
}
-#endif
- fprintf(VarTerm, "outqlen: %d\n", ModemQlen());
- fprintf(VarTerm, "DialScript = %s\n", VarDialScript);
- fprintf(VarTerm, "LoginScript = %s\n", VarLoginScript);
- fprintf(VarTerm, "PhoneNumber(s) = %s\n", VarPhoneList);
+ log_DumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
+
+ if (p->link.lcp.fsm.state <= ST_CLOSED) {
+ /* In -dedicated mode, we just discard input until LCP is started */
+ if (p->type != PHYS_DEDICATED) {
+ cp = hdlc_Detect(p, rbuff, n);
+ if (cp) {
+ /* LCP packet is detected. Turn ourselves into packet mode */
+ if (cp != rbuff) {
+ /* Get rid of the bit before the HDLC header */
+ bundle_WriteTermPrompt(p->dl->bundle, p->dl, rbuff, cp - rbuff);
+ bundle_WriteTermPrompt(p->dl->bundle, p->dl, "\r\n", 2);
+ }
+ datalink_Up(p->dl, 0, 1);
+ } else
+ bundle_WriteTermPrompt(p->dl->bundle, p->dl, rbuff, n);
+ }
+ } else if (n > 0)
+ async_Input(bundle, rbuff, n, p);
+}
- fprintf(VarTerm, "\n");
- throughput_disp(&throughput, VarTerm);
+static int
+modem_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
+{
+ return physical_UpdateSet(d, r, w, e, n, 0);
+}
- return 0;
+struct physical *
+iov2modem(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, int fd)
+{
+ struct physical *p;
+ int len;
+
+ p = (struct physical *)iov[(*niov)++].iov_base;
+ p->link.name = dl->name;
+ throughput_init(&p->link.throughput);
+ memset(&p->Timer, '\0', sizeof p->Timer);
+ memset(p->link.Queue, '\0', sizeof p->link.Queue);
+
+ p->desc.UpdateSet = modem_UpdateSet;
+ p->desc.IsSet = physical_IsSet;
+ p->desc.Read = modem_DescriptorRead;
+ p->desc.Write = modem_DescriptorWrite;
+ p->desc.next = NULL;
+ p->type = PHYS_DIRECT;
+ p->dl = dl;
+ p->name.base = strncmp(p->name.full, _PATH_DEV, len) ?
+ p->name.full : p->name.full + len;
+ p->mbits = 0;
+ p->dev_is_modem = 1;
+ p->out = NULL;
+ p->connect_count = 1;
+
+ p->link.lcp.fsm.bundle = dl->bundle;
+ p->link.lcp.fsm.link = &p->link;
+ memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer);
+ memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer);
+ memset(&p->link.lcp.fsm.StoppedTimer, '\0',
+ sizeof p->link.lcp.fsm.StoppedTimer);
+ p->link.lcp.fsm.parent = &dl->fsmp;
+ lcp_SetupCallbacks(&p->link.lcp);
+
+ p->link.ccp.fsm.bundle = dl->bundle;
+ p->link.ccp.fsm.link = &p->link;
+ /* Our in.state & out.state are NULL (no link-level ccp yet) */
+ memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer);
+ memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer);
+ memset(&p->link.ccp.fsm.StoppedTimer, '\0',
+ sizeof p->link.ccp.fsm.StoppedTimer);
+ p->link.ccp.fsm.parent = &dl->fsmp;
+ ccp_SetupCallbacks(&p->link.ccp);
+
+ p->hdlc.lqm.owner = &p->link.lcp;
+ p->hdlc.ReportTimer.state = TIMER_STOPPED;
+ p->hdlc.lqm.timer.state = TIMER_STOPPED;
+
+ p->fd = fd;
+
+ if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load)
+ lqr_reStart(&p->link.lcp);
+ hdlc_StartTimer(&p->hdlc);
+
+ throughput_start(&p->link.throughput, "modem throughput",
+ Enabled(dl->bundle, OPT_THROUGHPUT));
+ if (p->Timer.state != TIMER_STOPPED) {
+ p->Timer.state = TIMER_STOPPED; /* Special - see modem2iov() */
+ modem_StartTimer(dl->bundle, p);
+ }
+ /* Don't need to lock the device in -direct mode */
+
+ return p;
+}
+
+int
+modem2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov)
+{
+ if (p) {
+ hdlc_StopTimer(&p->hdlc);
+ lqr_StopTimer(p);
+ timer_Stop(&p->link.lcp.fsm.FsmTimer);
+ timer_Stop(&p->link.ccp.fsm.FsmTimer);
+ timer_Stop(&p->link.lcp.fsm.OpenTimer);
+ timer_Stop(&p->link.ccp.fsm.OpenTimer);
+ timer_Stop(&p->link.lcp.fsm.StoppedTimer);
+ timer_Stop(&p->link.ccp.fsm.StoppedTimer);
+ if (p->Timer.state != TIMER_STOPPED) {
+ timer_Stop(&p->Timer);
+ p->Timer.state = TIMER_RUNNING; /* Special - see iov2modem() */
+ }
+ timer_Stop(&p->link.throughput.Timer);
+ }
+
+ if (*niov >= maxiov) {
+ log_Printf(LogERROR, "ToBinary: No room for physical !\n");
+ if (p)
+ free(p);
+ return -1;
+ }
+
+ iov[*niov].iov_base = p ? p : malloc(sizeof *p);
+ iov[*niov].iov_len = sizeof *p;
+ (*niov)++;
+
+ return p ? p->fd : 0;
}
diff --git a/usr.sbin/ppp/modem.h b/usr.sbin/ppp/modem.h
index e4b6dbb10587..f85a475b0cb3 100644
--- a/usr.sbin/ppp/modem.h
+++ b/usr.sbin/ppp/modem.h
@@ -15,27 +15,28 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: modem.h,v 1.15 1998/01/10 01:55:11 brian Exp $
+ * $Id: modem.h,v 1.16.2.17 1998/05/02 21:57:49 brian Exp $
*
* TODO:
*/
-extern int RawModem(void);
-extern void WriteModem(int, const char *, int);
-extern void ModemStartOutput(int);
-extern int OpenModem(void);
-extern int ModemSpeed(void);
-extern int ModemQlen(void);
-extern int DialModem(void);
+struct iovec;
+struct datalink;
+struct physical;
+struct bundle;
+struct ccp;
+struct cmdargs;
+
+extern int modem_Raw(struct physical *, struct bundle *);
+extern struct physical *modem_Create(struct datalink *, int);
+extern int modem_Open(struct physical *, struct bundle *);
+extern int modem_Speed(struct physical *);
extern speed_t IntToSpeed(int);
-extern void ModemTimeout(void *v);
-extern void DownConnection(void);
-extern void ModemOutput(int, struct mbuf *);
-extern int ChangeParity(const char *);
-extern void HangupModem(int);
-extern int ShowModemStatus(struct cmdargs const *);
-extern void Enqueue(struct mqueue *, struct mbuf *);
-extern struct mbuf *Dequeue(struct mqueue *);
-extern void SequenceQueues(void);
-extern void ModemAddInOctets(int);
-extern void ModemAddOutOctets(int);
+extern int modem_SetParity(struct physical *, const char *);
+extern int modem_ShowStatus(struct cmdargs const *);
+extern void modem_Close(struct physical *);
+extern void modem_Offline(struct physical *);
+extern void modem_Destroy(struct physical *);
+extern struct physical *iov2modem(struct datalink *, struct iovec *, int *,
+ int, int);
+extern int modem2iov(struct physical *, struct iovec *, int *, int);
diff --git a/usr.sbin/ppp/mp.c b/usr.sbin/ppp/mp.c
new file mode 100644
index 000000000000..d022b1befe4e
--- /dev/null
+++ b/usr.sbin/ppp/mp.c
@@ -0,0 +1,992 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: mp.c,v 1.1.2.29 1998/05/15 18:21:41 brian Exp $
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <net/if_dl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "command.h"
+#include "mbuf.h"
+#include "log.h"
+#include "defs.h"
+#include "timer.h"
+#include "fsm.h"
+#include "iplist.h"
+#include "throughput.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "auth.h"
+#include "lcp.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "async.h"
+#include "ccp.h"
+#include "link.h"
+#include "descriptor.h"
+#include "physical.h"
+#include "chat.h"
+#include "lcpproto.h"
+#include "filter.h"
+#include "mp.h"
+#include "chap.h"
+#include "datalink.h"
+#include "bundle.h"
+#include "ip.h"
+#include "prompt.h"
+#include "id.h"
+#include "arp.h"
+
+void
+peerid_Init(struct peerid *peer)
+{
+ peer->enddisc.class = 0;
+ *peer->enddisc.address = '\0';
+ peer->enddisc.len = 0;
+ *peer->authname = '\0';
+}
+
+int
+peerid_Equal(const struct peerid *p1, const struct peerid *p2)
+{
+ return !strcmp(p1->authname, p2->authname) &&
+ p1->enddisc.class == p2->enddisc.class &&
+ p1->enddisc.len == p2->enddisc.len &&
+ !memcmp(p1->enddisc.address, p2->enddisc.address, p1->enddisc.len);
+}
+
+static u_int32_t
+inc_seq(unsigned is12bit, u_int32_t seq)
+{
+ seq++;
+ if (is12bit) {
+ if (seq & 0xfffff000)
+ seq = 0;
+ } else if (seq & 0xff000000)
+ seq = 0;
+ return seq;
+}
+
+static int
+isbefore(unsigned is12bit, u_int32_t seq1, u_int32_t seq2)
+{
+ u_int32_t max = (is12bit ? 0xfff : 0xffffff) - 0x200;
+
+ if (seq1 > max) {
+ if (seq2 < 0x200 || seq2 > seq1)
+ return 1;
+ } else if ((seq1 > 0x200 || seq2 <= max) && seq1 < seq2)
+ return 1;
+
+ return 0;
+}
+
+static int
+mp_ReadHeader(struct mp *mp, struct mbuf *m, struct mp_header *header)
+{
+ if (mp->local_is12bit) {
+ header->seq = ntohs(*(u_int16_t *)MBUF_CTOP(m));
+ if (header->seq & 0x3000) {
+ log_Printf(LogWARN, "Oops - MP header without required zero bits\n");
+ return 0;
+ }
+ header->begin = header->seq & 0x8000 ? 1 : 0;
+ header->end = header->seq & 0x4000 ? 1 : 0;
+ header->seq &= 0x0fff;
+ return 2;
+ } else {
+ header->seq = ntohl(*(u_int32_t *)MBUF_CTOP(m));
+ if (header->seq & 0x3f000000) {
+ log_Printf(LogWARN, "Oops - MP header without required zero bits\n");
+ return 0;
+ }
+ header->begin = header->seq & 0x80000000 ? 1 : 0;
+ header->end = header->seq & 0x40000000 ? 1 : 0;
+ header->seq &= 0x00ffffff;
+ return 4;
+ }
+}
+
+static void
+mp_LayerStart(void *v, struct fsm *fp)
+{
+ /* The given FSM (ccp) is about to start up ! */
+}
+
+static void
+mp_LayerUp(void *v, struct fsm *fp)
+{
+ /* The given fsm (ccp) is now up */
+}
+
+static void
+mp_LayerDown(void *v, struct fsm *fp)
+{
+ /* The given FSM (ccp) has been told to come down */
+}
+
+static void
+mp_LayerFinish(void *v, struct fsm *fp)
+{
+ /* The given fsm (ccp) is now down */
+ if (fp->state == ST_CLOSED && fp->open_mode == OPEN_PASSIVE)
+ fsm_Open(fp); /* CCP goes to ST_STOPPED */
+}
+
+void
+mp_Init(struct mp *mp, struct bundle *bundle)
+{
+ mp->peer_is12bit = mp->local_is12bit = 0;
+ mp->peer_mrru = mp->local_mrru = 0;
+
+ peerid_Init(&mp->peer);
+
+ mp->out.seq = 0;
+ mp->out.link = 0;
+ mp->seq.min_in = 0;
+ mp->seq.next_in = 0;
+ mp->inbufs = NULL;
+ mp->bundle = bundle;
+
+ mp->link.type = MP_LINK;
+ mp->link.name = "mp";
+ mp->link.len = sizeof *mp;
+
+ throughput_init(&mp->link.throughput);
+ memset(mp->link.Queue, '\0', sizeof mp->link.Queue);
+ memset(mp->link.proto_in, '\0', sizeof mp->link.proto_in);
+ memset(mp->link.proto_out, '\0', sizeof mp->link.proto_out);
+
+ mp->fsmp.LayerStart = mp_LayerStart;
+ mp->fsmp.LayerUp = mp_LayerUp;
+ mp->fsmp.LayerDown = mp_LayerDown;
+ mp->fsmp.LayerFinish = mp_LayerFinish;
+ mp->fsmp.object = mp;
+
+ mpserver_Init(&mp->server);
+
+ mp->cfg.mrru = 0;
+ mp->cfg.shortseq = NEG_ENABLED|NEG_ACCEPTED;
+ mp->cfg.enddisc.class = 0;
+ *mp->cfg.enddisc.address = '\0';
+ mp->cfg.enddisc.len = 0;
+
+ lcp_Init(&mp->link.lcp, mp->bundle, &mp->link, NULL);
+ ccp_Init(&mp->link.ccp, mp->bundle, &mp->link, &mp->fsmp);
+}
+
+int
+mp_Up(struct mp *mp, struct datalink *dl)
+{
+ struct lcp *lcp = &dl->physical->link.lcp;
+
+ if (mp->active) {
+ /* We're adding a link - do a last validation on our parameters */
+ if (!peerid_Equal(&dl->peer, &mp->peer)) {
+ log_Printf(LogPHASE, "%s: Inappropriate peer !\n", dl->name);
+ return MP_FAILED;
+ }
+ if (mp->local_mrru != lcp->want_mrru ||
+ mp->peer_mrru != lcp->his_mrru ||
+ mp->local_is12bit != lcp->want_shortseq ||
+ mp->peer_is12bit != lcp->his_shortseq) {
+ log_Printf(LogPHASE, "%s: Invalid MRRU/SHORTSEQ MP parameters !\n",
+ dl->name);
+ return MP_FAILED;
+ }
+ return MP_ADDED;
+ } else {
+ /* First link in multilink mode */
+
+ mp->local_mrru = lcp->want_mrru;
+ mp->peer_mrru = lcp->his_mrru;
+ mp->local_is12bit = lcp->want_shortseq;
+ mp->peer_is12bit = lcp->his_shortseq;
+ mp->peer = dl->peer;
+
+ throughput_init(&mp->link.throughput);
+ memset(mp->link.Queue, '\0', sizeof mp->link.Queue);
+ memset(mp->link.proto_in, '\0', sizeof mp->link.proto_in);
+ memset(mp->link.proto_out, '\0', sizeof mp->link.proto_out);
+
+ mp->out.seq = 0;
+ mp->out.link = 0;
+ mp->seq.min_in = 0;
+ mp->seq.next_in = 0;
+
+ /*
+ * Now we create our server socket.
+ * If it already exists, join it. Otherwise, create and own it
+ */
+ switch (mpserver_Open(&mp->server, &mp->peer)) {
+ case MPSERVER_CONNECTED:
+ log_Printf(LogPHASE, "mp: Transfer link on %s\n",
+ mp->server.socket.sun_path);
+ mp->server.send.dl = dl; /* Defer 'till it's safe to send */
+ return MP_LINKSENT;
+ case MPSERVER_FAILED:
+ return MP_FAILED;
+ case MPSERVER_LISTENING:
+ log_Printf(LogPHASE, "mp: Listening on %s\n", mp->server.socket.sun_path);
+ log_Printf(LogPHASE, " First link: %s\n", dl->name);
+
+ /* Re-point our IPCP layer at our MP link */
+ ipcp_SetLink(&mp->bundle->ncp.ipcp, &mp->link);
+
+ /* Our lcp's already up 'cos of the NULL parent */
+ fsm_Up(&mp->link.ccp.fsm);
+ fsm_Open(&mp->link.ccp.fsm);
+
+ mp->active = 1;
+ break;
+ }
+ }
+
+ return MP_UP;
+}
+
+void
+mp_Down(struct mp *mp)
+{
+ if (mp->active) {
+ struct mbuf *next;
+
+ /* Don't want any more of these */
+ mpserver_Close(&mp->server);
+
+ /* CCP goes down with a bang */
+ fsm_Down(&mp->link.ccp.fsm);
+ fsm_Close(&mp->link.ccp.fsm);
+
+ /* Received fragments go in the bit-bucket */
+ while (mp->inbufs) {
+ next = mp->inbufs->pnext;
+ mbuf_Free(mp->inbufs);
+ mp->inbufs = next;
+ }
+
+ peerid_Init(&mp->peer);
+ mp->active = 0;
+ }
+}
+
+void
+mp_linkInit(struct mp_link *mplink)
+{
+ mplink->seq = 0;
+ mplink->weight = 1500;
+}
+
+void
+mp_Input(struct mp *mp, struct mbuf *m, struct physical *p)
+{
+ struct mp_header mh, h;
+ struct mbuf *q, *last;
+ int32_t seq;
+
+ if (mp_ReadHeader(mp, m, &mh) == 0) {
+ mbuf_Free(m);
+ return;
+ }
+
+ seq = p->dl->mp.seq;
+ p->dl->mp.seq = mh.seq;
+ if (mp->seq.min_in == seq) {
+ /*
+ * We've received new data on the link that has our min (oldest) seq.
+ * Figure out which link now has the smallest (oldest) seq.
+ */
+ struct datalink *dl;
+
+ mp->seq.min_in = p->dl->mp.seq;
+ for (dl = mp->bundle->links; dl; dl = dl->next)
+ if (mp->seq.min_in > dl->mp.seq)
+ mp->seq.min_in = dl->mp.seq;
+ }
+
+ /*
+ * Now process as many of our fragments as we can, adding our new
+ * fragment in as we go, and ordering with the oldest at the top of
+ * the queue.
+ */
+
+ if (!mp->inbufs) {
+ mp->inbufs = m;
+ m = NULL;
+ }
+
+ last = NULL;
+ seq = mp->seq.next_in;
+ q = mp->inbufs;
+ while (q) {
+ mp_ReadHeader(mp, q, &h);
+ if (m && isbefore(mp->local_is12bit, mh.seq, h.seq)) {
+ /* Our received fragment fits in before this one, so link it in */
+ if (last)
+ last->pnext = m;
+ else
+ mp->inbufs = m;
+ m->pnext = q;
+ q = m;
+ h = mh;
+ m = NULL;
+ }
+
+ if (h.seq != seq) {
+ /* we're missing something :-( */
+ if (mp->seq.min_in > seq) {
+ /* we're never gonna get it */
+ struct mbuf *next;
+
+ /* Zap all older fragments */
+ while (mp->inbufs != q) {
+ log_Printf(LogDEBUG, "Drop frag\n");
+ next = mp->inbufs->pnext;
+ mbuf_Free(mp->inbufs);
+ mp->inbufs = next;
+ }
+
+ /*
+ * Zap everything until the next `end' fragment OR just before
+ * the next `begin' fragment OR 'till seq.min_in - whichever
+ * comes first.
+ */
+ do {
+ mp_ReadHeader(mp, mp->inbufs, &h);
+ if (h.begin) {
+ /* We might be able to process this ! */
+ h.seq--; /* We're gonna look for fragment with h.seq+1 */
+ break;
+ }
+ next = mp->inbufs->pnext;
+ log_Printf(LogDEBUG, "Drop frag %u\n", h.seq);
+ mbuf_Free(mp->inbufs);
+ mp->inbufs = next;
+ } while (mp->inbufs && (h.seq >= mp->seq.min_in || h.end));
+
+ /*
+ * Continue processing things from here.
+ * This deals with the possibility that we received a fragment
+ * on the slowest link that invalidates some of our data (because
+ * of the hole at `q'), but where there are subsequent `whole'
+ * packets that have already been received.
+ */
+
+ mp->seq.next_in = seq = inc_seq(mp->local_is12bit, h.seq);
+ last = NULL;
+ q = mp->inbufs;
+ } else
+ /* we may still receive the missing fragment */
+ break;
+ } else if (h.end) {
+ /* We've got something, reassemble */
+ struct mbuf **frag = &q;
+ int len;
+ u_long first = -1;
+
+ do {
+ *frag = mp->inbufs;
+ mp->inbufs = mp->inbufs->pnext;
+ len = mp_ReadHeader(mp, *frag, &h);
+ if (first == -1)
+ first = h.seq;
+ (*frag)->offset += len;
+ (*frag)->cnt -= len;
+ (*frag)->pnext = NULL;
+ if (frag == &q && !h.begin) {
+ log_Printf(LogWARN, "Oops - MP frag %lu should have a begin flag\n",
+ (u_long)h.seq);
+ mbuf_Free(q);
+ q = NULL;
+ } else if (frag != &q && h.begin) {
+ log_Printf(LogWARN, "Oops - MP frag %lu should have an end flag\n",
+ (u_long)h.seq - 1);
+ /*
+ * Stuff our fragment back at the front of the queue and zap
+ * our half-assembed packet.
+ */
+ (*frag)->pnext = mp->inbufs;
+ mp->inbufs = *frag;
+ *frag = NULL;
+ mbuf_Free(q);
+ q = NULL;
+ frag = &q;
+ h.end = 0; /* just in case it's a whole packet */
+ } else
+ do
+ frag = &(*frag)->next;
+ while (*frag != NULL);
+ } while (!h.end);
+
+ if (q) {
+ u_short proto;
+ u_char ch;
+
+ q = mbuf_Read(q, &ch, 1);
+ proto = ch;
+ if (!(proto & 1)) {
+ q = mbuf_Read(q, &ch, 1);
+ proto <<= 8;
+ proto += ch;
+ }
+ if (log_IsKept(LogDEBUG))
+ log_Printf(LogDEBUG, "MP: Reassembled frags %ld-%lu, length %d\n",
+ first, (u_long)h.seq, mbuf_Length(q));
+ hdlc_DecodePacket(mp->bundle, proto, q, &mp->link);
+ }
+
+ mp->seq.next_in = seq = inc_seq(mp->local_is12bit, h.seq);
+ last = NULL;
+ q = mp->inbufs;
+ } else {
+ /* Look for the next fragment */
+ seq = inc_seq(mp->local_is12bit, seq);
+ last = q;
+ q = q->pnext;
+ }
+ }
+
+ if (m) {
+ /* We still have to find a home for our new fragment */
+ last = NULL;
+ for (q = mp->inbufs; q; last = q, q = q->pnext) {
+ mp_ReadHeader(mp, q, &h);
+ if (isbefore(mp->local_is12bit, mh.seq, h.seq))
+ break;
+ }
+ /* Our received fragment fits in here */
+ if (last)
+ last->pnext = m;
+ else
+ mp->inbufs = m;
+ m->pnext = q;
+ }
+}
+
+static void
+mp_Output(struct mp *mp, struct link *l, struct mbuf *m, u_int32_t begin,
+ u_int32_t end)
+{
+ struct mbuf *mo;
+
+ /* Stuff an MP header on the front of our packet and send it */
+ mo = mbuf_Alloc(4, MB_MP);
+ mo->next = m;
+ if (mp->peer_is12bit) {
+ u_int16_t *seq16;
+
+ seq16 = (u_int16_t *)MBUF_CTOP(mo);
+ *seq16 = htons((begin << 15) | (end << 14) | (u_int16_t)mp->out.seq);
+ mo->cnt = 2;
+ } else {
+ u_int32_t *seq32;
+
+ seq32 = (u_int32_t *)MBUF_CTOP(mo);
+ *seq32 = htonl((begin << 31) | (end << 30) | (u_int32_t)mp->out.seq);
+ mo->cnt = 4;
+ }
+ if (log_IsKept(LogDEBUG))
+ log_Printf(LogDEBUG, "MP[frag %d]: Send %d bytes on link `%s'\n",
+ mp->out.seq, mbuf_Length(mo), l->name);
+ mp->out.seq = inc_seq(mp->peer_is12bit, mp->out.seq);
+
+ if (!ccp_Compress(&l->ccp, l, PRI_NORMAL, PROTO_MP, mo))
+ hdlc_Output(l, PRI_NORMAL, PROTO_MP, mo);
+}
+
+int
+mp_FillQueues(struct bundle *bundle)
+{
+ struct mp *mp = &bundle->ncp.mp;
+ struct datalink *dl, *fdl;
+ int total, add, len, thislink, nlinks;
+ u_int32_t begin, end;
+ struct mbuf *m, *mo;
+
+ thislink = nlinks = 0;
+ for (fdl = NULL, dl = bundle->links; dl; dl = dl->next) {
+ if (!fdl) {
+ if (thislink == mp->out.link)
+ fdl = dl;
+ else
+ thislink++;
+ }
+ nlinks++;
+ }
+
+ if (!fdl) {
+ fdl = bundle->links;
+ if (!fdl)
+ return 0;
+ thislink = 0;
+ }
+
+ total = 0;
+ for (dl = fdl; nlinks > 0; dl = dl->next, nlinks--, thislink++) {
+ if (!dl) {
+ dl = bundle->links;
+ thislink = 0;
+ }
+
+ if (dl->state != DATALINK_OPEN)
+ continue;
+
+ if (dl->physical->out)
+ /* this link has suffered a short write. Let it continue */
+ continue;
+
+ add = link_QueueLen(&dl->physical->link);
+ total += add;
+ if (add)
+ /* this link has got stuff already queued. Let it continue */
+ continue;
+
+ if (!link_QueueLen(&mp->link) && !ip_FlushPacket(&mp->link, bundle))
+ /* Nothing else to send */
+ break;
+
+ m = link_Dequeue(&mp->link);
+ len = mbuf_Length(m);
+ begin = 1;
+ end = 0;
+
+ while (!end) {
+ if (dl->state == DATALINK_OPEN) {
+ if (len <= dl->mp.weight + LINK_MINWEIGHT) {
+ /*
+ * XXX: Should we remember how much of our `weight' wasn't sent
+ * so that we can compensate next time ?
+ */
+ mo = m;
+ end = 1;
+ } else {
+ mo = mbuf_Alloc(dl->mp.weight, MB_MP);
+ mo->cnt = dl->mp.weight;
+ len -= mo->cnt;
+ m = mbuf_Read(m, MBUF_CTOP(mo), mo->cnt);
+ }
+ mp_Output(mp, &dl->physical->link, mo, begin, end);
+ begin = 0;
+ }
+
+ if (!end) {
+ nlinks--;
+ dl = dl->next;
+ if (!dl) {
+ dl = bundle->links;
+ thislink = 0;
+ } else
+ thislink++;
+ }
+ }
+ }
+ mp->out.link = thislink; /* Start here next time */
+
+ return total;
+}
+
+int
+mp_SetDatalinkWeight(struct cmdargs const *arg)
+{
+ int val;
+
+ if (arg->argc != arg->argn+1)
+ return -1;
+
+ val = atoi(arg->argv[arg->argn]);
+ if (val < LINK_MINWEIGHT) {
+ log_Printf(LogWARN, "Link weights must not be less than %d\n",
+ LINK_MINWEIGHT);
+ return 1;
+ }
+ arg->cx->mp.weight = val;
+ return 0;
+}
+
+int
+mp_ShowStatus(struct cmdargs const *arg)
+{
+ struct mp *mp = &arg->bundle->ncp.mp;
+
+ prompt_Printf(arg->prompt, "Multilink is %sactive\n", mp->active ? "" : "in");
+ if (mp->active) {
+ struct mbuf *m;
+ int bufs = 0;
+
+ prompt_Printf(arg->prompt, "Socket: %s\n",
+ mp->server.socket.sun_path);
+ for (m = mp->inbufs; m; m = m->pnext)
+ bufs++;
+ prompt_Printf(arg->prompt, "Pending frags: %d\n", bufs);
+ }
+
+ prompt_Printf(arg->prompt, "\nMy Side:\n");
+ if (mp->active) {
+ prompt_Printf(arg->prompt, " MRRU: %u\n", mp->local_mrru);
+ prompt_Printf(arg->prompt, " Short Seq: %s\n",
+ mp->local_is12bit ? "on" : "off");
+ }
+ prompt_Printf(arg->prompt, " Discriminator: %s\n",
+ mp_Enddisc(mp->cfg.enddisc.class, mp->cfg.enddisc.address,
+ mp->cfg.enddisc.len));
+
+ prompt_Printf(arg->prompt, "\nHis Side:\n");
+ if (mp->active) {
+ prompt_Printf(arg->prompt, " Auth Name: %s\n", mp->peer.authname);
+ prompt_Printf(arg->prompt, " Next SEQ: %u\n", mp->out.seq);
+ prompt_Printf(arg->prompt, " MRRU: %u\n", mp->peer_mrru);
+ prompt_Printf(arg->prompt, " Short Seq: %s\n",
+ mp->peer_is12bit ? "on" : "off");
+ }
+ prompt_Printf(arg->prompt, " Discriminator: %s\n",
+ mp_Enddisc(mp->peer.enddisc.class, mp->peer.enddisc.address,
+ mp->peer.enddisc.len));
+
+ prompt_Printf(arg->prompt, "\nDefaults:\n");
+
+ prompt_Printf(arg->prompt, " MRRU: ");
+ if (mp->cfg.mrru)
+ prompt_Printf(arg->prompt, "%d (multilink enabled)\n", mp->cfg.mrru);
+ else
+ prompt_Printf(arg->prompt, "disabled\n");
+ prompt_Printf(arg->prompt, " Short Seq: %s\n",
+ command_ShowNegval(mp->cfg.shortseq));
+
+ return 0;
+}
+
+const char *
+mp_Enddisc(u_char c, const char *address, int len)
+{
+ static char result[100];
+ int f, header;
+
+ switch (c) {
+ case ENDDISC_NULL:
+ sprintf(result, "Null Class");
+ break;
+
+ case ENDDISC_LOCAL:
+ snprintf(result, sizeof result, "Local Addr: %.*s", len, address);
+ break;
+
+ case ENDDISC_IP:
+ if (len == 4)
+ snprintf(result, sizeof result, "IP %s",
+ inet_ntoa(*(const struct in_addr *)address));
+ else
+ sprintf(result, "IP[%d] ???", len);
+ break;
+
+ case ENDDISC_MAC:
+ if (len == 6) {
+ const u_char *m = (const u_char *)address;
+ snprintf(result, sizeof result, "MAC %02x:%02x:%02x:%02x:%02x:%02x",
+ m[0], m[1], m[2], m[3], m[4], m[5]);
+ } else
+ sprintf(result, "MAC[%d] ???", len);
+ break;
+
+ case ENDDISC_MAGIC:
+ sprintf(result, "Magic: 0x");
+ header = strlen(result);
+ if (len > sizeof result - header - 1)
+ len = sizeof result - header - 1;
+ for (f = 0; f < len; f++)
+ sprintf(result + header + 2 * f, "%02x", address[f]);
+ break;
+
+ case ENDDISC_PSN:
+ snprintf(result, sizeof result, "PSN: %.*s", len, address);
+ break;
+
+ default:
+ sprintf(result, "%d: ", (int)c);
+ header = strlen(result);
+ if (len > sizeof result - header - 1)
+ len = sizeof result - header - 1;
+ for (f = 0; f < len; f++)
+ sprintf(result + header + 2 * f, "%02x", address[f]);
+ break;
+ }
+ return result;
+}
+
+int
+mp_SetEnddisc(struct cmdargs const *arg)
+{
+ struct mp *mp = &arg->bundle->ncp.mp;
+ struct in_addr addr;
+
+ if (bundle_Phase(arg->bundle) != PHASE_DEAD) {
+ log_Printf(LogWARN, "set enddisc: Only available at phase DEAD\n");
+ return 1;
+ }
+
+ if (arg->argc == arg->argn) {
+ mp->cfg.enddisc.class = 0;
+ *mp->cfg.enddisc.address = '\0';
+ mp->cfg.enddisc.len = 0;
+ } else if (arg->argc > arg->argn) {
+ if (!strcasecmp(arg->argv[arg->argn], "label")) {
+ mp->cfg.enddisc.class = ENDDISC_LOCAL;
+ strcpy(mp->cfg.enddisc.address, arg->bundle->cfg.label);
+ mp->cfg.enddisc.len = strlen(mp->cfg.enddisc.address);
+ } else if (!strcasecmp(arg->argv[arg->argn], "ip")) {
+ if (arg->bundle->ncp.ipcp.my_ip.s_addr == INADDR_ANY)
+ addr = arg->bundle->ncp.ipcp.cfg.my_range.ipaddr;
+ else
+ addr = arg->bundle->ncp.ipcp.my_ip;
+ memcpy(mp->cfg.enddisc.address, &addr.s_addr, sizeof addr.s_addr);
+ mp->cfg.enddisc.class = ENDDISC_IP;
+ mp->cfg.enddisc.len = sizeof arg->bundle->ncp.ipcp.my_ip.s_addr;
+ } else if (!strcasecmp(arg->argv[arg->argn], "mac")) {
+ struct sockaddr_dl hwaddr;
+ int s;
+
+ if (arg->bundle->ncp.ipcp.my_ip.s_addr == INADDR_ANY)
+ addr = arg->bundle->ncp.ipcp.cfg.my_range.ipaddr;
+ else
+ addr = arg->bundle->ncp.ipcp.my_ip;
+
+ s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "set enddisc: socket(): %s\n", strerror(errno));
+ return 2;
+ }
+ if (get_ether_addr(s, addr, &hwaddr)) {
+ mp->cfg.enddisc.class = ENDDISC_MAC;
+ memcpy(mp->cfg.enddisc.address, hwaddr.sdl_data + hwaddr.sdl_nlen,
+ hwaddr.sdl_alen);
+ mp->cfg.enddisc.len = hwaddr.sdl_alen;
+ } else {
+ log_Printf(LogWARN, "set enddisc: Can't locate MAC address for %s\n",
+ inet_ntoa(addr));
+ close(s);
+ return 4;
+ }
+ close(s);
+ } else if (!strcasecmp(arg->argv[arg->argn], "magic")) {
+ int f;
+
+ randinit();
+ for (f = 0; f < 20; f += sizeof(long))
+ *(long *)(mp->cfg.enddisc.address + f) = random();
+ mp->cfg.enddisc.class = ENDDISC_MAGIC;
+ mp->cfg.enddisc.len = 20;
+ } else if (!strcasecmp(arg->argv[arg->argn], "psn")) {
+ if (arg->argc > arg->argn+1) {
+ mp->cfg.enddisc.class = ENDDISC_PSN;
+ strcpy(mp->cfg.enddisc.address, arg->argv[arg->argn+1]);
+ mp->cfg.enddisc.len = strlen(mp->cfg.enddisc.address);
+ } else {
+ log_Printf(LogWARN, "PSN endpoint requires additional data\n");
+ return 5;
+ }
+ } else {
+ log_Printf(LogWARN, "%s: Unrecognised endpoint type\n",
+ arg->argv[arg->argn]);
+ return 6;
+ }
+ }
+
+ return 0;
+}
+
+static int
+mpserver_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
+ int *n)
+{
+ struct mpserver *s = descriptor2mpserver(d);
+
+ if (s->send.dl != NULL) {
+ /* We've connect()ed */
+ if (!link_QueueLen(&s->send.dl->physical->link) &&
+ !s->send.dl->physical->out) {
+ /* Only send if we've transmitted all our data (i.e. the ConfigAck) */
+ datalink_RemoveFromSet(s->send.dl, r, w, e);
+ bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
+ s->send.dl = NULL;
+ close(s->fd);
+ s->fd = -1;
+ } else
+ /* Never read from a datalink that's on death row ! */
+ datalink_RemoveFromSet(s->send.dl, r, NULL, NULL);
+ } else if (r && s->fd >= 0) {
+ if (*n < s->fd + 1)
+ *n = s->fd + 1;
+ FD_SET(s->fd, r);
+ log_Printf(LogTIMER, "mp: fdset(r) %d\n", s->fd);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+mpserver_IsSet(struct descriptor *d, const fd_set *fdset)
+{
+ struct mpserver *s = descriptor2mpserver(d);
+ return s->fd >= 0 && FD_ISSET(s->fd, fdset);
+}
+
+static void
+mpserver_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ struct mpserver *s = descriptor2mpserver(d);
+ struct sockaddr in;
+ int fd, size;
+
+ size = sizeof in;
+ fd = accept(s->fd, &in, &size);
+ if (fd < 0) {
+ log_Printf(LogERROR, "mpserver_Read: accept(): %s\n", strerror(errno));
+ return;
+ }
+
+ if (in.sa_family == AF_LOCAL)
+ bundle_ReceiveDatalink(bundle, fd, (struct sockaddr_un *)&in);
+
+ close(fd);
+}
+
+static void
+mpserver_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ /* We never want to write here ! */
+ log_Printf(LogERROR, "mpserver_Write: Internal error: Bad call !\n");
+}
+
+void
+mpserver_Init(struct mpserver *s)
+{
+ s->desc.type = MPSERVER_DESCRIPTOR;
+ s->desc.next = NULL;
+ s->desc.UpdateSet = mpserver_UpdateSet;
+ s->desc.IsSet = mpserver_IsSet;
+ s->desc.Read = mpserver_Read;
+ s->desc.Write = mpserver_Write;
+ s->send.dl = NULL;
+ s->fd = -1;
+ memset(&s->socket, '\0', sizeof s->socket);
+}
+
+int
+mpserver_Open(struct mpserver *s, struct peerid *peer)
+{
+ int f, l;
+ mode_t mask;
+
+ if (s->fd != -1) {
+ log_Printf(LogERROR, "Internal error ! mpserver already open\n");
+ mpserver_Close(s);
+ }
+
+ l = snprintf(s->socket.sun_path, sizeof s->socket.sun_path, "%sppp-%s-%02x-",
+ _PATH_VARRUN, peer->authname, peer->enddisc.class);
+
+ for (f = 0; f < peer->enddisc.len && l < sizeof s->socket.sun_path - 2; f++) {
+ snprintf(s->socket.sun_path + l, sizeof s->socket.sun_path - l,
+ "%02x", *(u_char *)(peer->enddisc.address+f));
+ l += 2;
+ }
+
+ s->socket.sun_family = AF_LOCAL;
+ s->socket.sun_len = sizeof s->socket;
+ s->fd = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (s->fd < 0) {
+ log_Printf(LogERROR, "mpserver: socket: %s\n", strerror(errno));
+ return MPSERVER_FAILED;
+ }
+
+ setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR, (struct sockaddr *)&s->socket,
+ sizeof s->socket);
+ mask = umask(0177);
+ if (ID0bind_un(s->fd, &s->socket) < 0) {
+ if (errno != EADDRINUSE) {
+ log_Printf(LogPHASE, "mpserver: can't create bundle socket %s (%s)\n",
+ s->socket.sun_path, strerror(errno));
+ umask(mask);
+ close(s->fd);
+ s->fd = -1;
+ return MPSERVER_FAILED;
+ }
+ umask(mask);
+ if (ID0connect_un(s->fd, &s->socket) < 0) {
+ log_Printf(LogPHASE, "mpserver: can't connect to bundle socket %s (%s)\n",
+ s->socket.sun_path, strerror(errno));
+ if (errno == ECONNREFUSED)
+ log_Printf(LogPHASE, " Has the previous server died badly ?\n");
+ close(s->fd);
+ s->fd = -1;
+ return MPSERVER_FAILED;
+ }
+
+ /* Donate our link to the other guy */
+ return MPSERVER_CONNECTED;
+ }
+
+ /* Listen for other ppp invocations that want to donate links */
+ if (listen(s->fd, 5) != 0) {
+ log_Printf(LogERROR, "mpserver: Unable to listen to socket"
+ " - BUNDLE overload?\n");
+ mpserver_Close(s);
+ }
+
+ return MPSERVER_LISTENING;
+}
+
+void
+mpserver_Close(struct mpserver *s)
+{
+ if (s->send.dl != NULL) {
+ bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
+ s->send.dl = NULL;
+ close(s->fd);
+ s->fd = -1;
+ } else if (s->fd >= 0) {
+ close(s->fd);
+ if (ID0unlink(s->socket.sun_path) == -1)
+ log_Printf(LogERROR, "%s: Failed to remove: %s\n", s->socket.sun_path,
+ strerror(errno));
+ memset(&s->socket, '\0', sizeof s->socket);
+ s->fd = -1;
+ }
+}
diff --git a/usr.sbin/ppp/mp.h b/usr.sbin/ppp/mp.h
new file mode 100644
index 000000000000..4f91365cb1b5
--- /dev/null
+++ b/usr.sbin/ppp/mp.h
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: mp.h,v 1.1.2.12 1998/05/03 22:13:13 brian Exp $
+ */
+
+struct mbuf;
+struct physical;
+struct bundle;
+struct cmdargs;
+struct datalink;
+
+#define ENDDISC_NULL 0
+#define ENDDISC_LOCAL 1
+#define ENDDISC_IP 2
+#define ENDDISC_MAC 3
+#define ENDDISC_MAGIC 4
+#define ENDDISC_PSN 5
+
+#define MP_LINKSENT 0 /* We attached the link to another ppp */
+#define MP_UP 1 /* We've started MP */
+#define MP_ADDED 2 /* We've added the link to our MP */
+#define MP_FAILED 3 /* No go */
+
+#define MPSERVER_CONNECTED 0
+#define MPSERVER_LISTENING 1
+#define MPSERVER_FAILED 2
+
+struct enddisc {
+ u_char class;
+ char address[50];
+ int len;
+};
+
+struct peerid {
+ struct enddisc enddisc; /* Peers endpoint discriminator */
+ char authname[50]; /* Peers name (authenticated) */
+};
+
+struct mpserver {
+ struct descriptor desc;
+ int fd; /* listen()ing or connect()ing here */
+ struct sockaddr_un socket; /* On this socket */
+
+ struct {
+ struct datalink *dl; /* Send this datalink */
+ } send; /* (in UpdateSet()) */
+};
+
+struct mp {
+ struct link link;
+
+ unsigned active : 1;
+ unsigned peer_is12bit : 1; /* 12/24bit seq nos */
+ unsigned local_is12bit : 1;
+ u_short peer_mrru;
+ u_short local_mrru;
+
+ struct peerid peer; /* Who are we talking to */
+ struct mpserver server; /* Our ``sharing'' socket */
+
+ struct {
+ u_int32_t seq; /* next outgoing seq */
+ int link; /* Next link to send on */
+ } out;
+
+ struct {
+ u_int32_t min_in; /* minimum received incoming seq */
+ u_int32_t next_in; /* next incoming seq to process */
+ } seq;
+
+ struct {
+ u_short mrru; /* Max Reconstructed Receive Unit */
+ unsigned shortseq : 2; /* I want short Sequence Numbers */
+ struct enddisc enddisc; /* endpoint discriminator */
+ } cfg;
+
+ struct mbuf *inbufs; /* Received fragments */
+ struct fsm_parent fsmp; /* Our callback functions */
+ struct bundle *bundle; /* Parent */
+};
+
+struct mp_link {
+ u_int32_t seq; /* 12 or 24 bit incoming seq */
+ int weight; /* bytes to send with each write */
+};
+
+struct mp_header {
+ unsigned begin : 1;
+ unsigned end : 1;
+ u_int32_t seq;
+};
+
+#define descriptor2mpserver(d) \
+ ((d)->type == MPSERVER_DESCRIPTOR ? (struct mpserver *)(d) : NULL)
+#define mpserver_IsOpen(s) ((s)->fd != -1)
+
+extern void peerid_Init(struct peerid *);
+extern int peerid_Equal(const struct peerid *, const struct peerid *);
+extern void mpserver_Init(struct mpserver *);
+extern int mpserver_Open(struct mpserver *, struct peerid *);
+extern void mpserver_Close(struct mpserver *);
+extern void mp_Init(struct mp *, struct bundle *);
+extern void mp_linkInit(struct mp_link *);
+extern int mp_Up(struct mp *, struct datalink *);
+extern void mp_Down(struct mp *);
+extern void mp_Input(struct mp *, struct mbuf *, struct physical *);
+extern int mp_FillQueues(struct bundle *);
+extern int mp_SetDatalinkWeight(struct cmdargs const *);
+extern int mp_ShowStatus(struct cmdargs const *);
+extern const char *mp_Enddisc(u_char, const char *, int);
+extern int mp_SetEnddisc(struct cmdargs const *);
diff --git a/usr.sbin/ppp/nat_cmd.c b/usr.sbin/ppp/nat_cmd.c
index d79ff328256d..c4265fdd7c1d 100644
--- a/usr.sbin/ppp/nat_cmd.c
+++ b/usr.sbin/ppp/nat_cmd.c
@@ -2,26 +2,25 @@
* The code in this file was written by Eivind Eklund <perhaps@yes.no>,
* who places it in the public domain without restriction.
*
- * $Id: alias_cmd.c,v 1.11 1997/12/24 10:28:37 brian Exp $
+ * $Id: alias_cmd.c,v 1.12.2.8 1998/05/01 19:23:43 brian Exp $
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
-#include "defs.h"
#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
-#include "vars.h"
#include "alias_cmd.h"
+#include "descriptor.h"
+#include "prompt.h"
static int StrToAddr(const char *, struct in_addr *);
@@ -30,13 +29,12 @@ static int StrToAddrAndPort(const char *, struct in_addr *, u_short *, const cha
int
-AliasRedirectPort(struct cmdargs const *arg)
+alias_RedirectPort(struct cmdargs const *arg)
{
- if (!(mode & MODE_ALIAS)) {
- if (VarTerm)
- fprintf(VarTerm, "Alias not enabled\n");
+ if (!alias_IsEnabled()) {
+ prompt_Printf(arg->prompt, "Alias not enabled\n");
return 1;
- } else if (arg->argc == 3) {
+ } else if (arg->argc == arg->argn+3) {
char proto_constant;
const char *proto;
u_short local_port;
@@ -46,45 +44,44 @@ AliasRedirectPort(struct cmdargs const *arg)
struct in_addr null_addr;
struct alias_link *link;
- proto = arg->argv[0];
+ proto = arg->argv[arg->argn];
if (strcmp(proto, "tcp") == 0) {
proto_constant = IPPROTO_TCP;
} else if (strcmp(proto, "udp") == 0) {
proto_constant = IPPROTO_UDP;
} else {
- if (VarTerm) {
- fprintf(VarTerm, "port redirect: protocol must be tcp or udp\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name,
- arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "port redirect: protocol must be"
+ " tcp or udp\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- error = StrToAddrAndPort(arg->argv[1], &local_addr, &local_port, proto);
+ error = StrToAddrAndPort(arg->argv[arg->argn+1], &local_addr, &local_port,
+ proto);
if (error) {
- if (VarTerm) {
- fprintf(VarTerm, "port redirect: error reading local addr:port\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "port redirect: error reading"
+ " local addr:port\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- error = StrToPort(arg->argv[2], &alias_port, proto);
+ error = StrToPort(arg->argv[arg->argn+2], &alias_port, proto);
if (error) {
- if (VarTerm) {
- fprintf(VarTerm, "port redirect: error reading alias port\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "port redirect: error reading alias port\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- null_addr.s_addr = 0;
+ null_addr.s_addr = INADDR_ANY;
- link = VarPacketAliasRedirectPort(local_addr, local_port,
+ link = (*PacketAlias.RedirectPort)(local_addr, local_port,
null_addr, 0,
null_addr, alias_port,
proto_constant);
- if (link == NULL && VarTerm)
- fprintf(VarTerm, "port redirect: error returned by packed"
+ if (link == NULL)
+ prompt_Printf(arg->prompt, "port redirect: error returned by packed"
" aliasing engine (code=%d)\n", error);
} else
return -1;
@@ -94,36 +91,35 @@ AliasRedirectPort(struct cmdargs const *arg)
int
-AliasRedirectAddr(struct cmdargs const *arg)
+alias_RedirectAddr(struct cmdargs const *arg)
{
- if (!(mode & MODE_ALIAS)) {
- if (VarTerm)
- fprintf(VarTerm, "alias not enabled\n");
+ if (!alias_IsEnabled()) {
+ prompt_Printf(arg->prompt, "alias not enabled\n");
return 1;
- } else if (arg->argc == 2) {
+ } else if (arg->argc == arg->argn+2) {
int error;
struct in_addr local_addr;
struct in_addr alias_addr;
struct alias_link *link;
- error = StrToAddr(arg->argv[0], &local_addr);
+ error = StrToAddr(arg->argv[arg->argn], &local_addr);
if (error) {
- if (VarTerm)
- fprintf(VarTerm, "address redirect: invalid local address\n");
+ prompt_Printf(arg->prompt, "address redirect: invalid local address\n");
return 1;
}
- error = StrToAddr(arg->argv[1], &alias_addr);
+ error = StrToAddr(arg->argv[arg->argn+1], &alias_addr);
if (error) {
- if (VarTerm) {
- fprintf(VarTerm, "address redirect: invalid alias address\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
- }
+ prompt_Printf(arg->prompt, "address redirect: invalid alias address\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
return 1;
}
- link = VarPacketAliasRedirectAddr(local_addr, alias_addr);
- if (link == NULL && VarTerm) {
- fprintf(VarTerm, "address redirect: packet aliasing engine error\n");
- fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
+ link = (*PacketAlias.RedirectAddr)(local_addr, alias_addr);
+ if (link == NULL) {
+ prompt_Printf(arg->prompt, "address redirect: packet aliasing"
+ " engine error\n");
+ prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
+ arg->cmd->syntax);
}
} else
return -1;
@@ -142,7 +138,7 @@ StrToAddr(const char *str, struct in_addr *addr)
hp = gethostbyname(str);
if (!hp) {
- LogPrintf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
+ log_Printf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
return -1;
}
*addr = *((struct in_addr *) hp->h_addr);
@@ -164,7 +160,7 @@ StrToPort(const char *str, u_short *port, const char *proto)
}
sp = getservbyname(str, proto);
if (!sp) {
- LogPrintf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
+ log_Printf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
str, proto);
return -1;
}
@@ -181,7 +177,7 @@ StrToAddrAndPort(const char *str, struct in_addr *addr, u_short *port, const cha
colon = strchr(str, ':');
if (!colon) {
- LogPrintf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
+ log_Printf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
return -1;
}
diff --git a/usr.sbin/ppp/nat_cmd.h b/usr.sbin/ppp/nat_cmd.h
index 31eaf12cbdc5..495397c14070 100644
--- a/usr.sbin/ppp/nat_cmd.h
+++ b/usr.sbin/ppp/nat_cmd.h
@@ -2,8 +2,10 @@
* The code in this file was written by Eivind Eklund <perhaps@yes.no>,
* who places it in the public domain without restriction.
*
- * $Id: alias_cmd.h,v 1.6 1997/12/21 14:28:24 brian Exp $
+ * $Id: alias_cmd.h,v 1.7.2.2 1998/05/01 19:23:44 brian Exp $
*/
-extern int AliasRedirectPort(struct cmdargs const *);
-extern int AliasRedirectAddr(struct cmdargs const *);
+struct cmdargs;
+
+extern int alias_RedirectPort(struct cmdargs const *);
+extern int alias_RedirectAddr(struct cmdargs const *);
diff --git a/usr.sbin/ppp/os.c b/usr.sbin/ppp/os.c
deleted file mode 100644
index aee7f75cd492..000000000000
--- a/usr.sbin/ppp/os.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * PPP OS Layer Interface 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.
- *
- * $Id: os.c,v 1.42 1998/01/21 02:15:23 brian Exp $
- *
- */
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "command.h"
-#include "mbuf.h"
-#include "log.h"
-#include "id.h"
-#include "defs.h"
-#include "timer.h"
-#include "fsm.h"
-#include "ipcp.h"
-#include "os.h"
-#include "loadalias.h"
-#include "vars.h"
-#include "arp.h"
-#include "systems.h"
-#include "route.h"
-#include "lcp.h"
-#include "ccp.h"
-
-char *IfDevName;
-
-static struct ifaliasreq ifra;
-static struct ifreq ifrq;
-static struct in_addr oldmine, oldhis;
-static int linkup;
-
-enum set_method { SET_UP, SET_DOWN, SET_TRY };
-
-static int
-SetIpDevice(struct in_addr myaddr,
- struct in_addr hisaddr,
- struct in_addr netmask,
- enum set_method how)
-{
- struct sockaddr_in *sock_in;
- int s;
- u_long mask, addr;
-
- s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno));
- return (-1);
- }
- if (how == SET_DOWN) {
- if (Enabled(ConfProxy))
- cifproxyarp(s, oldhis);
- if (oldmine.s_addr == 0 && oldhis.s_addr == 0) {
- close(s);
- return (0);
- }
- memset(&ifra.ifra_addr, '\0', sizeof ifra.ifra_addr);
- memset(&ifra.ifra_broadaddr, '\0', sizeof ifra.ifra_broadaddr);
- memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
- if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
- LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCDIFADDR): %s\n",
- strerror(errno));
- close(s);
- return (-1);
- }
- oldmine.s_addr = oldhis.s_addr = 0;
- } else {
- /* If given addresses are alreay set, then ignore this request */
- if (oldmine.s_addr == myaddr.s_addr && oldhis.s_addr == hisaddr.s_addr) {
- close(s);
- return (0);
- }
-
- /*
- * If different address has been set, then delete it first.
- */
- if (oldmine.s_addr || oldhis.s_addr) {
- memset(&ifra.ifra_addr, '\0', sizeof ifra.ifra_addr);
- memset(&ifra.ifra_broadaddr, '\0', sizeof ifra.ifra_broadaddr);
- memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
- if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
- LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCDIFADDR): %s\n",
- strerror(errno));
- close(s);
- return (-1);
- }
- }
-
- /* Set interface address */
- sock_in = (struct sockaddr_in *) & (ifra.ifra_addr);
- sock_in->sin_family = AF_INET;
- sock_in->sin_addr = myaddr;
- sock_in->sin_len = sizeof *sock_in;
-
- /* Set destination address */
- sock_in = (struct sockaddr_in *) & (ifra.ifra_broadaddr);
- sock_in->sin_family = AF_INET;
- sock_in->sin_addr = hisaddr;
- sock_in->sin_len = sizeof *sock_in;
-
- addr = ntohl(myaddr.s_addr);
- if (IN_CLASSA(addr))
- mask = IN_CLASSA_NET;
- else if (IN_CLASSB(addr))
- mask = IN_CLASSB_NET;
- else
- mask = IN_CLASSC_NET;
-
- /*
- * if subnet mask is given, use it instead of class mask.
- */
- if (netmask.s_addr && (ntohl(netmask.s_addr) & mask) == mask)
- mask = ntohl(netmask.s_addr);
-
- sock_in = (struct sockaddr_in *) & (ifra.ifra_mask);
- sock_in->sin_family = AF_INET;
- sock_in->sin_addr.s_addr = htonl(mask);
- sock_in->sin_len = sizeof *sock_in;
-
- if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) {
- if (how != SET_TRY)
- LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCAIFADDR): %s\n",
- strerror(errno));
- close(s);
- return (-1);
- }
-
- oldhis.s_addr = hisaddr.s_addr;
- oldmine.s_addr = myaddr.s_addr;
- if (Enabled(ConfProxy))
- sifproxyarp(s, hisaddr);
- }
- close(s);
- return (0);
-}
-
-int
-CleanInterface(const char *name)
-{
- int s;
-
- s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno));
- return (-1);
- }
- strncpy(ifrq.ifr_name, name, sizeof ifrq.ifr_name - 1);
- ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
- while (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0) {
- memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
- ifra.ifra_addr = ifrq.ifr_addr;
- if (ID0ioctl(s, SIOCGIFDSTADDR, &ifrq) < 0) {
- if (ifra.ifra_addr.sa_family == AF_INET)
- LogPrintf(LogERROR, "tun_configure: Can't get dst for %s on %s !\n",
- inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
- name);
- close(s);
- return 0;
- }
- ifra.ifra_broadaddr = ifrq.ifr_dstaddr;
- if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
- if (ifra.ifra_addr.sa_family == AF_INET)
- LogPrintf(LogERROR, "tun_configure: Can't delete %s address on %s !\n",
- inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
- name);
- close(s);
- return 0;
- }
- }
- close(s);
-
- return 1;
-}
-
-int
-OsTrySetIpaddress(struct in_addr myaddr, struct in_addr hisaddr)
-{
- return (SetIpDevice(myaddr, hisaddr, ifnetmask, SET_TRY));
-}
-
-int
-OsSetIpaddress(struct in_addr myaddr, struct in_addr hisaddr)
-{
- return (SetIpDevice(myaddr, hisaddr, ifnetmask, SET_UP));
-}
-
-static struct in_addr peer_addr;
-
-void
-OsLinkup()
-{
- char *s;
-
- if (linkup == 0) {
- reconnectState = RECON_UNKNOWN;
- if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
- char c = EX_NORMAL;
-
- if (write(BGFiledes[1], &c, 1) == 1)
- LogPrintf(LogPHASE, "Parent notified of success.\n");
- else
- LogPrintf(LogPHASE, "Failed to notify parent of success.\n");
- close(BGFiledes[1]);
- BGFiledes[1] = -1;
- }
- peer_addr = IpcpInfo.his_ipaddr;
- s = (char *) inet_ntoa(peer_addr);
- if (LogIsKept(LogLINK))
- LogPrintf(LogLINK, "OsLinkup: %s\n", s);
- else
- LogPrintf(LogLCP, "OsLinkup: %s\n", s);
-
- if (SelectSystem(inet_ntoa(IpcpInfo.want_ipaddr), LINKUPFILE) < 0) {
- if (GetLabel()) {
- if (SelectSystem(GetLabel(), LINKUPFILE) < 0)
- SelectSystem("MYADDR", LINKUPFILE);
- } else
- SelectSystem("MYADDR", LINKUPFILE);
- }
- linkup = 1;
- }
-}
-
-int
-OsLinkIsUp()
-{
- return linkup;
-}
-
-void
-OsLinkdown()
-{
- char *s;
- int Level;
-
- if (linkup) {
- s = (char *) inet_ntoa(peer_addr);
- Level = LogIsKept(LogLINK) ? LogLINK : LogIPCP;
- LogPrintf(Level, "OsLinkdown: %s\n", s);
-
- FsmDown(&IpcpFsm); /* IPCP must come down */
- FsmDown(&CcpFsm); /* CCP must come down */
-
- linkup = 0;
- if (SelectSystem(s, LINKDOWNFILE) < 0) {
- if (GetLabel()) {
- if (SelectSystem(GetLabel(), LINKDOWNFILE) < 0)
- SelectSystem("MYADDR", LINKDOWNFILE);
- } else
- SelectSystem("MYADDR", LINKDOWNFILE);
- }
- }
-}
-
-int
-OsInterfaceDown(int final)
-{
- struct in_addr zeroaddr;
- int s;
-
- OsLinkdown();
- if (!final && (mode & MODE_DAEMON)) /* We still want interface alive */
- return (0);
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- LogPrintf(LogERROR, "OsInterfaceDown: socket: %s\n", strerror(errno));
- return (-1);
- }
- ifrq.ifr_flags &= ~IFF_UP;
- if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
- LogPrintf(LogERROR, "OsInterfaceDown: ioctl(SIOCSIFFLAGS): %s\n",
- strerror(errno));
- close(s);
- return (-1);
- }
- zeroaddr.s_addr = 0;
- SetIpDevice(zeroaddr, zeroaddr, zeroaddr, SET_DOWN);
-
- close(s);
- return (0);
-}
-
-/*
- * Open tunnel device and returns its descriptor
- */
-
-#define MAX_TUN 256
-/* MAX_TUN is set at an arbitrarily large value *
- * as the loop aborts when it reaches the first *
- * 'Device not configured' (ENXIO), or the third *
- * 'No such file or directory' (ENOENT) error. */
-int
-OpenTunnel(int *ptun)
-{
- int s;
- char ifname[IFNAMSIZ];
- static char devname[14]; /* sufficient room for "/dev/tun65535" */
- unsigned unit, enoentcount = 0;
- int err;
-
- err = ENOENT;
- for (unit = 0; unit <= MAX_TUN; unit++) {
- snprintf(devname, sizeof devname, "/dev/tun%d", unit);
- tun_out = ID0open(devname, O_RDWR);
- if (tun_out >= 0)
- break;
- if (errno == ENXIO) {
- unit = MAX_TUN;
- err = errno;
- } else if (errno == ENOENT) {
- enoentcount++;
- if (enoentcount > 2)
- unit = MAX_TUN;
- } else
- err = errno;
- }
- if (unit > MAX_TUN) {
- if (VarTerm)
- fprintf(VarTerm, "No tunnel device is available (%s).\n", strerror(err));
- return -1;
- }
- *ptun = unit;
-
- LogSetTun(unit);
-
- /*
- * At first, name the interface.
- */
- strncpy(ifname, devname + 5, IFNAMSIZ - 1);
-
- memset(&ifra, '\0', sizeof ifra);
- memset(&ifrq, '\0', sizeof ifrq);
-
- strncpy(ifrq.ifr_name, ifname, IFNAMSIZ - 1);
- strncpy(ifra.ifra_name, ifname, IFNAMSIZ - 1);
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- LogPrintf(LogERROR, "OpenTunnel: socket(): %s\n", strerror(errno));
- return (-1);
- }
-
- /*
- * Now, bring up the interface.
- */
- if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
- LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCGIFFLAGS): %s\n",
- strerror(errno));
- close(s);
- return (-1);
- }
- ifrq.ifr_flags |= IFF_UP;
- if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
- LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCSIFFLAGS): %s\n",
- strerror(errno));
- close(s);
- return (-1);
- }
- tun_in = tun_out;
- IfDevName = devname + 5;
- if (GetIfIndex(IfDevName) < 0) {
- LogPrintf(LogERROR, "OpenTunnel: Can't find ifindex.\n");
- close(s);
- return (-1);
- }
- if (VarTerm)
- fprintf(VarTerm, "Using interface: %s\n", IfDevName);
- LogPrintf(LogPHASE, "Using interface: %s\n", IfDevName);
- close(s);
- return (0);
-}
diff --git a/usr.sbin/ppp/os.h b/usr.sbin/ppp/os.h
deleted file mode 100644
index 7c0b5f10ee22..000000000000
--- a/usr.sbin/ppp/os.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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. 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.
- *
- * $Id: os.h,v 1.13 1997/12/13 02:37:30 brian Exp $
- *
- * TODO:
- */
-
-extern char *IfDevName;
-
-extern int OsSetIpaddress(struct in_addr, struct in_addr);
-extern int OsTrySetIpaddress(struct in_addr, struct in_addr);
-extern int OsInterfaceDown(int);
-extern int OpenTunnel(int *);
-extern void OsLinkup(void);
-extern int OsLinkIsUp(void);
-extern void OsLinkdown(void);
-extern int CleanInterface(const char *);
diff --git a/usr.sbin/ppp/pap.c b/usr.sbin/ppp/pap.c
index cc3042218e0f..6c70274a506c 100644
--- a/usr.sbin/ppp/pap.c
+++ b/usr.sbin/ppp/pap.c
@@ -18,81 +18,78 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: pap.c,v 1.21 1998/02/19 02:10:13 brian Exp $
+ * $Id: pap.c,v 1.20.2.28 1998/05/01 19:25:30 brian Exp $
*
* TODO:
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
+
+#include <termios.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#ifdef __OpenBSD__
-#include <util.h>
-#else
-#include <libutil.h>
-#endif
-#include <utmp.h>
-
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "lcp.h"
+#include "auth.h"
#include "pap.h"
-#include "loadalias.h"
-#include "vars.h"
+#include "lqr.h"
#include "hdlc.h"
#include "lcpproto.h"
-#include "phase.h"
-#include "auth.h"
-#include "id.h"
+#include "async.h"
+#include "throughput.h"
+#include "ccp.h"
+#include "link.h"
+#include "descriptor.h"
+#include "physical.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "mp.h"
+#include "bundle.h"
+#include "chat.h"
+#include "chap.h"
+#include "datalink.h"
static const char *papcodes[] = { "???", "REQUEST", "ACK", "NAK" };
-static void
-SendPapChallenge(int papid)
+void
+pap_SendChallenge(struct authinfo *auth, int papid, struct physical *physical)
{
struct fsmheader lh;
struct mbuf *bp;
u_char *cp;
int namelen, keylen, plen;
- namelen = strlen(VarAuthName);
- keylen = strlen(VarAuthKey);
+ namelen = strlen(physical->dl->bundle->cfg.auth.name);
+ keylen = strlen(physical->dl->bundle->cfg.auth.key);
plen = namelen + keylen + 2;
- LogPrintf(LogDEBUG, "SendPapChallenge: namelen = %d, keylen = %d\n",
+ log_Printf(LogDEBUG, "pap_SendChallenge: namelen = %d, keylen = %d\n",
namelen, keylen);
- if (LogIsKept(LogDEBUG))
- LogPrintf(LogPHASE, "PAP: %s (%s)\n", VarAuthName, VarAuthKey);
- else
- LogPrintf(LogPHASE, "PAP: %s\n", VarAuthName);
+ log_Printf(LogPHASE, "PAP: %s\n", physical->dl->bundle->cfg.auth.name);
lh.code = PAP_REQUEST;
lh.id = papid;
lh.length = htons(plen + sizeof(struct fsmheader));
- bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
+ bp = mbuf_Alloc(plen + sizeof(struct fsmheader), MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
*cp++ = namelen;
- memcpy(cp, VarAuthName, namelen);
+ memcpy(cp, physical->dl->bundle->cfg.auth.name, namelen);
cp += namelen;
*cp++ = keylen;
- memcpy(cp, VarAuthKey, keylen);
+ memcpy(cp, physical->dl->bundle->cfg.auth.key, keylen);
- HdlcOutput(PRI_LINK, PROTO_PAP, bp);
+ hdlc_Output(&physical->link, PRI_LINK, PROTO_PAP, bp);
}
-struct authinfo AuthPapInfo = {
- SendPapChallenge,
-};
-
static void
-SendPapCode(int id, int code, const char *message)
+SendPapCode(int id, int code, const char *message, struct physical *physical)
{
struct fsmheader lh;
struct mbuf *bp;
@@ -104,20 +101,21 @@ SendPapCode(int id, int code, const char *message)
mlen = strlen(message);
plen = mlen + 1;
lh.length = htons(plen + sizeof(struct fsmheader));
- bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
+ bp = mbuf_Alloc(plen + sizeof(struct fsmheader), MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
*cp++ = mlen;
memcpy(cp, message, mlen);
- LogPrintf(LogPHASE, "PapOutput: %s\n", papcodes[code]);
- HdlcOutput(PRI_LINK, PROTO_PAP, bp);
+ log_Printf(LogPHASE, "PapOutput: %s\n", papcodes[code]);
+ hdlc_Output(&physical->link, PRI_LINK, PROTO_PAP, bp);
}
/*
* Validate given username and passwrd against with secret table
*/
static int
-PapValidate(u_char * name, u_char * key)
+PapValidate(struct bundle *bundle, u_char *name, u_char *key,
+ struct physical *physical)
{
int nlen, klen;
@@ -125,31 +123,17 @@ PapValidate(u_char * name, u_char * key)
klen = *key;
*key++ = 0;
key[klen] = 0;
- LogPrintf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
+ log_Printf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
name, nlen, key, klen);
-#ifndef NOPASSWDAUTH
- if (Enabled(ConfPasswdAuth)) {
- struct passwd *pwd;
- int result;
-
- LogPrintf(LogLCP, "Using PasswdAuth\n");
- result = (pwd = getpwnam(name)) &&
- !strcmp(crypt(key, pwd->pw_passwd), pwd->pw_passwd);
- endpwent();
- return result;
- }
-#endif
-
- return (AuthValidate(SECRETFILE, name, key));
+ return auth_Validate(bundle, name, key, physical);
}
void
-PapInput(struct mbuf * bp)
+pap_Input(struct bundle *bundle, struct mbuf *bp, struct physical *physical)
{
- int len = plength(bp);
+ int len = mbuf_Length(bp);
struct fsmheader *php;
- struct lcpstate *lcp = &LcpInfo;
u_char *cp;
if (len >= sizeof(struct fsmheader)) {
@@ -157,60 +141,57 @@ PapInput(struct mbuf * bp)
if (len >= ntohs(php->length)) {
if (php->code < PAP_REQUEST || php->code > PAP_NAK)
php->code = 0;
- LogPrintf(LogPHASE, "PapInput: %s\n", papcodes[php->code]);
+ log_Printf(LogPHASE, "pap_Input: %s\n", papcodes[php->code]);
switch (php->code) {
case PAP_REQUEST:
cp = (u_char *) (php + 1);
- if (PapValidate(cp, cp + *cp + 1)) {
- SendPapCode(php->id, PAP_ACK, "Greetings!!");
- lcp->auth_ineed = 0;
- if (lcp->auth_iwait == 0) {
- if ((mode & MODE_DIRECT) && isatty(modem) && Enabled(ConfUtmp)) {
- if (Utmp)
- LogPrintf(LogERROR, "Oops, already logged in on %s\n",
- VarBaseDevice);
- else {
- struct utmp ut;
- memset(&ut, 0, sizeof ut);
- time(&ut.ut_time);
- strncpy(ut.ut_name, cp+1, sizeof ut.ut_name);
- strncpy(ut.ut_line, VarBaseDevice, sizeof ut.ut_line - 1);
- ID0login(&ut);
- Utmp = 1;
- }
- }
- NewPhase(PHASE_NETWORK);
- }
+ if (PapValidate(bundle, cp, cp + *cp + 1, physical)) {
+ datalink_GotAuthname(physical->dl, cp+1, *cp);
+ SendPapCode(php->id, PAP_ACK, "Greetings!!", physical);
+ physical->link.lcp.auth_ineed = 0;
+ if (Enabled(bundle, OPT_UTMP))
+ physical_Login(physical, cp + 1);
+
+ if (physical->link.lcp.auth_iwait == 0)
+ /*
+ * Either I didn't need to authenticate, or I've already been
+ * told that I got the answer right.
+ */
+ datalink_AuthOk(physical->dl);
+
} else {
- SendPapCode(php->id, PAP_NAK, "Login incorrect");
- reconnect(RECON_FALSE);
- LcpClose();
+ SendPapCode(php->id, PAP_NAK, "Login incorrect", physical);
+ datalink_AuthNotOk(physical->dl);
}
break;
case PAP_ACK:
- StopAuthTimer(&AuthPapInfo);
+ auth_StopTimer(&physical->dl->pap);
cp = (u_char *) (php + 1);
len = *cp++;
cp[len] = 0;
- LogPrintf(LogPHASE, "Received PAP_ACK (%s)\n", cp);
- if (lcp->auth_iwait == PROTO_PAP) {
- lcp->auth_iwait = 0;
- if (lcp->auth_ineed == 0)
- NewPhase(PHASE_NETWORK);
+ log_Printf(LogPHASE, "Received PAP_ACK (%s)\n", cp);
+ if (physical->link.lcp.auth_iwait == PROTO_PAP) {
+ physical->link.lcp.auth_iwait = 0;
+ if (physical->link.lcp.auth_ineed == 0)
+ /*
+ * We've succeeded in our ``login''
+ * If we're not expecting the peer to authenticate (or he already
+ * has), proceed to network phase.
+ */
+ datalink_AuthOk(physical->dl);
}
break;
case PAP_NAK:
- StopAuthTimer(&AuthPapInfo);
+ auth_StopTimer(&physical->dl->pap);
cp = (u_char *) (php + 1);
len = *cp++;
cp[len] = 0;
- LogPrintf(LogPHASE, "Received PAP_NAK (%s)\n", cp);
- reconnect(RECON_FALSE);
- LcpClose();
+ log_Printf(LogPHASE, "Received PAP_NAK (%s)\n", cp);
+ datalink_AuthNotOk(physical->dl);
break;
}
}
}
- pfree(bp);
+ mbuf_Free(bp);
}
diff --git a/usr.sbin/ppp/pap.h b/usr.sbin/ppp/pap.h
index 6ef0792f18c5..b4b63af46dce 100644
--- a/usr.sbin/ppp/pap.h
+++ b/usr.sbin/ppp/pap.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: pap.h,v 1.4 1997/10/26 01:03:29 brian Exp $
+ * $Id: pap.h,v 1.5.2.5 1998/05/01 19:25:32 brian Exp $
*
* TODO:
*/
@@ -24,6 +24,10 @@
#define PAP_ACK 2
#define PAP_NAK 3
-extern struct authinfo AuthPapInfo;
+struct mbuf;
+struct physical;
+struct authinfo;
+struct bundle;
-extern void PapInput(struct mbuf *);
+extern void pap_Input(struct bundle *, struct mbuf *, struct physical *);
+extern void pap_SendChallenge(struct authinfo *, int, struct physical *);
diff --git a/usr.sbin/ppp/phase.c b/usr.sbin/ppp/phase.c
deleted file mode 100644
index 9522f8c25486..000000000000
--- a/usr.sbin/ppp/phase.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-
- * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id$
- */
-
-#include <sys/param.h>
-#include <netinet/in.h>
-
-#include <stdio.h>
-
-#include "command.h"
-#include "mbuf.h"
-#include "log.h"
-#include "lcp.h"
-#include "lcpproto.h"
-#include "timer.h"
-#include "auth.h"
-#include "pap.h"
-#include "chap.h"
-#include "defs.h"
-#include "ipcp.h"
-#include "ccp.h"
-#include "main.h"
-#include "loadalias.h"
-#include "vars.h"
-#include "phase.h"
-
-int phase = 0; /* Curent phase */
-
-static const char *PhaseNames[] = {
- "Dead", "Establish", "Authenticate", "Network", "Terminate"
-};
-
-static const char *
-Auth2Nam(u_short auth)
-{
- switch (auth) {
- case PROTO_PAP:
- return "PAP";
- case PROTO_CHAP:
- return "CHAP";
- case 0:
- return "none";
- }
- return "unknown";
-}
-
-void
-NewPhase(int new)
-{
- struct lcpstate *lcp = &LcpInfo;
-
- phase = new;
- LogPrintf(LogPHASE, "NewPhase: %s\n", PhaseNames[phase]);
- switch (phase) {
- case PHASE_AUTHENTICATE:
- lcp->auth_ineed = lcp->want_auth;
- lcp->auth_iwait = lcp->his_auth;
- if (lcp->his_auth || lcp->want_auth) {
- LogPrintf(LogPHASE, " his = %s, mine = %s\n",
- Auth2Nam(lcp->his_auth), Auth2Nam(lcp->want_auth));
- if (lcp->his_auth == PROTO_PAP)
- StartAuthChallenge(&AuthPapInfo);
- if (lcp->want_auth == PROTO_CHAP)
- StartAuthChallenge(&AuthChapInfo);
- } else
- NewPhase(PHASE_NETWORK);
- break;
- case PHASE_NETWORK:
- IpcpUp();
- IpcpOpen();
- CcpUp();
- CcpOpen();
- break;
- case PHASE_DEAD:
- if (mode & MODE_DIRECT)
- Cleanup(EX_DEAD);
- if (mode & MODE_BACKGROUND && reconnectState != RECON_TRUE)
- Cleanup(EX_DEAD);
- break;
- }
-}
diff --git a/usr.sbin/ppp/phase.h b/usr.sbin/ppp/phase.h
deleted file mode 100644
index 1ed568e86fb3..000000000000
--- a/usr.sbin/ppp/phase.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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. 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.
- *
- * $Id: phase.h,v 1.8 1997/10/26 01:03:32 brian Exp $
- *
- * TODO:
- */
-
-#define PHASE_DEAD 0 /* Link is dead */
-#define PHASE_ESTABLISH 1 /* Establishing link */
-#define PHASE_AUTHENTICATE 2 /* Being authenticated */
-#define PHASE_NETWORK 3
-#define PHASE_TERMINATE 4 /* Terminating link */
-
-extern int phase; /* Curent phase */
-
-extern void NewPhase(int);
diff --git a/usr.sbin/ppp/physical.c b/usr.sbin/ppp/physical.c
new file mode 100644
index 000000000000..6826e061377f
--- /dev/null
+++ b/usr.sbin/ppp/physical.c
@@ -0,0 +1,230 @@
+/*
+ * Written by Eivind Eklund <eivind@yes.no>
+ * for Yes Interactive
+ *
+ * Copyright (C) 1998, Yes Interactive. All rights reserved.
+ *
+ * Redistribution and use in any form is permitted. Redistribution in
+ * source form should include the above copyright and this set of
+ * conditions, because large sections american law seems to have been
+ * created by a bunch of jerks on drugs that are now illegal, forcing
+ * me to include this copyright-stuff instead of placing this in the
+ * public domain. The name of of 'Yes Interactive' or 'Eivind Eklund'
+ * 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.
+ *
+ * $Id: physical.c,v 1.1.2.34 1998/05/21 01:12:20 brian Exp $
+ *
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <sys/tty.h>
+
+#include "defs.h"
+#include "mbuf.h"
+#include "timer.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "throughput.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "async.h"
+#include "ccp.h"
+#include "link.h"
+#include "descriptor.h"
+#include "physical.h"
+#include "log.h"
+#include "id.h"
+
+/* External calls - should possibly be moved inline */
+extern int IntToSpeed(int);
+
+
+int
+physical_GetFD(struct physical *phys) {
+ return phys->fd;
+}
+
+int
+physical_IsATTY(struct physical *phys) {
+ return isatty(phys->fd);
+}
+
+int
+physical_IsSync(struct physical *phys) {
+ return phys->cfg.speed == 0;
+}
+
+const char *physical_GetDevice(struct physical *phys)
+{
+ return phys->name.full;
+}
+
+void
+physical_SetDeviceList(struct physical *p, int argc, const char *const *argv)
+{
+ int f, pos;
+
+ p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
+ for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) {
+ if (pos)
+ p->cfg.devlist[pos++] = ' ';
+ strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1);
+ pos += strlen(p->cfg.devlist + pos);
+ }
+}
+
+
+int
+physical_SetSpeed(struct physical *phys, int speed) {
+ if (IntToSpeed(speed) != B0) {
+ phys->cfg.speed = speed;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void
+physical_SetSync(struct physical *phys) {
+ phys->cfg.speed = 0;
+}
+
+
+int
+physical_SetRtsCts(struct physical *phys, int enable) {
+ phys->cfg.rts_cts = enable ? 1 : 0;
+ return 1;
+}
+
+/* Encapsulation for a read on the FD. Avoids some exposure, and
+ concentrates control. */
+ssize_t
+physical_Read(struct physical *phys, void *buf, size_t nbytes) {
+ return read(phys->fd, buf, nbytes);
+}
+
+ssize_t
+physical_Write(struct physical *phys, const void *buf, size_t nbytes) {
+ return write(phys->fd, buf, nbytes);
+}
+
+int
+physical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
+ int *n, int force)
+{
+ struct physical *p = descriptor2physical(d);
+ int sets;
+
+ sets = 0;
+ if (p->fd >= 0) {
+ if (r) {
+ FD_SET(p->fd, r);
+ log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd);
+ sets++;
+ }
+ if (e) {
+ FD_SET(p->fd, e);
+ log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd);
+ sets++;
+ }
+ if (w && (force || link_QueueLen(&p->link))) {
+ FD_SET(p->fd, w);
+ log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd);
+ sets++;
+ }
+ if (sets && *n < p->fd + 1)
+ *n = p->fd + 1;
+ }
+
+ return sets;
+}
+
+int
+physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
+{
+ int sets;
+
+ sets = 0;
+ if (p->fd >= 0) {
+ if (r && FD_ISSET(p->fd, r)) {
+ FD_CLR(p->fd, r);
+ log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd);
+ sets++;
+ }
+ if (e && FD_ISSET(p->fd, e)) {
+ FD_CLR(p->fd, e);
+ log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd);
+ sets++;
+ }
+ if (w && FD_ISSET(p->fd, w)) {
+ FD_CLR(p->fd, w);
+ log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd);
+ sets++;
+ }
+ }
+
+ return sets;
+}
+
+int
+physical_IsSet(struct descriptor *d, const fd_set *fdset)
+{
+ struct physical *p = descriptor2physical(d);
+ return p->fd >= 0 && FD_ISSET(p->fd, fdset);
+}
+
+void
+physical_Login(struct physical *phys, const char *name)
+{
+ if (phys->type == PHYS_DIRECT && physical_IsATTY(phys)) {
+ if (phys->Utmp)
+ log_Printf(LogERROR, "Oops, already logged in on %s\n", phys->name.base);
+ else {
+ struct utmp ut;
+ const char *connstr;
+
+ memset(&ut, 0, sizeof ut);
+ time(&ut.ut_time);
+ strncpy(ut.ut_name, name, sizeof ut.ut_name);
+ strncpy(ut.ut_line, phys->name.base, sizeof ut.ut_line);
+ if ((connstr = getenv("CONNECT")))
+ /* mgetty sets this to the connection speed */
+ strncpy(ut.ut_host, connstr, sizeof ut.ut_host);
+ ID0login(&ut);
+ phys->Utmp = 1;
+ }
+ }
+}
+
+void
+physical_Logout(struct physical *phys)
+{
+ if (phys->Utmp) {
+ ID0logout(phys->name.base);
+ phys->Utmp = 0;
+ }
+}
+
+int
+physical_SetMode(struct physical *p, int mode)
+{
+ if (p->type & (PHYS_DIRECT|PHYS_DEDICATED)
+ || mode & (PHYS_DIRECT|PHYS_DEDICATED)) {
+ log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name,
+ mode2Nam(p->type), mode2Nam(mode));
+ return 0;
+ }
+ p->type = mode;
+ return 1;
+}
diff --git a/usr.sbin/ppp/physical.h b/usr.sbin/ppp/physical.h
new file mode 100644
index 000000000000..c99fdea2a6fc
--- /dev/null
+++ b/usr.sbin/ppp/physical.h
@@ -0,0 +1,101 @@
+/*
+ * Written by Eivind Eklund <eivind@yes.no>
+ * for Yes Interactive
+ *
+ * Copyright (C) 1998, Yes Interactive. All rights reserved.
+ *
+ * Redistribution and use in any form is permitted. Redistribution in
+ * source form should include the above copyright and this set of
+ * conditions, because large sections american law seems to have been
+ * created by a bunch of jerks on drugs that are now illegal, forcing
+ * me to include this copyright-stuff instead of placing this in the
+ * public domain. The name of of 'Yes Interactive' or 'Eivind Eklund'
+ * 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.
+ *
+ * $Id: physical.h,v 1.1.2.26 1998/05/15 23:58:26 brian Exp $
+ *
+ */
+
+struct bundle;
+
+struct physical {
+ struct link link;
+ struct descriptor desc;
+ int type; /* What sort of PHYS_* link are we ? */
+ struct async async; /* Our async state */
+ struct hdlc hdlc; /* Our hdlc state */
+ int fd; /* File descriptor for this device */
+ int mbits; /* Current DCD status */
+ unsigned dev_is_modem : 1; /* Is the device an actual modem?
+ Faked for sync devices, though...
+ (Possibly this should be
+ dev_is_not_tcp?) XXX-ML */
+
+ struct mbuf *out; /* mbuf that suffered a short write */
+ int connect_count;
+ struct datalink *dl; /* my owner */
+
+ struct {
+ char full[40];
+ char *base;
+ } name;
+
+ unsigned Utmp : 1; /* Are we in utmp ? */
+
+ /* XXX-ML Most of the below is device specific, and probably do not
+ belong in the generic physical struct. It comes from modem.c. */
+
+ struct {
+ unsigned rts_cts : 1; /* Is rts/cts enabled? */
+ unsigned parity; /* What parity is enabled? (TTY flags) */
+ unsigned speed; /* Modem speed */
+ char devlist[LINE_LEN]; /* Comma-separated list of devices */
+ } cfg;
+
+ struct termios ios; /* To be able to reset from raw mode */
+
+ struct pppTimer Timer; /* CD checks */
+};
+
+#define field2phys(fp, name) \
+ ((struct physical *)((char *)fp - (int)(&((struct physical *)0)->name)))
+
+#define link2physical(l) \
+ ((l)->type == PHYSICAL_LINK ? field2phys(l, link) : NULL)
+
+#define descriptor2physical(d) \
+ ((d)->type == PHYSICAL_DESCRIPTOR ? field2phys(d, desc) : NULL)
+
+extern int physical_GetFD(struct physical *);
+extern int physical_IsATTY(struct physical *);
+extern int physical_IsSync(struct physical *);
+extern const char *physical_GetDevice(struct physical *);
+extern void physical_SetDeviceList(struct physical *, int, const char *const *);
+extern int physical_SetSpeed(struct physical *, int);
+
+/*
+ * XXX-ML I'm not certain this is the right way to handle this, but we
+ * can solve that later.
+ */
+extern void physical_SetSync(struct physical *);
+
+/*
+ * Can this be set? (Might not be a relevant attribute for this
+ * device, for instance)
+ */
+extern int physical_SetRtsCts(struct physical *, int);
+
+extern ssize_t physical_Read(struct physical *, void *, size_t);
+extern ssize_t physical_Write(struct physical *, const void *, size_t);
+extern int physical_UpdateSet(struct descriptor *, fd_set *, fd_set *,
+ fd_set *, int *, int);
+extern int physical_IsSet(struct descriptor *, const fd_set *);
+extern void physical_Login(struct physical *, const char *);
+extern void physical_Logout(struct physical *);
+extern int physical_RemoveFromSet(struct physical *, fd_set *, fd_set *,
+ fd_set *);
+extern int physical_SetMode(struct physical *, int);
diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8
index d79583fbbc85..5f01e583ab2e 100644
--- a/usr.sbin/ppp/ppp.8
+++ b/usr.sbin/ppp/ppp.8
@@ -1,13 +1,12 @@
-.\" $Id: ppp.8,v 1.98 1998/03/12 02:23:42 brian Exp $
+.\" $Id: ppp.8,v 1.97.2.38 1998/05/21 01:13:32 brian Exp $
.Dd 20 September 1995
.Os FreeBSD
.Dt PPP 8
.Sh NAME
.Nm ppp
-.Nd Point to Point Protocol (a.k.a. iijppp)
+.Nd Point to Point Protocol (a.k.a. user-ppp)
.Sh SYNOPSIS
.Nm
-.\" SOMEONE FIX ME ! The .Op macro can't handle enough args !
[
.Fl auto |
.Fl background |
@@ -100,22 +99,26 @@ With PAP or CHAP, it is possible to skip the Unix style
.Xr login 1
proceedure, and use the
.Em PPP
-protocol for authentication instead.
+protocol for authentication instead. If the peer requests Microsoft
+CHAP authentication and
+.Nm
+is compiled with DES support, an appropriate MD4/DES response will be
+made.
.It Supports Proxy Arp.
When
.Em PPP
is set up as server, you can also configure it to do proxy arp for your
connection.
.It Supports packet filtering.
-User can define four kinds of filters:
-.Em ifilter
-for incoming packets,
-.Em ofilter
-for outgoing packets,
-.Em dfilter
-to define a dialing trigger packet and
-.Em afilter
-for keeping a connection alive with the trigger packet.
+User can define four kinds of filters: the
+.Em in
+filter for incoming packets, the
+.Em out
+filter for outgoing packets, the
+.Em dial
+filter to define a dialing trigger packet and the
+.Em alive
+filter for keeping a connection alive with the trigger packet.
.It Tunnel driver supports bpf.
The user can use
.Xr tcpdump 1
@@ -123,23 +126,34 @@ to check the packet flow over the
.Em PPP
link.
.It Supports PPP over TCP capability.
-.It Supports IETF draft Predictor-1 compression.
+If a device name is specified as
+.Em host Ns No : Ns Em port ,
+.Nm
+will open a TCP connection for transporting data rather than using a
+conventional serial device.
+.It Supports IETF draft Predictor-1 and DEFLATE compression.
.Nm
-supports not only VJ-compression but also Predictor-1 compression.
+supports not only VJ-compression but also Predictor-1 and DEFLATE compression.
Normally, a modem has built-in compression (e.g. v42.bis) and the system
may receive higher data rates from it as a result of such compression.
While this is generally a good thing in most other situations, this
higher speed data imposes a penalty on the system by increasing the
number of serial interrupts the system has to process in talking to the
-modem and also increases latency. Unlike VJ-compression, Predictor-1
-compression pre-compresses
+modem and also increases latency. Unlike VJ-compression, Predictor-1 and
+DEFLATE compression pre-compresses
.Em all
-data flowing through the link, thus reducing overhead to a minimum.
+network traffic flowing through the link, thus reducing overheads to a
+minimum.
.It Supports Microsoft's IPCP extensions.
Name Server Addresses and NetBIOS Name Server Addresses can be negotiated
with clients using the Microsoft
.Em PPP
stack (ie. Win95, WinNT)
+.It Supports Multilink PPP
+It is possible to configure
+.Nm
+to open more than one physical connection to the peer, combining the
+bandwidth of all links for better throughput.
.Sh PERMISSIONS
.Nm Ppp
is installed as user
@@ -169,8 +183,10 @@ zero.
.Sh GETTING STARTED
When you first run
.Nm
-you may need to deal with some initial configuration details. First,
-your kernel should include a tunnel device (the GENERIC kernel includes
+you may need to deal with some initial configuration details.
+.Bl -bullet
+.It
+Your kernel must include a tunnel device (the GENERIC kernel includes
one by default). If it doesn't, or if you require more than one tun
interface, you'll need to rebuild your kernel with the following line in
your kernel configuration file:
@@ -182,7 +198,8 @@ where
is the maximum number of
.Em PPP
connections you wish to support.
-Second, check your
+.It
+Check your
.Pa /dev
directory for the tunnel device entries
.Pa /dev/tunN ,
@@ -192,7 +209,22 @@ represents the number of the tun device, starting at zero.
If they don't exist, you can create them by running "sh ./MAKEDEV tunN".
This will create tun devices 0 through
.Ar N .
-Last of all, create a log file.
+.It
+Make sure that your system has a group named
+.Dq network
+in the
+.Pa /etc/group
+file and that that group contains the names of all users expected to use
+.Nm ppp .
+Refer to the
+.Xr group 5
+manual page for details. Each of these uses must also be given access
+using the
+.Dq allow users
+command in
+.Pa /etc/ppp/ppp.conf .
+.It
+Create a log file.
.Nm Ppp
uses
.Xr syslog 3
@@ -207,7 +239,9 @@ file:
.Ed
.Pp
Make sure you use actual TABs here. If you use spaces, the line will be
-silently ignored.
+silently ignored by
+.Xr syslogd 8 .
+.Pp
It is possible to have more than one
.Em PPP
log file by creating a link to the
@@ -220,7 +254,7 @@ executable:
and using
.Bd -literal -offset indent
!ppp0
-*.* /var/log/ppp0.log
+*.*<TAB>/var/log/ppp0.log
.Ed
.Pp
in
@@ -231,6 +265,20 @@ signal to
.Xr syslogd 8
after altering
.Pa /etc/syslog.conf .
+.It
+Although not strictly relevent to
+.Nm ppp Ns No s
+operation, you should configure your resolver so that it works correctly.
+This can be done by configuring a local DNS
+.Pq using Xr named 8
+or by adding the correct
+.Sq nameserver
+lines to the file
+.Pa /etc/resolv.conf .
+Refer to the
+.Xr resolv.conf 5
+manual page for details.
+.El
.Sh MANUAL DIALING
In the following examples, we assume that your machine name is
.Dv awfulhak .
@@ -289,19 +337,48 @@ When the peer starts to talk in
detects this automatically and returns to command mode.
.Bd -literal -offset indent
ppp ON awfulhak>
+Ppp ON awfulhak>
+PPp ON awfulhak>
PPP ON awfulhak>
.Ed
.Pp
+If it does not, it's possible that the peer is waiting for your end to
+start negotiating. To force
+.Nm
+to start sending PPP configuration packets to the peer, use the
+.Dq ~p
+command to enter packet mode.
+.Pp
You are now connected! Note that
.Sq PPP
in the prompt has changed to capital letters to indicate that you have
-a peer connection. The show command can be used to see how things are
-going:
+a peer connection. If only some of the three Ps go uppercase, wait 'till
+either everything is uppercase or lowercase. If they revert to lowercase,
+it means that
+.Nm
+couldn't successfully negotiate with the peer. This is probably because
+your PAP or CHAP authentication name or key is incorrect. A good first step
+for troubleshooting at this point would be to
+.Dq set log local phase .
+Refer to the
+.Dq set log
+command description below for further details.
+.Pp
+When the link is established, the show command can be used to see how
+things are going:
.Bd -literal -offset indent
+PPP ON awfulhak> show modem
+* Modem related information is shown here *
+PPP ON awfulhak> show ccp
+* CCP (compression) related information is shown here *
PPP ON awfulhak> show lcp
-* LCP related information is shown here *
+* LCP (line control) related information is shown here *
PPP ON awfulhak> show ipcp
-* IPCP related information is shown here *
+* IPCP (IP) related information is shown here *
+PPP ON awfulhak> show link
+* Link (high level) related information is shown here *
+PPP ON awfulhak> show bundle
+* Logical (high level) connection related information is shown here *
.Ed
.Pp
At this point, your machine has a host route to the peer. This means
@@ -323,6 +400,12 @@ use the keyword
in place of
.Sq HISADDR .
This will create a direct route on the tun interface.
+If it fails due to an existing route, you can overwrite the existing
+route using
+.Bd -literal -offset indent
+PPP ON awfulhak> add! default HISADDR
+.Ed
+.Pp
You can now use your network applications (ping, telnet, ftp etc.)
in other windows on your machine.
Refer to the
@@ -336,7 +419,7 @@ See the example definitions in
.Pa /etc/ppp/ppp.conf
is pretty simple).
Each line contains one comment, inclusion, label or command:
-.Bl -bullet -compact
+.Bl -bullet
.It
A line starting with a
.Pq Dq #
@@ -408,18 +491,37 @@ connection is established. See the provided
.Dq pmdemand
example in
.Pa /etc/ppp/ppp.conf.sample
-which adds a default route. The strings
+which runs a script in the background after the connection is established.
+The literal strings
.Dv HISADDR ,
.Dv MYADDR
and
.Dv INTERFACE
-are available as the relevent IP addresses and interface name.
-Similarly, when a connection is closed, the
+may be used, and will be replaced with the relevent IP addresses and interface
+name. Similarly, when a connection is closed, the
contents of the
.Pa /etc/ppp/ppp.linkdown
file are executed.
Both of these files have the same format as
.Pa /etc/ppp/ppp.conf .
+.Pp
+In previous versions of
+.Nm ppp ,
+it was necessary to re-add routes such as the default route in the
+.Pa ppp.linkup
+file.
+.Nm Ppp
+now supports
+.Sq sticky routes ,
+where all routes that contain the
+.Dv HISADDR
+or
+.Dv MYADDR
+literals will automatically be updated when the values of
+.Dv HISADDR
+and/or
+.Dv MYADDR
+change.
.Sh BACKGROUND DIALING
If you want to establish a connection using
.Nm
@@ -429,12 +531,7 @@ entry or an
.Xr at 1
job) you should use the
.Fl background
-option. You must also specify the destination label in
-.Pa /etc/ppp/ppp.conf
-to use. This label must contain the
-.Dq set ifaddr
-command to define the remote peers IP address. (refer to
-.Pa /etc/ppp/ppp.conf.sample )
+option.
When
.Fl background
is specified,
@@ -464,8 +561,6 @@ command to define the remote peers IP address. (refer to
.Pa /etc/ppp/ppp.conf.sample )
.Bd -literal -offset indent
# ppp -auto pmdemand
-...
-#
.Ed
.Pp
When
@@ -475,33 +570,26 @@ or
is specified,
.Nm
runs as a daemon but you can still configure or examine its
-configuration by using the diagnostic port as follows (this
-can be done in
-.Fl background
-and
-.Fl direct
-mode too):
+configuration by using the
+.Dq set server
+command in
+.Pa /etc/ppp/ppp.conf ,
+.Pq for example, Dq set server +3000 mypasswd
+and connecting to the diagnostic port as follows:
.Bd -literal -offset indent
-# pppctl -v 3000 show ipcp
+# pppctl 3000 (assuming tun0 - see the ``set server'' description)
Password:
-IPCP [Opened]
- his side: xxxx
- ....
+PPP ON awfulhak> show who
+tcp (127.0.0.1:1028) *
.Ed
.Pp
-Currently,
-.Xr telnet 1
-may also be used to talk interactively.
-.Pp
-In order to achieve this, you must use the
-.Dq set server
-command as described below. It is possible to retrospectively make a running
+The
+.Dq show who
+command lists users that are currently connected to
.Nm
-program listen on a diagnostic port by configuring
-.Pa /etc/ppp/ppp.secret ,
-and sending it a
-.Dv USR1
-signal.
+itself. If the diagnostic socket is closed or changed to a different
+socket, all connections are immediately dropped.
+.Pp
In
.Fl auto
mode, when an outgoing packet is detected,
@@ -638,95 +726,116 @@ to enable a
.Xr getty 8
on the port where the modem is attached.
For example:
+.Pp
.Dl ttyd1 "/usr/libexec/getty std.38400" dialup on secure
+.Pp
Don't forget to send a
.Dv HUP
signal to the
.Xr init 8
process to start the
-.Xr getty 8 .
-.Dl # kill -HUP 1
-.It
-Prepare an account for the incoming user.
-.Bd -literal
-ppp:xxxx:66:66:PPP Login User:/home/ppp:/usr/local/bin/ppplogin
-.Ed
+.Xr getty 8 :
.Pp
+.Dl # kill -HUP 1
.It
Create a
.Pa /usr/local/bin/ppplogin
file with the following contents:
.Bd -literal -offset indent
-#!/bin/sh -p
-exec /usr/sbin/ppp -direct
+#! /bin/sh
+exec /usr/sbin/ppp -direct incoming
.Ed
.Pp
-(You can specify a label name for further control.)
-.Pp
Direct mode
.Pq Fl direct
lets
.Nm
work with stdin and stdout. You can also use
.Xr pppctl 8
-or
-.Xr telnet 1
to connect to a configured diagnostic port, in the same manner as with
client-side
.Nm ppp .
+.Pp
+Here, the
+.Ar incoming
+label must be set up in
+.Pa /etc/ppp/ppp.conf .
.It
-Optional support for Microsoft's IPCP Name Server and NetBIOS
-Name Server negotiation can be enabled use
-.Dq enable msext
-and
-.Dq set ns pri-addr [sec-addr]
-along with
-.Dq set nbns pri-addr [sec-addr]
-in your
-.Pa /etc/ppp/ppp.conf
-file.
+Prepare an account for the incoming user.
+.Bd -literal
+ppp:xxxx:66:66:PPP Login User:/home/ppp:/usr/local/bin/ppplogin
+.Ed
+.Pp
+Refer to the manual entries for
+.Xr adduser 8
+and
+.Xr vipw 8
+for details.
+.It
+Support for IPCP Domain Name Server and NetBIOS Name Server negotiation
+can be enabled using the
+.Dq enable dns
+and
+.Dq set nbns
+commands. Refer to their descriptions below.
.El
.Pp
.Sh RECEIVING INCOMING PPP CONNECTIONS (Method 2)
-This method differs in that it recommends the use of
-.Em mgetty+sendfax
-to handle the modem connections. The latest versions (0.99 and higher)
-can be compiled with the
-.Dq AUTO_PPP
-option to allow detection of clients speaking
-.Em PPP
-to the login prompt.
-Follow these steps:
+This method differs in that we use
+.Nm ppp
+to authenticate the connection rather than
+.Xr login 1 :
.Bl -enum
.It
-Get, configure, and install mgetty+sendfax v0.99 or later making
-sure you have used the AUTO_PPP option.
+Configure your default section in
+.Pa /etc/gettytab
+with automatic ppp recognition by specifying the
+.Dq pp
+capability:
+.Bd -literal
+default:\\
+ :pp=/usr/local/bin/ppplogin:\\
+ .....
+.Ed
+.It
+Configure your serial device(s), enable a
+.Xr getty 8
+and create
+.Pa /usr/local/bin/ppplogin
+as in the first three steps for method 1 above.
.It
-Edit
-.Pa /etc/ttys
-to enable a mgetty on the port where the modem is attached. For
-example:
-.Dl cuaa1 "/usr/local/sbin/mgetty -s 57600" dialup on
+Add either
+.Dq enable chap
+or
+.Dq enable pap
+.Pq or both
+to
+.Pa /etc/ppp/ppp.conf
+under the
+.Sq incoming
+label (or whatever label
+.Pa ppplogin
+uses).
.It
-Prepare an account for the incoming user.
+Create an entry in
+.Pa /etc/ppp/ppp.secret
+for each incoming user:
.Bd -literal
-Pfred:xxxx:66:66:Fred's PPP:/home/ppp:/etc/ppp/ppp-dialup
+Pfred<TAB>xxxx
+Pgeorge<TAB>yyyy
.Ed
.Pp
-.It
-Examine the files
-.Pa /etc/ppp/sample.ppp-dialup ,
-.Pa /etc/ppp/sample.ppp-pap-dialup
-and
-.Pa /etc/ppp/ppp.conf.sample
-for ideas.
-.Pa /etc/ppp/ppp-pap-dialup
-is supposed to be called from
-.Pa /usr/local/etc/mgetty+sendfax/login.conf
-from a line like
-.Dl /AutoPPP/ - - /etc/ppp/ppp-pap-dialup
-.El
-.Pp
+Now, as soon as
+.Xr getty 8
+detects a ppp connection (by recognising the HDLC frame headers), it runs
+.Dq /usr/local/bin/ppplogin .
+.Pp
+It is
+.Em VITAL
+that either PAP or CHAP are enabled as above. If they are not, you are
+allowing anybody to establish ppp session with your machine
+.Em without
+a password, opening yourself up to all sorts of potential attacks.
.Sh AUTHENTICATING INCOMING CONNECTIONS
Normally, the receiver of a connection requires that the peer
authenticates themself. This may be done using
@@ -816,7 +925,7 @@ on ui-gate (the receiver) should contain the following:
ppp-in:
set timeout 0
set ifaddr 10.0.4.1 10.0.4.2
- add 10.0.1.0 255.255.255.0 10.0.4.2
+ add 10.0.1.0/24 10.0.4.2
.Ed
.Pp
You may also want to enable PAP or CHAP for security. To enable PAP, add
@@ -831,6 +940,14 @@ You'll also need to create the following entry in
MyAuthName MyAuthPasswd
.Ed
.Pp
+If
+.Ar MyAuthPasswd
+is a
+.Pq Dq * ,
+the password is looked up in the
+.Xr passwd 5
+database.
+.Pp
The entry in
.Pa /etc/ppp/ppp.conf
on awfulhak (the initiator) should contain the following:
@@ -839,10 +956,10 @@ ui-gate:
set escape 0xff
set device ui-gate:ppp-in
set dial
- set timeout 30 15 5
- set log Phase Chat Connect Carrier hdlc LCP IPCP CCP tun
+ set timeout 30
+ set log Phase Chat Connect hdlc LCP IPCP CCP tun
set ifaddr 10.0.4.2 10.0.4.1
- add 10.0.2.0 255.255.255.0 10.0.4.1
+ add 10.0.2.0/24 10.0.4.1
.Ed
.Pp
Again, if you're enabling PAP, you'll also need:
@@ -911,35 +1028,98 @@ and that other machines have designated the
host as the gateway for the LAN.
.Sh PACKET FILTERING
This implementation supports packet filtering. There are four kinds of
-filters; ifilter, ofilter, dfilter and afilter. Here are the basics:
-.Bl -bullet -compact
+filters; the
+.Em in
+filter, the
+.Em out
+filter, the
+.Em dial
+filter and the
+.Em alive
+filter. Here are the basics:
+.Bl -bullet
.It
A filter definition has the following syntax:
-set filter-name rule-no action [src_addr/src_width] [dst_addr/dst_width]
-[proto [src [lt|eq|gt] port ]] [dst [lt|eq|gt] port] [estab]
+.Pp
+set filter
+.Ar name
+.Ar rule-no
+.Ar action
+.Op Ar src_addr Ns Op / Ns Ar width
+.Op Ar dst_addr Ns Op / Ns Ar width
+[
+.Ar proto
+.Op src Op Ar cmp No Ar port
+.Op dst Op Ar cmp No Ar port
+.Op estab
+.Op syn
+.Op finrst
+]
.Bl -enum
.It
-.Sq filter-name
-should be one of ifilter, ofilter, dfilter or afilter.
+.Ar Name
+should be one of
+.Sq in ,
+.Sq out ,
+.Sq dial
+or
+.Sq alive .
.It
-There are two actions:
-.Sq permit
+.Ar Rule-no
+is a numeric value between
+.Sq 0
and
+.Sq 19
+specifying the rule number. Rules are specified in numeric order according to
+.Ar rule-no ,
+but only if rule
+.Sq 0
+is defined.
+.It
+.Ar Action
+is either
+.Sq permit
+or
.Sq deny .
If a given packet
matches the rule, the associated action is taken immediately.
.It
-.Sq src_width
+.Op Ar src_addr Ns Op / Ns Ar width
and
-.Sq dst_width
-work like a netmask to represent an address range.
+.Op Ar dst_addr Ns Op / Ns Ar width
+are the source and destination IP number specifications. If
+.Op / Ns Ar width
+is specified, it gives the number of relevent netmask bits,
+allowing the specification of an address range.
.It
-.Sq proto
-must be one of icmp, udp or tcp.
+.Ar Proto
+must be one of
+.Sq icmp ,
+.Sq udp
+or
+.Sq tcp .
.It
-.Sq port number
-can be specified by number and service name from
+.Ar Cmp
+is one of
+.Sq \&lt ,
+.Sq \&eq
+or
+.Sq \&gt ,
+meaning less-than, equal and greater-than respectively.
+.Ar Port
+can be specified as a numeric port or by service name from
.Pa /etc/services .
+.It
+The
+.Sq estab ,
+.Sq syn ,
+and
+.Sq finrst
+flags are only allowed when
+.Ar proto
+is set to
+.Sq tcp ,
+and represent the TH_ACK, TH_SYN and TH_FIN or TH_RST TCP flags respectively.
.El
.Pp
.It
@@ -951,41 +1131,47 @@ If no rule is matched to a packet, that packet will be discarded
(blocked).
.It
Use
-.Dq set filter-name -1
+.Dq set filter Ar name No -1
to flush all rules.
.El
.Pp
See
-.Pa /etc/ppp/ppp.conf.filter.example .
-.Sh SETTING IDLE, LINE QUALITY REQUEST, RETRY TIMER
-To check/set idle timer, use the
-.Dq show timeout
+.Pa /etc/ppp/ppp.conf.example .
+.Sh SETTING THE IDLE TIMER
+To check/set the idle timer, use the
+.Dq show bundle
and
-.Dq set timeout idle [LQR [FSM-resend]]
+.Dq set timeout
commands:
.Bd -literal -offset indent
ppp ON awfulhak> set timeout 600
.Ed
.Pp
-The timeout period is measured in seconds, the default values for which
-are timeout = 180 or 3 min, lqrtimer = 30sec and retrytimer = 3sec.
+The timeout period is measured in seconds, the default value for which
+is 180 seconds
+.Pq or 3 min .
To disable the idle timer function, use the command
.Bd -literal -offset indent
ppp ON awfulhak> set timeout 0
.Ed
.Pp
In
+.Fl ddial
+and
+.Fl direct
+modes, the idle timeout is ignored. In
.Fl auto
-mode, an idle timeout causes the
+mode, when the idle timeout causes the
.Em PPP
session to be
-closed, though the
+closed, the
.Nm
program itself remains running. Another trigger packet will cause it to
-attempt to reestablish the link.
+attempt to re-establish the link.
.Sh PREDICTOR-1 and DEFLATE COMPRESSION
-This version supports CCP and Predictor type 1 or deflate compression
-based on the current IETF-draft specs. As a default behaviour,
+.Nm Ppp
+supports both Predictor type 1 and deflate compression.
+By default,
.Nm
will attempt to use (or be willing to accept) both compression protocols
when the peer agrees
@@ -998,11 +1184,26 @@ and
.Dq deny
commands if you wish to disable this functionality.
.Pp
-It is possible to use a different algorithm in each direction by using
-only one of
+It is possible to use a different compression algorithm in each direction
+by using only one of
.Dq disable deflate
and
-.Dq deny deflate .
+.Dq deny deflate
+.Pq assuming that the peer supports both algorithms .
+.Pp
+By default, when negotiating DEFLATE,
+.Nm
+will use a window size of 15. Refer to the
+.Dq set deflate
+command if you wish to change this behaviour.
+.Pp
+A special algorithm called DEFLATE24 is also available, and is disabled
+and denied by default. This is exactly the same as DEFLATE except that
+it uses CCP ID 24 to negotiate. This allows
+.Nm
+to successfully negotiate DEFLATE with
+.Nm pppd
+version 2.3.*.
.Sh CONTROLLING IP ADDRESS
.Nm
uses IPCP to negotiate IP addresses. Each side of the connection
@@ -1030,15 +1231,18 @@ is the IP address which the remote side should use and
.Sq netmask
is the netmask that should be used.
.Sq Src_addr
-and
+defaults to the current
+.Xr hostname 1 ,
.Sq dst_addr
-default to 0.0.0.0, and
+defaults to 0.0.0.0, and
.Sq netmask
defaults to whatever mask is appropriate for
.Sq src_addr .
It is only possible to make
.Sq netmask
-smaller than the default. The usual value is 255.255.255.255.
+smaller than the default. The usual value is 255.255.255.255, as
+most kernels ignore the netmask of a POINTOPOINT interface.
+.Pp
Some incorrect
.Em PPP
implementations require that the peer negotiates a specific IP
@@ -1053,6 +1257,7 @@ set ifaddr 192.244.177.38 192.244.177.2 255.255.255.255 0.0.0.0
.Ed
.Pp
The above specification means:
+.Pp
.Bl -bullet -compact
.It
I will first suggest that my IP address should be 0.0.0.0, but I
@@ -1076,6 +1281,7 @@ user to specify IP address more loosely:
.Pp
A number followed by a slash (/) represent the number of bits significant in
the IP address. The above example signifies that:
+.Pp
.Bl -bullet -compact
.It
I'd like to use 192.244.177.38 as my address if it is possible, but I'll
@@ -1267,16 +1473,13 @@ be ignored as it is less restrictive than the default mask for your
An example for a connection where you don't know your IP number or your
ISPs IP number would be:
.Bd -literal -offset indent
-set ifaddr 10.10.10.10/0 10.10.11.11/0 0.0.0.0 0.0.0.0
+set ifaddr 10.0.0.1/0 10.0.0.2/0 0.0.0.0 0.0.0.0
.Ed
.Pp
.It
In most cases, your ISP will also be your default router. If this is
-the case, and if you're using
-.Fl auto
-mode, add the lines
+the case, add the line
.Bd -literal -offset indent
-delete ALL
add default HISADDR
.Ed
.Pp
@@ -1285,43 +1488,21 @@ to
.Pp
This tells
.Nm
-to delete all non-direct routing entries for the tun interface that
-.Nm
-is running on, then to add a default route to 10.10.11.11. If you're
-not using
-.Fl auto
-mode, this isn't necessary as
-.Nm
-will dial immediately and may negotiate new IP numbers with the peer.
-.Pp
-If you're not using
-.Fl auto
-mode, or if you're using dynamic IP numbers, you must also put these
-two lines in the
-.Pa /etc/ppp/ppp.linkup
-file:
-.Bd -literal -offset indent
-delete ALL
-add default HISADDR
-.Ed
+to add a default route to whatever the peer address is
+.Pq 10.0.0.2 in this example .
+This route is
+.Sq sticky ,
+meaning that should the value of
+.Dv HISADDR
+change, the route will be updated accordingly.
.Pp
-HISADDR is a macro meaning the "other side"s IP number, and is
-available once an IP number has been agreed (using IPCP) or set
-.Pq using Dq set ifaddr .
-Now, once a connection is established,
+Previous versions of
.Nm
-will delete all non-direct interface routes, and add a default route
-pointing at the peers IP number. You should use the same label as the
-one used in
-.Pa /etc/ppp/ppp.conf .
-.Pp
-If commands are being typed interactively, the only requirement is
-to type
-.Bd -literal -offset indent
-add default HISADDR
-.Ed
-.Pp
-after a successful dial.
+required a similar entry in the
+.Pa /etc/ppp/ppp.linkup
+file. Since the advent of
+.Sq sticky routes ,
+his is no longer required.
.It
If your provider requests that you use PAP/CHAP authentication methods, add
the next lines to your
@@ -1350,20 +1531,19 @@ is able to generate the following log info either via
or directly to the screen:
.Bl -column SMMMMMM -offset indent
.It Li Async Dump async level packet in hex
-.It Li Carrier Log Chat lines with 'CARRIER'
.It Li CCP Generate a CCP packet trace
.It Li Chat Generate Chat script trace log
.It Li Command Log commands executed
.It Li Connect Generate complete Chat log
-.It Li Debug Log (very verbose) debug information
+.It Li Debug Log debug information
.It Li HDLC Dump HDLC packet in hex
.It Li ID0 Log all function calls specifically made as user id 0.
.It Li IPCP Generate an IPCP packet trace
.It Li LCP Generate an LCP packet trace
-.It Li Link Log address assignments and link up/down events
.It Li LQM Generate LQR report
.It Li Phase Phase transition log output
.It Li TCP/IP Dump all TCP/IP packets
+.It Li Timer Log timer manipulation
.It Li TUN Include the tun device on each log line
.It Li Warning Output to the terminal device. If there is currently no
terminal, output is sent to the log file using LOG_WARNING.
@@ -1376,7 +1556,7 @@ The
.Dq set log
command allows you to set the logging output level. Multiple levels
can be specified on a single command line. The default is equivalent to
-.Dq set log Carrier Link Phase .
+.Dq set log Phase .
.Pp
It is also possible to log directly to the screen. The syntax is
the same except that the word
@@ -1385,21 +1565,21 @@ should immediately follow
.Dq set log .
The default is
.Dq set log local
-(ie. no direct screen logging).
+(ie. only the un-maskable warning, error and alert output).
.Pp
If The first argument to
.Dq set log Op local
begins with a '+' or a '-' character, the current log levels are
not cleared, for example:
.Bd -literal -offset indent
-PPP ON awfulhak> set log carrier link phase
+PPP ON awfulhak> set log phase
PPP ON awfulhak> show log
-Log: Carrier Link Phase Warning Error Alert
+Log: Phase Warning Error Alert
Local: Warning Error Alert
-PPP ON awfulhak> set log -link +tcp/ip -warning
+PPP ON awfulhak> set log +tcp/ip -warning
PPP ON awfulhak> set log local +command
PPP ON awfulhak> show log
-Log: Carrier Phase TCP/IP Warning Error Alert
+Log: Phase TCP/IP Warning Error Alert
Local: Command Warning Error Alert
.Ed
.Pp
@@ -1428,19 +1608,173 @@ mode.
These signals tell
.Nm
to exit.
-.It USR1
-This signal, when not in interactive mode, tells
-.Nm
-to close any existing server socket and open an Internet socket using
-port 3000 plus the current tunnel device number. This can only be
-achieved if a suitable local password is specified in
-.Pa /etc/ppp/ppp.secret .
.It USR2
This signal, tells
.Nm
-to close any existing server socket.
+to close any existing server socket, dropping all existing diagnostic
+connections.
.El
.Pp
+.Sh MULTILINK PPP
+If you wish to use more than one physical link to connect to a
+.Em PPP
+peer, that peer must also understand the
+.Em MULTILINK PPP
+protocol. Refer to RFC 1990 for specification details.
+.Pp
+The peer is identified using a combination of his
+.Dq endpoint discriminator
+and his
+.Dq authentication id .
+Either or both of these may be specified. It is recommended that
+at least one is specified, otherwise there is no way of ensuring that
+all links are actually connected to the same peer program, and some
+confusing lock-ups may result. Locally, these identification variables
+are specified using the
+.Dq set enddisc
+and
+.Dq set authname
+commands. The
+.Sq authname
+.Pq and Sq authkey
+must be agreed in advance with the peer.
+.Pp
+Multilink capabilities are enabled using the
+.Dq set mrru
+command (set maximum reconstructed receive unit). Once multilink
+is enabled,
+.Nm
+will attempt to negotiate a multilink connection with the peer.
+.Pp
+By default, only one
+.Sq link
+is available
+.Pq called Sq deflink .
+To create more links, the
+.Dq clone
+command is used. This command will clone existing links, where all
+characteristics are the same except:
+.Bl -enum
+.It
+The new link has its own name as specified on the
+.Dq clone
+command line.
+.It
+The new link is an
+.Sq interactive
+link. It's mode may subsequently be changed using the
+.Dq set mode
+command.
+.It
+The new link is in a
+.Sq closed
+state.
+.El
+.Pp
+A summary of all available links can be seen using the
+.Dq show links
+command.
+.Pp
+Once a new link has been created, command usage varies. All link
+specific commands must be prefixed with the
+.Dq link Ar name
+command, specifying on which link the command is to be applied. When
+only a single link is available,
+.Nm
+is smart enough not to require the
+.Dq link Ar name
+prefix.
+.Pp
+Some commands can still be used without specifying a link - resulting
+in an operation at the
+.Sq bundle
+level. For example, once two or more links are available, the command
+.Dq show ccp
+will show CCP configuration and statistics at the multilink level, and
+.Dq link deflink show ccp
+will show the same information at the
+.Dq deflink
+link level.
+.Pp
+Armed with this information, the following configuration might be used:
+.Pp
+.Bd -literal -offset indent
+mp:
+ set timeout 0
+ set log phase chat
+ set device /dev/cuaa0 /dev/cuaa1 /dev/cuaa2
+ set phone "123456789"
+ set dial "ABORT BUSY ABORT NO\\sCARRIER TIMEOUT 5 \\"\\" ATZ \e
+ OK-AT-OK \\\\dATDT\\\\T TIMEOUT 45 CONNECT"
+ set login
+ set ifaddr 10.0.0.1/0 10.0.0.2/0
+ set authname ppp
+ set authkey ppppassword
+
+ set mrru 1500
+ clone 1,2,3
+ link deflink remove
+.Ed
+.Pp
+Note how all cloning is done at the end of the configuration. Usually,
+the link will be configured first, then cloned. If you wish all links
+to be up all the time, you can add the following line to the end of your
+configuration.
+.Pp
+.Bd -literal -offset indent
+ link 1,2,3 set mode ddial
+.Ed
+.Pp
+If you want the links to dial on demand, this command could be used:
+.Pp
+.Bd -literal -offset indent
+ link * set mode auto
+.Ed
+.Pp
+Links may be tied to specific names by removing the
+.Dq set device
+line above, and specifying the following after the
+.Dq clone
+command:
+.Pp
+.Bd -literal -offset indent
+ link 1 set device /dev/cuaa0
+ link 2 set device /dev/cuaa1
+ link 3 set device /dev/cuaa2
+.Ed
+.Pp
+Use the
+.Dq help
+command to see which commands require context (using the
+.Dq link
+command), which have optional
+context and which should not have any context.
+.Pp
+When
+.Nm
+has negotiated
+.Em MULTILINK
+mode with the peer, it creates a unix domain socket in the
+.Pa /var/run
+directory. This socket is used to pass link information (including
+the actual link file descriptor) between different
+.Nm
+invocations. This facilitates
+.Nm ppp Ns No s
+ability to be run from a
+.Xr getty 8
+or directly from
+.Pa /etc/gettydefs
+(using the
+.Sq pp=
+capability), without needing to have initial control of the serial
+line. Once
+.Nm
+negotiates multilink mode, it will pass its open link to any
+already running process. If there is no already running process,
+.Nm
+will act as the master, creating the socket and listening for new
+connections.
.Sh PPP COMMAND LIST
This section lists the available commands and their effect. They are
usable either from an interactive
@@ -1451,7 +1785,7 @@ or
.Xr telnet 1
session.
.Bl -tag -width 20
-.It accept|deny|enable|disable option....
+.It accept|deny|enable|disable Ar option....
These directives tell
.Nm
how to negotiate the initial connection with the peer. Each
@@ -1501,9 +1835,10 @@ CHAP is accepted by default.
Some
.Em PPP
implementations use "MS-CHAP" rather than MD5 when encrypting the
-challenge. Refer to the description of the
-.Dq set encrypt
-command for further details.
+challenge. MS-CHAP is a combination of MD4 and DES. If
+.Nm was build
+on a machine with DES libraries available, it will respond to MS-CHAP
+authentication requests, but will never request them.
.It deflate
Default: Enabled and Accepted. This option decides if deflate
compression will be used by the Compression Control Protocol (CCP).
@@ -1536,17 +1871,69 @@ in
is capable of negotiating with
.Nm pppd ,
but only if
-.Dq pppd-deflate
+.Dq deflate24
is
.Ar enable Ns No d
and
.Ar accept Ns No ed .
+.It deflate24
+Default: Disabled and Denied. This is a variance of the
+.Ar deflate
+option, allowing negotiation with the
+.Xr pppd 8
+program. Refer to the
+.Ar deflate
+section above for details. It is disabled by default as it violates
+.Pa rfc1975 .
+.It dns
+Default: Enabled and Denied. This option allows DNS negotiation.
+.Pp
+If
+.Dq enable Ns No d,
+.Nm
+will request that the peer confirms the entries in
+.Pa /etc/resolv.conf .
+If the peer NAKs our request (suggesting new IP numbers),
+.Pa /etc/resolv.conf
+is updated and another request is sent to confirm the new entries.
+.Pp
+If
+.Dq accept Ns No ed,
+.Nm
+will answer any DNS queries requested by the peer rather than rejecting
+them. The answer is taken from
+.Pa /etc/resolv.conf
+unless the
+.Dq set dns
+command is used as an override.
.It lqr
Default: Disabled and Accepted. This option decides if Link Quality
-Requests will be sent. LQR is a protocol that allows
+Requests will be sent or accepted. LQR is a protocol that allows
.Nm
to determine that the link is down without relying on the modems
-carrier detect.
+carrier detect. When LQR is enabled,
+.Nm
+sends the
+.Em QUALPROTO
+option (see
+.Dq set lqrperiod
+below) as part of the LCP request. If the peer agrees, both sides will
+exchange LQR packets at the agreed frequency, allowing detailed link
+quality monitoring by enabling LQM logging. If the peer doesn't agree,
+ppp will send ECHO LQR requests instead. These packets pass no
+information of interest, but they
+.Em MUST
+be replied to by the peer.
+.Pp
+Whether using LQR or ECHO LQR,
+.Nm
+will abruptly drop the connection if 5 unacknowledged packets have been
+sent rather than sending a 6th. A message is logged at the
+.Em PHASE
+level, and any appropriate
+.Dq reconnect
+values are honoured as if the peer were responsible for dropping the
+connection.
.It pap
Default: Disabled and Accepted. PAP stands for Password Authentication
Protocol. Only one of PAP and CHAP (above) may be negotiated. With
@@ -1571,15 +1958,6 @@ and
in
.Pa /etc/ppp/ppp.conf .
PAP is accepted by default.
-.It pppd-deflate
-Default: Disabled and Denied. This is a variance of the
-.Ar deflate
-option, allowing negotiation with the
-.Xr pppd 8
-program. Refer to the
-.Ar deflate
-section above for details. It is disabled by default as it violates
-.Pa rfc1975 .
.It pred1
Default: Enabled and Accepted. This option decides if Predictor 1
compression will be used by the Compression Control Protocol (CCP).
@@ -1587,20 +1965,49 @@ compression will be used by the Compression Control Protocol (CCP).
Default: Enabled and Accepted. This option is used to negotiate
PFC (Protocol Field Compression), a mechanism where the protocol
field number is reduced to one octet rather than two.
+.It shortseq
+Default: Enabled and Accepted. This option determines if
+.Nm
+will request and accept requests for short
+.Pq 12 bit
+sequence numbers when negotiating multilink mode. This is only
+applicable if our MRRU is set (thus enabling multilink).
.It vjcomp
-Default: Enabled and Accepted. This option decides if Van Jacobson
+Default: Enabled and Accepted. This option determines if Van Jacobson
header compression will be used.
.El
.Pp
The following options are not actually negotiated with the peer.
Therefore, accepting or denying them makes no sense.
.Bl -tag -width 20
-.It msext
-Default: Disabled. This option allows the use of Microsoft's
+.It idcheck
+Default: Enabled. When
+.Nm
+exchanges low-level LCP, CCP and IPCP configuration traffic, the
+.Em Identifier
+field of any replies is expected to be the same as that of the request.
+By default,
+.Nm
+drops any reply packets that do not contain the expected identifier
+field, reporting the fact at the respective log level. If
+.Ar idcheck
+is disabled,
+.Nm
+will ignore the identifier field.
+.It loopback
+Default: Enabled. When
+.Ar loopback
+is enabled,
+.Nm
+will automatically loop back packets being sent
+out with a destination address equal to that of the
.Em PPP
-extensions, supporting the negotiation of the DNS and the NetBIOS NS.
-Enabling this allows us to pass back the values given in "set ns"
-and "set nbns".
+interface. If disabled,
+.Nm
+will send the packet, probably resulting in an ICMP redirect from
+the other end. It is convenient to have this option enabled when
+the interface is also the default route as it avoids the necessity
+of a loopback route.
.It passwdauth
Default: Disabled. Enabling this option will tell the PAP authentication
code to use the password file (see
@@ -1608,12 +2015,34 @@ code to use the password file (see
to authenticate the caller rather than the
.Pa /etc/ppp/ppp.secret
file.
+.Pa /etc/ppp/ppp.secret
+is checked before
+.Xr passwd 5 .
.It proxy
Default: Disabled. Enabling this option will tell
.Nm
to proxy ARP for the peer.
+.It sroutes
+Default: Enabled. When the
+.Dq add
+command is used with the
+.Dv HISADDR
+or
+.Dv MYADDR
+values, entries are stored in the
+.Sq stick route
+list. Each time
+.Dv HISADDR
+or
+.Dv MYADDR
+change, this list is re-applied to the routing table.
+.Pp
+Disabling this option will prevent the re-application of sticky routes,
+altough the
+.Sq stick route
+list will still be maintained.
.It throughput
-Default: Disabled. Enabling this option will tell
+Default: Enabled. This option tells
.Nm
to gather thoroughput statistics. Input and output is sampled over
a rolling 5 second window, and current, best and total figures are
@@ -1621,7 +2050,7 @@ retained. This data is output when the relevent
.Em PPP
layer shuts down, and is also available using the
.Dq show
-command. Troughput statistics are available at the
+command. Throughput statistics are available at the
.Dq IPCP
and
.Dq modem
@@ -1639,25 +2068,31 @@ not to make any utmp or wtmp entries. This is usually only necessary if
you require the user to both login and authenticate themselves.
.El
.Pp
-.It add[!] dest mask gateway
+.It add[!] Ar dest[/nn] [mask] gateway
.Ar Dest
-is the destination IP address and
-.Ar mask
-is its mask.
+is the destination IP address. The netmask is specified either as a
+number of bits with
+.Ar /nn
+or as an IP number using
+.Ar mask .
.Ar 0 0
-refers to the default route, and it is possible to use the symbolic name
+or simply
+.Ar 0
+with no mask refers to the default route. It is also possible to use the
+literal name
.Sq default
-in place of both the
-.Ar dest
-and
-.Ar mask
-arguments.
+instead of
+.Ar 0 .
.Ar Gateway
is the next hop gateway to get to the given
.Ar dest
-machine/network. It is possible to use the symbolic names
+machine/network. Refer to the
+.Xr route 8
+command for further details.
+.Pp
+It is possible to use the symbolic names
.Sq MYADDR
-and
+or
.Sq HISADDR
as the destination, and either
.Sq HISADDR
@@ -1668,7 +2103,7 @@ as the
.Sq MYADDR
is replaced with the interface address,
.Sq HISADDR
-is replaced with the interfaces destination address and
+is replaced with the interface destination address and
.Sq INTERFACE
is replaced with the current interface name. If the interfaces destination
address has not yet been assigned
@@ -1678,23 +2113,32 @@ the current
is used instead of
.Sq HISADDR .
.Pp
-Refer to the
-.Dq set ifaddr
-command below for details of some restrictions regarding the use of this
-command in the
-.Pa ppp.conf
-file.
-.Pp
If the
.Ar add!
command is used
-.Pq note the following Dq \&! ,
+.Pq note the trailing Dq \&! ,
then if the route already exists, it will be updated as with the
.Sq route change
command (see
.Xr route 8
for further details).
-.It allow .....
+.Pp
+Routes that contain the
+.Dq HISADDR
+or
+.Dq MYADDR
+constants are considered
+.Sq sticky .
+They are stored in a list (use
+.Dq show ipcp
+to see the list), and each time the value of
+.Dv HISADDR
+or
+.Dv MYADDR
+changes, the appropriate routing table entries are updated. This facility
+may be disabled using
+.Dq disable sroutes .
+.It allow Ar command Op Ar args
This command controls access to
.Nm
and its configuration files. It is possible to allow user-level access,
@@ -1712,13 +2156,15 @@ mode.
.Pp
User id 0 is immune to these commands.
.Bl -tag -width 20
-.It allow user|users logname...
-By default, only user id 0 is allowed access. If this command is specified,
-all of the listed users are allowed access to the section in which the
+.It allow user[s] Ar logname...
+By default, only user id 0 is allowed access to
+.Nm ppp .
+If this command is used, all of the listed users are allowed access to
+the section in which the
.Dq allow users
command is found. The
.Sq default
-section is always checked first (although it is only ever automatically
+section is always checked first (even though it is only ever automatically
loaded at startup). Each successive
.Dq allow users
command overrides the previous one, so it's possible to allow users access
@@ -1729,11 +2175,11 @@ section, and then specifying a new user list for that label.
If user
.Sq *
is specified, access is allowed to all users.
-.It allow mode|modes modelist...
-By default, access using all
+.It allow mode[s] Ar modelist...
+By default, access using any
.Nm
-modes is possible. If this command is used, it restricts the access
-modes allowed to load the label under which this command is specified.
+mode is possible. If this command is used, it restricts the access
+mode allowed to load the label under which this command is specified.
Again, as with the
.Dq allow users
command, each
@@ -1751,9 +2197,13 @@ Possible modes are:
.Sq background
and
.Sq * .
+.Pp
+When running in multilink mode, a section can be loaded if it allows
+.Em any
+of the currently existing line modes.
.El
.Pp
-.It alias .....
+.It alias Ar command Op Ar args
This command allows the control of the aliasing (or masquerading)
facilities that are built into
.Nm ppp .
@@ -1770,26 +2220,35 @@ The
.Fl alias
command line flag is synonymous with
.Dq alias enable yes .
-.It alias port [proto targetIP:targetPORT [aliasIP:]aliasPORT]
+.It alias port Op Ar proto targetIP:targetPORT [aliasIP:]aliasPORT
This command allows us to redirect connections arriving at
-.Dq aliasPORT
-for machine [aliasIP] to
-.Dq targetPORT
+.Ar aliasPORT
+for machine
+.Ar aliasIP
+to
+.Ar targetPORT
on
-.Dq targetIP .
-If proto is specified, only connections of the given protocol
+.Ar targetIP .
+.Ar Proto
+may be either
+.Sq tcp
+or
+.Sq udp ,
+and only connections of the given protocol
are matched. This option is useful if you wish to run things like
Internet phone on the machines behind your gateway.
-.It alias addr [addr_local addr_alias]
+.It alias addr Op Ar addr_local addr_alias
This command allows data for
-.Dq addr_alias
+.Ar addr_alias
to be redirected to
-.Dq addr_local .
+.Ar addr_local .
It is useful if you own a small number of real IP numbers that
you wish to map to specific machines behind your gateway.
.It alias deny_incoming [yes|no]
If set to yes, this command will refuse all incoming connections
by dropping the packets in much the same way as a firewall would.
+.It alias help|?
+This command gives a summary of available alias commands.
.It alias log [yes|no]
This option causes various aliasing statistics and information to
be logged to the file
@@ -1807,13 +2266,12 @@ IRC connection.
Only alter outgoing packets with an unregistered source ad-
dress. According to RFC 1918, unregistered source addresses
are 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.
-.It alias help|?
-This command gives a summary of available alias commands.
.El
.Pp
-.It [!]bg command
-The given command is executed in the background.
-Any of the pseudo arguments
+.It [!]bg Ar command
+The given
+.Ar command
+is executed in the background. Any of the pseudo arguments
.Dv HISADDR ,
.Dv INTERFACE
and
@@ -1823,19 +2281,46 @@ will be replaced with the appropriate values. If you wish to pause
while the command executes, use the
.Dv shell
command instead.
-.It close
-Close the current connection (but don't quit).
-.It delete[!] dest
+.It clone Ar name[,name]...
+Clone the specified link, creating one or more new links according to the
+.Ar name
+argument(s). This command must be used from the
+.Dq link
+command below unless you've only got a single link (in which case that
+link becomes the default). Links may be removed using the
+.Dq remove
+command below.
+.Pp
+The default link name is
+.Dq deflink .
+.It close Op lcp|ccp[!]
+If no arguments are given, or if
+.Dq lcp
+is specified, the link will be closed. If
+.Dq ccp
+is specified, only the relevent compression layer is closed. If the
+.Dq \&!
+is used, the compression layer will remain in the closed state, otherwise
+it will re-enter the STOPPED state, waiting for the peer to initiate
+further CCP negotiation. In any event, this command does not disconnect
+the user from
+.Nm
+or exit
+.Nm ppp .
+See the
+.Dq quit
+command below.
+.It delete[!] Ar dest
This command deletes the route with the given
.Ar dest
IP address. If
.Ar dest
is specified as
.Sq ALL ,
-all non-direct entries in the routing for the current interface that
-.Nm
-is using are deleted. This means all entries for tunN, except the entry
-representing the actual link. If
+all non-direct entries in the routing table for the current interface,
+and all
+.Sq sticky route
+entries are deleted. If
.Ar dest
is specified as
.Sq default ,
@@ -1844,41 +2329,73 @@ the default route is deleted.
If the
.Ar delete!
command is used
-.Pq note the following Dq \&! ,
+.Pq note the trailing Dq \&! ,
.Nm
will not complain if the route does not already exist.
-.It dial|call [remote]
+.It dial|call Op Ar label
If
-.Dq remote
+.Ar label
is specified, a connection is established using the
.Dq dial
and
.Dq login
scripts for the given
-.Dq remote
-system. Otherwise, the current settings are used to establish
-the connection.
-.It display
-Displays the current status of the negotiable protocol
-values as specified under
-.Dq accept|deny|enable|disable option....
-above.
-.It down
-Bring the link down ungracefully, as if the physical layer had become
-unavailable. It's not considered polite to use this command.
-.It help|? [command]
+.Ar label .
+Otherwise, the current settings are used to establish
+the connection, and all closed links are brought up.
+.It down Op Ar lcp|ccp
+Bring the relevent layer down ungracefully, as if the underlying layer
+had become unavailable. It's not considered polite to use this command on
+a Finite State Machine that's in the OPEN state. If no arguments are
+supplied,
+.Sq lcp
+is assumed.
+.It help|? Op Ar command
Show a list of available commands. If
-.Dq command
+.Ar command
is specified, show the usage string for that command.
-.It load [remote]
+.It [data]link Ar name[,name...] command Op Ar args
+This command may prefix any other command if the user wishes to
+specify which link the command should affect. This is only
+applicable after multiple links have been created in Multilink
+mode using the
+.Dq clone
+command.
+.Pp
+.Ar Name
+specifies the name of an existing link. If
+.Ar name
+is a comma separated list,
+.Ar command
+is executed on each link. If
+.Ar name
+is
+.Dq * ,
+.Ar command
+is executed on all links.
+.It load Op Ar label
Load the given
-.Dq remote
-label. If
-.Dq remote
+.Ar label
+from the
+.Pa ppp.conf
+file. If
+.Ar label
is not given, the
-.Dq default
-label is assumed.
-.It passwd pass
+.Ar default
+label is used.
+.It open Op lcp|ccp
+This is the opposite of the
+.Dq close
+command. Using
+.Dq open
+with no arguments or with the
+.Dq lcp
+argument is the same as using
+.Dq dial
+in that all closed links are brought up. If the
+.Dq ccp
+argument is used, the relevent compression layer is opened.
+.It passwd Ar pass
Specify the password required for access to the full
.Nm
command set. This password is required when connecting to the diagnostic
@@ -1886,68 +2403,63 @@ port (see the
.Dq set server
command).
.Ar Pass
-may be specified either on the
+is specified on the
.Dq set server
-command line or by putting an entry in
-.Pa /var/log/ppp.secret
-for the local host. The value of
+command line. The value of
.Ar pass
is not logged when
.Ar command
logging is active, instead, the literal string
-.Dq ********
+.Sq ********
is logged.
.It quit|bye [all]
-Exit
-.Nm ppp .
If
-.Nm
-is in interactive mode or if the
-.Dq all
-argument is given,
-.Nm
-will exit, closing the connection. A simple
.Dq quit
-issued from a
-.Xr pppctl 8
+is executed from the controlling connection or from a command file,
+ppp will exit after closing all connections. Otherwise, if the user
+is connected to a diagnostic socket, the connection is simply dropped.
+.Pp
+If the
+.Ar
+all argument is given,
+.Nm
+will exit despite the source of the command after closing all existing
+connections.
+.It remove|rm
+This command removes the given link. It is only really useful in
+multilink mode. A link must be
+in the
+.Dv CLOSED
+state before it is removed.
+.It rename|mv Ar name
+This command renames the given link to
+.Ar name .
+It will fail if
+.Ar name
+is already used by another link.
+.Pp
+The default link name is
+.Sq deflink .
+Renaming it to
+.Sq modem ,
+.Sq cuaa0
or
-.Xr telnet 1
-session will not close the current connection.
+.Sq USR
+may make the log file more readable.
.It save
This option is not (yet) implemented.
-.It set[up] var value
+.It set[up] Ar var value
This option allows the setting of any of the following variables:
.Bl -tag -width 20
-.It set accmap hex-value
+.It set accmap Ar hex-value
ACCMap stands for Asyncronous Control Character Map. This is always
-negotiated with the peer, and defaults to a value of 0x00000000.
+negotiated with the peer, and defaults to a value of 00000000 in hex.
This protocol is required to defeat hardware that depends on passing
certain characters from end to end (such as XON/XOFF etc).
-.It set filter-name rule-no action [src_addr/src_width]
-[dst_addr/dst_width] [proto [src [lt|eq|gt] port ]]
-[dst [lt|eq|gt] port] [estab]
.Pp
-.Nm Ppp
-supports four filter sets. The afilter specifies packets that keep
-the connection alive - reseting the idle timer. The dfilter specifies
-packets that cause
-.Nm
-to dial when in
-.Fl auto
-mode. The ifilter specifies packets that are allowed to travel
-into the machine and the ofilter specifies packets that are allowed
-out of the machine. By default all filter sets allow all packets
-to pass.
-Rules are processed in order according to
-.Dq n .
-Up to 20 rules may be given for each set. If a packet doesn't match
-any of the rules in a given set, it is discarded. In the case of
-ifilters and ofilters, this means that the packet is dropped. In
-the case of afilters it means that the packet will not reset the
-idle timer and in the case of dfilters it means that the packet will
-not trigger a dial.
-Refer to the section on PACKET FILTERING above for further details.
-.It set authkey|key value
+For the XON/XOFF scenario, use
+.Dq set accmap 000a0000 .
+.It set authkey|key Ar value
This sets the authentication key (or password) used in client mode
PAP or CHAP negotiation to the given value. It can also be used to
specify the password to be used in the dial or login scripts in place
@@ -1956,13 +2468,69 @@ of the '\\P' sequence, preventing the actual password from being logged. If
logging is in effect,
.Ar value
is logged as
-.Ar ********
+.Sq ********
for security reasons.
-.It set authname id
+.It set authname Ar id
This sets the authentication id used in client mode PAP or CHAP negotiation.
-.It set ctsrts
-This sets hardware flow control and is the default.
-.It set device|line value[,value...]
+.It set autoload Ar maxduration maxload Op Ar minduration minload
+These settings apply only in multilink mode and all default to zero.
+When more than one
+.Ar demand-dial
+.Pq also known as Fl auto
+mode link is available, only the first link is made active when
+.Nm
+first reads data from the tun device. The next
+.Ar demand-dial
+link will be opened only when at least
+.Ar maxload
+packets have been in the send queue for
+.Ar maxduration
+seconds. Because both values default to zero,
+.Ar demand-dial
+links will simply come up one at a time by default.
+.Pp
+If two or more links are open, at least one of which is a
+.Ar demand-dial
+link, a
+.Ar demand-dial
+link will be closed when there is less than
+.Ar minpackets
+in the queue for more than
+.Ar minduration .
+If
+.Ar minduration
+is zero, this timer is disabled. Because both values default to zero,
+.Ar demand-dial
+links will stay active until the bundle idle timer expires.
+.It set ctsrts|crtscts on|off
+This sets hardware flow control. Hardware flow control is
+.Ar on
+by default.
+.It set deflate Ar out-winsize Op Ar in-winsize
+This sets the DEFLATE algorithms default outgoing and incoming window
+sizes. Both
+.Ar out-winsize
+and
+.Ar in-winsize
+must be values between
+.Em 8
+and
+.Em 15 .
+If
+.Ar in-winsize
+is specified,
+.Nm
+will insist that this window size is used and will not accept any other
+values from the peer.
+.It set dns Op Ar primary Op Ar secondary
+This command specifies DNS overrides for the
+.Dq accept dns
+command. Refer to the
+.Dq accept
+command description above for details. This command does not affect the
+IP numbers requested using
+.Dq enable dns .
+.It set device|line Ar value[,value...]
This sets the device(s) to which
.Nm
will talk to the given
@@ -1973,9 +2541,20 @@ If
.Dq value
does not begin with
.Pa /dev/ ,
-it must be of the format
+it must either begin with an exclaimation mark
+.Pq Dq \&!
+or be of the format
.Dq host:port .
-If this is the case,
+.Pp
+If it begins with an exclaimation mark, the rest of the device name is
+treated as a program name, and that program is executed when the device
+is opened. Standard input, output and error are fed back to
+.Nm
+and are read and written as if they were a regular device.
+.Pp
+If a
+.Dq host:port
+pair is given,
.Nm
will attempt to connect to the given
.Dq host
@@ -1983,13 +2562,15 @@ on the given
.Dq port .
Refer to the section on
.Em PPP OVER TCP
-above for further details. If multiple
+above for further details.
+.Pp
+If multiple
.Dq values
are specified,
.Nm
will attempt to open each one in turn until it succeeds or runs out of
devices.
-.It set dial chat-script
+.It set dial Ar chat-script
This specifies the chat script that will be used to dial the other
side. See also the
.Dq set login
@@ -2057,7 +2638,7 @@ command), and standard error is read by
.Nm
and substituted as the expect or send string. If
.Nm
-is running in interactive mode, file descriptor 4 is attached to
+is running in interactive mode, file descriptor 3 is attached to
.Pa /dev/tty .
.Pp
For example (wrapped for readability);
@@ -2116,64 +2697,132 @@ This, of course means that it is possible to execute an entirely external
command rather than using the internal one. See
.Xr chat 8
for a good alternative.
+.It set enddisc Op label|IP|MAC|magic|psn value
+This command sets our local endpoint discriminator. If set prior to
+LCP negotiation,
+.Nm
+will send the information to the peer using the LCP endpoint discriminator
+option. The following discriminators may be set:
+.Bd -literal -offset indent
+.It label
+The current label is used.
+.It IP
+Our local IP number is used. As LCP is negotiated prior to IPCP, it is
+possible that the IPCP layer will subsequently change this value. If
+it does, the endpoint descriminator stays at the old value unless manually
+reset.
+.It MAC
+This is similar to the
+.Ar IP
+option above, except that the MAC address associated with the local IP
+number is used. If the local IP number is not resident on any ethernet
+interface, the command will fail.
+.Pp
+As the local IP number defaults to whatever the machine host name is,
+.Dq set enddisc mac
+is usually done prior to any
+.Dq set ifaddr
+commands.
+.It magic
+A 20 digit random number is used.
+.It psn Ar value
+The given
+.Ar value
+is used.
+.Ar Value
+should be set to an absolute public switched network number with the
+country code first.
+.Ed
.Pp
-.It set hangup chat-script
-This specifies the chat script that will be used to reset the modem
-before it is closed. It should not normally be necessary, but can
-be used for devices that fail to reset themselves properly on close.
-.It set encrypt MSChap|MD5
-This specifies the encryption algorithm to request and use when issuing
-the CHAP challenge, and defaults to MD5. If this is set to MSChap,
-.Nm
-will behave like a Microsoft RAS when sending the CHAP challenge (assuming
-CHAP is enabled). When responding to a challenge,
-.Nm
-determines how to encrypt the response based on the challenge, so this
-setting is ignored.
-.Bl -tag -width NOTE:
-.It NOTE:
-Because the Microsoft encryption algorithm uses a combination of MD4 and DES,
-if you have not installed DES encryption software on your machine
-before building
-.Nm ppp ,
-this option will not be available - only MD5 will be used.
-.El
-.Pp
-.It set escape value...
+If no arguments are given, the endpoint discriminator is reset.
+.It set escape Ar value...
This option is similar to the
.Dq set accmap
option above. It allows the user to specify a set of characters that
will be `escaped' as they travel across the link.
-.It set ifaddr [myaddr [hisaddr [netmask [triggeraddr]]]]
+.It set filter dial|alive|in|out rule-no permit|deny Ar "[src_addr/width] [dst_addr/width] [proto [src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"
+.Nm Ppp
+supports four filter sets. The
+.Em alive
+filter specifies packets that keep the connection alive - reseting the
+idle timer. The
+.Em dial
+filter specifies packets that cause
+.Nm
+to dial when in
+.Fl auto
+mode. The
+.Em in
+filter specifies packets that are allowed to travel
+into the machine and the
+.Em out
+filter specifies packets that are allowed out of the machine.
+.Pp
+Filtering is done prior to any IP alterations that might be done by the
+alias engine. By default all filter sets allow all packets to pass.
+Rules are processed in order according to
+.Ar rule-no .
+Up to 20 rules may be given for each set. If a packet doesn't match
+any of the rules in a given set, it is discarded. In the case of
+.Em in
+and
+.Em out
+filters, this means that the packet is dropped. In the case of
+.Em alive
+filters it means that the packet will not reset the idle timer and in
+the case of
+.Em dial
+filters it means that the packet will not trigger a dial. A packet failing
+to trigger a dial will be dropped rather than queued. Refer to the
+section on PACKET FILTERING above for further details.
+.It set hangup Ar chat-script
+This specifies the chat script that will be used to reset the modem
+before it is closed. It should not normally be necessary, but can
+be used for devices that fail to reset themselves properly on close.
+.It set help|? Op Ar command
+This command gives a summary of available set commands, or if
+.Ar command
+is specified, the command usage is shown.
+.It set ifaddr Ar [myaddr [hisaddr [netmask [triggeraddr]]]]
This command specifies the IP addresses that will be used during
IPCP negotiation. Addresses are specified using the format
+.Pp
.Dl a.b.c.d/n
-Where a.b.c.d is the preferred IP, but n specifies how many bits
-of the address we will insist on. If the /n bit is omitted, it
-defaults to /32 unless the IP address is 0.0.0.0 in which case
-the mask defaults to /0.
+.Pp
+Where
+.Ar a.b.c.d
+is the preferred IP, but
+.Ar n
+specifies how many bits of the address we will insist on. If
+.Ar /n
+is omitted, it defaults to
+.Ar /32
+unless the IP address is 0.0.0.0 in which case it defaults to
+.Ar /0 .
.Pp
.Ar Hisaddr
may also be specified as a range of IP numbers in the format
+.Pp
.Dl a.b.c.d[-d.e.f.g][,h.i.j.k[-l,m,n,o]]...
+.Pp
for example:
+.Pp
.Dl set ifaddr 10.0.0.1 10.0.1.2-10.0.1.10,10.0.1.20
+.Pp
will only negotiate
.Ar 10.0.0.1
-as the local IP number, but will assign any of the given 10 IP
+as the local IP number, but may assign any of the given 10 IP
numbers to the peer. If the peer requests one of these numbers,
and that number is not already in use,
.Nm
will grant the peers request. This is useful if the peer wants
to re-establish a link using the same IP number as was previously
-allocated. If the peer requests an IP number that's either outside
+allocated (thus maintaining any existing tcp connections).
+.Pp
+If the peer requests an IP number that's either outside
of this range or is already in use,
.Nm
-will start by suggesting a random unused IP number from the range.
-If the peer doesn't subsequently agree,
-.Nm
-will suggest each of the other numbers in succession until a number
-is chosen or until too many IPCP Configure Requests have been sent.
+will suggest a random unused IP number from the range.
.Pp
If
.Ar triggeraddr
@@ -2181,7 +2830,11 @@ is specified, it is used in place of
.Ar myaddr
in the initial IPCP negotiation. However, only an address in the
.Ar myaddr
-range will be accepted.
+range will be accepted. This is useful when negotiating with some
+.Dv PPP
+implementations that will not assign an IP number unless their peer
+requests
+.Ar 0.0.0.0 .
.Pp
It should be noted that in
.Fl auto
@@ -2190,71 +2843,94 @@ mode,
will configure the interface immediately upon reading the
.Dq set ifaddr
line in the config file. In any other mode, these values are just
-used for the IPCP negotiations, and the interface isn't configured
-until the IPCP layer is up. As a result, it is impossible
-.Pq or at least unwise
-to use the
-.Dq add
-command in
-.Pa ppp.conf
-unless using
-.Fl auto
-mode (the
-.Pa ppp.linkup
-file should be used instead). Use
-.Dq allow mode auto
-to restrict the current profile to
-.Fl auto
-mode only.
+used for IPCP negotiations, and the interface isn't configured
+until the IPCP layer is up.
.Pp
-Note also that the
-.Ar hisaddr
-argument may be overridden in the
+Note that the
+.Ar HISADDR
+argument may be overridden by the third field in the
.Pa ppp.secret
-file once the client has authenticated themself. Refer to the
+file once the client has authenticated themself
+.Pq if PAP or CHAP are Dq enabled .
+Refer to the
.Em AUTHENTICATING INCOMING CONNECTIONS
section for details.
-.It set loopback on|off
-When set to
-.Ar on
-(the default),
-.Nm
-will automatically loop back packets being sent
-out with a destination address equal to that of the
-.Em PPP
-interface. If set to
-.Ar off ,
-.Nm
-will send the packet, probably resulting in an ICMP redirect from
-the other end.
-.It set log [local] [+|-]value...
+.Pp
+In all cases, if the interface is already configured,
+.Nm
+will try to maintain the interface IP numbers so that any existing
+bound sockets will remain valid.
+.It set ccpretry Ar period
+.It set chapretry Ar period
+.It set ipcpretry Ar period
+.It set lcpretry Ar period
+.It set papretry Ar period
+These commands set the number of seconds that
+.Nm
+will wait before resending Finite State Machine (FSM) Request packets.
+The default
+.Ar period
+for all FSMs is 3 seconds (which should suffice in most cases).
+.It set log [local] [+|-] Ns Ar value...
This command allows the adjustment of the current log level. Refer
to the Logging Facility section for further details.
-.It set login chat-script
+.It set login Ar chat-script
This
.Ar chat-script
compliments the dial-script. If both are specified, the login
script will be executed after the dial script. Escape sequences
available in the dial script are also available here.
-.It set mru value
-The default MRU is 1500. If it is increased, the other side *may*
-increase its mtu. There is no use decreasing the MRU to below the
-default as the
+.It set lqrperiod Ar frequency
+This command sets the
+.Ar frequency
+in seconds at which
+.Em LQR
+or
+.Em ECHO LQR
+packets are sent. The default is 30 seconds. You must also use the
+.Dq enable lqr
+command if you wish to send LQR requests to the peer.
+.It set mode Ar interactive|auto|ddial|background
+This command allows you to change the
+.Sq mode
+of the specified link. This is normally only useful in multilink mode,
+but may also be used in unilink mode.
+.Pp
+It is not possible to change a link that is
+.Sq direct
+or
+.Sq dedicated .
+.It set mrru Ar value
+Setting this option enables Multilink PPP negotiations, also known as
+Multilink Protocol or MP. There is no default MRRU (Maximum
+Reconstructed Receive Unit) value.
+.Em PPP
+protocol *must* be able to accept packets of at
+least 1500 octets.
+.It set mru Ar value
+The default MRU (Maximum Receive Unit) is 1500. If it is increased, the
+other side *may* increase its mtu. There is no point in decreasing the
+MRU to below the default as the
.Em PPP
protocol *must* be able to accept packets of at
least 1500 octets.
-.It set mtu value
-The default MTU is 1500. This may be increased by the MRU specified
-by the peer. It may only be subsequently decreased by this option.
-Increasing it is not valid as the peer is not necessarily able to
-receive the increased packet size.
-.It set ns x.x.x.x y.y.y.y
-This option allows the setting of the Microsoft DNS servers that
-will be negotiated.
-.It set nbns x.x.x.x y.y.y.y
-This option allows the setting of the Microsoft NetBIOS DNS servers that
-will be negotiated.
-.It set openmode active|passive Op delay
+.It set mtu Ar value
+The default MTU is 1500. At negotiation time,
+.Nm
+will accept whatever MRU or MRRU that the peer wants (assuming it's
+not less than 296 bytes). If the MTU is set,
+.Nm
+will not accept MRU/MRRU values less that the set value. When
+negotiations are complete, the MTU is assigned to the interface, even
+if the peer requested a higher value MRU/MRRU. This can be useful for
+limiting your packet size (giving better bandwidth sharing at the expense
+of more header data).
+.It set nbns Op Ar x.x.x.x Op Ar y.y.y.y
+This option allows the setting of the Microsoft NetBIOS name server
+values to be returned at the peers request. If no values are given,
+.Nm
+will reject any such requests.
+.It set openmode active|passive Op Ar delay
By default,
.Ar openmode
is always
@@ -2274,7 +2950,7 @@ may be specified here in seconds.
.It set parity odd|even|none|mark
This allows the line parity to be set. The default value is
.Ar none .
-.It set phone telno[|telno]...[:telno[|telno]...]...
+.It set phone Ar telno[|telno]...[:telno[|telno]...]...
This allows the specification of the phone number to be used in
place of the \\\\T string in the dial and login chat scripts.
Multiple phone numbers may be given separated by a pipe (|) or
@@ -2289,7 +2965,7 @@ the maximum number of times specified by
below. In
.Fl background
mode, each number is attempted at most once.
-.It set reconnect timeout ntries
+.It set reconnect Ar timeout ntries
Should the line drop unexpectedly (due to loss of CD or LQR
failure), a connection will be re-established after the given
.Ar timeout .
@@ -2302,7 +2978,7 @@ defaults to zero. A value of
for
.Ar timeout
will result in a variable pause, somewhere between 0 and 30 seconds.
-.It set redial seconds[.nseconds] [attempts]
+.It set redial Ar seconds[.nseconds] [attempts]
.Nm Ppp
can be instructed to attempt to redial
.Ar attempts
@@ -2315,43 +2991,20 @@ is taken before dialing each number. A pause of
is taken before starting at the first number again. A value of
.Ar random
may be used here too.
-.It set stopped [LCPseconds [IPCPseconds [CCPseconds]]]
-If this option is set,
-.Nm
-will time out after the given FSM (Finite State Machine) has been in
-the stopped state for the given number of
-.Dq seconds .
-This option may be useful if you see
-.Nm
-failing to respond in the stopped state, or if you wish to
-.Dq set openmode passive
-and time out if the peer doesn't send a Configure Request within the
-given time. Use
-.Dq set log +lcp +ipcp +ccp
-to make
-.Nm
-log all state transitions.
-.Pp
-The default value is zero, where
-.Nm
-doesn't time out in the stopped state.
-.Pp
-This value should not be set to less than the openmode delay (see
-.Dq set openmode
-above).
-.It set server|socket TcpPort|LocalName|none [password] [mask]
+.It set server|socket Ar TcpPort|LocalName|none password Op Ar mask
This command tells
.Nm
to listen on the given socket or
.Sq diagnostic port
-for incoming command connections. This is not possible if
-.Nm
-is in interactive mode. The word
+for incoming command connections.
+.Pp
+The word
.Ar none
instructs
.Nm
-to close any existing socket. If you wish to specify a unix domain
-socket,
+to close any existing socket.
+.Pp
+If you wish to specify a unix domain socket,
.Ar LocalName
must be specified as an absolute file name, otherwise it is assumed
to be the name or number of a TCP port. You may specify the octal umask that
@@ -2364,14 +3017,22 @@ for umask details. Refer to
.Xr services 5
for details of how to translate TCP port names.
.Pp
-You may also specify the password that must be used by the client when
-connecting to this socket. If the password is not specified here,
-.Pa /etc/ppp/ppp.secret
-is searched for a machine name that's the same as your local host name
-without any domain suffix. Refer to
-.Xr hostname 1
-for further details. If a password is specified as the empty string,
-no password is required.
+You must also specify the password that must be entered by the client
+(using the
+.Dq passwd
+command above) when connecting to this socket. If the password is
+specified as an empty string, no password is required for connecting clients.
+.Pp
+When specifying a unix domain socket, the first
+.Dq %d
+sequence found in the socket name will be replaced with the current
+interface unit number. This is useful when you wish to use the same
+profile for more than one connection.
+.Pp
+In a similar manner TCP sockets may be prefixed with the
+.Dq +
+character, in which case the current interface unit number is added to
+the port number.
.Pp
When using
.Nm
@@ -2382,17 +3043,45 @@ command is the preferred mechanism of communications. Currently,
can also be used, but link encryption may be implemented in the future, so
.Xr telnet 1
should not be relied upon.
-.It set speed value
+.It set speed Ar value
This sets the speed of the serial device.
-.It set timeout idle [LQR [FSM-resend]]
-This command allows the setting of the idle timer, the LQR timer (if
-enabled) and the finite state machine
-.Pq FSM
-retry timer.
-.It set vj slots nslots
-This command sets the initial number of
-.Ar slots
-that
+.It set stopped Ar [LCPseconds [CCPseconds]]
+If this option is set,
+.Nm
+will time out after the given FSM (Finite State Machine) has been in
+the stopped state for the given number of
+.Dq seconds .
+This option may be useful if the peer sends a terminate request,
+but never actually closes the connection despite our sending a terminate
+acknowledgement. This is also useful if you wish to
+.Dq set openmode passive
+and time out if the peer doesn't send a Configure Request within the
+given time. Use
+.Dq set log +lcp +ccp
+to make
+.Nm
+log the appropriate state transitions.
+.Pp
+The default value is zero, where
+.Nm
+doesn't time out in the stopped state.
+.Pp
+This value should not be set to less than the openmode delay (see
+.Dq set openmode
+above).
+.It set timeout Ar idleseconds
+This command allows the setting of the idle timer. Refer to the
+section titled
+.Dq SETTING THE IDLE TIMER
+for further details.
+.It set vj slotcomp on|off
+This command tells
+.Nm
+whether it should attempt to negotiate VJ slot compression. By default,
+slot compression is turned
+.Ar on .
+.It set vj slots Ar nslots
+This command sets the initial number of slots that
.Nm
will try to negotiate with the peer when VJ compression is enabled (see the
.Sq enable
@@ -2403,23 +3092,16 @@ must be between
and
.Ar 16
inclusive.
-.It set vj slotcomp on|off
-This command tells
-.Nm
-whether it should attempt to negotiate VJ slot compression. By default,
-slot compression is turned
-.Ar on .
-.It set help|?
-This command gives a summary of available set commands.
.El
.Pp
-.It shell|! [command]
+.It shell|! Op Ar command
If
-.Dq command
+.Ar command
is not specified a shell is invoked according to the
.Dv SHELL
-environment variable. Otherwise, the given command is executed.
-Any of the pseudo arguments
+environment variable. Otherwise, the given
+.Ar command
+is executed. Any of the pseudo arguments
.Dv HISADDR ,
.Dv INTERFACE
and
@@ -2431,60 +3113,50 @@ that this command is executed in the foreground -
will not continue running until this process has exited. Use the
.Dv bg
command if you wish processing to happen in the background.
-.It show var
+.It show Ar var
This command allows the user to examine the following:
.Bl -tag -width 20
-.It show [adio]filter
-List the current rules for the given filter.
-.It show auth
-Show the current authname and encryption values. If you have built
-.Nm
-without DES support, the encryption value is not displayed as it will
-always be
-.Ar MD5 .
+.It show bundle
+Show the current bundle settings.
.It show ccp
-Show the current CCP statistics.
+Show the current CCP compression statistics.
.It show compress
-Show the current compress statistics.
+Show the current VJ compression statistics.
.It show escape
Show the current escape characters.
+.It show filter Op Ar name
+List the current rules for the given filter. If
+.Ar name
+is not specified, all filters are shown.
.It show hdlc
Show the current HDLC statistics.
+.It show help|?
+Give a summary of available show commands.
.It show ipcp
Show the current IPCP statistics.
.It show lcp
Show the current LCP statistics.
-.It show loopback
-Show the current loopback status.
+.It show [data]link
+Show high level link information.
+.It show links
+Show a list of available logical links.
.It show log
Show the current log values.
.It show mem
Show current memory statistics.
.It show modem
-Show current modem statistics.
-.It show mru
-Show the current MRU.
-.It show mtu
-Show the current MTU.
+Show low level link information.
.It show proto
Show current protocol totals.
-.It show reconnect
-Show the current reconnect values.
-.It show redial
-Show the current redial values.
-.It show stopped
-Show the current stopped timeouts.
.It show route
Show the current routing tables.
-.It show timeout
-Show the current timeout values.
-.It show msext
-Show the current Microsoft extension values.
+.It show stopped
+Show the current stopped timeouts.
+.It show timer
+Show the active alarm timers.
.It show version
Show the current version number of
.Nm ppp .
-.It show help|?
-Give a summary of available show commands.
.El
.Pp
.It term
@@ -2498,7 +3170,7 @@ automatically enables Packet Mode and goes back into command mode.
.El
.Pp
.Sh MORE DETAILS
-.Bl -bullet -compact
+.Bl -bullet
.It
Read the example configuration files. They are a good source of information.
.It
@@ -2509,7 +3181,16 @@ Use
.Dq set ?
and
.Dq set ? <var>
-commands.
+to get online information about what's available.
+.It
+The following urls contain useful information:
+.Bl -bullet -compact
+.It
+http://www.FreeBSD.org/FAQ/userppp.html
+.It
+http://www.FreeBSD.org/handbook/userppp.html
+.El
+.Pp
.El
.Pp
.Sh FILES
@@ -2566,34 +3247,56 @@ and
modes.
.It Pa /etc/services
Get port number if port number is using service name.
+.It Pa /var/run/ppp-authname-class-value
+In multilink mode, unix domain sockets are created using the peer
+authentication name
+.Pq Sq authname ,
+the peer endpoint discriminator class
+.Pq Sq class
+and the peer endpoint discriminator value
+.Pq Sq value .
+As the endpoint discriminator value may be a binary value, it is turned
+to HEX to determine the actual file name.
+.Pp
+This socket is used to pass links between different instances of
+.Nm ppp .
.El
.Pp
.Sh SEE ALSO
+.Xr adduser 8 ,
.Xr at 1 ,
.Xr chat 8 ,
.Xr crontab 5 ,
.Xr ftp 1 ,
.Xr getty 8 ,
+.Xr group 5 ,
.Xr gzip 1 ,
.Xr hostname 1 ,
.Xr inetd 8 ,
.Xr init 8 ,
.Xr login 1 ,
+.Xr named 8 ,
.Xr passwd 5 ,
.Xr ping 8 ,
.Xr pppctl 8 ,
.Xr pppd 8 ,
.Xr route 8 ,
+.Xr resolv.conf 5 ,
.Xr syslog 3 ,
.Xr syslog.conf 5 ,
.Xr syslogd 8 ,
.Xr tcpdump 1 ,
.Xr telnet 1 ,
.Xr traceroute 8 ,
-.Xr uucplock 3
+.Xr uucplock 3 ,
+.Xr vipw 8
.Sh HISTORY
This program was originally written by Toshiharu OHNO (tony-o@iij.ad.jp),
and was submitted to FreeBSD-2.0.5 by Atsushi Murai (amurai@spec.co.jp).
.Pp
-It has since been substantially modified by Brian Somers (brian@Awfulhak.org),
-and was ported to OpenBSD in November '97 (just after the 2.2 release).
+It was substantially modified during 1997 by Brian Somers
+(brian@Awfulhak.org), and was ported to OpenBSD in November that year
+(just after the 2.2 release).
+.Pp
+Most of the code was rewritten by Brian Somers in early 1998 when
+multilink ppp support was added.
diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4
index d79583fbbc85..5f01e583ab2e 100644
--- a/usr.sbin/ppp/ppp.8.m4
+++ b/usr.sbin/ppp/ppp.8.m4
@@ -1,13 +1,12 @@
-.\" $Id: ppp.8,v 1.98 1998/03/12 02:23:42 brian Exp $
+.\" $Id: ppp.8,v 1.97.2.38 1998/05/21 01:13:32 brian Exp $
.Dd 20 September 1995
.Os FreeBSD
.Dt PPP 8
.Sh NAME
.Nm ppp
-.Nd Point to Point Protocol (a.k.a. iijppp)
+.Nd Point to Point Protocol (a.k.a. user-ppp)
.Sh SYNOPSIS
.Nm
-.\" SOMEONE FIX ME ! The .Op macro can't handle enough args !
[
.Fl auto |
.Fl background |
@@ -100,22 +99,26 @@ With PAP or CHAP, it is possible to skip the Unix style
.Xr login 1
proceedure, and use the
.Em PPP
-protocol for authentication instead.
+protocol for authentication instead. If the peer requests Microsoft
+CHAP authentication and
+.Nm
+is compiled with DES support, an appropriate MD4/DES response will be
+made.
.It Supports Proxy Arp.
When
.Em PPP
is set up as server, you can also configure it to do proxy arp for your
connection.
.It Supports packet filtering.
-User can define four kinds of filters:
-.Em ifilter
-for incoming packets,
-.Em ofilter
-for outgoing packets,
-.Em dfilter
-to define a dialing trigger packet and
-.Em afilter
-for keeping a connection alive with the trigger packet.
+User can define four kinds of filters: the
+.Em in
+filter for incoming packets, the
+.Em out
+filter for outgoing packets, the
+.Em dial
+filter to define a dialing trigger packet and the
+.Em alive
+filter for keeping a connection alive with the trigger packet.
.It Tunnel driver supports bpf.
The user can use
.Xr tcpdump 1
@@ -123,23 +126,34 @@ to check the packet flow over the
.Em PPP
link.
.It Supports PPP over TCP capability.
-.It Supports IETF draft Predictor-1 compression.
+If a device name is specified as
+.Em host Ns No : Ns Em port ,
+.Nm
+will open a TCP connection for transporting data rather than using a
+conventional serial device.
+.It Supports IETF draft Predictor-1 and DEFLATE compression.
.Nm
-supports not only VJ-compression but also Predictor-1 compression.
+supports not only VJ-compression but also Predictor-1 and DEFLATE compression.
Normally, a modem has built-in compression (e.g. v42.bis) and the system
may receive higher data rates from it as a result of such compression.
While this is generally a good thing in most other situations, this
higher speed data imposes a penalty on the system by increasing the
number of serial interrupts the system has to process in talking to the
-modem and also increases latency. Unlike VJ-compression, Predictor-1
-compression pre-compresses
+modem and also increases latency. Unlike VJ-compression, Predictor-1 and
+DEFLATE compression pre-compresses
.Em all
-data flowing through the link, thus reducing overhead to a minimum.
+network traffic flowing through the link, thus reducing overheads to a
+minimum.
.It Supports Microsoft's IPCP extensions.
Name Server Addresses and NetBIOS Name Server Addresses can be negotiated
with clients using the Microsoft
.Em PPP
stack (ie. Win95, WinNT)
+.It Supports Multilink PPP
+It is possible to configure
+.Nm
+to open more than one physical connection to the peer, combining the
+bandwidth of all links for better throughput.
.Sh PERMISSIONS
.Nm Ppp
is installed as user
@@ -169,8 +183,10 @@ zero.
.Sh GETTING STARTED
When you first run
.Nm
-you may need to deal with some initial configuration details. First,
-your kernel should include a tunnel device (the GENERIC kernel includes
+you may need to deal with some initial configuration details.
+.Bl -bullet
+.It
+Your kernel must include a tunnel device (the GENERIC kernel includes
one by default). If it doesn't, or if you require more than one tun
interface, you'll need to rebuild your kernel with the following line in
your kernel configuration file:
@@ -182,7 +198,8 @@ where
is the maximum number of
.Em PPP
connections you wish to support.
-Second, check your
+.It
+Check your
.Pa /dev
directory for the tunnel device entries
.Pa /dev/tunN ,
@@ -192,7 +209,22 @@ represents the number of the tun device, starting at zero.
If they don't exist, you can create them by running "sh ./MAKEDEV tunN".
This will create tun devices 0 through
.Ar N .
-Last of all, create a log file.
+.It
+Make sure that your system has a group named
+.Dq network
+in the
+.Pa /etc/group
+file and that that group contains the names of all users expected to use
+.Nm ppp .
+Refer to the
+.Xr group 5
+manual page for details. Each of these uses must also be given access
+using the
+.Dq allow users
+command in
+.Pa /etc/ppp/ppp.conf .
+.It
+Create a log file.
.Nm Ppp
uses
.Xr syslog 3
@@ -207,7 +239,9 @@ file:
.Ed
.Pp
Make sure you use actual TABs here. If you use spaces, the line will be
-silently ignored.
+silently ignored by
+.Xr syslogd 8 .
+.Pp
It is possible to have more than one
.Em PPP
log file by creating a link to the
@@ -220,7 +254,7 @@ executable:
and using
.Bd -literal -offset indent
!ppp0
-*.* /var/log/ppp0.log
+*.*<TAB>/var/log/ppp0.log
.Ed
.Pp
in
@@ -231,6 +265,20 @@ signal to
.Xr syslogd 8
after altering
.Pa /etc/syslog.conf .
+.It
+Although not strictly relevent to
+.Nm ppp Ns No s
+operation, you should configure your resolver so that it works correctly.
+This can be done by configuring a local DNS
+.Pq using Xr named 8
+or by adding the correct
+.Sq nameserver
+lines to the file
+.Pa /etc/resolv.conf .
+Refer to the
+.Xr resolv.conf 5
+manual page for details.
+.El
.Sh MANUAL DIALING
In the following examples, we assume that your machine name is
.Dv awfulhak .
@@ -289,19 +337,48 @@ When the peer starts to talk in
detects this automatically and returns to command mode.
.Bd -literal -offset indent
ppp ON awfulhak>
+Ppp ON awfulhak>
+PPp ON awfulhak>
PPP ON awfulhak>
.Ed
.Pp
+If it does not, it's possible that the peer is waiting for your end to
+start negotiating. To force
+.Nm
+to start sending PPP configuration packets to the peer, use the
+.Dq ~p
+command to enter packet mode.
+.Pp
You are now connected! Note that
.Sq PPP
in the prompt has changed to capital letters to indicate that you have
-a peer connection. The show command can be used to see how things are
-going:
+a peer connection. If only some of the three Ps go uppercase, wait 'till
+either everything is uppercase or lowercase. If they revert to lowercase,
+it means that
+.Nm
+couldn't successfully negotiate with the peer. This is probably because
+your PAP or CHAP authentication name or key is incorrect. A good first step
+for troubleshooting at this point would be to
+.Dq set log local phase .
+Refer to the
+.Dq set log
+command description below for further details.
+.Pp
+When the link is established, the show command can be used to see how
+things are going:
.Bd -literal -offset indent
+PPP ON awfulhak> show modem
+* Modem related information is shown here *
+PPP ON awfulhak> show ccp
+* CCP (compression) related information is shown here *
PPP ON awfulhak> show lcp
-* LCP related information is shown here *
+* LCP (line control) related information is shown here *
PPP ON awfulhak> show ipcp
-* IPCP related information is shown here *
+* IPCP (IP) related information is shown here *
+PPP ON awfulhak> show link
+* Link (high level) related information is shown here *
+PPP ON awfulhak> show bundle
+* Logical (high level) connection related information is shown here *
.Ed
.Pp
At this point, your machine has a host route to the peer. This means
@@ -323,6 +400,12 @@ use the keyword
in place of
.Sq HISADDR .
This will create a direct route on the tun interface.
+If it fails due to an existing route, you can overwrite the existing
+route using
+.Bd -literal -offset indent
+PPP ON awfulhak> add! default HISADDR
+.Ed
+.Pp
You can now use your network applications (ping, telnet, ftp etc.)
in other windows on your machine.
Refer to the
@@ -336,7 +419,7 @@ See the example definitions in
.Pa /etc/ppp/ppp.conf
is pretty simple).
Each line contains one comment, inclusion, label or command:
-.Bl -bullet -compact
+.Bl -bullet
.It
A line starting with a
.Pq Dq #
@@ -408,18 +491,37 @@ connection is established. See the provided
.Dq pmdemand
example in
.Pa /etc/ppp/ppp.conf.sample
-which adds a default route. The strings
+which runs a script in the background after the connection is established.
+The literal strings
.Dv HISADDR ,
.Dv MYADDR
and
.Dv INTERFACE
-are available as the relevent IP addresses and interface name.
-Similarly, when a connection is closed, the
+may be used, and will be replaced with the relevent IP addresses and interface
+name. Similarly, when a connection is closed, the
contents of the
.Pa /etc/ppp/ppp.linkdown
file are executed.
Both of these files have the same format as
.Pa /etc/ppp/ppp.conf .
+.Pp
+In previous versions of
+.Nm ppp ,
+it was necessary to re-add routes such as the default route in the
+.Pa ppp.linkup
+file.
+.Nm Ppp
+now supports
+.Sq sticky routes ,
+where all routes that contain the
+.Dv HISADDR
+or
+.Dv MYADDR
+literals will automatically be updated when the values of
+.Dv HISADDR
+and/or
+.Dv MYADDR
+change.
.Sh BACKGROUND DIALING
If you want to establish a connection using
.Nm
@@ -429,12 +531,7 @@ entry or an
.Xr at 1
job) you should use the
.Fl background
-option. You must also specify the destination label in
-.Pa /etc/ppp/ppp.conf
-to use. This label must contain the
-.Dq set ifaddr
-command to define the remote peers IP address. (refer to
-.Pa /etc/ppp/ppp.conf.sample )
+option.
When
.Fl background
is specified,
@@ -464,8 +561,6 @@ command to define the remote peers IP address. (refer to
.Pa /etc/ppp/ppp.conf.sample )
.Bd -literal -offset indent
# ppp -auto pmdemand
-...
-#
.Ed
.Pp
When
@@ -475,33 +570,26 @@ or
is specified,
.Nm
runs as a daemon but you can still configure or examine its
-configuration by using the diagnostic port as follows (this
-can be done in
-.Fl background
-and
-.Fl direct
-mode too):
+configuration by using the
+.Dq set server
+command in
+.Pa /etc/ppp/ppp.conf ,
+.Pq for example, Dq set server +3000 mypasswd
+and connecting to the diagnostic port as follows:
.Bd -literal -offset indent
-# pppctl -v 3000 show ipcp
+# pppctl 3000 (assuming tun0 - see the ``set server'' description)
Password:
-IPCP [Opened]
- his side: xxxx
- ....
+PPP ON awfulhak> show who
+tcp (127.0.0.1:1028) *
.Ed
.Pp
-Currently,
-.Xr telnet 1
-may also be used to talk interactively.
-.Pp
-In order to achieve this, you must use the
-.Dq set server
-command as described below. It is possible to retrospectively make a running
+The
+.Dq show who
+command lists users that are currently connected to
.Nm
-program listen on a diagnostic port by configuring
-.Pa /etc/ppp/ppp.secret ,
-and sending it a
-.Dv USR1
-signal.
+itself. If the diagnostic socket is closed or changed to a different
+socket, all connections are immediately dropped.
+.Pp
In
.Fl auto
mode, when an outgoing packet is detected,
@@ -638,95 +726,116 @@ to enable a
.Xr getty 8
on the port where the modem is attached.
For example:
+.Pp
.Dl ttyd1 "/usr/libexec/getty std.38400" dialup on secure
+.Pp
Don't forget to send a
.Dv HUP
signal to the
.Xr init 8
process to start the
-.Xr getty 8 .
-.Dl # kill -HUP 1
-.It
-Prepare an account for the incoming user.
-.Bd -literal
-ppp:xxxx:66:66:PPP Login User:/home/ppp:/usr/local/bin/ppplogin
-.Ed
+.Xr getty 8 :
.Pp
+.Dl # kill -HUP 1
.It
Create a
.Pa /usr/local/bin/ppplogin
file with the following contents:
.Bd -literal -offset indent
-#!/bin/sh -p
-exec /usr/sbin/ppp -direct
+#! /bin/sh
+exec /usr/sbin/ppp -direct incoming
.Ed
.Pp
-(You can specify a label name for further control.)
-.Pp
Direct mode
.Pq Fl direct
lets
.Nm
work with stdin and stdout. You can also use
.Xr pppctl 8
-or
-.Xr telnet 1
to connect to a configured diagnostic port, in the same manner as with
client-side
.Nm ppp .
+.Pp
+Here, the
+.Ar incoming
+label must be set up in
+.Pa /etc/ppp/ppp.conf .
.It
-Optional support for Microsoft's IPCP Name Server and NetBIOS
-Name Server negotiation can be enabled use
-.Dq enable msext
-and
-.Dq set ns pri-addr [sec-addr]
-along with
-.Dq set nbns pri-addr [sec-addr]
-in your
-.Pa /etc/ppp/ppp.conf
-file.
+Prepare an account for the incoming user.
+.Bd -literal
+ppp:xxxx:66:66:PPP Login User:/home/ppp:/usr/local/bin/ppplogin
+.Ed
+.Pp
+Refer to the manual entries for
+.Xr adduser 8
+and
+.Xr vipw 8
+for details.
+.It
+Support for IPCP Domain Name Server and NetBIOS Name Server negotiation
+can be enabled using the
+.Dq enable dns
+and
+.Dq set nbns
+commands. Refer to their descriptions below.
.El
.Pp
.Sh RECEIVING INCOMING PPP CONNECTIONS (Method 2)
-This method differs in that it recommends the use of
-.Em mgetty+sendfax
-to handle the modem connections. The latest versions (0.99 and higher)
-can be compiled with the
-.Dq AUTO_PPP
-option to allow detection of clients speaking
-.Em PPP
-to the login prompt.
-Follow these steps:
+This method differs in that we use
+.Nm ppp
+to authenticate the connection rather than
+.Xr login 1 :
.Bl -enum
.It
-Get, configure, and install mgetty+sendfax v0.99 or later making
-sure you have used the AUTO_PPP option.
+Configure your default section in
+.Pa /etc/gettytab
+with automatic ppp recognition by specifying the
+.Dq pp
+capability:
+.Bd -literal
+default:\\
+ :pp=/usr/local/bin/ppplogin:\\
+ .....
+.Ed
+.It
+Configure your serial device(s), enable a
+.Xr getty 8
+and create
+.Pa /usr/local/bin/ppplogin
+as in the first three steps for method 1 above.
.It
-Edit
-.Pa /etc/ttys
-to enable a mgetty on the port where the modem is attached. For
-example:
-.Dl cuaa1 "/usr/local/sbin/mgetty -s 57600" dialup on
+Add either
+.Dq enable chap
+or
+.Dq enable pap
+.Pq or both
+to
+.Pa /etc/ppp/ppp.conf
+under the
+.Sq incoming
+label (or whatever label
+.Pa ppplogin
+uses).
.It
-Prepare an account for the incoming user.
+Create an entry in
+.Pa /etc/ppp/ppp.secret
+for each incoming user:
.Bd -literal
-Pfred:xxxx:66:66:Fred's PPP:/home/ppp:/etc/ppp/ppp-dialup
+Pfred<TAB>xxxx
+Pgeorge<TAB>yyyy
.Ed
.Pp
-.It
-Examine the files
-.Pa /etc/ppp/sample.ppp-dialup ,
-.Pa /etc/ppp/sample.ppp-pap-dialup
-and
-.Pa /etc/ppp/ppp.conf.sample
-for ideas.
-.Pa /etc/ppp/ppp-pap-dialup
-is supposed to be called from
-.Pa /usr/local/etc/mgetty+sendfax/login.conf
-from a line like
-.Dl /AutoPPP/ - - /etc/ppp/ppp-pap-dialup
-.El
-.Pp
+Now, as soon as
+.Xr getty 8
+detects a ppp connection (by recognising the HDLC frame headers), it runs
+.Dq /usr/local/bin/ppplogin .
+.Pp
+It is
+.Em VITAL
+that either PAP or CHAP are enabled as above. If they are not, you are
+allowing anybody to establish ppp session with your machine
+.Em without
+a password, opening yourself up to all sorts of potential attacks.
.Sh AUTHENTICATING INCOMING CONNECTIONS
Normally, the receiver of a connection requires that the peer
authenticates themself. This may be done using
@@ -816,7 +925,7 @@ on ui-gate (the receiver) should contain the following:
ppp-in:
set timeout 0
set ifaddr 10.0.4.1 10.0.4.2
- add 10.0.1.0 255.255.255.0 10.0.4.2
+ add 10.0.1.0/24 10.0.4.2
.Ed
.Pp
You may also want to enable PAP or CHAP for security. To enable PAP, add
@@ -831,6 +940,14 @@ You'll also need to create the following entry in
MyAuthName MyAuthPasswd
.Ed
.Pp
+If
+.Ar MyAuthPasswd
+is a
+.Pq Dq * ,
+the password is looked up in the
+.Xr passwd 5
+database.
+.Pp
The entry in
.Pa /etc/ppp/ppp.conf
on awfulhak (the initiator) should contain the following:
@@ -839,10 +956,10 @@ ui-gate:
set escape 0xff
set device ui-gate:ppp-in
set dial
- set timeout 30 15 5
- set log Phase Chat Connect Carrier hdlc LCP IPCP CCP tun
+ set timeout 30
+ set log Phase Chat Connect hdlc LCP IPCP CCP tun
set ifaddr 10.0.4.2 10.0.4.1
- add 10.0.2.0 255.255.255.0 10.0.4.1
+ add 10.0.2.0/24 10.0.4.1
.Ed
.Pp
Again, if you're enabling PAP, you'll also need:
@@ -911,35 +1028,98 @@ and that other machines have designated the
host as the gateway for the LAN.
.Sh PACKET FILTERING
This implementation supports packet filtering. There are four kinds of
-filters; ifilter, ofilter, dfilter and afilter. Here are the basics:
-.Bl -bullet -compact
+filters; the
+.Em in
+filter, the
+.Em out
+filter, the
+.Em dial
+filter and the
+.Em alive
+filter. Here are the basics:
+.Bl -bullet
.It
A filter definition has the following syntax:
-set filter-name rule-no action [src_addr/src_width] [dst_addr/dst_width]
-[proto [src [lt|eq|gt] port ]] [dst [lt|eq|gt] port] [estab]
+.Pp
+set filter
+.Ar name
+.Ar rule-no
+.Ar action
+.Op Ar src_addr Ns Op / Ns Ar width
+.Op Ar dst_addr Ns Op / Ns Ar width
+[
+.Ar proto
+.Op src Op Ar cmp No Ar port
+.Op dst Op Ar cmp No Ar port
+.Op estab
+.Op syn
+.Op finrst
+]
.Bl -enum
.It
-.Sq filter-name
-should be one of ifilter, ofilter, dfilter or afilter.
+.Ar Name
+should be one of
+.Sq in ,
+.Sq out ,
+.Sq dial
+or
+.Sq alive .
.It
-There are two actions:
-.Sq permit
+.Ar Rule-no
+is a numeric value between
+.Sq 0
and
+.Sq 19
+specifying the rule number. Rules are specified in numeric order according to
+.Ar rule-no ,
+but only if rule
+.Sq 0
+is defined.
+.It
+.Ar Action
+is either
+.Sq permit
+or
.Sq deny .
If a given packet
matches the rule, the associated action is taken immediately.
.It
-.Sq src_width
+.Op Ar src_addr Ns Op / Ns Ar width
and
-.Sq dst_width
-work like a netmask to represent an address range.
+.Op Ar dst_addr Ns Op / Ns Ar width
+are the source and destination IP number specifications. If
+.Op / Ns Ar width
+is specified, it gives the number of relevent netmask bits,
+allowing the specification of an address range.
.It
-.Sq proto
-must be one of icmp, udp or tcp.
+.Ar Proto
+must be one of
+.Sq icmp ,
+.Sq udp
+or
+.Sq tcp .
.It
-.Sq port number
-can be specified by number and service name from
+.Ar Cmp
+is one of
+.Sq \&lt ,
+.Sq \&eq
+or
+.Sq \&gt ,
+meaning less-than, equal and greater-than respectively.
+.Ar Port
+can be specified as a numeric port or by service name from
.Pa /etc/services .
+.It
+The
+.Sq estab ,
+.Sq syn ,
+and
+.Sq finrst
+flags are only allowed when
+.Ar proto
+is set to
+.Sq tcp ,
+and represent the TH_ACK, TH_SYN and TH_FIN or TH_RST TCP flags respectively.
.El
.Pp
.It
@@ -951,41 +1131,47 @@ If no rule is matched to a packet, that packet will be discarded
(blocked).
.It
Use
-.Dq set filter-name -1
+.Dq set filter Ar name No -1
to flush all rules.
.El
.Pp
See
-.Pa /etc/ppp/ppp.conf.filter.example .
-.Sh SETTING IDLE, LINE QUALITY REQUEST, RETRY TIMER
-To check/set idle timer, use the
-.Dq show timeout
+.Pa /etc/ppp/ppp.conf.example .
+.Sh SETTING THE IDLE TIMER
+To check/set the idle timer, use the
+.Dq show bundle
and
-.Dq set timeout idle [LQR [FSM-resend]]
+.Dq set timeout
commands:
.Bd -literal -offset indent
ppp ON awfulhak> set timeout 600
.Ed
.Pp
-The timeout period is measured in seconds, the default values for which
-are timeout = 180 or 3 min, lqrtimer = 30sec and retrytimer = 3sec.
+The timeout period is measured in seconds, the default value for which
+is 180 seconds
+.Pq or 3 min .
To disable the idle timer function, use the command
.Bd -literal -offset indent
ppp ON awfulhak> set timeout 0
.Ed
.Pp
In
+.Fl ddial
+and
+.Fl direct
+modes, the idle timeout is ignored. In
.Fl auto
-mode, an idle timeout causes the
+mode, when the idle timeout causes the
.Em PPP
session to be
-closed, though the
+closed, the
.Nm
program itself remains running. Another trigger packet will cause it to
-attempt to reestablish the link.
+attempt to re-establish the link.
.Sh PREDICTOR-1 and DEFLATE COMPRESSION
-This version supports CCP and Predictor type 1 or deflate compression
-based on the current IETF-draft specs. As a default behaviour,
+.Nm Ppp
+supports both Predictor type 1 and deflate compression.
+By default,
.Nm
will attempt to use (or be willing to accept) both compression protocols
when the peer agrees
@@ -998,11 +1184,26 @@ and
.Dq deny
commands if you wish to disable this functionality.
.Pp
-It is possible to use a different algorithm in each direction by using
-only one of
+It is possible to use a different compression algorithm in each direction
+by using only one of
.Dq disable deflate
and
-.Dq deny deflate .
+.Dq deny deflate
+.Pq assuming that the peer supports both algorithms .
+.Pp
+By default, when negotiating DEFLATE,
+.Nm
+will use a window size of 15. Refer to the
+.Dq set deflate
+command if you wish to change this behaviour.
+.Pp
+A special algorithm called DEFLATE24 is also available, and is disabled
+and denied by default. This is exactly the same as DEFLATE except that
+it uses CCP ID 24 to negotiate. This allows
+.Nm
+to successfully negotiate DEFLATE with
+.Nm pppd
+version 2.3.*.
.Sh CONTROLLING IP ADDRESS
.Nm
uses IPCP to negotiate IP addresses. Each side of the connection
@@ -1030,15 +1231,18 @@ is the IP address which the remote side should use and
.Sq netmask
is the netmask that should be used.
.Sq Src_addr
-and
+defaults to the current
+.Xr hostname 1 ,
.Sq dst_addr
-default to 0.0.0.0, and
+defaults to 0.0.0.0, and
.Sq netmask
defaults to whatever mask is appropriate for
.Sq src_addr .
It is only possible to make
.Sq netmask
-smaller than the default. The usual value is 255.255.255.255.
+smaller than the default. The usual value is 255.255.255.255, as
+most kernels ignore the netmask of a POINTOPOINT interface.
+.Pp
Some incorrect
.Em PPP
implementations require that the peer negotiates a specific IP
@@ -1053,6 +1257,7 @@ set ifaddr 192.244.177.38 192.244.177.2 255.255.255.255 0.0.0.0
.Ed
.Pp
The above specification means:
+.Pp
.Bl -bullet -compact
.It
I will first suggest that my IP address should be 0.0.0.0, but I
@@ -1076,6 +1281,7 @@ user to specify IP address more loosely:
.Pp
A number followed by a slash (/) represent the number of bits significant in
the IP address. The above example signifies that:
+.Pp
.Bl -bullet -compact
.It
I'd like to use 192.244.177.38 as my address if it is possible, but I'll
@@ -1267,16 +1473,13 @@ be ignored as it is less restrictive than the default mask for your
An example for a connection where you don't know your IP number or your
ISPs IP number would be:
.Bd -literal -offset indent
-set ifaddr 10.10.10.10/0 10.10.11.11/0 0.0.0.0 0.0.0.0
+set ifaddr 10.0.0.1/0 10.0.0.2/0 0.0.0.0 0.0.0.0
.Ed
.Pp
.It
In most cases, your ISP will also be your default router. If this is
-the case, and if you're using
-.Fl auto
-mode, add the lines
+the case, add the line
.Bd -literal -offset indent
-delete ALL
add default HISADDR
.Ed
.Pp
@@ -1285,43 +1488,21 @@ to
.Pp
This tells
.Nm
-to delete all non-direct routing entries for the tun interface that
-.Nm
-is running on, then to add a default route to 10.10.11.11. If you're
-not using
-.Fl auto
-mode, this isn't necessary as
-.Nm
-will dial immediately and may negotiate new IP numbers with the peer.
-.Pp
-If you're not using
-.Fl auto
-mode, or if you're using dynamic IP numbers, you must also put these
-two lines in the
-.Pa /etc/ppp/ppp.linkup
-file:
-.Bd -literal -offset indent
-delete ALL
-add default HISADDR
-.Ed
+to add a default route to whatever the peer address is
+.Pq 10.0.0.2 in this example .
+This route is
+.Sq sticky ,
+meaning that should the value of
+.Dv HISADDR
+change, the route will be updated accordingly.
.Pp
-HISADDR is a macro meaning the "other side"s IP number, and is
-available once an IP number has been agreed (using IPCP) or set
-.Pq using Dq set ifaddr .
-Now, once a connection is established,
+Previous versions of
.Nm
-will delete all non-direct interface routes, and add a default route
-pointing at the peers IP number. You should use the same label as the
-one used in
-.Pa /etc/ppp/ppp.conf .
-.Pp
-If commands are being typed interactively, the only requirement is
-to type
-.Bd -literal -offset indent
-add default HISADDR
-.Ed
-.Pp
-after a successful dial.
+required a similar entry in the
+.Pa /etc/ppp/ppp.linkup
+file. Since the advent of
+.Sq sticky routes ,
+his is no longer required.
.It
If your provider requests that you use PAP/CHAP authentication methods, add
the next lines to your
@@ -1350,20 +1531,19 @@ is able to generate the following log info either via
or directly to the screen:
.Bl -column SMMMMMM -offset indent
.It Li Async Dump async level packet in hex
-.It Li Carrier Log Chat lines with 'CARRIER'
.It Li CCP Generate a CCP packet trace
.It Li Chat Generate Chat script trace log
.It Li Command Log commands executed
.It Li Connect Generate complete Chat log
-.It Li Debug Log (very verbose) debug information
+.It Li Debug Log debug information
.It Li HDLC Dump HDLC packet in hex
.It Li ID0 Log all function calls specifically made as user id 0.
.It Li IPCP Generate an IPCP packet trace
.It Li LCP Generate an LCP packet trace
-.It Li Link Log address assignments and link up/down events
.It Li LQM Generate LQR report
.It Li Phase Phase transition log output
.It Li TCP/IP Dump all TCP/IP packets
+.It Li Timer Log timer manipulation
.It Li TUN Include the tun device on each log line
.It Li Warning Output to the terminal device. If there is currently no
terminal, output is sent to the log file using LOG_WARNING.
@@ -1376,7 +1556,7 @@ The
.Dq set log
command allows you to set the logging output level. Multiple levels
can be specified on a single command line. The default is equivalent to
-.Dq set log Carrier Link Phase .
+.Dq set log Phase .
.Pp
It is also possible to log directly to the screen. The syntax is
the same except that the word
@@ -1385,21 +1565,21 @@ should immediately follow
.Dq set log .
The default is
.Dq set log local
-(ie. no direct screen logging).
+(ie. only the un-maskable warning, error and alert output).
.Pp
If The first argument to
.Dq set log Op local
begins with a '+' or a '-' character, the current log levels are
not cleared, for example:
.Bd -literal -offset indent
-PPP ON awfulhak> set log carrier link phase
+PPP ON awfulhak> set log phase
PPP ON awfulhak> show log
-Log: Carrier Link Phase Warning Error Alert
+Log: Phase Warning Error Alert
Local: Warning Error Alert
-PPP ON awfulhak> set log -link +tcp/ip -warning
+PPP ON awfulhak> set log +tcp/ip -warning
PPP ON awfulhak> set log local +command
PPP ON awfulhak> show log
-Log: Carrier Phase TCP/IP Warning Error Alert
+Log: Phase TCP/IP Warning Error Alert
Local: Command Warning Error Alert
.Ed
.Pp
@@ -1428,19 +1608,173 @@ mode.
These signals tell
.Nm
to exit.
-.It USR1
-This signal, when not in interactive mode, tells
-.Nm
-to close any existing server socket and open an Internet socket using
-port 3000 plus the current tunnel device number. This can only be
-achieved if a suitable local password is specified in
-.Pa /etc/ppp/ppp.secret .
.It USR2
This signal, tells
.Nm
-to close any existing server socket.
+to close any existing server socket, dropping all existing diagnostic
+connections.
.El
.Pp
+.Sh MULTILINK PPP
+If you wish to use more than one physical link to connect to a
+.Em PPP
+peer, that peer must also understand the
+.Em MULTILINK PPP
+protocol. Refer to RFC 1990 for specification details.
+.Pp
+The peer is identified using a combination of his
+.Dq endpoint discriminator
+and his
+.Dq authentication id .
+Either or both of these may be specified. It is recommended that
+at least one is specified, otherwise there is no way of ensuring that
+all links are actually connected to the same peer program, and some
+confusing lock-ups may result. Locally, these identification variables
+are specified using the
+.Dq set enddisc
+and
+.Dq set authname
+commands. The
+.Sq authname
+.Pq and Sq authkey
+must be agreed in advance with the peer.
+.Pp
+Multilink capabilities are enabled using the
+.Dq set mrru
+command (set maximum reconstructed receive unit). Once multilink
+is enabled,
+.Nm
+will attempt to negotiate a multilink connection with the peer.
+.Pp
+By default, only one
+.Sq link
+is available
+.Pq called Sq deflink .
+To create more links, the
+.Dq clone
+command is used. This command will clone existing links, where all
+characteristics are the same except:
+.Bl -enum
+.It
+The new link has its own name as specified on the
+.Dq clone
+command line.
+.It
+The new link is an
+.Sq interactive
+link. It's mode may subsequently be changed using the
+.Dq set mode
+command.
+.It
+The new link is in a
+.Sq closed
+state.
+.El
+.Pp
+A summary of all available links can be seen using the
+.Dq show links
+command.
+.Pp
+Once a new link has been created, command usage varies. All link
+specific commands must be prefixed with the
+.Dq link Ar name
+command, specifying on which link the command is to be applied. When
+only a single link is available,
+.Nm
+is smart enough not to require the
+.Dq link Ar name
+prefix.
+.Pp
+Some commands can still be used without specifying a link - resulting
+in an operation at the
+.Sq bundle
+level. For example, once two or more links are available, the command
+.Dq show ccp
+will show CCP configuration and statistics at the multilink level, and
+.Dq link deflink show ccp
+will show the same information at the
+.Dq deflink
+link level.
+.Pp
+Armed with this information, the following configuration might be used:
+.Pp
+.Bd -literal -offset indent
+mp:
+ set timeout 0
+ set log phase chat
+ set device /dev/cuaa0 /dev/cuaa1 /dev/cuaa2
+ set phone "123456789"
+ set dial "ABORT BUSY ABORT NO\\sCARRIER TIMEOUT 5 \\"\\" ATZ \e
+ OK-AT-OK \\\\dATDT\\\\T TIMEOUT 45 CONNECT"
+ set login
+ set ifaddr 10.0.0.1/0 10.0.0.2/0
+ set authname ppp
+ set authkey ppppassword
+
+ set mrru 1500
+ clone 1,2,3
+ link deflink remove
+.Ed
+.Pp
+Note how all cloning is done at the end of the configuration. Usually,
+the link will be configured first, then cloned. If you wish all links
+to be up all the time, you can add the following line to the end of your
+configuration.
+.Pp
+.Bd -literal -offset indent
+ link 1,2,3 set mode ddial
+.Ed
+.Pp
+If you want the links to dial on demand, this command could be used:
+.Pp
+.Bd -literal -offset indent
+ link * set mode auto
+.Ed
+.Pp
+Links may be tied to specific names by removing the
+.Dq set device
+line above, and specifying the following after the
+.Dq clone
+command:
+.Pp
+.Bd -literal -offset indent
+ link 1 set device /dev/cuaa0
+ link 2 set device /dev/cuaa1
+ link 3 set device /dev/cuaa2
+.Ed
+.Pp
+Use the
+.Dq help
+command to see which commands require context (using the
+.Dq link
+command), which have optional
+context and which should not have any context.
+.Pp
+When
+.Nm
+has negotiated
+.Em MULTILINK
+mode with the peer, it creates a unix domain socket in the
+.Pa /var/run
+directory. This socket is used to pass link information (including
+the actual link file descriptor) between different
+.Nm
+invocations. This facilitates
+.Nm ppp Ns No s
+ability to be run from a
+.Xr getty 8
+or directly from
+.Pa /etc/gettydefs
+(using the
+.Sq pp=
+capability), without needing to have initial control of the serial
+line. Once
+.Nm
+negotiates multilink mode, it will pass its open link to any
+already running process. If there is no already running process,
+.Nm
+will act as the master, creating the socket and listening for new
+connections.
.Sh PPP COMMAND LIST
This section lists the available commands and their effect. They are
usable either from an interactive
@@ -1451,7 +1785,7 @@ or
.Xr telnet 1
session.
.Bl -tag -width 20
-.It accept|deny|enable|disable option....
+.It accept|deny|enable|disable Ar option....
These directives tell
.Nm
how to negotiate the initial connection with the peer. Each
@@ -1501,9 +1835,10 @@ CHAP is accepted by default.
Some
.Em PPP
implementations use "MS-CHAP" rather than MD5 when encrypting the
-challenge. Refer to the description of the
-.Dq set encrypt
-command for further details.
+challenge. MS-CHAP is a combination of MD4 and DES. If
+.Nm was build
+on a machine with DES libraries available, it will respond to MS-CHAP
+authentication requests, but will never request them.
.It deflate
Default: Enabled and Accepted. This option decides if deflate
compression will be used by the Compression Control Protocol (CCP).
@@ -1536,17 +1871,69 @@ in
is capable of negotiating with
.Nm pppd ,
but only if
-.Dq pppd-deflate
+.Dq deflate24
is
.Ar enable Ns No d
and
.Ar accept Ns No ed .
+.It deflate24
+Default: Disabled and Denied. This is a variance of the
+.Ar deflate
+option, allowing negotiation with the
+.Xr pppd 8
+program. Refer to the
+.Ar deflate
+section above for details. It is disabled by default as it violates
+.Pa rfc1975 .
+.It dns
+Default: Enabled and Denied. This option allows DNS negotiation.
+.Pp
+If
+.Dq enable Ns No d,
+.Nm
+will request that the peer confirms the entries in
+.Pa /etc/resolv.conf .
+If the peer NAKs our request (suggesting new IP numbers),
+.Pa /etc/resolv.conf
+is updated and another request is sent to confirm the new entries.
+.Pp
+If
+.Dq accept Ns No ed,
+.Nm
+will answer any DNS queries requested by the peer rather than rejecting
+them. The answer is taken from
+.Pa /etc/resolv.conf
+unless the
+.Dq set dns
+command is used as an override.
.It lqr
Default: Disabled and Accepted. This option decides if Link Quality
-Requests will be sent. LQR is a protocol that allows
+Requests will be sent or accepted. LQR is a protocol that allows
.Nm
to determine that the link is down without relying on the modems
-carrier detect.
+carrier detect. When LQR is enabled,
+.Nm
+sends the
+.Em QUALPROTO
+option (see
+.Dq set lqrperiod
+below) as part of the LCP request. If the peer agrees, both sides will
+exchange LQR packets at the agreed frequency, allowing detailed link
+quality monitoring by enabling LQM logging. If the peer doesn't agree,
+ppp will send ECHO LQR requests instead. These packets pass no
+information of interest, but they
+.Em MUST
+be replied to by the peer.
+.Pp
+Whether using LQR or ECHO LQR,
+.Nm
+will abruptly drop the connection if 5 unacknowledged packets have been
+sent rather than sending a 6th. A message is logged at the
+.Em PHASE
+level, and any appropriate
+.Dq reconnect
+values are honoured as if the peer were responsible for dropping the
+connection.
.It pap
Default: Disabled and Accepted. PAP stands for Password Authentication
Protocol. Only one of PAP and CHAP (above) may be negotiated. With
@@ -1571,15 +1958,6 @@ and
in
.Pa /etc/ppp/ppp.conf .
PAP is accepted by default.
-.It pppd-deflate
-Default: Disabled and Denied. This is a variance of the
-.Ar deflate
-option, allowing negotiation with the
-.Xr pppd 8
-program. Refer to the
-.Ar deflate
-section above for details. It is disabled by default as it violates
-.Pa rfc1975 .
.It pred1
Default: Enabled and Accepted. This option decides if Predictor 1
compression will be used by the Compression Control Protocol (CCP).
@@ -1587,20 +1965,49 @@ compression will be used by the Compression Control Protocol (CCP).
Default: Enabled and Accepted. This option is used to negotiate
PFC (Protocol Field Compression), a mechanism where the protocol
field number is reduced to one octet rather than two.
+.It shortseq
+Default: Enabled and Accepted. This option determines if
+.Nm
+will request and accept requests for short
+.Pq 12 bit
+sequence numbers when negotiating multilink mode. This is only
+applicable if our MRRU is set (thus enabling multilink).
.It vjcomp
-Default: Enabled and Accepted. This option decides if Van Jacobson
+Default: Enabled and Accepted. This option determines if Van Jacobson
header compression will be used.
.El
.Pp
The following options are not actually negotiated with the peer.
Therefore, accepting or denying them makes no sense.
.Bl -tag -width 20
-.It msext
-Default: Disabled. This option allows the use of Microsoft's
+.It idcheck
+Default: Enabled. When
+.Nm
+exchanges low-level LCP, CCP and IPCP configuration traffic, the
+.Em Identifier
+field of any replies is expected to be the same as that of the request.
+By default,
+.Nm
+drops any reply packets that do not contain the expected identifier
+field, reporting the fact at the respective log level. If
+.Ar idcheck
+is disabled,
+.Nm
+will ignore the identifier field.
+.It loopback
+Default: Enabled. When
+.Ar loopback
+is enabled,
+.Nm
+will automatically loop back packets being sent
+out with a destination address equal to that of the
.Em PPP
-extensions, supporting the negotiation of the DNS and the NetBIOS NS.
-Enabling this allows us to pass back the values given in "set ns"
-and "set nbns".
+interface. If disabled,
+.Nm
+will send the packet, probably resulting in an ICMP redirect from
+the other end. It is convenient to have this option enabled when
+the interface is also the default route as it avoids the necessity
+of a loopback route.
.It passwdauth
Default: Disabled. Enabling this option will tell the PAP authentication
code to use the password file (see
@@ -1608,12 +2015,34 @@ code to use the password file (see
to authenticate the caller rather than the
.Pa /etc/ppp/ppp.secret
file.
+.Pa /etc/ppp/ppp.secret
+is checked before
+.Xr passwd 5 .
.It proxy
Default: Disabled. Enabling this option will tell
.Nm
to proxy ARP for the peer.
+.It sroutes
+Default: Enabled. When the
+.Dq add
+command is used with the
+.Dv HISADDR
+or
+.Dv MYADDR
+values, entries are stored in the
+.Sq stick route
+list. Each time
+.Dv HISADDR
+or
+.Dv MYADDR
+change, this list is re-applied to the routing table.
+.Pp
+Disabling this option will prevent the re-application of sticky routes,
+altough the
+.Sq stick route
+list will still be maintained.
.It throughput
-Default: Disabled. Enabling this option will tell
+Default: Enabled. This option tells
.Nm
to gather thoroughput statistics. Input and output is sampled over
a rolling 5 second window, and current, best and total figures are
@@ -1621,7 +2050,7 @@ retained. This data is output when the relevent
.Em PPP
layer shuts down, and is also available using the
.Dq show
-command. Troughput statistics are available at the
+command. Throughput statistics are available at the
.Dq IPCP
and
.Dq modem
@@ -1639,25 +2068,31 @@ not to make any utmp or wtmp entries. This is usually only necessary if
you require the user to both login and authenticate themselves.
.El
.Pp
-.It add[!] dest mask gateway
+.It add[!] Ar dest[/nn] [mask] gateway
.Ar Dest
-is the destination IP address and
-.Ar mask
-is its mask.
+is the destination IP address. The netmask is specified either as a
+number of bits with
+.Ar /nn
+or as an IP number using
+.Ar mask .
.Ar 0 0
-refers to the default route, and it is possible to use the symbolic name
+or simply
+.Ar 0
+with no mask refers to the default route. It is also possible to use the
+literal name
.Sq default
-in place of both the
-.Ar dest
-and
-.Ar mask
-arguments.
+instead of
+.Ar 0 .
.Ar Gateway
is the next hop gateway to get to the given
.Ar dest
-machine/network. It is possible to use the symbolic names
+machine/network. Refer to the
+.Xr route 8
+command for further details.
+.Pp
+It is possible to use the symbolic names
.Sq MYADDR
-and
+or
.Sq HISADDR
as the destination, and either
.Sq HISADDR
@@ -1668,7 +2103,7 @@ as the
.Sq MYADDR
is replaced with the interface address,
.Sq HISADDR
-is replaced with the interfaces destination address and
+is replaced with the interface destination address and
.Sq INTERFACE
is replaced with the current interface name. If the interfaces destination
address has not yet been assigned
@@ -1678,23 +2113,32 @@ the current
is used instead of
.Sq HISADDR .
.Pp
-Refer to the
-.Dq set ifaddr
-command below for details of some restrictions regarding the use of this
-command in the
-.Pa ppp.conf
-file.
-.Pp
If the
.Ar add!
command is used
-.Pq note the following Dq \&! ,
+.Pq note the trailing Dq \&! ,
then if the route already exists, it will be updated as with the
.Sq route change
command (see
.Xr route 8
for further details).
-.It allow .....
+.Pp
+Routes that contain the
+.Dq HISADDR
+or
+.Dq MYADDR
+constants are considered
+.Sq sticky .
+They are stored in a list (use
+.Dq show ipcp
+to see the list), and each time the value of
+.Dv HISADDR
+or
+.Dv MYADDR
+changes, the appropriate routing table entries are updated. This facility
+may be disabled using
+.Dq disable sroutes .
+.It allow Ar command Op Ar args
This command controls access to
.Nm
and its configuration files. It is possible to allow user-level access,
@@ -1712,13 +2156,15 @@ mode.
.Pp
User id 0 is immune to these commands.
.Bl -tag -width 20
-.It allow user|users logname...
-By default, only user id 0 is allowed access. If this command is specified,
-all of the listed users are allowed access to the section in which the
+.It allow user[s] Ar logname...
+By default, only user id 0 is allowed access to
+.Nm ppp .
+If this command is used, all of the listed users are allowed access to
+the section in which the
.Dq allow users
command is found. The
.Sq default
-section is always checked first (although it is only ever automatically
+section is always checked first (even though it is only ever automatically
loaded at startup). Each successive
.Dq allow users
command overrides the previous one, so it's possible to allow users access
@@ -1729,11 +2175,11 @@ section, and then specifying a new user list for that label.
If user
.Sq *
is specified, access is allowed to all users.
-.It allow mode|modes modelist...
-By default, access using all
+.It allow mode[s] Ar modelist...
+By default, access using any
.Nm
-modes is possible. If this command is used, it restricts the access
-modes allowed to load the label under which this command is specified.
+mode is possible. If this command is used, it restricts the access
+mode allowed to load the label under which this command is specified.
Again, as with the
.Dq allow users
command, each
@@ -1751,9 +2197,13 @@ Possible modes are:
.Sq background
and
.Sq * .
+.Pp
+When running in multilink mode, a section can be loaded if it allows
+.Em any
+of the currently existing line modes.
.El
.Pp
-.It alias .....
+.It alias Ar command Op Ar args
This command allows the control of the aliasing (or masquerading)
facilities that are built into
.Nm ppp .
@@ -1770,26 +2220,35 @@ The
.Fl alias
command line flag is synonymous with
.Dq alias enable yes .
-.It alias port [proto targetIP:targetPORT [aliasIP:]aliasPORT]
+.It alias port Op Ar proto targetIP:targetPORT [aliasIP:]aliasPORT
This command allows us to redirect connections arriving at
-.Dq aliasPORT
-for machine [aliasIP] to
-.Dq targetPORT
+.Ar aliasPORT
+for machine
+.Ar aliasIP
+to
+.Ar targetPORT
on
-.Dq targetIP .
-If proto is specified, only connections of the given protocol
+.Ar targetIP .
+.Ar Proto
+may be either
+.Sq tcp
+or
+.Sq udp ,
+and only connections of the given protocol
are matched. This option is useful if you wish to run things like
Internet phone on the machines behind your gateway.
-.It alias addr [addr_local addr_alias]
+.It alias addr Op Ar addr_local addr_alias
This command allows data for
-.Dq addr_alias
+.Ar addr_alias
to be redirected to
-.Dq addr_local .
+.Ar addr_local .
It is useful if you own a small number of real IP numbers that
you wish to map to specific machines behind your gateway.
.It alias deny_incoming [yes|no]
If set to yes, this command will refuse all incoming connections
by dropping the packets in much the same way as a firewall would.
+.It alias help|?
+This command gives a summary of available alias commands.
.It alias log [yes|no]
This option causes various aliasing statistics and information to
be logged to the file
@@ -1807,13 +2266,12 @@ IRC connection.
Only alter outgoing packets with an unregistered source ad-
dress. According to RFC 1918, unregistered source addresses
are 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.
-.It alias help|?
-This command gives a summary of available alias commands.
.El
.Pp
-.It [!]bg command
-The given command is executed in the background.
-Any of the pseudo arguments
+.It [!]bg Ar command
+The given
+.Ar command
+is executed in the background. Any of the pseudo arguments
.Dv HISADDR ,
.Dv INTERFACE
and
@@ -1823,19 +2281,46 @@ will be replaced with the appropriate values. If you wish to pause
while the command executes, use the
.Dv shell
command instead.
-.It close
-Close the current connection (but don't quit).
-.It delete[!] dest
+.It clone Ar name[,name]...
+Clone the specified link, creating one or more new links according to the
+.Ar name
+argument(s). This command must be used from the
+.Dq link
+command below unless you've only got a single link (in which case that
+link becomes the default). Links may be removed using the
+.Dq remove
+command below.
+.Pp
+The default link name is
+.Dq deflink .
+.It close Op lcp|ccp[!]
+If no arguments are given, or if
+.Dq lcp
+is specified, the link will be closed. If
+.Dq ccp
+is specified, only the relevent compression layer is closed. If the
+.Dq \&!
+is used, the compression layer will remain in the closed state, otherwise
+it will re-enter the STOPPED state, waiting for the peer to initiate
+further CCP negotiation. In any event, this command does not disconnect
+the user from
+.Nm
+or exit
+.Nm ppp .
+See the
+.Dq quit
+command below.
+.It delete[!] Ar dest
This command deletes the route with the given
.Ar dest
IP address. If
.Ar dest
is specified as
.Sq ALL ,
-all non-direct entries in the routing for the current interface that
-.Nm
-is using are deleted. This means all entries for tunN, except the entry
-representing the actual link. If
+all non-direct entries in the routing table for the current interface,
+and all
+.Sq sticky route
+entries are deleted. If
.Ar dest
is specified as
.Sq default ,
@@ -1844,41 +2329,73 @@ the default route is deleted.
If the
.Ar delete!
command is used
-.Pq note the following Dq \&! ,
+.Pq note the trailing Dq \&! ,
.Nm
will not complain if the route does not already exist.
-.It dial|call [remote]
+.It dial|call Op Ar label
If
-.Dq remote
+.Ar label
is specified, a connection is established using the
.Dq dial
and
.Dq login
scripts for the given
-.Dq remote
-system. Otherwise, the current settings are used to establish
-the connection.
-.It display
-Displays the current status of the negotiable protocol
-values as specified under
-.Dq accept|deny|enable|disable option....
-above.
-.It down
-Bring the link down ungracefully, as if the physical layer had become
-unavailable. It's not considered polite to use this command.
-.It help|? [command]
+.Ar label .
+Otherwise, the current settings are used to establish
+the connection, and all closed links are brought up.
+.It down Op Ar lcp|ccp
+Bring the relevent layer down ungracefully, as if the underlying layer
+had become unavailable. It's not considered polite to use this command on
+a Finite State Machine that's in the OPEN state. If no arguments are
+supplied,
+.Sq lcp
+is assumed.
+.It help|? Op Ar command
Show a list of available commands. If
-.Dq command
+.Ar command
is specified, show the usage string for that command.
-.It load [remote]
+.It [data]link Ar name[,name...] command Op Ar args
+This command may prefix any other command if the user wishes to
+specify which link the command should affect. This is only
+applicable after multiple links have been created in Multilink
+mode using the
+.Dq clone
+command.
+.Pp
+.Ar Name
+specifies the name of an existing link. If
+.Ar name
+is a comma separated list,
+.Ar command
+is executed on each link. If
+.Ar name
+is
+.Dq * ,
+.Ar command
+is executed on all links.
+.It load Op Ar label
Load the given
-.Dq remote
-label. If
-.Dq remote
+.Ar label
+from the
+.Pa ppp.conf
+file. If
+.Ar label
is not given, the
-.Dq default
-label is assumed.
-.It passwd pass
+.Ar default
+label is used.
+.It open Op lcp|ccp
+This is the opposite of the
+.Dq close
+command. Using
+.Dq open
+with no arguments or with the
+.Dq lcp
+argument is the same as using
+.Dq dial
+in that all closed links are brought up. If the
+.Dq ccp
+argument is used, the relevent compression layer is opened.
+.It passwd Ar pass
Specify the password required for access to the full
.Nm
command set. This password is required when connecting to the diagnostic
@@ -1886,68 +2403,63 @@ port (see the
.Dq set server
command).
.Ar Pass
-may be specified either on the
+is specified on the
.Dq set server
-command line or by putting an entry in
-.Pa /var/log/ppp.secret
-for the local host. The value of
+command line. The value of
.Ar pass
is not logged when
.Ar command
logging is active, instead, the literal string
-.Dq ********
+.Sq ********
is logged.
.It quit|bye [all]
-Exit
-.Nm ppp .
If
-.Nm
-is in interactive mode or if the
-.Dq all
-argument is given,
-.Nm
-will exit, closing the connection. A simple
.Dq quit
-issued from a
-.Xr pppctl 8
+is executed from the controlling connection or from a command file,
+ppp will exit after closing all connections. Otherwise, if the user
+is connected to a diagnostic socket, the connection is simply dropped.
+.Pp
+If the
+.Ar
+all argument is given,
+.Nm
+will exit despite the source of the command after closing all existing
+connections.
+.It remove|rm
+This command removes the given link. It is only really useful in
+multilink mode. A link must be
+in the
+.Dv CLOSED
+state before it is removed.
+.It rename|mv Ar name
+This command renames the given link to
+.Ar name .
+It will fail if
+.Ar name
+is already used by another link.
+.Pp
+The default link name is
+.Sq deflink .
+Renaming it to
+.Sq modem ,
+.Sq cuaa0
or
-.Xr telnet 1
-session will not close the current connection.
+.Sq USR
+may make the log file more readable.
.It save
This option is not (yet) implemented.
-.It set[up] var value
+.It set[up] Ar var value
This option allows the setting of any of the following variables:
.Bl -tag -width 20
-.It set accmap hex-value
+.It set accmap Ar hex-value
ACCMap stands for Asyncronous Control Character Map. This is always
-negotiated with the peer, and defaults to a value of 0x00000000.
+negotiated with the peer, and defaults to a value of 00000000 in hex.
This protocol is required to defeat hardware that depends on passing
certain characters from end to end (such as XON/XOFF etc).
-.It set filter-name rule-no action [src_addr/src_width]
-[dst_addr/dst_width] [proto [src [lt|eq|gt] port ]]
-[dst [lt|eq|gt] port] [estab]
.Pp
-.Nm Ppp
-supports four filter sets. The afilter specifies packets that keep
-the connection alive - reseting the idle timer. The dfilter specifies
-packets that cause
-.Nm
-to dial when in
-.Fl auto
-mode. The ifilter specifies packets that are allowed to travel
-into the machine and the ofilter specifies packets that are allowed
-out of the machine. By default all filter sets allow all packets
-to pass.
-Rules are processed in order according to
-.Dq n .
-Up to 20 rules may be given for each set. If a packet doesn't match
-any of the rules in a given set, it is discarded. In the case of
-ifilters and ofilters, this means that the packet is dropped. In
-the case of afilters it means that the packet will not reset the
-idle timer and in the case of dfilters it means that the packet will
-not trigger a dial.
-Refer to the section on PACKET FILTERING above for further details.
-.It set authkey|key value
+For the XON/XOFF scenario, use
+.Dq set accmap 000a0000 .
+.It set authkey|key Ar value
This sets the authentication key (or password) used in client mode
PAP or CHAP negotiation to the given value. It can also be used to
specify the password to be used in the dial or login scripts in place
@@ -1956,13 +2468,69 @@ of the '\\P' sequence, preventing the actual password from being logged. If
logging is in effect,
.Ar value
is logged as
-.Ar ********
+.Sq ********
for security reasons.
-.It set authname id
+.It set authname Ar id
This sets the authentication id used in client mode PAP or CHAP negotiation.
-.It set ctsrts
-This sets hardware flow control and is the default.
-.It set device|line value[,value...]
+.It set autoload Ar maxduration maxload Op Ar minduration minload
+These settings apply only in multilink mode and all default to zero.
+When more than one
+.Ar demand-dial
+.Pq also known as Fl auto
+mode link is available, only the first link is made active when
+.Nm
+first reads data from the tun device. The next
+.Ar demand-dial
+link will be opened only when at least
+.Ar maxload
+packets have been in the send queue for
+.Ar maxduration
+seconds. Because both values default to zero,
+.Ar demand-dial
+links will simply come up one at a time by default.
+.Pp
+If two or more links are open, at least one of which is a
+.Ar demand-dial
+link, a
+.Ar demand-dial
+link will be closed when there is less than
+.Ar minpackets
+in the queue for more than
+.Ar minduration .
+If
+.Ar minduration
+is zero, this timer is disabled. Because both values default to zero,
+.Ar demand-dial
+links will stay active until the bundle idle timer expires.
+.It set ctsrts|crtscts on|off
+This sets hardware flow control. Hardware flow control is
+.Ar on
+by default.
+.It set deflate Ar out-winsize Op Ar in-winsize
+This sets the DEFLATE algorithms default outgoing and incoming window
+sizes. Both
+.Ar out-winsize
+and
+.Ar in-winsize
+must be values between
+.Em 8
+and
+.Em 15 .
+If
+.Ar in-winsize
+is specified,
+.Nm
+will insist that this window size is used and will not accept any other
+values from the peer.
+.It set dns Op Ar primary Op Ar secondary
+This command specifies DNS overrides for the
+.Dq accept dns
+command. Refer to the
+.Dq accept
+command description above for details. This command does not affect the
+IP numbers requested using
+.Dq enable dns .
+.It set device|line Ar value[,value...]
This sets the device(s) to which
.Nm
will talk to the given
@@ -1973,9 +2541,20 @@ If
.Dq value
does not begin with
.Pa /dev/ ,
-it must be of the format
+it must either begin with an exclaimation mark
+.Pq Dq \&!
+or be of the format
.Dq host:port .
-If this is the case,
+.Pp
+If it begins with an exclaimation mark, the rest of the device name is
+treated as a program name, and that program is executed when the device
+is opened. Standard input, output and error are fed back to
+.Nm
+and are read and written as if they were a regular device.
+.Pp
+If a
+.Dq host:port
+pair is given,
.Nm
will attempt to connect to the given
.Dq host
@@ -1983,13 +2562,15 @@ on the given
.Dq port .
Refer to the section on
.Em PPP OVER TCP
-above for further details. If multiple
+above for further details.
+.Pp
+If multiple
.Dq values
are specified,
.Nm
will attempt to open each one in turn until it succeeds or runs out of
devices.
-.It set dial chat-script
+.It set dial Ar chat-script
This specifies the chat script that will be used to dial the other
side. See also the
.Dq set login
@@ -2057,7 +2638,7 @@ command), and standard error is read by
.Nm
and substituted as the expect or send string. If
.Nm
-is running in interactive mode, file descriptor 4 is attached to
+is running in interactive mode, file descriptor 3 is attached to
.Pa /dev/tty .
.Pp
For example (wrapped for readability);
@@ -2116,64 +2697,132 @@ This, of course means that it is possible to execute an entirely external
command rather than using the internal one. See
.Xr chat 8
for a good alternative.
+.It set enddisc Op label|IP|MAC|magic|psn value
+This command sets our local endpoint discriminator. If set prior to
+LCP negotiation,
+.Nm
+will send the information to the peer using the LCP endpoint discriminator
+option. The following discriminators may be set:
+.Bd -literal -offset indent
+.It label
+The current label is used.
+.It IP
+Our local IP number is used. As LCP is negotiated prior to IPCP, it is
+possible that the IPCP layer will subsequently change this value. If
+it does, the endpoint descriminator stays at the old value unless manually
+reset.
+.It MAC
+This is similar to the
+.Ar IP
+option above, except that the MAC address associated with the local IP
+number is used. If the local IP number is not resident on any ethernet
+interface, the command will fail.
+.Pp
+As the local IP number defaults to whatever the machine host name is,
+.Dq set enddisc mac
+is usually done prior to any
+.Dq set ifaddr
+commands.
+.It magic
+A 20 digit random number is used.
+.It psn Ar value
+The given
+.Ar value
+is used.
+.Ar Value
+should be set to an absolute public switched network number with the
+country code first.
+.Ed
.Pp
-.It set hangup chat-script
-This specifies the chat script that will be used to reset the modem
-before it is closed. It should not normally be necessary, but can
-be used for devices that fail to reset themselves properly on close.
-.It set encrypt MSChap|MD5
-This specifies the encryption algorithm to request and use when issuing
-the CHAP challenge, and defaults to MD5. If this is set to MSChap,
-.Nm
-will behave like a Microsoft RAS when sending the CHAP challenge (assuming
-CHAP is enabled). When responding to a challenge,
-.Nm
-determines how to encrypt the response based on the challenge, so this
-setting is ignored.
-.Bl -tag -width NOTE:
-.It NOTE:
-Because the Microsoft encryption algorithm uses a combination of MD4 and DES,
-if you have not installed DES encryption software on your machine
-before building
-.Nm ppp ,
-this option will not be available - only MD5 will be used.
-.El
-.Pp
-.It set escape value...
+If no arguments are given, the endpoint discriminator is reset.
+.It set escape Ar value...
This option is similar to the
.Dq set accmap
option above. It allows the user to specify a set of characters that
will be `escaped' as they travel across the link.
-.It set ifaddr [myaddr [hisaddr [netmask [triggeraddr]]]]
+.It set filter dial|alive|in|out rule-no permit|deny Ar "[src_addr/width] [dst_addr/width] [proto [src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"
+.Nm Ppp
+supports four filter sets. The
+.Em alive
+filter specifies packets that keep the connection alive - reseting the
+idle timer. The
+.Em dial
+filter specifies packets that cause
+.Nm
+to dial when in
+.Fl auto
+mode. The
+.Em in
+filter specifies packets that are allowed to travel
+into the machine and the
+.Em out
+filter specifies packets that are allowed out of the machine.
+.Pp
+Filtering is done prior to any IP alterations that might be done by the
+alias engine. By default all filter sets allow all packets to pass.
+Rules are processed in order according to
+.Ar rule-no .
+Up to 20 rules may be given for each set. If a packet doesn't match
+any of the rules in a given set, it is discarded. In the case of
+.Em in
+and
+.Em out
+filters, this means that the packet is dropped. In the case of
+.Em alive
+filters it means that the packet will not reset the idle timer and in
+the case of
+.Em dial
+filters it means that the packet will not trigger a dial. A packet failing
+to trigger a dial will be dropped rather than queued. Refer to the
+section on PACKET FILTERING above for further details.
+.It set hangup Ar chat-script
+This specifies the chat script that will be used to reset the modem
+before it is closed. It should not normally be necessary, but can
+be used for devices that fail to reset themselves properly on close.
+.It set help|? Op Ar command
+This command gives a summary of available set commands, or if
+.Ar command
+is specified, the command usage is shown.
+.It set ifaddr Ar [myaddr [hisaddr [netmask [triggeraddr]]]]
This command specifies the IP addresses that will be used during
IPCP negotiation. Addresses are specified using the format
+.Pp
.Dl a.b.c.d/n
-Where a.b.c.d is the preferred IP, but n specifies how many bits
-of the address we will insist on. If the /n bit is omitted, it
-defaults to /32 unless the IP address is 0.0.0.0 in which case
-the mask defaults to /0.
+.Pp
+Where
+.Ar a.b.c.d
+is the preferred IP, but
+.Ar n
+specifies how many bits of the address we will insist on. If
+.Ar /n
+is omitted, it defaults to
+.Ar /32
+unless the IP address is 0.0.0.0 in which case it defaults to
+.Ar /0 .
.Pp
.Ar Hisaddr
may also be specified as a range of IP numbers in the format
+.Pp
.Dl a.b.c.d[-d.e.f.g][,h.i.j.k[-l,m,n,o]]...
+.Pp
for example:
+.Pp
.Dl set ifaddr 10.0.0.1 10.0.1.2-10.0.1.10,10.0.1.20
+.Pp
will only negotiate
.Ar 10.0.0.1
-as the local IP number, but will assign any of the given 10 IP
+as the local IP number, but may assign any of the given 10 IP
numbers to the peer. If the peer requests one of these numbers,
and that number is not already in use,
.Nm
will grant the peers request. This is useful if the peer wants
to re-establish a link using the same IP number as was previously
-allocated. If the peer requests an IP number that's either outside
+allocated (thus maintaining any existing tcp connections).
+.Pp
+If the peer requests an IP number that's either outside
of this range or is already in use,
.Nm
-will start by suggesting a random unused IP number from the range.
-If the peer doesn't subsequently agree,
-.Nm
-will suggest each of the other numbers in succession until a number
-is chosen or until too many IPCP Configure Requests have been sent.
+will suggest a random unused IP number from the range.
.Pp
If
.Ar triggeraddr
@@ -2181,7 +2830,11 @@ is specified, it is used in place of
.Ar myaddr
in the initial IPCP negotiation. However, only an address in the
.Ar myaddr
-range will be accepted.
+range will be accepted. This is useful when negotiating with some
+.Dv PPP
+implementations that will not assign an IP number unless their peer
+requests
+.Ar 0.0.0.0 .
.Pp
It should be noted that in
.Fl auto
@@ -2190,71 +2843,94 @@ mode,
will configure the interface immediately upon reading the
.Dq set ifaddr
line in the config file. In any other mode, these values are just
-used for the IPCP negotiations, and the interface isn't configured
-until the IPCP layer is up. As a result, it is impossible
-.Pq or at least unwise
-to use the
-.Dq add
-command in
-.Pa ppp.conf
-unless using
-.Fl auto
-mode (the
-.Pa ppp.linkup
-file should be used instead). Use
-.Dq allow mode auto
-to restrict the current profile to
-.Fl auto
-mode only.
+used for IPCP negotiations, and the interface isn't configured
+until the IPCP layer is up.
.Pp
-Note also that the
-.Ar hisaddr
-argument may be overridden in the
+Note that the
+.Ar HISADDR
+argument may be overridden by the third field in the
.Pa ppp.secret
-file once the client has authenticated themself. Refer to the
+file once the client has authenticated themself
+.Pq if PAP or CHAP are Dq enabled .
+Refer to the
.Em AUTHENTICATING INCOMING CONNECTIONS
section for details.
-.It set loopback on|off
-When set to
-.Ar on
-(the default),
-.Nm
-will automatically loop back packets being sent
-out with a destination address equal to that of the
-.Em PPP
-interface. If set to
-.Ar off ,
-.Nm
-will send the packet, probably resulting in an ICMP redirect from
-the other end.
-.It set log [local] [+|-]value...
+.Pp
+In all cases, if the interface is already configured,
+.Nm
+will try to maintain the interface IP numbers so that any existing
+bound sockets will remain valid.
+.It set ccpretry Ar period
+.It set chapretry Ar period
+.It set ipcpretry Ar period
+.It set lcpretry Ar period
+.It set papretry Ar period
+These commands set the number of seconds that
+.Nm
+will wait before resending Finite State Machine (FSM) Request packets.
+The default
+.Ar period
+for all FSMs is 3 seconds (which should suffice in most cases).
+.It set log [local] [+|-] Ns Ar value...
This command allows the adjustment of the current log level. Refer
to the Logging Facility section for further details.
-.It set login chat-script
+.It set login Ar chat-script
This
.Ar chat-script
compliments the dial-script. If both are specified, the login
script will be executed after the dial script. Escape sequences
available in the dial script are also available here.
-.It set mru value
-The default MRU is 1500. If it is increased, the other side *may*
-increase its mtu. There is no use decreasing the MRU to below the
-default as the
+.It set lqrperiod Ar frequency
+This command sets the
+.Ar frequency
+in seconds at which
+.Em LQR
+or
+.Em ECHO LQR
+packets are sent. The default is 30 seconds. You must also use the
+.Dq enable lqr
+command if you wish to send LQR requests to the peer.
+.It set mode Ar interactive|auto|ddial|background
+This command allows you to change the
+.Sq mode
+of the specified link. This is normally only useful in multilink mode,
+but may also be used in unilink mode.
+.Pp
+It is not possible to change a link that is
+.Sq direct
+or
+.Sq dedicated .
+.It set mrru Ar value
+Setting this option enables Multilink PPP negotiations, also known as
+Multilink Protocol or MP. There is no default MRRU (Maximum
+Reconstructed Receive Unit) value.
+.Em PPP
+protocol *must* be able to accept packets of at
+least 1500 octets.
+.It set mru Ar value
+The default MRU (Maximum Receive Unit) is 1500. If it is increased, the
+other side *may* increase its mtu. There is no point in decreasing the
+MRU to below the default as the
.Em PPP
protocol *must* be able to accept packets of at
least 1500 octets.
-.It set mtu value
-The default MTU is 1500. This may be increased by the MRU specified
-by the peer. It may only be subsequently decreased by this option.
-Increasing it is not valid as the peer is not necessarily able to
-receive the increased packet size.
-.It set ns x.x.x.x y.y.y.y
-This option allows the setting of the Microsoft DNS servers that
-will be negotiated.
-.It set nbns x.x.x.x y.y.y.y
-This option allows the setting of the Microsoft NetBIOS DNS servers that
-will be negotiated.
-.It set openmode active|passive Op delay
+.It set mtu Ar value
+The default MTU is 1500. At negotiation time,
+.Nm
+will accept whatever MRU or MRRU that the peer wants (assuming it's
+not less than 296 bytes). If the MTU is set,
+.Nm
+will not accept MRU/MRRU values less that the set value. When
+negotiations are complete, the MTU is assigned to the interface, even
+if the peer requested a higher value MRU/MRRU. This can be useful for
+limiting your packet size (giving better bandwidth sharing at the expense
+of more header data).
+.It set nbns Op Ar x.x.x.x Op Ar y.y.y.y
+This option allows the setting of the Microsoft NetBIOS name server
+values to be returned at the peers request. If no values are given,
+.Nm
+will reject any such requests.
+.It set openmode active|passive Op Ar delay
By default,
.Ar openmode
is always
@@ -2274,7 +2950,7 @@ may be specified here in seconds.
.It set parity odd|even|none|mark
This allows the line parity to be set. The default value is
.Ar none .
-.It set phone telno[|telno]...[:telno[|telno]...]...
+.It set phone Ar telno[|telno]...[:telno[|telno]...]...
This allows the specification of the phone number to be used in
place of the \\\\T string in the dial and login chat scripts.
Multiple phone numbers may be given separated by a pipe (|) or
@@ -2289,7 +2965,7 @@ the maximum number of times specified by
below. In
.Fl background
mode, each number is attempted at most once.
-.It set reconnect timeout ntries
+.It set reconnect Ar timeout ntries
Should the line drop unexpectedly (due to loss of CD or LQR
failure), a connection will be re-established after the given
.Ar timeout .
@@ -2302,7 +2978,7 @@ defaults to zero. A value of
for
.Ar timeout
will result in a variable pause, somewhere between 0 and 30 seconds.
-.It set redial seconds[.nseconds] [attempts]
+.It set redial Ar seconds[.nseconds] [attempts]
.Nm Ppp
can be instructed to attempt to redial
.Ar attempts
@@ -2315,43 +2991,20 @@ is taken before dialing each number. A pause of
is taken before starting at the first number again. A value of
.Ar random
may be used here too.
-.It set stopped [LCPseconds [IPCPseconds [CCPseconds]]]
-If this option is set,
-.Nm
-will time out after the given FSM (Finite State Machine) has been in
-the stopped state for the given number of
-.Dq seconds .
-This option may be useful if you see
-.Nm
-failing to respond in the stopped state, or if you wish to
-.Dq set openmode passive
-and time out if the peer doesn't send a Configure Request within the
-given time. Use
-.Dq set log +lcp +ipcp +ccp
-to make
-.Nm
-log all state transitions.
-.Pp
-The default value is zero, where
-.Nm
-doesn't time out in the stopped state.
-.Pp
-This value should not be set to less than the openmode delay (see
-.Dq set openmode
-above).
-.It set server|socket TcpPort|LocalName|none [password] [mask]
+.It set server|socket Ar TcpPort|LocalName|none password Op Ar mask
This command tells
.Nm
to listen on the given socket or
.Sq diagnostic port
-for incoming command connections. This is not possible if
-.Nm
-is in interactive mode. The word
+for incoming command connections.
+.Pp
+The word
.Ar none
instructs
.Nm
-to close any existing socket. If you wish to specify a unix domain
-socket,
+to close any existing socket.
+.Pp
+If you wish to specify a unix domain socket,
.Ar LocalName
must be specified as an absolute file name, otherwise it is assumed
to be the name or number of a TCP port. You may specify the octal umask that
@@ -2364,14 +3017,22 @@ for umask details. Refer to
.Xr services 5
for details of how to translate TCP port names.
.Pp
-You may also specify the password that must be used by the client when
-connecting to this socket. If the password is not specified here,
-.Pa /etc/ppp/ppp.secret
-is searched for a machine name that's the same as your local host name
-without any domain suffix. Refer to
-.Xr hostname 1
-for further details. If a password is specified as the empty string,
-no password is required.
+You must also specify the password that must be entered by the client
+(using the
+.Dq passwd
+command above) when connecting to this socket. If the password is
+specified as an empty string, no password is required for connecting clients.
+.Pp
+When specifying a unix domain socket, the first
+.Dq %d
+sequence found in the socket name will be replaced with the current
+interface unit number. This is useful when you wish to use the same
+profile for more than one connection.
+.Pp
+In a similar manner TCP sockets may be prefixed with the
+.Dq +
+character, in which case the current interface unit number is added to
+the port number.
.Pp
When using
.Nm
@@ -2382,17 +3043,45 @@ command is the preferred mechanism of communications. Currently,
can also be used, but link encryption may be implemented in the future, so
.Xr telnet 1
should not be relied upon.
-.It set speed value
+.It set speed Ar value
This sets the speed of the serial device.
-.It set timeout idle [LQR [FSM-resend]]
-This command allows the setting of the idle timer, the LQR timer (if
-enabled) and the finite state machine
-.Pq FSM
-retry timer.
-.It set vj slots nslots
-This command sets the initial number of
-.Ar slots
-that
+.It set stopped Ar [LCPseconds [CCPseconds]]
+If this option is set,
+.Nm
+will time out after the given FSM (Finite State Machine) has been in
+the stopped state for the given number of
+.Dq seconds .
+This option may be useful if the peer sends a terminate request,
+but never actually closes the connection despite our sending a terminate
+acknowledgement. This is also useful if you wish to
+.Dq set openmode passive
+and time out if the peer doesn't send a Configure Request within the
+given time. Use
+.Dq set log +lcp +ccp
+to make
+.Nm
+log the appropriate state transitions.
+.Pp
+The default value is zero, where
+.Nm
+doesn't time out in the stopped state.
+.Pp
+This value should not be set to less than the openmode delay (see
+.Dq set openmode
+above).
+.It set timeout Ar idleseconds
+This command allows the setting of the idle timer. Refer to the
+section titled
+.Dq SETTING THE IDLE TIMER
+for further details.
+.It set vj slotcomp on|off
+This command tells
+.Nm
+whether it should attempt to negotiate VJ slot compression. By default,
+slot compression is turned
+.Ar on .
+.It set vj slots Ar nslots
+This command sets the initial number of slots that
.Nm
will try to negotiate with the peer when VJ compression is enabled (see the
.Sq enable
@@ -2403,23 +3092,16 @@ must be between
and
.Ar 16
inclusive.
-.It set vj slotcomp on|off
-This command tells
-.Nm
-whether it should attempt to negotiate VJ slot compression. By default,
-slot compression is turned
-.Ar on .
-.It set help|?
-This command gives a summary of available set commands.
.El
.Pp
-.It shell|! [command]
+.It shell|! Op Ar command
If
-.Dq command
+.Ar command
is not specified a shell is invoked according to the
.Dv SHELL
-environment variable. Otherwise, the given command is executed.
-Any of the pseudo arguments
+environment variable. Otherwise, the given
+.Ar command
+is executed. Any of the pseudo arguments
.Dv HISADDR ,
.Dv INTERFACE
and
@@ -2431,60 +3113,50 @@ that this command is executed in the foreground -
will not continue running until this process has exited. Use the
.Dv bg
command if you wish processing to happen in the background.
-.It show var
+.It show Ar var
This command allows the user to examine the following:
.Bl -tag -width 20
-.It show [adio]filter
-List the current rules for the given filter.
-.It show auth
-Show the current authname and encryption values. If you have built
-.Nm
-without DES support, the encryption value is not displayed as it will
-always be
-.Ar MD5 .
+.It show bundle
+Show the current bundle settings.
.It show ccp
-Show the current CCP statistics.
+Show the current CCP compression statistics.
.It show compress
-Show the current compress statistics.
+Show the current VJ compression statistics.
.It show escape
Show the current escape characters.
+.It show filter Op Ar name
+List the current rules for the given filter. If
+.Ar name
+is not specified, all filters are shown.
.It show hdlc
Show the current HDLC statistics.
+.It show help|?
+Give a summary of available show commands.
.It show ipcp
Show the current IPCP statistics.
.It show lcp
Show the current LCP statistics.
-.It show loopback
-Show the current loopback status.
+.It show [data]link
+Show high level link information.
+.It show links
+Show a list of available logical links.
.It show log
Show the current log values.
.It show mem
Show current memory statistics.
.It show modem
-Show current modem statistics.
-.It show mru
-Show the current MRU.
-.It show mtu
-Show the current MTU.
+Show low level link information.
.It show proto
Show current protocol totals.
-.It show reconnect
-Show the current reconnect values.
-.It show redial
-Show the current redial values.
-.It show stopped
-Show the current stopped timeouts.
.It show route
Show the current routing tables.
-.It show timeout
-Show the current timeout values.
-.It show msext
-Show the current Microsoft extension values.
+.It show stopped
+Show the current stopped timeouts.
+.It show timer
+Show the active alarm timers.
.It show version
Show the current version number of
.Nm ppp .
-.It show help|?
-Give a summary of available show commands.
.El
.Pp
.It term
@@ -2498,7 +3170,7 @@ automatically enables Packet Mode and goes back into command mode.
.El
.Pp
.Sh MORE DETAILS
-.Bl -bullet -compact
+.Bl -bullet
.It
Read the example configuration files. They are a good source of information.
.It
@@ -2509,7 +3181,16 @@ Use
.Dq set ?
and
.Dq set ? <var>
-commands.
+to get online information about what's available.
+.It
+The following urls contain useful information:
+.Bl -bullet -compact
+.It
+http://www.FreeBSD.org/FAQ/userppp.html
+.It
+http://www.FreeBSD.org/handbook/userppp.html
+.El
+.Pp
.El
.Pp
.Sh FILES
@@ -2566,34 +3247,56 @@ and
modes.
.It Pa /etc/services
Get port number if port number is using service name.
+.It Pa /var/run/ppp-authname-class-value
+In multilink mode, unix domain sockets are created using the peer
+authentication name
+.Pq Sq authname ,
+the peer endpoint discriminator class
+.Pq Sq class
+and the peer endpoint discriminator value
+.Pq Sq value .
+As the endpoint discriminator value may be a binary value, it is turned
+to HEX to determine the actual file name.
+.Pp
+This socket is used to pass links between different instances of
+.Nm ppp .
.El
.Pp
.Sh SEE ALSO
+.Xr adduser 8 ,
.Xr at 1 ,
.Xr chat 8 ,
.Xr crontab 5 ,
.Xr ftp 1 ,
.Xr getty 8 ,
+.Xr group 5 ,
.Xr gzip 1 ,
.Xr hostname 1 ,
.Xr inetd 8 ,
.Xr init 8 ,
.Xr login 1 ,
+.Xr named 8 ,
.Xr passwd 5 ,
.Xr ping 8 ,
.Xr pppctl 8 ,
.Xr pppd 8 ,
.Xr route 8 ,
+.Xr resolv.conf 5 ,
.Xr syslog 3 ,
.Xr syslog.conf 5 ,
.Xr syslogd 8 ,
.Xr tcpdump 1 ,
.Xr telnet 1 ,
.Xr traceroute 8 ,
-.Xr uucplock 3
+.Xr uucplock 3 ,
+.Xr vipw 8
.Sh HISTORY
This program was originally written by Toshiharu OHNO (tony-o@iij.ad.jp),
and was submitted to FreeBSD-2.0.5 by Atsushi Murai (amurai@spec.co.jp).
.Pp
-It has since been substantially modified by Brian Somers (brian@Awfulhak.org),
-and was ported to OpenBSD in November '97 (just after the 2.2 release).
+It was substantially modified during 1997 by Brian Somers
+(brian@Awfulhak.org), and was ported to OpenBSD in November that year
+(just after the 2.2 release).
+.Pp
+Most of the code was rewritten by Brian Somers in early 1998 when
+multilink ppp support was added.
diff --git a/usr.sbin/ppp/pred.c b/usr.sbin/ppp/pred.c
index d5ff543b656d..ccbf0737830a 100644
--- a/usr.sbin/ppp/pred.c
+++ b/usr.sbin/ppp/pred.c
@@ -26,26 +26,20 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pred.c,v 1.19 1997/12/21 12:11:08 brian Exp $
+ * $Id: pred.c,v 1.20.2.12 1998/05/01 19:25:40 brian Exp $
*/
-#include <sys/param.h>
-#include <netinet/in.h>
+#include <sys/types.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
-#include "defs.h"
-#include "loadalias.h"
-#include "vars.h"
#include "timer.h"
#include "fsm.h"
+#include "lqr.h"
#include "hdlc.h"
-#include "lcpproto.h"
#include "lcp.h"
#include "ccp.h"
#include "pred.h"
@@ -56,16 +50,16 @@
* A better hash function would result in additional compression,
* at the expense of time.
*/
-#define IHASH(x) do {iHash = (iHash << 4) ^ (x);} while(0)
-#define OHASH(x) do {oHash = (oHash << 4) ^ (x);} while(0)
+#define HASH(state, x) state->hash = (state->hash << 4) ^ (x)
#define GUESS_TABLE_SIZE 65536
-static unsigned short int iHash, oHash;
-static unsigned char *InputGuessTable;
-static unsigned char *OutputGuessTable;
+struct pred1_state {
+ u_short hash;
+ u_char dict[GUESS_TABLE_SIZE];
+};
static int
-compress(u_char * source, u_char * dest, int len)
+compress(struct pred1_state *state, u_char *source, u_char *dest, int len)
{
int i, bitmask;
unsigned char *flagdest, flags, *orgdest;
@@ -75,13 +69,13 @@ compress(u_char * source, u_char * dest, int len)
flagdest = dest++;
flags = 0; /* All guess wrong initially */
for (bitmask = 1, i = 0; i < 8 && len; i++, bitmask <<= 1) {
- if (OutputGuessTable[oHash] == *source) {
+ if (state->dict[state->hash] == *source) {
flags |= bitmask; /* Guess was right - don't output */
} else {
- OutputGuessTable[oHash] = *source;
+ state->dict[state->hash] = *source;
*dest++ = *source; /* Guess wrong, output char */
}
- OHASH(*source++);
+ HASH(state, *source++);
len--;
}
*flagdest = flags;
@@ -90,19 +84,17 @@ compress(u_char * source, u_char * dest, int len)
}
static void
-SyncTable(u_char * source, u_char * dest, int len)
+SyncTable(struct pred1_state *state, u_char * source, u_char * dest, int len)
{
-
while (len--) {
- if (InputGuessTable[iHash] != *source) {
- InputGuessTable[iHash] = *source;
- }
- IHASH(*dest++ = *source++);
+ if (state->dict[state->hash] != *source)
+ state->dict[state->hash] = *source;
+ HASH(state, *dest++ = *source++);
}
}
static int
-decompress(u_char * source, u_char * dest, int len)
+decompress(struct pred1_state *state, u_char * source, u_char * dest, int len)
{
int i, bitmask;
unsigned char flags, *orgdest;
@@ -113,157 +105,151 @@ decompress(u_char * source, u_char * dest, int len)
len--;
for (i = 0, bitmask = 1; i < 8; i++, bitmask <<= 1) {
if (flags & bitmask) {
- *dest = InputGuessTable[iHash]; /* Guess correct */
+ *dest = state->dict[state->hash]; /* Guess correct */
} else {
if (!len)
break; /* we seem to be really done -- cabo */
- InputGuessTable[iHash] = *source; /* Guess wrong */
+ state->dict[state->hash] = *source; /* Guess wrong */
*dest = *source++; /* Read from source */
len--;
}
- IHASH(*dest++);
+ HASH(state, *dest++);
}
}
return (dest - orgdest);
}
static void
-Pred1TermInput(void)
+Pred1Term(void *v)
{
- if (InputGuessTable != NULL) {
- free(InputGuessTable);
- InputGuessTable = NULL;
- }
+ struct pred1_state *state = (struct pred1_state *)v;
+ free(state);
}
static void
-Pred1TermOutput(void)
+Pred1ResetInput(void *v)
{
- if (OutputGuessTable != NULL) {
- free(OutputGuessTable);
- OutputGuessTable = NULL;
- }
+ struct pred1_state *state = (struct pred1_state *)v;
+ state->hash = 0;
+ memset(state->dict, '\0', sizeof state->dict);
+ log_Printf(LogCCP, "Predictor1: Input channel reset\n");
}
static void
-Pred1ResetInput(void)
+Pred1ResetOutput(void *v)
{
- iHash = 0;
- memset(InputGuessTable, '\0', GUESS_TABLE_SIZE);
- LogPrintf(LogCCP, "Predictor1: Input channel reset\n");
+ struct pred1_state *state = (struct pred1_state *)v;
+ state->hash = 0;
+ memset(state->dict, '\0', sizeof state->dict);
+ log_Printf(LogCCP, "Predictor1: Output channel reset\n");
}
-static void
-Pred1ResetOutput(void)
+static void *
+Pred1InitInput(struct lcp_opt *o)
{
- oHash = 0;
- memset(OutputGuessTable, '\0', GUESS_TABLE_SIZE);
- LogPrintf(LogCCP, "Predictor1: Output channel reset\n");
+ struct pred1_state *state;
+ state = (struct pred1_state *)malloc(sizeof(struct pred1_state));
+ if (state != NULL)
+ Pred1ResetInput(state);
+ return state;
}
-static int
-Pred1InitInput(void)
+static void *
+Pred1InitOutput(struct lcp_opt *o)
{
- if (InputGuessTable == NULL)
- if ((InputGuessTable = malloc(GUESS_TABLE_SIZE)) == NULL)
- return 0;
- Pred1ResetInput();
- return 1;
+ struct pred1_state *state;
+ state = (struct pred1_state *)malloc(sizeof(struct pred1_state));
+ if (state != NULL)
+ Pred1ResetOutput(state);
+ return state;
}
static int
-Pred1InitOutput(void)
-{
- if (OutputGuessTable == NULL)
- if ((OutputGuessTable = malloc(GUESS_TABLE_SIZE)) == NULL)
- return 0;
- Pred1ResetOutput();
- return 1;
-}
-
-static int
-Pred1Output(int pri, u_short proto, struct mbuf * bp)
+Pred1Output(void *v, struct ccp *ccp, struct link *l, int pri, u_short proto,
+ struct mbuf *bp)
{
+ struct pred1_state *state = (struct pred1_state *)v;
struct mbuf *mwp;
u_char *cp, *wp, *hp;
int orglen, len;
u_char bufp[MAX_MTU + 2];
u_short fcs;
- orglen = plength(bp) + 2; /* add count of proto */
- mwp = mballoc((orglen + 2) / 8 * 9 + 12, MB_HDLCOUT);
+ orglen = mbuf_Length(bp) + 2; /* add count of proto */
+ mwp = mbuf_Alloc((orglen + 2) / 8 * 9 + 12, MB_HDLCOUT);
hp = wp = MBUF_CTOP(mwp);
cp = bufp;
*wp++ = *cp++ = orglen >> 8;
*wp++ = *cp++ = orglen & 0377;
*cp++ = proto >> 8;
*cp++ = proto & 0377;
- mbread(bp, cp, orglen - 2);
- fcs = HdlcFcs(INITFCS, bufp, 2 + orglen);
+ mbuf_Read(bp, cp, orglen - 2);
+ fcs = hdlc_Fcs(INITFCS, bufp, 2 + orglen);
fcs = ~fcs;
- len = compress(bufp + 2, wp, orglen);
- LogPrintf(LogDEBUG, "Pred1Output: orglen (%d) --> len (%d)\n", orglen, len);
- CcpInfo.uncompout += orglen;
+ len = compress(state, bufp + 2, wp, orglen);
+ log_Printf(LogDEBUG, "Pred1Output: orglen (%d) --> len (%d)\n", orglen, len);
+ ccp->uncompout += orglen;
if (len < orglen) {
*hp |= 0x80;
wp += len;
- CcpInfo.compout += len;
+ ccp->compout += len;
} else {
memcpy(wp, bufp + 2, orglen);
wp += orglen;
- CcpInfo.compout += orglen;
+ ccp->compout += orglen;
}
*wp++ = fcs & 0377;
*wp++ = fcs >> 8;
mwp->cnt = wp - MBUF_CTOP(mwp);
- HdlcOutput(PRI_NORMAL, PROTO_COMPD, mwp);
+ hdlc_Output(l, PRI_NORMAL, ccp_Proto(ccp), mwp);
return 1;
}
static struct mbuf *
-Pred1Input(u_short *proto, struct mbuf *bp)
+Pred1Input(void *v, struct ccp *ccp, u_short *proto, struct mbuf *bp)
{
+ struct pred1_state *state = (struct pred1_state *)v;
u_char *cp, *pp;
int len, olen, len1;
struct mbuf *wp;
u_char *bufp;
u_short fcs;
- wp = mballoc(MAX_MTU + 2, MB_IPIN);
+ wp = mbuf_Alloc(MAX_MTU + 2, MB_IPIN);
cp = MBUF_CTOP(bp);
- olen = plength(bp);
+ olen = mbuf_Length(bp);
pp = bufp = MBUF_CTOP(wp);
*pp++ = *cp & 0177;
len = *cp++ << 8;
*pp++ = *cp;
len += *cp++;
- CcpInfo.uncompin += len & 0x7fff;
+ ccp->uncompin += len & 0x7fff;
if (len & 0x8000) {
- len1 = decompress(cp, pp, olen - 4);
- CcpInfo.compin += olen;
+ len1 = decompress(state, cp, pp, olen - 4);
+ ccp->compin += olen;
len &= 0x7fff;
if (len != len1) { /* Error is detected. Send reset request */
- LogPrintf(LogCCP, "Pred1: Length error\n");
- CcpSendResetReq(&CcpFsm);
- pfree(bp);
- pfree(wp);
+ log_Printf(LogCCP, "Pred1: Length error\n");
+ ccp_SendResetReq(&ccp->fsm);
+ mbuf_Free(bp);
+ mbuf_Free(wp);
return NULL;
}
cp += olen - 4;
pp += len1;
} else {
- CcpInfo.compin += len;
- SyncTable(cp, pp, len);
+ ccp->compin += len;
+ SyncTable(state, cp, pp, len);
cp += len;
pp += len;
}
*pp++ = *cp++; /* CRC */
*pp++ = *cp++;
- fcs = HdlcFcs(INITFCS, bufp, wp->cnt = pp - bufp);
+ fcs = hdlc_Fcs(INITFCS, bufp, wp->cnt = pp - bufp);
if (fcs != GOODFCS)
- LogPrintf(LogDEBUG, "Pred1Input: fcs = 0x%04x (%s), len = 0x%x,"
+ log_Printf(LogDEBUG, "Pred1Input: fcs = 0x%04x (%s), len = 0x%x,"
" olen = 0x%x\n", fcs, (fcs == GOODFCS) ? "good" : "bad",
len, olen);
if (fcs == GOODFCS) {
@@ -279,19 +265,19 @@ Pred1Input(u_short *proto, struct mbuf *bp)
wp->cnt -= 2;
*proto = (*proto << 8) | *pp++;
}
- pfree(bp);
+ mbuf_Free(bp);
return wp;
} else {
- LogDumpBp(LogHDLC, "Bad FCS", wp);
- CcpSendResetReq(&CcpFsm);
- pfree(wp);
+ log_DumpBp(LogHDLC, "Bad FCS", wp);
+ ccp_SendResetReq(&ccp->fsm);
+ mbuf_Free(wp);
}
- pfree(bp);
+ mbuf_Free(bp);
return NULL;
}
static void
-Pred1DictSetup(u_short proto, struct mbuf * bp)
+Pred1DictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf * bp)
{
}
@@ -302,40 +288,44 @@ Pred1DispOpts(struct lcp_opt *o)
}
static void
-Pred1GetOpts(struct lcp_opt *o)
+Pred1InitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
{
- o->id = TY_PRED1;
o->len = 2;
}
static int
-Pred1SetOpts(struct lcp_opt *o)
+Pred1SetOptsOutput(struct lcp_opt *o)
{
- if (o->id != TY_PRED1 || o->len != 2) {
- Pred1GetOpts(o);
+ if (o->len != 2) {
+ o->len = 2;
return MODE_NAK;
}
return MODE_ACK;
}
+static int
+Pred1SetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
+{
+ return Pred1SetOptsOutput(o);
+}
+
const struct ccp_algorithm Pred1Algorithm = {
TY_PRED1,
- ConfPred1,
+ CCP_NEG_PRED1,
Pred1DispOpts,
{
- Pred1GetOpts,
- Pred1SetOpts,
+ Pred1SetOptsInput,
Pred1InitInput,
- Pred1TermInput,
+ Pred1Term,
Pred1ResetInput,
Pred1Input,
Pred1DictSetup
},
{
- Pred1GetOpts,
- Pred1SetOpts,
+ Pred1InitOptsOutput,
+ Pred1SetOptsOutput,
Pred1InitOutput,
- Pred1TermOutput,
+ Pred1Term,
Pred1ResetOutput,
Pred1Output
},
diff --git a/usr.sbin/ppp/prompt.c b/usr.sbin/ppp/prompt.c
new file mode 100644
index 000000000000..81d927be1d95
--- /dev/null
+++ b/usr.sbin/ppp/prompt.c
@@ -0,0 +1,522 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: prompt.c,v 1.1.2.30 1998/05/10 22:20:17 brian Exp $
+ */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "defs.h"
+#include "timer.h"
+#include "command.h"
+#include "log.h"
+#include "descriptor.h"
+#include "prompt.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "auth.h"
+#include "iplist.h"
+#include "throughput.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "async.h"
+#include "mbuf.h"
+#include "ccp.h"
+#include "link.h"
+#include "physical.h"
+#include "mp.h"
+#include "bundle.h"
+#include "chat.h"
+#include "chap.h"
+#include "datalink.h"
+#include "server.h"
+
+static void
+prompt_Display(struct prompt *p)
+{
+ static char shostname[MAXHOSTNAMELEN];
+ const char *pconnect, *pauth;
+
+ if (p->TermMode || !p->needprompt)
+ return;
+
+ p->needprompt = 0;
+
+ if (p->nonewline)
+ p->nonewline = 0;
+ else
+ fprintf(p->Term, "\n");
+
+ if (p->auth == LOCAL_AUTH)
+ pauth = " ON ";
+ else
+ pauth = " on ";
+
+ if (p->bundle->ncp.ipcp.fsm.state == ST_OPENED)
+ pconnect = "PPP";
+ else if (bundle_Phase(p->bundle) == PHASE_NETWORK)
+ pconnect = "PPp";
+ else if (bundle_Phase(p->bundle) == PHASE_AUTHENTICATE)
+ pconnect = "Ppp";
+ else
+ pconnect = "ppp";
+
+ if (*shostname == '\0') {
+ char *dot;
+
+ if (gethostname(shostname, sizeof shostname))
+ strcpy(shostname, "localhost");
+ else if ((dot = strchr(shostname, '.')))
+ *dot = '\0';
+ }
+
+ fprintf(p->Term, "%s%s%s> ", pconnect, pauth, shostname);
+ fflush(p->Term);
+}
+
+static int
+prompt_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
+{
+ struct prompt *p = descriptor2prompt(d);
+ int sets;
+
+ sets = 0;
+
+ if (!p->active)
+ return sets;
+
+ if (p->fd_in >= 0) {
+ if (r) {
+ FD_SET(p->fd_in, r);
+ log_Printf(LogTIMER, "prompt %s: fdset(r) %d\n", p->src.from, p->fd_in);
+ sets++;
+ }
+ if (e) {
+ FD_SET(p->fd_in, e);
+ log_Printf(LogTIMER, "prompt %s: fdset(e) %d\n", p->src.from, p->fd_in);
+ sets++;
+ }
+ if (sets && *n < p->fd_in + 1)
+ *n = p->fd_in + 1;
+ }
+
+ prompt_Display(p);
+
+ return sets;
+}
+
+static int
+prompt_IsSet(struct descriptor *d, const fd_set *fdset)
+{
+ struct prompt *p = descriptor2prompt(d);
+ return p->fd_in >= 0 && FD_ISSET(p->fd_in, fdset);
+}
+
+
+static void
+prompt_ShowHelp(struct prompt *p)
+{
+ prompt_Printf(p, "The following commands are available:\r\n");
+ prompt_Printf(p, " ~p\tEnter Packet mode\r\n");
+ prompt_Printf(p, " ~-\tDecrease log level\r\n");
+ prompt_Printf(p, " ~+\tIncrease log level\r\n");
+ prompt_Printf(p, " ~t\tShow timers\r\n");
+ prompt_Printf(p, " ~m\tShow memory map\r\n");
+ prompt_Printf(p, " ~.\tTerminate program\r\n");
+ prompt_Printf(p, " ~?\tThis help\r\n");
+}
+
+static void
+prompt_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ struct prompt *p = descriptor2prompt(d);
+ int n;
+ char ch;
+ static int ttystate;
+ char linebuff[LINE_LEN];
+
+ if (p->TermMode == NULL) {
+ n = read(p->fd_in, linebuff, sizeof linebuff - 1);
+ if (n > 0) {
+ if (linebuff[n-1] == '\n')
+ linebuff[--n] = '\0';
+ else
+ linebuff[n] = '\0';
+ p->nonewline = 1; /* Maybe command_Decode does a prompt */
+ prompt_Required(p);
+ if (n)
+ command_Decode(bundle, linebuff, n, p, p->src.from);
+ } else if (n <= 0) {
+ log_Printf(LogPHASE, "Client connection closed.\n");
+ prompt_Destroy(p, 0);
+ }
+ return;
+ }
+
+ switch (p->TermMode->state) {
+ case DATALINK_CLOSED:
+ prompt_Printf(p, "Link lost, terminal mode.\n");
+ prompt_TtyCommandMode(p);
+ p->nonewline = 0;
+ prompt_Required(p);
+ return;
+
+ case DATALINK_READY:
+ break;
+
+ case DATALINK_OPEN:
+ prompt_Printf(p, "\nPacket mode detected.\n");
+ prompt_TtyCommandMode(p);
+ p->nonewline = 0;
+ /* We'll get a prompt because of our status change */
+ /* Fall through */
+
+ default:
+ /* Wait 'till we're in a state we care about */
+ return;
+ }
+
+ /*
+ * We are in terminal mode, decode special sequences
+ */
+ n = read(p->fd_in, &ch, 1);
+ log_Printf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
+
+ if (n > 0) {
+ switch (ttystate) {
+ case 0:
+ if (ch == '~')
+ ttystate++;
+ else
+ if (physical_Write(p->TermMode->physical, &ch, n) < 0) {
+ log_Printf(LogERROR, "error writing to modem: %s\n", strerror(errno));
+ prompt_TtyCommandMode(p);
+ }
+ break;
+ case 1:
+ switch (ch) {
+ case '?':
+ prompt_ShowHelp(p);
+ break;
+ case 'p':
+ datalink_Up(p->TermMode, 0, 1);
+ prompt_Printf(p, "\nPacket mode.\n");
+ prompt_TtyCommandMode(p);
+ break;
+ case '.':
+ prompt_TtyCommandMode(p);
+ p->nonewline = 0;
+ prompt_Required(p);
+ break;
+ case 't':
+ timer_Show(0, p);
+ break;
+ case 'm':
+ mbuf_Show(NULL);
+ break;
+ default:
+ if (physical_Write(p->TermMode->physical, &ch, n) < 0) {
+ log_Printf(LogERROR, "error writing to modem: %s\n", strerror(errno));
+ prompt_TtyCommandMode(p);
+ }
+ break;
+ }
+ ttystate = 0;
+ break;
+ }
+ }
+}
+
+static void
+prompt_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ /* We never want to write here ! */
+ log_Printf(LogERROR, "prompt_Write: Internal error: Bad call !\n");
+}
+
+struct prompt *
+prompt_Create(struct server *s, struct bundle *bundle, int fd)
+{
+ struct prompt *p = (struct prompt *)malloc(sizeof(struct prompt));
+
+ if (p != NULL) {
+ p->desc.type = PROMPT_DESCRIPTOR;
+ p->desc.next = NULL;
+ p->desc.UpdateSet = prompt_UpdateSet;
+ p->desc.IsSet = prompt_IsSet;
+ p->desc.Read = prompt_Read;
+ p->desc.Write = prompt_Write;
+
+ if (fd == PROMPT_STD) {
+ p->fd_in = STDIN_FILENO;
+ p->fd_out = STDOUT_FILENO;
+ p->Term = stdout;
+ p->owner = NULL;
+ p->auth = LOCAL_AUTH;
+ p->src.type = "Controller";
+ strncpy(p->src.from, ttyname(p->fd_out), sizeof p->src.from - 1);
+ p->src.from[sizeof p->src.from - 1] = '\0';
+ tcgetattr(p->fd_in, &p->oldtio); /* Save original tty mode */
+ } else {
+ p->fd_in = p->fd_out = fd;
+ p->Term = fdopen(fd, "a+");
+ p->owner = s;
+ p->auth = *s->passwd ? LOCAL_NO_AUTH : LOCAL_AUTH;
+ p->src.type = "unknown";
+ *p->src.from = '\0';
+ }
+ p->TermMode = NULL;
+ p->nonewline = 1;
+ p->needprompt = 1;
+ p->active = 1;
+ p->bundle = bundle;
+ if (p->bundle)
+ bundle_RegisterDescriptor(p->bundle, &p->desc);
+ log_RegisterPrompt(p);
+ log_DiscardAllLocal(&p->logmask);
+ }
+
+ return p;
+}
+
+void
+prompt_Destroy(struct prompt *p, int verbose)
+{
+ if (p->Term != stdout) {
+ fclose(p->Term);
+ close(p->fd_in);
+ if (p->fd_out != p->fd_in)
+ close(p->fd_out);
+ if (verbose)
+ log_Printf(LogPHASE, "Client connection dropped.\n");
+ } else
+ prompt_TtyOldMode(p);
+
+ log_UnRegisterPrompt(p);
+ bundle_UnRegisterDescriptor(p->bundle, &p->desc);
+ free(p);
+}
+
+void
+prompt_Printf(struct prompt *p, const char *fmt,...)
+{
+ if (p && p->active) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(p->Term, fmt, ap);
+ fflush(p->Term);
+ va_end(ap);
+ p->nonewline = 1;
+ }
+}
+
+void
+prompt_vPrintf(struct prompt *p, const char *fmt, va_list ap)
+{
+ if (p && p->active) {
+ vfprintf(p->Term, fmt, ap);
+ fflush(p->Term);
+ p->nonewline = 1;
+ }
+}
+
+void
+prompt_TtyInit(struct prompt *p)
+{
+ int stat, fd = p ? p->fd_in : STDIN_FILENO;
+ struct termios newtio;
+
+ stat = fcntl(fd, F_GETFL, 0);
+ if (stat > 0) {
+ stat |= O_NONBLOCK;
+ fcntl(fd, F_SETFL, stat);
+ }
+
+ if (p)
+ newtio = p->oldtio;
+ else
+ tcgetattr(fd, &newtio);
+
+ newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
+ newtio.c_iflag = 0;
+ newtio.c_oflag &= ~OPOST;
+ newtio.c_cc[VEOF] = _POSIX_VDISABLE;
+ if (!p)
+ newtio.c_cc[VINTR] = _POSIX_VDISABLE;
+ newtio.c_cc[VMIN] = 1;
+ newtio.c_cc[VTIME] = 0;
+ newtio.c_cflag |= CS8;
+ tcsetattr(fd, TCSANOW, &newtio);
+ if (p)
+ p->comtio = newtio;
+}
+
+/*
+ * Set tty into command mode. We allow canonical input and echo processing.
+ */
+void
+prompt_TtyCommandMode(struct prompt *p)
+{
+ struct termios newtio;
+ int stat;
+
+ tcgetattr(p->fd_in, &newtio);
+ newtio.c_lflag |= (ECHO | ISIG | ICANON);
+ newtio.c_iflag = p->oldtio.c_iflag;
+ newtio.c_oflag |= OPOST;
+ tcsetattr(p->fd_in, TCSADRAIN, &newtio);
+
+ stat = fcntl(p->fd_in, F_GETFL, 0);
+ if (stat > 0) {
+ stat |= O_NONBLOCK;
+ fcntl(p->fd_in, F_SETFL, stat);
+ }
+
+ p->TermMode = NULL;
+}
+
+/*
+ * Set tty into terminal mode which is used while we invoke term command.
+ */
+void
+prompt_TtyTermMode(struct prompt *p, struct datalink *dl)
+{
+ int stat;
+
+ prompt_Printf(p, "Entering terminal mode on %s.\n", dl->name);
+ prompt_Printf(p, "Type `~?' for help.\n");
+
+ if (p->Term == stdout)
+ tcsetattr(p->fd_in, TCSADRAIN, &p->comtio);
+
+ stat = fcntl(p->fd_in, F_GETFL, 0);
+ if (stat > 0) {
+ stat &= ~O_NONBLOCK;
+ fcntl(p->fd_in, F_SETFL, stat);
+ }
+ p->TermMode = dl;
+}
+
+void
+prompt_TtyOldMode(struct prompt *p)
+{
+ int stat;
+
+ stat = fcntl(p->fd_in, F_GETFL, 0);
+ if (stat > 0) {
+ stat &= ~O_NONBLOCK;
+ fcntl(p->fd_in, F_SETFL, stat);
+ }
+
+ if (p->Term == stdout)
+ tcsetattr(p->fd_in, TCSADRAIN, &p->oldtio);
+}
+
+pid_t
+prompt_pgrp(struct prompt *p)
+{
+ return tcgetpgrp(p->fd_in);
+}
+
+int
+PasswdCommand(struct cmdargs const *arg)
+{
+ const char *pass;
+
+ if (!arg->prompt) {
+ log_Printf(LogWARN, "passwd: Cannot specify without a prompt\n");
+ return 0;
+ }
+
+ if (arg->prompt->owner == NULL) {
+ log_Printf(LogWARN, "passwd: Not required\n");
+ return 0;
+ }
+
+ if (arg->argc == arg->argn)
+ pass = "";
+ else if (arg->argc > arg->argn+1)
+ return -1;
+ else
+ pass = arg->argv[arg->argn];
+
+ if (!strcmp(arg->prompt->owner->passwd, pass))
+ arg->prompt->auth = LOCAL_AUTH;
+ else
+ arg->prompt->auth = LOCAL_NO_AUTH;
+
+ return 0;
+}
+
+static struct pppTimer bgtimer;
+
+static void
+prompt_TimedContinue(void *v)
+{
+ prompt_Continue((struct prompt *)v);
+}
+
+void
+prompt_Continue(struct prompt *p)
+{
+ timer_Stop(&bgtimer);
+ if (getpgrp() == prompt_pgrp(p)) {
+ prompt_TtyCommandMode(p);
+ p->nonewline = 1;
+ prompt_Required(p);
+ p->active = 1;
+ } else if (!p->owner) {
+ bgtimer.func = prompt_TimedContinue;
+ bgtimer.name = "prompt bg";
+ bgtimer.load = SECTICKS;
+ bgtimer.arg = p;
+ timer_Start(&bgtimer);
+ }
+}
+
+void
+prompt_Suspend(struct prompt *p)
+{
+ if (getpgrp() == prompt_pgrp(p)) {
+ prompt_TtyOldMode(p);
+ p->active = 0;
+ }
+}
diff --git a/usr.sbin/ppp/prompt.h b/usr.sbin/ppp/prompt.h
new file mode 100644
index 000000000000..53a5bfa1eff8
--- /dev/null
+++ b/usr.sbin/ppp/prompt.h
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: prompt.h,v 1.1.2.9 1998/05/01 19:25:44 brian Exp $
+ */
+
+#define LOCAL_AUTH 0x01
+#define LOCAL_NO_AUTH 0x02
+#define LOCAL_DENY 0x03
+#define LOCAL_CX 0x04 /* OR'd value - require a context */
+#define LOCAL_CX_OPT 0x08 /* OR'd value - optional context */
+
+struct server;
+struct datalink;
+struct bundle;
+struct cmdargs;
+
+struct prompt {
+ struct descriptor desc;
+ int fd_in, fd_out;
+ struct datalink *TermMode; /* The modem we're talking directly to */
+ FILE *Term; /* sits on top of fd_out */
+ u_char auth; /* Local Authorized status */
+ struct server *owner; /* who created me */
+ struct bundle *bundle; /* who I'm controlling */
+ unsigned nonewline : 1; /* need a newline before our prompt ? */
+ unsigned needprompt : 1; /* Show a prompt at the next UpdateSet() */
+ unsigned active : 1; /* Is the prompt active (^Z) */
+
+ struct {
+ const char *type; /* Type of connection */
+ char from[40]; /* Source of connection */
+ } src;
+
+ struct prompt *lognext; /* Maintained in log.c */
+ u_long logmask; /* Maintained in log.c */
+
+ struct termios oldtio; /* Original tty mode */
+ struct termios comtio; /* Command level tty mode */
+};
+
+#define descriptor2prompt(d) \
+ ((d)->type == PROMPT_DESCRIPTOR ? (struct prompt *)(d) : NULL)
+
+#define PROMPT_STD (-1)
+extern struct prompt *prompt_Create(struct server *, struct bundle *, int);
+extern void prompt_Destroy(struct prompt *, int);
+extern void prompt_Required(struct prompt *);
+#ifdef __GNUC__
+extern void prompt_Printf(struct prompt *, const char *, ...)
+ __attribute__ ((format (printf, 2, 3)));
+#else
+extern void prompt_Printf(struct prompt *, const char *, ...);
+#endif
+extern void prompt_vPrintf(struct prompt *, const char *, _BSD_VA_LIST_);
+#define PROMPT_DONT_WANT_INT 1
+#define PROMPT_WANT_INT 0
+extern void prompt_TtyInit(struct prompt *);
+extern void prompt_TtyCommandMode(struct prompt *);
+extern void prompt_TtyTermMode(struct prompt *, struct datalink *);
+extern void prompt_TtyOldMode(struct prompt *);
+extern pid_t prompt_pgrp(struct prompt *);
+extern int PasswdCommand(struct cmdargs const *);
+extern void prompt_Suspend(struct prompt *);
+extern void prompt_Continue(struct prompt *);
+#define prompt_IsTermMode(p, dl) ((p)->TermMode == (dl) ? 1 : 0)
+#define prompt_IsController(p) (!(p) || (p)->owner ? 0 : 1)
+#define prompt_Required(p) ((p)->needprompt = 1)
diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c
index b5b7653e9cc9..d87f87997b85 100644
--- a/usr.sbin/ppp/route.c
+++ b/usr.sbin/ppp/route.c
@@ -17,12 +17,11 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: route.c,v 1.43 1998/03/13 01:36:10 brian Exp $
+ * $Id: route.c,v 1.42.2.25 1998/05/16 21:19:00 brian Exp $
*
*/
-#include <sys/param.h>
-#include <sys/time.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include <net/if_types.h>
#include <net/route.h>
@@ -30,155 +29,42 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if_dl.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <errno.h>
-#include <machine/endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/ioctl.h>
#include <sys/sysctl.h>
-#include <unistd.h>
+#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
-#include "loadalias.h"
#include "defs.h"
-#include "vars.h"
-#include "id.h"
-#include "os.h"
-#include "ipcp.h"
#include "iplist.h"
+#include "timer.h"
+#include "throughput.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "mp.h"
+#include "bundle.h"
#include "route.h"
-
-static int IfIndex;
-
-struct rtmsg {
- struct rt_msghdr m_rtm;
- char m_space[64];
-};
-
-static int seqno;
-
-void
-OsSetRoute(int cmd,
- struct in_addr dst,
- struct in_addr gateway,
- struct in_addr mask,
- int bang)
-{
- struct rtmsg rtmes;
- int s, nb, wb;
- char *cp;
- const char *cmdstr;
- struct sockaddr_in rtdata;
-
- if (bang)
- cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!");
- else
- cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
- s = ID0socket(PF_ROUTE, SOCK_RAW, 0);
- if (s < 0) {
- LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno));
- return;
- }
- memset(&rtmes, '\0', sizeof rtmes);
- rtmes.m_rtm.rtm_version = RTM_VERSION;
- rtmes.m_rtm.rtm_type = cmd;
- rtmes.m_rtm.rtm_addrs = RTA_DST;
- rtmes.m_rtm.rtm_seq = ++seqno;
- rtmes.m_rtm.rtm_pid = getpid();
- rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
-
- memset(&rtdata, '\0', sizeof rtdata);
- rtdata.sin_len = 16;
- rtdata.sin_family = AF_INET;
- rtdata.sin_port = 0;
- rtdata.sin_addr = dst;
-
- cp = rtmes.m_space;
- memcpy(cp, &rtdata, 16);
- cp += 16;
- if (cmd == RTM_ADD) {
- if (gateway.s_addr == INADDR_ANY) {
- /* Add a route through the interface */
- struct sockaddr_dl dl;
- const char *iname;
- int ilen;
-
- iname = Index2Nam(IfIndex);
- ilen = strlen(iname);
- dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen;
- dl.sdl_family = AF_LINK;
- dl.sdl_index = IfIndex;
- dl.sdl_type = 0;
- dl.sdl_nlen = ilen;
- dl.sdl_alen = 0;
- dl.sdl_slen = 0;
- strncpy(dl.sdl_data, iname, sizeof dl.sdl_data);
-
- memcpy(cp, &dl, dl.sdl_len);
- cp += dl.sdl_len;
- rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
- } else {
- rtdata.sin_addr = gateway;
- memcpy(cp, &rtdata, 16);
- cp += 16;
- rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
- }
- }
-
- if (dst.s_addr == INADDR_ANY)
- mask.s_addr = INADDR_ANY;
-
- if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) {
- rtdata.sin_addr = mask;
- memcpy(cp, &rtdata, 16);
- cp += 16;
- rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
- }
-
- nb = cp - (char *) &rtmes;
- rtmes.m_rtm.rtm_msglen = nb;
- wb = ID0write(s, &rtmes, nb);
- if (wb < 0) {
- LogPrintf(LogTCPIP, "OsSetRoute failure:\n");
- LogPrintf(LogTCPIP, "OsSetRoute: Cmd = %s\n", cmdstr);
- LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst));
- LogPrintf(LogTCPIP, "OsSetRoute: Gateway = %s\n", inet_ntoa(gateway));
- LogPrintf(LogTCPIP, "OsSetRoute: Mask = %s\n", inet_ntoa(mask));
-failed:
- if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST ||
- (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) {
- if (!bang)
- LogPrintf(LogWARN, "Add route failed: %s already exists\n",
- inet_ntoa(dst));
- else {
- rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE;
- if ((wb = ID0write(s, &rtmes, nb)) < 0)
- goto failed;
- }
- } else if (cmd == RTM_DELETE &&
- (rtmes.m_rtm.rtm_errno == ESRCH ||
- (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) {
- if (!bang)
- LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n",
- inet_ntoa(dst));
- } else if (rtmes.m_rtm.rtm_errno == 0)
- LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr,
- inet_ntoa(dst), strerror(errno));
- else
- LogPrintf(LogWARN, "%s route failed: %s: %s\n",
- cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
- }
- LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n",
- wb, cmdstr, dst.s_addr, gateway.s_addr);
- close(s);
-}
+#include "prompt.h"
static void
-p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width)
+p_sockaddr(struct prompt *prompt, struct sockaddr *phost,
+ struct sockaddr *pmask, int width)
{
char buf[29];
struct sockaddr_in *ihost = (struct sockaddr_in *)phost;
@@ -238,7 +124,7 @@ p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width)
strcpy(buf, "??:??:??:??:??:??");
} else
sprintf(buf, "<IFT type %d>", dl->sdl_type);
- } else if (dl->sdl_slen)
+ } else if (dl->sdl_slen)
sprintf(buf, "<slen %d?>", dl->sdl_slen);
else
sprintf(buf, "link#%d", dl->sdl_index);
@@ -249,7 +135,7 @@ p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width)
break;
}
- fprintf(VarTerm, "%-*s ", width-1, buf);
+ prompt_Printf(prompt, "%-*s ", width-1, buf);
}
static struct bits {
@@ -290,21 +176,19 @@ static struct bits {
#endif
static void
-p_flags(u_long f, int max)
+p_flags(struct prompt *prompt, u_long f, int max)
{
- if (VarTerm) {
- char name[33], *flags;
- register struct bits *p = bits;
-
- if (max > sizeof name - 1)
- max = sizeof name - 1;
-
- for (flags = name; p->b_mask && flags - name < max; p++)
- if (p->b_mask & f)
- *flags++ = p->b_val;
- *flags = '\0';
- fprintf(VarTerm, "%-*.*s", max, max, name);
- }
+ char name[33], *flags;
+ register struct bits *p = bits;
+
+ if (max > sizeof name - 1)
+ max = sizeof name - 1;
+
+ for (flags = name; p->b_mask && flags - name < max; p++)
+ if (p->b_mask & f)
+ *flags++ = p->b_val;
+ *flags = '\0';
+ prompt_Printf(prompt, "%-*.*s", max, max, name);
}
const char *
@@ -328,7 +212,7 @@ Index2Nam(int idx)
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
- LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno));
+ log_Printf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno));
return "???";
}
if ((buf = malloc(needed)) == NULL)
@@ -352,7 +236,7 @@ Index2Nam(int idx)
else
ifs = (char **)malloc(sizeof(char *) * have);
if (!ifs) {
- LogPrintf(LogDEBUG, "Index2Nam: %s\n", strerror(errno));
+ log_Printf(LogDEBUG, "Index2Nam: %s\n", strerror(errno));
nifs = 0;
return "???";
}
@@ -365,20 +249,20 @@ Index2Nam(int idx)
if (nifs < ifm->ifm_index)
nifs = ifm->ifm_index;
}
- } else if (LogIsKept(LogDEBUG))
- LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n",
+ } else if (log_IsKept(LogDEBUG))
+ log_Printf(LogDEBUG, "Skipping out-of-range interface %d!\n",
ifm->ifm_index);
}
free(buf);
}
- if (LogIsKept(LogDEBUG) && !debug_done) {
+ if (log_IsKept(LogDEBUG) && !debug_done) {
int f;
- LogPrintf(LogDEBUG, "Found the following interfaces:\n");
+ log_Printf(LogDEBUG, "Found the following interfaces:\n");
for (f = 0; f < nifs; f++)
if (ifs[f] != NULL)
- LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]);
+ log_Printf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]);
debug_done = 1;
}
@@ -389,7 +273,7 @@ Index2Nam(int idx)
}
int
-ShowRoute(struct cmdargs const *arg)
+route_Show(struct cmdargs const *arg)
{
struct rt_msghdr *rtm;
struct sockaddr *sa_dst, *sa_gw, *sa_mask;
@@ -397,9 +281,6 @@ ShowRoute(struct cmdargs const *arg)
size_t needed;
int mib[6];
- if (!VarTerm)
- return 1;
-
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
@@ -407,7 +288,7 @@ ShowRoute(struct cmdargs const *arg)
mib[4] = NET_RT_DUMP;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
- LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno));
+ log_Printf(LogERROR, "route_Show: sysctl: estimate: %s\n", strerror(errno));
return (1);
}
if (needed < 0)
@@ -416,13 +297,14 @@ ShowRoute(struct cmdargs const *arg)
if (sp == NULL)
return (1);
if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
- LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno));
+ log_Printf(LogERROR, "route_Show: sysctl: getroute: %s\n", strerror(errno));
free(sp);
return (1);
}
ep = sp + needed;
- fprintf(VarTerm, "%-20s%-20sFlags Netif\n", "Destination", "Gateway");
+ prompt_Printf(arg->prompt, "%-20s%-20sFlags Netif\n",
+ "Destination", "Gateway");
for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *) cp;
wp = (char *)(rtm+1);
@@ -445,11 +327,11 @@ ShowRoute(struct cmdargs const *arg)
} else
sa_mask = NULL;
- p_sockaddr(sa_dst, sa_mask, 20);
- p_sockaddr(sa_gw, NULL, 20);
+ p_sockaddr(arg->prompt, sa_dst, sa_mask, 20);
+ p_sockaddr(arg->prompt, sa_gw, NULL, 20);
- p_flags(rtm->rtm_flags, 6);
- fprintf(VarTerm, " %s\n", Index2Nam(rtm->rtm_index));
+ p_flags(arg->prompt, rtm->rtm_flags, 6);
+ prompt_Printf(arg->prompt, " %s\n", Index2Nam(rtm->rtm_index));
}
free(sp);
return 0;
@@ -459,7 +341,7 @@ ShowRoute(struct cmdargs const *arg)
* Delete routes associated with our interface
*/
void
-DeleteIfRoutes(int all)
+route_IfDelete(struct bundle *bundle, int all)
{
struct rt_msghdr *rtm;
struct sockaddr *sa;
@@ -469,7 +351,7 @@ DeleteIfRoutes(int all)
char *sp, *cp, *ep;
int mib[6];
- LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex);
+ log_Printf(LogDEBUG, "route_IfDelete (%d)\n", bundle->ifp.Index);
sa_none.s_addr = INADDR_ANY;
mib[0] = CTL_NET;
@@ -479,7 +361,7 @@ DeleteIfRoutes(int all)
mib[4] = NET_RT_DUMP;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
- LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n",
+ log_Printf(LogERROR, "route_IfDelete: sysctl: estimate: %s\n",
strerror(errno));
return;
}
@@ -491,7 +373,7 @@ DeleteIfRoutes(int all)
return;
if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
- LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n",
+ log_Printf(LogERROR, "route_IfDelete: sysctl: getroute: %s\n",
strerror(errno));
free(sp);
return;
@@ -503,7 +385,8 @@ DeleteIfRoutes(int all)
* We do 2 passes. The first deletes all cloned routes. The second
* deletes all non-cloned routes. This is necessary to avoid
* potential errors from trying to delete route X after route Y where
- * route X was cloned from route Y (which is no longer there).
+ * route X was cloned from route Y (and is no longer there 'cos it
+ * may have gone with route Y).
*/
if (RTF_WASCLONED == 0 && pass == 0)
/* So we can't tell ! */
@@ -511,25 +394,25 @@ DeleteIfRoutes(int all)
for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *) cp;
sa = (struct sockaddr *) (rtm + 1);
- LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s),"
+ log_Printf(LogDEBUG, "route_IfDelete: addrs: %x, Netif: %d (%s),"
" flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index,
Index2Nam(rtm->rtm_index), rtm->rtm_flags,
inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY &&
- rtm->rtm_index == IfIndex &&
+ rtm->rtm_index == bundle->ifp.Index &&
(all || (rtm->rtm_flags & RTF_GATEWAY))) {
sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
sa = (struct sockaddr *)((char *)sa + sa->sa_len);
if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) {
if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
(pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
- LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass);
- OsSetRoute(RTM_DELETE, sa_dst, sa_none, sa_none, 0);
+ log_Printf(LogDEBUG, "route_IfDelete: Remove it (pass %d)\n", pass);
+ bundle_SetRoute(bundle, RTM_DELETE, sa_dst, sa_none, sa_none, 0);
} else
- LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass);
+ log_Printf(LogDEBUG, "route_IfDelete: Skip it (pass %d)\n", pass);
} else
- LogPrintf(LogDEBUG,
- "DeleteIfRoutes: Can't remove routes of %d family !\n",
+ log_Printf(LogDEBUG,
+ "route_IfDelete: Can't remove routes of %d family !\n",
sa->sa_family);
}
}
@@ -546,33 +429,133 @@ GetIfIndex(char *name)
idx = 1;
while (strcmp(got = Index2Nam(idx), "???"))
if (!strcmp(got, name))
- return IfIndex = idx;
+ return idx;
else
idx++;
return -1;
}
-struct in_addr
-ChooseHisAddr(const struct in_addr gw)
+void
+route_Change(struct bundle *bundle, struct sticky_route *r,
+ struct in_addr me, struct in_addr peer)
+{
+ struct in_addr none, del;
+
+ none.s_addr = INADDR_ANY;
+ for (; r; r = r->next) {
+ if ((r->type & ROUTE_DSTMYADDR) && r->dst.s_addr != me.s_addr) {
+ del.s_addr = r->dst.s_addr & r->mask.s_addr;
+ bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1);
+ r->dst = me;
+ if (r->type & ROUTE_GWHISADDR)
+ r->gw = peer;
+ } else if ((r->type & ROUTE_DSTHISADDR) && r->dst.s_addr != peer.s_addr) {
+ del.s_addr = r->dst.s_addr & r->mask.s_addr;
+ bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1);
+ r->dst = peer;
+ if (r->type & ROUTE_GWHISADDR)
+ r->gw = peer;
+ } else if ((r->type & ROUTE_GWHISADDR) && r->gw.s_addr != peer.s_addr)
+ r->gw = peer;
+ bundle_SetRoute(bundle, RTM_ADD, r->dst, r->gw, r->mask, 1);
+ }
+}
+
+void
+route_Clean(struct bundle *bundle, struct sticky_route *r)
+{
+ struct in_addr none, del;
+
+ none.s_addr = INADDR_ANY;
+ for (; r; r = r->next) {
+ del.s_addr = r->dst.s_addr & r->mask.s_addr;
+ bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1);
+ }
+}
+
+void
+route_Add(struct sticky_route **rp, int type, struct in_addr dst,
+ struct in_addr mask, struct in_addr gw)
+{
+ if (type != ROUTE_STATIC) {
+ struct sticky_route *r;
+ int dsttype = type & ROUTE_DSTANY;
+
+ r = NULL;
+ while (*rp) {
+ if ((dsttype && dsttype == ((*rp)->type & ROUTE_DSTANY)) ||
+ (!dsttype && (*rp)->dst.s_addr == dst.s_addr)) {
+ r = *rp;
+ *rp = r->next;
+ } else
+ rp = &(*rp)->next;
+ }
+
+ if (!r)
+ r = (struct sticky_route *)malloc(sizeof(struct sticky_route));
+ r->type = type;
+ r->next = NULL;
+ r->dst = dst;
+ r->mask = mask;
+ r->gw = gw;
+ *rp = r;
+ }
+}
+
+void
+route_Delete(struct sticky_route **rp, int type, struct in_addr dst)
{
- struct in_addr try;
- int f;
-
- for (f = 0; f < DefHisChoice.nItems; f++) {
- try = iplist_next(&DefHisChoice);
- LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n",
- f, inet_ntoa(try));
- if (OsTrySetIpaddress(gw, try) == 0) {
- LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n",
- inet_ntoa(try));
+ struct sticky_route *r;
+ int dsttype = type & ROUTE_DSTANY;
+
+ for (; *rp; rp = &(*rp)->next) {
+ if ((dsttype && dsttype == ((*rp)->type & ROUTE_DSTANY)) ||
+ (!dsttype && dst.s_addr == ((*rp)->dst.s_addr & (*rp)->mask.s_addr))) {
+ r = *rp;
+ *rp = r->next;
+ free(r);
break;
}
}
+}
+
+void
+route_DeleteAll(struct sticky_route **rp)
+{
+ struct sticky_route *r, *rn;
- if (f == DefHisChoice.nItems) {
- LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
- try.s_addr = INADDR_ANY;
+ for (r = *rp; r; r = rn) {
+ rn = r->next;
+ free(r);
}
+ *rp = NULL;
+}
- return try;
+void
+route_ShowSticky(struct prompt *p, struct sticky_route *r)
+{
+ int def;
+
+ prompt_Printf(p, "Sticky routes:\n");
+ for (; r; r = r->next) {
+ def = r->dst.s_addr == INADDR_ANY && r->mask.s_addr == INADDR_ANY;
+
+ prompt_Printf(p, " add ");
+ if (r->type & ROUTE_DSTMYADDR)
+ prompt_Printf(p, "MYADDR");
+ else if (r->type & ROUTE_DSTHISADDR)
+ prompt_Printf(p, "HISADDR");
+ else if (!def)
+ prompt_Printf(p, "%s", inet_ntoa(r->dst));
+
+ if (def)
+ prompt_Printf(p, "default ");
+ else
+ prompt_Printf(p, " %s ", inet_ntoa(r->mask));
+
+ if (r->type & ROUTE_GWHISADDR)
+ prompt_Printf(p, "HISADDR\n");
+ else
+ prompt_Printf(p, "%s\n", inet_ntoa(r->gw));
+ }
}
diff --git a/usr.sbin/ppp/route.h b/usr.sbin/ppp/route.h
index 133848755b68..cd0877d5c496 100644
--- a/usr.sbin/ppp/route.h
+++ b/usr.sbin/ppp/route.h
@@ -17,13 +17,37 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: route.h,v 1.9 1997/12/30 02:45:48 brian Exp $
+ * $Id: route.h,v 1.10.2.6 1998/05/05 23:30:13 brian Exp $
*
*/
+struct bundle;
+struct cmdargs;
+
+#define ROUTE_STATIC 0
+#define ROUTE_DSTMYADDR 1
+#define ROUTE_DSTHISADDR 2
+#define ROUTE_DSTANY 3
+#define ROUTE_GWHISADDR 4 /* May be ORd with DST_MYADDR */
+
+struct sticky_route {
+ int type; /* ROUTE_* value (not _STATIC) */
+ struct sticky_route *next; /* next in list */
+
+ struct in_addr dst;
+ struct in_addr mask;
+ struct in_addr gw;
+};
+
extern int GetIfIndex(char *);
-extern int ShowRoute(struct cmdargs const *);
-extern void OsSetRoute(int, struct in_addr, struct in_addr, struct in_addr,int);
-extern void DeleteIfRoutes(int);
-extern struct in_addr ChooseHisAddr(const struct in_addr);
+extern int route_Show(struct cmdargs const *);
+extern void route_IfDelete(struct bundle *, int);
extern const char *Index2Nam(int);
+extern void route_Change(struct bundle *, struct sticky_route *,
+ struct in_addr, struct in_addr);
+extern void route_Add(struct sticky_route **, int, struct in_addr,
+ struct in_addr, struct in_addr);
+extern void route_Delete(struct sticky_route **, int, struct in_addr);
+extern void route_DeleteAll(struct sticky_route **);
+extern void route_Clean(struct bundle *, struct sticky_route *);
+extern void route_ShowSticky(struct prompt *, struct sticky_route *);
diff --git a/usr.sbin/ppp/server.c b/usr.sbin/ppp/server.c
index f0146aa857e4..ae0ca6bbc9c0 100644
--- a/usr.sbin/ppp/server.c
+++ b/usr.sbin/ppp/server.c
@@ -23,113 +23,213 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: server.c,v 1.16 1998/01/21 02:15:27 brian Exp $
+ * $Id: server.c,v 1.16.2.19 1998/05/10 22:20:20 brian Exp $
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
-#include <sys/un.h>
+#include <termios.h>
#include <unistd.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
-#include "loadalias.h"
#include "defs.h"
-#include "vars.h"
+#include "descriptor.h"
#include "server.h"
#include "id.h"
+#include "prompt.h"
+#include "timer.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "throughput.h"
+#include "link.h"
+#include "mp.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "bundle.h"
-int server = -1;
+static int
+server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
+{
+ struct server *s = descriptor2server(d);
-static struct sockaddr_un ifsun;
-static char *rm;
+ if (r && s->fd >= 0) {
+ if (*n < s->fd + 1)
+ *n = s->fd + 1;
+ FD_SET(s->fd, r);
+ log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd);
+ return 1;
+ }
+ return 0;
+}
-int
-ServerLocalOpen(const char *name, mode_t mask)
+static int
+server_IsSet(struct descriptor *d, const fd_set *fdset)
{
- int s;
+ struct server *s = descriptor2server(d);
+ return s->fd >= 0 && FD_ISSET(s->fd, fdset);
+}
- if (VarLocalAuth == LOCAL_DENY) {
- LogPrintf(LogWARN, "Local: Can't open socket %s: No password "
- "in ppp.secret\n", name);
- return 1;
+#define IN_SIZE sizeof(struct sockaddr_in)
+#define UN_SIZE sizeof(struct sockaddr_in)
+#define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
+
+static void
+server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ struct server *s = descriptor2server(d);
+ char hisaddr[ADDRSZ];
+ struct sockaddr *sa = (struct sockaddr *)hisaddr;
+ struct sockaddr_in *in = (struct sockaddr_in *)hisaddr;
+ int ssize = ADDRSZ, wfd;
+ struct prompt *p;
+
+ wfd = accept(s->fd, sa, &ssize);
+ if (wfd < 0) {
+ log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno));
+ return;
}
- if (mode & MODE_INTER) {
- LogPrintf(LogWARN, "Local: Can't open socket in interactive mode\n");
- return 1;
+ switch (sa->sa_family) {
+ case AF_LOCAL:
+ log_Printf(LogPHASE, "Connected to local client.\n");
+ break;
+
+ case AF_INET:
+ if (ntohs(in->sin_port) < 1024) {
+ log_Printf(LogALERT, "Rejected client connection from %s:%u"
+ "(invalid port number) !\n",
+ inet_ntoa(in->sin_addr), ntohs(in->sin_port));
+ close(wfd);
+ return;
+ }
+ log_Printf(LogPHASE, "Connected to client from %s:%u\n",
+ inet_ntoa(in->sin_addr), in->sin_port);
+ break;
+
+ default:
+ write(wfd, "Unrecognised access !\n", 22);
+ close(wfd);
+ return;
}
- memset(&ifsun, '\0', sizeof ifsun);
- ifsun.sun_len = strlen(name);
- if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
- LogPrintf(LogERROR, "Local: %s: Path too long\n", name);
+ if ((p = prompt_Create(s, bundle, wfd)) == NULL) {
+ write(wfd, "Connection refused.\n", 20);
+ close(wfd);
+ } else {
+ switch (sa->sa_family) {
+ case AF_LOCAL:
+ p->src.type = "local";
+ strncpy(p->src.from, s->rm, sizeof p->src.from - 1);
+ p->src.from[sizeof p->src.from - 1] = '\0';
+ break;
+ case AF_INET:
+ p->src.type = "tcp";
+ snprintf(p->src.from, sizeof p->src.from, "%s:%u",
+ inet_ntoa(in->sin_addr), in->sin_port);
+ break;
+ }
+ prompt_TtyCommandMode(p);
+ prompt_Required(p);
+ }
+}
+
+static void
+server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
+{
+ /* We never want to write here ! */
+ log_Printf(LogERROR, "server_Write: Internal error: Bad call !\n");
+}
+
+struct server server = {
+ {
+ SERVER_DESCRIPTOR,
+ NULL,
+ server_UpdateSet,
+ server_IsSet,
+ server_Read,
+ server_Write
+ },
+ -1
+};
+
+int
+server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask)
+{
+ int s;
+
+ if (server.rm && !strcmp(server.rm, name)) {
+ if (chmod(server.rm, mask))
+ log_Printf(LogERROR, "Local: chmod: %s\n", strerror(errno));
+ return 0;
+ }
+
+ memset(&server.ifsun, '\0', sizeof server.ifsun);
+ server.ifsun.sun_len = strlen(name);
+ if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) {
+ log_Printf(LogERROR, "Local: %s: Path too long\n", name);
return 2;
}
- ifsun.sun_family = AF_LOCAL;
- strcpy(ifsun.sun_path, name);
+ server.ifsun.sun_family = AF_LOCAL;
+ strcpy(server.ifsun.sun_path, name);
s = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
if (s < 0) {
- LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno));
+ log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno));
return 3;
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
if (mask != (mode_t)-1)
mask = umask(mask);
- if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) {
+ if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) {
if (mask != (mode_t)-1)
umask(mask);
- LogPrintf(LogERROR, "Local: bind: %s\n", strerror(errno));
- if (errno == EADDRINUSE && VarTerm)
- fprintf(VarTerm, "Wait for a while, then try again.\n");
+ log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno));
close(s);
return 4;
}
if (mask != (mode_t)-1)
umask(mask);
if (listen(s, 5) != 0) {
- LogPrintf(LogERROR, "Local: Unable to listen to socket - OS overload?\n");
+ log_Printf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n");
close(s);
ID0unlink(name);
return 5;
}
- ServerClose();
- server = s;
- rm = ifsun.sun_path;
- LogPrintf(LogPHASE, "Listening at local socket %s.\n", name);
+ server_Close(bundle);
+ server.fd = s;
+ server.rm = server.ifsun.sun_path;
+ log_Printf(LogPHASE, "Listening at local socket %s.\n", name);
return 0;
}
int
-ServerTcpOpen(int port)
+server_TcpOpen(struct bundle *bundle, int port)
{
struct sockaddr_in ifsin;
int s;
- if (VarLocalAuth == LOCAL_DENY) {
- LogPrintf(LogWARN, "Tcp: Can't open socket %d: No password "
- "in ppp.secret\n", port);
- return 6;
- }
-
- if (mode & MODE_INTER) {
- LogPrintf(LogWARN, "Tcp: Can't open socket in interactive mode\n");
- return 6;
- }
+ if (server.port == port)
+ return 0;
s = ID0socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
- LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
+ log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
return 7;
}
memset(&ifsin, '\0', sizeof ifsin);
@@ -138,32 +238,36 @@ ServerTcpOpen(int port)
ifsin.sin_port = htons(port);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
- LogPrintf(LogERROR, "Tcp: bind: %s\n", strerror(errno));
- if (errno == EADDRINUSE && VarTerm)
- fprintf(VarTerm, "Wait for a while, then try again.\n");
+ log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno));
close(s);
return 8;
}
if (listen(s, 5) != 0) {
- LogPrintf(LogERROR, "Tcp: Unable to listen to socket - OS overload?\n");
+ log_Printf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n");
close(s);
return 9;
}
- ServerClose();
- server = s;
- LogPrintf(LogPHASE, "Listening at port %d.\n", port);
+ server_Close(bundle);
+ server.fd = s;
+ server.port = port;
+ log_Printf(LogPHASE, "Listening at port %d.\n", port);
return 0;
}
-void
-ServerClose()
+int
+server_Close(struct bundle *bundle)
{
- if (server >= 0) {
- close(server);
- if (rm) {
- ID0unlink(rm);
- rm = 0;
+ if (server.fd >= 0) {
+ close(server.fd);
+ if (server.rm) {
+ ID0unlink(server.rm);
+ server.rm = NULL;
}
+ server.fd = -1;
+ server.port = 0;
+ /* Drop associated prompts */
+ bundle_DelPromptDescriptors(bundle, &server);
+ return 1;
}
- server = -1;
+ return 0;
}
diff --git a/usr.sbin/ppp/server.h b/usr.sbin/ppp/server.h
index c0598bde82d6..55052ab78028 100644
--- a/usr.sbin/ppp/server.h
+++ b/usr.sbin/ppp/server.h
@@ -23,11 +23,27 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: server.h,v 1.4.2.5 1998/05/01 19:25:52 brian Exp $
*/
-extern int server;
+struct bundle;
-extern int ServerLocalOpen(const char *, mode_t);
-extern int ServerTcpOpen(int);
-extern void ServerClose(void);
+struct server {
+ struct descriptor desc;
+ int fd;
+ char passwd[50];
+
+ struct sockaddr_un ifsun; /* local socket */
+ char *rm; /* Points to local socket path */
+
+ u_short port; /* tcp socket */
+};
+
+#define descriptor2server(d) \
+ ((d)->type == SERVER_DESCRIPTOR ? (struct server *)(d) : NULL)
+
+extern struct server server;
+
+extern int server_LocalOpen(struct bundle *, const char *, mode_t);
+extern int server_TcpOpen(struct bundle *, int);
+extern int server_Close(struct bundle *);
diff --git a/usr.sbin/ppp/sig.c b/usr.sbin/ppp/sig.c
index 3cf1a30b3e03..b79e7e9866f8 100644
--- a/usr.sbin/ppp/sig.c
+++ b/usr.sbin/ppp/sig.c
@@ -23,15 +23,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: sig.c,v 1.11 1997/12/21 12:11:08 brian Exp $
+ * $Id: sig.c,v 1.11.2.5 1998/05/01 19:25:56 brian Exp $
*/
#include <sys/types.h>
#include <signal.h>
-#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "sig.h"
@@ -54,13 +52,13 @@ signal_recorder(int sig)
*/
sig_type
-pending_signal(int sig, sig_type fn)
+sig_signal(int sig, sig_type fn)
{
sig_type Result;
if (sig <= 0 || sig > NSIG) {
/* Oops - we must be a bit out of date (too many sigs ?) */
- LogPrintf(LogALERT, "Eeek! %s:%s: I must be out of date!\n",
+ log_Printf(LogALERT, "Eeek! %s:%d: I must be out of date!\n",
__FILE__, __LINE__);
return signal(sig, fn);
}
@@ -80,7 +78,7 @@ pending_signal(int sig, sig_type fn)
/* Call the handlers for any pending signals */
void
-handle_signals()
+sig_Handle()
{
int sig;
int got;
diff --git a/usr.sbin/ppp/sig.h b/usr.sbin/ppp/sig.h
index 324fdfb2c86e..5b0a4f02aab3 100644
--- a/usr.sbin/ppp/sig.h
+++ b/usr.sbin/ppp/sig.h
@@ -23,13 +23,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: sig.h,v 1.11.2.1 1998/05/01 19:25:57 brian Exp $
*/
typedef void (*sig_type)(int);
/* Call this instead of signal() */
-extern sig_type pending_signal(int, sig_type);
+extern sig_type sig_signal(int, sig_type);
/* Call this when you want things to *actually* happen */
-extern void handle_signals(void);
+extern void sig_Handle(void);
diff --git a/usr.sbin/ppp/slcompress.c b/usr.sbin/ppp/slcompress.c
index 1678531b6b18..df9c8d6ced9f 100644
--- a/usr.sbin/ppp/slcompress.c
+++ b/usr.sbin/ppp/slcompress.c
@@ -17,41 +17,43 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: slcompress.c,v 1.14 1997/11/22 03:37:50 brian Exp $
+ * $Id: slcompress.c,v 1.15.2.11 1998/05/01 19:25:59 brian Exp $
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
+#include <sys/un.h>
#include <stdio.h>
#include <string.h>
+#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "slcompress.h"
-#include "loadalias.h"
-#include "vars.h"
-
-static struct slstat {
- int sls_packets; /* outbound packets */
- int sls_compressed; /* outbound compressed packets */
- int sls_searches; /* searches for connection state */
- int sls_misses; /* times couldn't find conn. state */
- int sls_uncompressedin; /* inbound uncompressed packets */
- int sls_compressedin; /* inbound compressed packets */
- int sls_errorin; /* inbound unknown type packets */
- int sls_tossed; /* inbound packets tossed because of error */
-} slstat;
-
-#define INCR(counter) slstat.counter++;
+#include "descriptor.h"
+#include "prompt.h"
+#include "timer.h"
+#include "fsm.h"
+#include "throughput.h"
+#include "iplist.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
void
sl_compress_init(struct slcompress * comp, int max_state)
@@ -129,7 +131,8 @@ sl_compress_init(struct slcompress * comp, int max_state)
u_char
sl_compress_tcp(struct mbuf * m,
struct ip * ip,
- struct slcompress * comp,
+ struct slcompress *comp,
+ struct slstat *slstat,
int compress_cid)
{
register struct cstate *cs = comp->last_cs->cs_next;
@@ -147,15 +150,15 @@ sl_compress_tcp(struct mbuf * m,
* the caller has already made sure the packet is IP proto TCP).
*/
if ((ip->ip_off & htons(0x3fff)) || m->cnt < 40) {
- LogPrintf(LogDEBUG, "??? 1 ip_off = %x, cnt = %d\n",
+ log_Printf(LogDEBUG, "??? 1 ip_off = %x, cnt = %d\n",
ip->ip_off, m->cnt);
- LogDumpBp(LogDEBUG, "", m);
+ log_DumpBp(LogDEBUG, "", m);
return (TYPE_IP);
}
th = (struct tcphdr *) & ((int *) ip)[hlen];
if ((th->th_flags & (TH_SYN | TH_FIN | TH_RST | TH_ACK)) != TH_ACK) {
- LogPrintf(LogDEBUG, "??? 2 th_flags = %x\n", th->th_flags);
- LogDumpBp(LogDEBUG, "", m);
+ log_Printf(LogDEBUG, "??? 2 th_flags = %x\n", th->th_flags);
+ log_DumpBp(LogDEBUG, "", m);
return (TYPE_IP);
}
@@ -166,10 +169,10 @@ sl_compress_tcp(struct mbuf * m,
* it's most likely to be used again & we don't have to do any reordering
* if it's used.
*/
- INCR(sls_packets)
- if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
- ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
- *(int *) th != ((int *) &cs->cs_ip)[cs->cs_ip.ip_hl]) {
+ slstat->sls_packets++;
+ if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
+ ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
+ *(int *) th != ((int *) &cs->cs_ip)[cs->cs_ip.ip_hl]) {
/*
* Wasn't the first -- search for it.
@@ -187,10 +190,10 @@ sl_compress_tcp(struct mbuf * m,
do {
lcs = cs;
cs = cs->cs_next;
- INCR(sls_searches)
- if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
- && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
- && *(int *) th == ((int *) &cs->cs_ip)[cs->cs_ip.ip_hl])
+ slstat->sls_searches++;
+ if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
+ && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
+ && *(int *) th == ((int *) &cs->cs_ip)[cs->cs_ip.ip_hl])
goto found;
} while (cs != lastcs);
@@ -201,7 +204,7 @@ sl_compress_tcp(struct mbuf * m,
* state points to the newest and we only need to set last_cs to update
* the lru linkage.
*/
- INCR(sls_misses)
+ slstat->sls_misses++;
comp->last_cs = lcs;
#define THOFFSET(th) (th->th_off)
hlen += th->th_off;
@@ -382,8 +385,8 @@ found:
*cp++ = deltaA >> 8;
*cp++ = deltaA;
memcpy(cp, new_seq, deltaS);
- INCR(sls_compressed)
- return (TYPE_COMPRESSED_TCP);
+ slstat->sls_compressed++;
+ return (TYPE_COMPRESSED_TCP);
/*
* Update connection state cs & send uncompressed packet ('uncompressed'
@@ -399,10 +402,8 @@ uncompressed:
int
-sl_uncompress_tcp(u_char ** bufp,
- int len,
- u_int type,
- struct slcompress * comp)
+sl_uncompress_tcp(u_char ** bufp, int len, u_int type,
+ struct slcompress *comp, struct slstat *slstat)
{
register u_char *cp;
register u_int hlen, changes;
@@ -414,7 +415,7 @@ sl_uncompress_tcp(u_char ** bufp,
case TYPE_UNCOMPRESSED_TCP:
ip = (struct ip *) * bufp;
- if (ip->ip_p >= MAX_STATES)
+ if (ip->ip_p >= MAX_VJ_STATES)
goto bad;
cs = &comp->rstate[comp->last_recv = ip->ip_p];
comp->flags &= ~SLF_TOSS;
@@ -434,8 +435,8 @@ sl_uncompress_tcp(u_char ** bufp,
memcpy(&cs->cs_ip, ip, hlen);
cs->cs_ip.ip_sum = 0;
cs->cs_hlen = hlen;
- INCR(sls_uncompressedin)
- return (len);
+ slstat->sls_uncompressedin++;
+ return (len);
default:
goto bad;
@@ -444,17 +445,17 @@ sl_uncompress_tcp(u_char ** bufp,
break;
}
/* We've got a compressed packet. */
- INCR(sls_compressedin)
- cp = *bufp;
+ slstat->sls_compressedin++;
+ cp = *bufp;
changes = *cp++;
- LogPrintf(LogDEBUG, "compressed: changes = %02x\n", changes);
+ log_Printf(LogDEBUG, "compressed: changes = %02x\n", changes);
if (changes & NEW_C) {
/*
* Make sure the state index is in range, then grab the state. If we have
* a good state index, clear the 'discard' flag.
*/
- if (*cp >= MAX_STATES || comp->last_recv == 255)
+ if (*cp >= MAX_VJ_STATES || comp->last_recv == 255)
goto bad;
comp->flags &= ~SLF_TOSS;
@@ -467,8 +468,8 @@ sl_uncompress_tcp(u_char ** bufp,
* the packet.
*/
if (comp->flags & SLF_TOSS) {
- INCR(sls_tossed)
- return (0);
+ slstat->sls_tossed++;
+ return (0);
}
}
cs = &comp->rstate[comp->last_recv];
@@ -507,7 +508,7 @@ sl_uncompress_tcp(u_char ** bufp,
if (changes & NEW_A)
DECODEL(th->th_ack)
if (changes & NEW_S) {
- LogPrintf(LogDEBUG, "NEW_S: %02x, %02x, %02x\n",
+ log_Printf(LogDEBUG, "NEW_S: %02x, %02x, %02x\n",
*cp, cp[1], cp[2]);
DECODEL(th->th_seq)
}
@@ -518,8 +519,8 @@ sl_uncompress_tcp(u_char ** bufp,
} else
cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
- LogPrintf(LogDEBUG, "Uncompress: id = %04x, seq = %08x\n",
- cs->cs_ip.ip_id, ntohl(th->th_seq));
+ log_Printf(LogDEBUG, "Uncompress: id = %04x, seq = %08lx\n",
+ cs->cs_ip.ip_id, (u_long)ntohl(th->th_seq));
/*
* At this point, cp points to the first byte of data in the packet. If
@@ -565,23 +566,25 @@ sl_uncompress_tcp(u_char ** bufp,
return (len);
bad:
comp->flags |= SLF_TOSS;
- INCR(sls_errorin)
- return (0);
+ slstat->sls_errorin++;
+ return (0);
}
int
-ReportCompress(struct cmdargs const *arg)
+sl_Show(struct cmdargs const *arg)
{
- if (!VarTerm)
- return 1;
-
- fprintf(VarTerm, "Out: %d (compress) / %d (total)",
- slstat.sls_compressed, slstat.sls_packets);
- fprintf(VarTerm, " %d (miss) / %d (search)\n",
- slstat.sls_misses, slstat.sls_searches);
- fprintf(VarTerm, "In: %d (compress), %d (uncompress)",
- slstat.sls_compressedin, slstat.sls_uncompressedin);
- fprintf(VarTerm, " %d (error), %d (tossed)\n",
- slstat.sls_errorin, slstat.sls_tossed);
+ prompt_Printf(arg->prompt, "VJ compression statistics:\n");
+ prompt_Printf(arg->prompt, " Out: %d (compress) / %d (total)",
+ arg->bundle->ncp.ipcp.vj.slstat.sls_compressed,
+ arg->bundle->ncp.ipcp.vj.slstat.sls_packets);
+ prompt_Printf(arg->prompt, " %d (miss) / %d (search)\n",
+ arg->bundle->ncp.ipcp.vj.slstat.sls_misses,
+ arg->bundle->ncp.ipcp.vj.slstat.sls_searches);
+ prompt_Printf(arg->prompt, " In: %d (compress), %d (uncompress)",
+ arg->bundle->ncp.ipcp.vj.slstat.sls_compressedin,
+ arg->bundle->ncp.ipcp.vj.slstat.sls_uncompressedin);
+ prompt_Printf(arg->prompt, " %d (error), %d (tossed)\n",
+ arg->bundle->ncp.ipcp.vj.slstat.sls_errorin,
+ arg->bundle->ncp.ipcp.vj.slstat.sls_tossed);
return 0;
}
diff --git a/usr.sbin/ppp/slcompress.h b/usr.sbin/ppp/slcompress.h
index 56328207863c..ebe7f1bd55d6 100644
--- a/usr.sbin/ppp/slcompress.h
+++ b/usr.sbin/ppp/slcompress.h
@@ -1,8 +1,6 @@
/*
* Definitions for tcp compression routines.
*
- * $Header: /home/ncvs/src/usr.sbin/ppp/slcompress.h,v 1.9 1997/10/26 01:03:46 brian Exp $
- *
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
*
@@ -18,14 +16,16 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: slcompress.h,v 1.9 1997/10/26 01:03:46 brian Exp $
+ * $Id: slcompress.h,v 1.10.2.5 1998/05/01 19:26:00 brian Exp $
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
-#define MAX_STATES 16 /* must be > 2 and < 256 */
-#define MAX_HDR 128 /* XXX 4bsd-ism: should really be 128 */
+#define MIN_VJ_STATES 3
+#define MAX_VJ_STATES 255
+#define DEF_VJ_STATES 16 /* must be > 2 and < 256 */
+#define MAX_HDR 128
/*
* Compressed packet format:
@@ -120,15 +120,30 @@ struct slcompress {
u_char last_recv; /* last rcvd conn. id */
u_char last_xmit; /* last sent conn. id */
u_short flags;
- struct cstate tstate[MAX_STATES]; /* xmit connection states */
- struct cstate rstate[MAX_STATES]; /* receive connection states */
+ struct cstate tstate[MAX_VJ_STATES]; /* xmit connection states */
+ struct cstate rstate[MAX_VJ_STATES]; /* receive connection states */
+};
+
+struct slstat {
+ int sls_packets; /* outbound packets */
+ int sls_compressed; /* outbound compressed packets */
+ int sls_searches; /* searches for connection state */
+ int sls_misses; /* times couldn't find conn. state */
+ int sls_uncompressedin; /* inbound uncompressed packets */
+ int sls_compressedin; /* inbound compressed packets */
+ int sls_errorin; /* inbound unknown type packets */
+ int sls_tossed; /* inbound packets tossed because of error */
};
/* flag values */
#define SLF_TOSS 1 /* tossing rcvd frames because of input err */
+struct mbuf;
+struct cmdargs;
+
extern void sl_compress_init(struct slcompress *, int);
-extern u_char sl_compress_tcp
- (struct mbuf *, struct ip *, struct slcompress *, int);
-extern int sl_uncompress_tcp(u_char **, int, u_int, struct slcompress *);
-extern int ReportCompress(struct cmdargs const *);
+extern u_char sl_compress_tcp(struct mbuf *, struct ip *, struct slcompress *,
+ struct slstat *, int);
+extern int sl_uncompress_tcp(u_char **, int, u_int, struct slcompress *,
+ struct slstat *);
+extern int sl_Show(struct cmdargs const *);
diff --git a/usr.sbin/ppp/systems.c b/usr.sbin/ppp/systems.c
index 0c975b7b5c8b..ec7cbfd9a359 100644
--- a/usr.sbin/ppp/systems.c
+++ b/usr.sbin/ppp/systems.c
@@ -17,12 +17,11 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: systems.c,v 1.34 1997/12/24 09:29:17 brian Exp $
+ * $Id: systems.c,v 1.35.2.10 1998/05/15 23:58:29 brian Exp $
*
* TODO:
*/
#include <sys/param.h>
-#include <netinet/in.h>
#include <ctype.h>
#include <pwd.h>
@@ -32,16 +31,9 @@
#include <unistd.h>
#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "id.h"
#include "defs.h"
-#include "timer.h"
-#include "fsm.h"
-#include "loadalias.h"
-#include "pathnames.h"
-#include "vars.h"
-#include "server.h"
#include "systems.h"
#define issep(ch) ((ch) == ' ' || (ch) == '\t')
@@ -55,7 +47,7 @@ OpenSecret(const char *file)
snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file);
fp = ID0fopen(line, "r");
if (fp == NULL)
- LogPrintf(LogWARN, "OpenSecret: Can't open %s.\n", line);
+ log_Printf(LogWARN, "OpenSecret: Can't open %s.\n", line);
return (fp);
}
@@ -164,18 +156,22 @@ DecodeCtrlCommand(char *line, char *arg)
return CTRL_UNKNOWN;
}
+/* Initialised in system_IsValid(), set in ReadSystem(), used by system_IsValid() */
+static int modeok;
static int userok;
+static int modereq;
int
AllowUsers(struct cmdargs const *arg)
{
+ /* arg->bundle may be NULL (see system_IsValid()) ! */
int f;
char *user;
userok = 0;
user = getlogin();
if (user && *user)
- for (f = 0; f < arg->argc; f++)
+ for (f = arg->argn; f < arg->argc; f++)
if (!strcmp("*", arg->argv[f]) || !strcmp(user, arg->argv[f])) {
userok = 1;
break;
@@ -184,57 +180,82 @@ AllowUsers(struct cmdargs const *arg)
return 0;
}
-static struct {
- int mode;
- const char *name;
-} modes[] = {
- { MODE_INTER, "interactive" },
- { MODE_AUTO, "auto" },
- { MODE_DIRECT, "direct" },
- { MODE_DEDICATED, "dedicated" },
- { MODE_DDIAL, "ddial" },
- { MODE_BACKGROUND, "background" },
- { ~0, "*" },
- { 0, 0 }
-};
-
-static int modeok;
-
int
AllowModes(struct cmdargs const *arg)
{
- int f;
- int m;
- int allowed;
+ /* arg->bundle may be NULL (see system_IsValid()) ! */
+ int f, mode, allowed;
allowed = 0;
- for (f = 0; f < arg->argc; f++) {
- for (m = 0; modes[m].mode; m++)
- if (!strcasecmp(modes[m].name, arg->argv[f])) {
- allowed |= modes[m].mode;
- break;
- }
- if (modes[m].mode == 0)
- LogPrintf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]);
+ for (f = arg->argn; f < arg->argc; f++) {
+ mode = Nam2mode(arg->argv[f]);
+ if (mode == PHYS_NONE || mode == PHYS_ALL)
+ log_Printf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]);
+ else
+ allowed |= mode;
}
- modeok = (mode | allowed) == allowed ? 1 : 0;
+ modeok = modereq & allowed ? 1 : 0;
return 0;
}
+static char *
+strip(char *line)
+{
+ int len;
+
+ len = strlen(line);
+ while (len && (line[len-1] == '\n' || line[len-1] == '\r' ||
+ issep(line[len-1])))
+ line[--len] = '\0';
+
+ while (issep(*line))
+ line++;
+
+ if (*line == '#')
+ *line = '\0';
+
+ return line;
+}
+
+static int
+xgets(char *buf, int buflen, FILE *fp)
+{
+ int len, n;
+
+ n = 0;
+ while (fgets(buf, buflen-1, fp)) {
+ n++;
+ buf[buflen-1] = '\0';
+ len = strlen(buf);
+ while (len && (buf[len-1] == '\n' || buf[len-1] == '\r'))
+ buf[--len] = '\0';
+ if (len && buf[len-1] == '\\') {
+ buf += len - 1;
+ buflen -= len - 1;
+ if (!buflen) /* No buffer space */
+ break;
+ } else
+ break;
+ }
+ return n;
+}
+
static int
-ReadSystem(const char *name, const char *file, int doexec)
+ReadSystem(struct bundle *bundle, const char *name, const char *file,
+ int doexec, struct prompt *prompt)
{
FILE *fp;
char *cp, *wp;
int n, len;
- u_char olauth;
char line[LINE_LEN];
char filename[MAXPATHLEN];
int linenum;
int argc;
char **argv;
int allowcmd;
+ int indent;
+ char arg[LINE_LEN];
if (*file == '/')
snprintf(filename, sizeof filename, "%s", file);
@@ -242,73 +263,70 @@ ReadSystem(const char *name, const char *file, int doexec)
snprintf(filename, sizeof filename, "%s/%s", _PATH_PPP, file);
fp = ID0fopen(filename, "r");
if (fp == NULL) {
- LogPrintf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename);
+ log_Printf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename);
return (-1);
}
- LogPrintf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename);
+ log_Printf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename);
linenum = 0;
- while (fgets(line, sizeof line, fp)) {
- linenum++;
- cp = line;
+ while ((n = xgets(line, sizeof line, fp))) {
+ linenum += n;
+ if (issep(*line))
+ continue;
+
+ cp = strip(line);
+
switch (*cp) {
- case '#': /* comment */
+ case '\0': /* empty/comment */
break;
- case ' ':
- case '\t':
+
+ case '!':
+ switch (DecodeCtrlCommand(cp+1, arg)) {
+ case CTRL_INCLUDE:
+ log_Printf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg);
+ n = ReadSystem(bundle, name, arg, doexec, prompt);
+ log_Printf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg);
+ if (!n)
+ return 0; /* got it */
+ break;
+ default:
+ log_Printf(LogWARN, "%s: %s: Invalid command\n", filename, cp);
+ break;
+ }
break;
+
default:
- wp = strpbrk(cp, ":\n");
- if (wp == NULL) {
- LogPrintf(LogWARN, "Bad rule in %s (line %d) - missing colon.\n",
+ wp = strchr(cp, ':');
+ if (wp == NULL || wp[1] != '\0') {
+ log_Printf(LogWARN, "Bad rule in %s (line %d) - missing colon.\n",
filename, linenum);
- ServerClose();
- exit(1);
+ continue;
}
*wp = '\0';
- if (*cp == '!') {
- char arg[LINE_LEN];
- switch (DecodeCtrlCommand(cp+1, arg)) {
- case CTRL_INCLUDE:
- LogPrintf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg);
- n = ReadSystem(name, arg, doexec);
- LogPrintf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg);
- if (!n)
- return 0; /* got it */
- break;
- default:
- LogPrintf(LogWARN, "%s: %s: Invalid command\n", filename, cp);
- break;
+ cp = strip(cp); /* lose any spaces between the label and the ':' */
+
+ if (strcmp(cp, name) == 0) {
+ /* We're in business */
+ while ((n = xgets(line, sizeof line, fp))) {
+ linenum += n;
+ indent = issep(*line);
+ cp = strip(line);
+
+ if (*cp == '\0') /* empty / comment */
+ continue;
+
+ if (!indent) /* start of next section */
+ break;
+
+ len = strlen(cp);
+ command_Interpret(cp, len, &argc, &argv);
+ allowcmd = argc > 0 && !strcasecmp(*argv, "allow");
+ if ((!doexec && allowcmd) || (doexec && !allowcmd))
+ command_Run(bundle, argc, (char const *const *)argv, prompt, name);
}
- } else if (strcmp(cp, name) == 0) {
- while (fgets(line, sizeof line, fp)) {
- cp = line;
- if (issep(*cp)) {
- n = strspn(cp, " \t");
- cp += n;
- len = strlen(cp);
- if (!len || *cp == '#')
- continue;
- if (cp[len-1] == '\n')
- cp[--len] = '\0';
- if (!len)
- continue;
- InterpretCommand(cp, len, &argc, &argv);
- allowcmd = argc > 0 && !strcasecmp(*argv, "allow");
- if ((!doexec && allowcmd) || (doexec && !allowcmd)) {
- olauth = VarLocalAuth;
- if (VarLocalAuth == LOCAL_NO_AUTH)
- VarLocalAuth = LOCAL_AUTH;
- RunCommand(argc, (char const *const *)argv, name);
- VarLocalAuth = olauth;
- }
- } else if (*cp == '#' || *cp == '\n' || *cp == '\0') {
- continue;
- } else
- break;
- }
- fclose(fp);
- return (0);
+
+ fclose(fp); /* everything read - get out */
+ return 0;
}
break;
}
@@ -318,49 +336,28 @@ ReadSystem(const char *name, const char *file, int doexec)
}
int
-ValidSystem(const char *name)
+system_IsValid(const char *name, struct prompt *prompt, int mode)
{
+ /*
+ * Note: The ReadSystem() calls only result in calls to the Allow*
+ * functions. arg->bundle will be set to NULL for these commands !
+ */
if (ID0realuid() == 0)
return userok = modeok = 1;
userok = 0;
modeok = 1;
- ReadSystem("default", CONFFILE, 0);
+ modereq = mode;
+ ReadSystem(NULL, "default", CONFFILE, 0, prompt);
if (name != NULL)
- ReadSystem(name, CONFFILE, 0);
+ ReadSystem(NULL, name, CONFFILE, 0, prompt);
return userok && modeok;
}
int
-SelectSystem(const char *name, const char *file)
+system_Select(struct bundle *bundle, const char *name, const char *file,
+ struct prompt *prompt)
{
userok = modeok = 1;
- return ReadSystem(name, file, 1);
-}
-
-int
-LoadCommand(struct cmdargs const *arg)
-{
- const char *name;
-
- if (arg->argc > 0)
- name = *arg->argv;
- else
- name = "default";
-
- if (!ValidSystem(name)) {
- LogPrintf(LogERROR, "%s: Label not allowed\n", name);
- return 1;
- } else if (SelectSystem(name, CONFFILE) < 0) {
- LogPrintf(LogWARN, "%s: label not found.\n", name);
- return -1;
- } else
- SetLabel(arg->argc ? name : NULL);
- return 0;
-}
-
-int
-SaveCommand(struct cmdargs const *arg)
-{
- LogPrintf(LogWARN, "save command is not implemented (yet).\n");
- return 1;
+ modereq = PHYS_ALL;
+ return ReadSystem(bundle, name, file, 1, prompt);
}
diff --git a/usr.sbin/ppp/systems.h b/usr.sbin/ppp/systems.h
index e5d0bc34f54d..4ab115a2ace0 100644
--- a/usr.sbin/ppp/systems.h
+++ b/usr.sbin/ppp/systems.h
@@ -17,12 +17,17 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: systems.h,v 1.9 1997/11/11 22:58:14 brian Exp $
+ * $Id: systems.h,v 1.10.2.6 1998/05/15 23:58:30 brian Exp $
*
*/
-extern int SelectSystem(const char *, const char *);
-extern int ValidSystem(const char *);
+struct prompt;
+struct bundle;
+struct cmdargs;
+
+extern int system_Select(struct bundle *bundle, const char *, const char *,
+ struct prompt *);
+extern int system_IsValid(const char *, struct prompt *, int);
extern FILE *OpenSecret(const char *);
extern void CloseSecret(FILE *);
extern int AllowUsers(struct cmdargs const *);
diff --git a/usr.sbin/ppp/throughput.c b/usr.sbin/ppp/throughput.c
index 1901b5c9de63..6867e8793647 100644
--- a/usr.sbin/ppp/throughput.c
+++ b/usr.sbin/ppp/throughput.c
@@ -23,23 +23,21 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: throughput.c,v 1.4.4.9 1998/05/01 19:26:04 brian Exp $
*/
-#include <sys/param.h>
+#include <sys/types.h>
#include <stdio.h>
+#include <string.h>
+#include <termios.h>
#include <time.h>
-#include <netinet/in.h>
-#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "timer.h"
#include "throughput.h"
-#include "defs.h"
-#include "loadalias.h"
-#include "vars.h"
+#include "descriptor.h"
+#include "prompt.h"
void
throughput_init(struct pppThroughput *t)
@@ -50,26 +48,33 @@ throughput_init(struct pppThroughput *t)
for (f = 0; f < SAMPLE_PERIOD; f++)
t->SampleOctets[f] = 0;
t->OctetsPerSecond = t->BestOctetsPerSecond = t->nSample = 0;
+ memset(&t->Timer, '\0', sizeof t->Timer);
+ t->Timer.name = "throughput";
+ t->uptime = 0;
+ t->rolling = 0;
throughput_stop(t);
}
void
-throughput_disp(struct pppThroughput *t, FILE *f)
+throughput_disp(struct pppThroughput *t, struct prompt *prompt)
{
int secs_up;
secs_up = t->uptime ? time(NULL) - t->uptime : 0;
- fprintf(f, "Connect time: %d secs\n", secs_up);
+ prompt_Printf(prompt, "Connect time: %d secs\n", secs_up);
if (secs_up == 0)
secs_up = 1;
- fprintf(f, "%ld octets in, %ld octets out\n", t->OctetsIn, t->OctetsOut);
- if (Enabled(ConfThroughput)) {
- fprintf(f, " overall %5ld bytes/sec\n",
- (t->OctetsIn+t->OctetsOut)/secs_up);
- fprintf(f, " currently %5d bytes/sec\n", t->OctetsPerSecond);
- fprintf(f, " peak %5d bytes/sec\n", t->BestOctetsPerSecond);
+ prompt_Printf(prompt, "%ld octets in, %ld octets out\n",
+ t->OctetsIn, t->OctetsOut);
+ if (t->rolling) {
+ prompt_Printf(prompt, " overall %5ld bytes/sec\n",
+ (t->OctetsIn+t->OctetsOut)/secs_up);
+ prompt_Printf(prompt, " currently %5d bytes/sec\n", t->OctetsPerSecond);
+ prompt_Printf(prompt, " peak %5d bytes/sec\n",
+ t->BestOctetsPerSecond);
} else
- fprintf(f, "Overall %ld bytes/sec\n", (t->OctetsIn+t->OctetsOut)/secs_up);
+ prompt_Printf(prompt, "Overall %ld bytes/sec\n",
+ (t->OctetsIn+t->OctetsOut)/secs_up);
}
@@ -81,18 +86,18 @@ throughput_log(struct pppThroughput *t, int level, const char *title)
secs_up = t->uptime ? time(NULL) - t->uptime : 0;
if (title)
- LogPrintf(level, "%s: Connect time: %d secs: %ld octets in, %ld octets"
+ log_Printf(level, "%s: Connect time: %d secs: %ld octets in, %ld octets"
" out\n", title, secs_up, t->OctetsIn, t->OctetsOut);
else
- LogPrintf(level, "Connect time: %d secs: %ld octets in, %ld octets out\n",
+ log_Printf(level, "Connect time: %d secs: %ld octets in, %ld octets out\n",
secs_up, t->OctetsIn, t->OctetsOut);
if (secs_up == 0)
secs_up = 1;
- if (Enabled(ConfThroughput))
- LogPrintf(level, " total %ld bytes/sec, peak %d bytes/sec\n",
+ if (t->rolling)
+ log_Printf(level, " total %ld bytes/sec, peak %d bytes/sec\n",
(t->OctetsIn+t->OctetsOut)/secs_up, t->BestOctetsPerSecond);
else
- LogPrintf(level, " total %ld bytes/sec\n",
+ log_Printf(level, " total %ld bytes/sec\n",
(t->OctetsIn+t->OctetsOut)/secs_up);
}
}
@@ -103,8 +108,7 @@ throughput_sampler(void *v)
struct pppThroughput *t = (struct pppThroughput *)v;
u_long old;
- StopTimer(&t->Timer);
- t->Timer.state = TIMER_STOPPED;
+ timer_Stop(&t->Timer);
old = t->SampleOctets[t->nSample];
t->SampleOctets[t->nSample] = t->OctetsIn + t->OctetsOut;
@@ -114,28 +118,29 @@ throughput_sampler(void *v)
if (++t->nSample == SAMPLE_PERIOD)
t->nSample = 0;
- StartTimer(&t->Timer);
+ timer_Start(&t->Timer);
}
void
-throughput_start(struct pppThroughput *t)
+throughput_start(struct pppThroughput *t, const char *name, int rolling)
{
+ timer_Stop(&t->Timer);
throughput_init(t);
+ t->rolling = rolling ? 1 : 0;
time(&t->uptime);
- if (Enabled(ConfThroughput)) {
- t->Timer.state = TIMER_STOPPED;
+ if (t->rolling) {
t->Timer.load = SECTICKS;
t->Timer.func = throughput_sampler;
+ t->Timer.name = name;
t->Timer.arg = t;
- StartTimer(&t->Timer);
+ timer_Start(&t->Timer);
}
}
void
throughput_stop(struct pppThroughput *t)
{
- if (Enabled(ConfThroughput))
- StopTimer(&t->Timer);
+ timer_Stop(&t->Timer);
}
void
diff --git a/usr.sbin/ppp/throughput.h b/usr.sbin/ppp/throughput.h
index 6325d722dad6..7a2f065d2b1c 100644
--- a/usr.sbin/ppp/throughput.h
+++ b/usr.sbin/ppp/throughput.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: throughput.h,v 1.2.4.4 1998/04/16 00:26:19 brian Exp $
*/
#define SAMPLE_PERIOD 5
@@ -36,13 +36,14 @@ struct pppThroughput {
int OctetsPerSecond;
int BestOctetsPerSecond;
int nSample;
+ unsigned rolling : 1;
struct pppTimer Timer;
};
extern void throughput_init(struct pppThroughput *);
-extern void throughput_disp(struct pppThroughput *, FILE *);
+extern void throughput_disp(struct pppThroughput *, struct prompt *);
extern void throughput_log(struct pppThroughput *, int, const char *);
-extern void throughput_start(struct pppThroughput *);
+extern void throughput_start(struct pppThroughput *, const char *, int);
extern void throughput_stop(struct pppThroughput *);
extern void throughput_addin(struct pppThroughput *, int);
extern void throughput_addout(struct pppThroughput *, int);
diff --git a/usr.sbin/ppp/timer.c b/usr.sbin/ppp/timer.c
index fa53b3949f79..c8e41f1ff5fd 100644
--- a/usr.sbin/ppp/timer.c
+++ b/usr.sbin/ppp/timer.c
@@ -17,67 +17,68 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: timer.c,v 1.26 1997/12/29 22:23:52 brian Exp $
+ * $Id: timer.c,v 1.27.2.11 1998/05/08 01:15:18 brian Exp $
*
* TODO:
*/
-#include <signal.h>
-#ifdef SIGALRM
#include <errno.h>
-#endif
+#include <signal.h>
+#include <stdio.h>
#include <sys/time.h>
+#include <termios.h>
#include <unistd.h>
-#include "command.h"
-#include "mbuf.h"
#include "log.h"
#include "sig.h"
#include "timer.h"
+#include "descriptor.h"
+#include "prompt.h"
static struct pppTimer *TimerList = NULL;
static void StopTimerNoBlock(struct pppTimer *);
static void InitTimerService(void);
+static const char *
+tState2Nam(u_int state)
+{
+ static const char *StateNames[] = { "stopped", "running", "expired" };
+
+ if (state >= sizeof StateNames / sizeof StateNames[0])
+ return "unknown";
+ return StateNames[state];
+}
+
void
-StopTimer(struct pppTimer * tp)
+timer_Stop(struct pppTimer * tp)
{
-#ifdef SIGALRM
int omask;
omask = sigblock(sigmask(SIGALRM));
-#endif
StopTimerNoBlock(tp);
-#ifdef SIGALRM
sigsetmask(omask);
-#endif
}
void
-StartTimer(struct pppTimer * tp)
+timer_Start(struct pppTimer * tp)
{
struct pppTimer *t, *pt;
u_long ticks = 0;
-
-#ifdef SIGALRM
int omask;
omask = sigblock(sigmask(SIGALRM));
-#endif
- if (tp->state != TIMER_STOPPED) {
+ if (tp->state != TIMER_STOPPED)
StopTimerNoBlock(tp);
- }
+
if (tp->load == 0) {
- LogPrintf(LogDEBUG, "timer %x has 0 load!\n", tp);
+ log_Printf(LogTIMER, "%s timer[%p] has 0 load!\n", tp->name, tp);
sigsetmask(omask);
return;
}
pt = NULL;
for (t = TimerList; t; t = t->next) {
- LogPrintf(LogDEBUG, "StartTimer: %x(%d): ticks: %d, rest: %d\n",
- t, t->state, ticks, t->rest);
if (ticks + t->rest >= tp->load)
break;
ticks += t->rest;
@@ -86,8 +87,13 @@ StartTimer(struct pppTimer * tp)
tp->state = TIMER_RUNNING;
tp->rest = tp->load - ticks;
- LogPrintf(LogDEBUG, "StartTimer: Inserting %x before %x, rest = %d\n",
- tp, t, tp->rest);
+
+ if (t)
+ log_Printf(LogTIMER, "timer_Start: Inserting %s timer[%p] before %s "
+ "timer[%p], delta = %ld\n", tp->name, tp, t->name, t, tp->rest);
+ else
+ log_Printf(LogTIMER, "timer_Start: Inserting %s timer[%p]\n", tp->name, tp);
+
/* Insert given *tp just before *t */
tp->next = t;
if (pt) {
@@ -99,9 +105,7 @@ StartTimer(struct pppTimer * tp)
if (t)
t->rest -= tp->rest;
-#ifdef SIGALRM
sigsetmask(omask);
-#endif
}
static void
@@ -110,12 +114,10 @@ StopTimerNoBlock(struct pppTimer * tp)
struct pppTimer *t, *pt;
/*
- * A Running Timer should be removing TimerList, But STOPPED/EXPIRED is
- * already removing TimerList. So just marked as TIMER_STOPPED. Do not
- * change tp->enext!! (Might be Called by expired proc)
+ * A RUNNING timer must be removed from TimerList (->next list).
+ * A STOPPED timer isn't in any list, but may have a bogus [e]next field.
+ * An EXPIRED timer is in the ->enext list.
*/
- LogPrintf(LogDEBUG, "StopTimer: %x, next = %x state=%x\n",
- tp, tp->next, tp->state);
if (tp->state != TIMER_RUNNING) {
tp->next = NULL;
tp->state = TIMER_STOPPED;
@@ -130,24 +132,30 @@ StopTimerNoBlock(struct pppTimer * tp)
} else {
TimerList = t->next;
if (TimerList == NULL) /* Last one ? */
- TermTimerService(); /* Terminate Timer Service */
+ timer_TermService(); /* Terminate Timer Service */
}
if (t->next)
t->next->rest += tp->rest;
} else
- LogPrintf(LogERROR, "Oops, timer not found!!\n");
+ log_Printf(LogERROR, "Oops, %s timer not found!!\n", tp->name);
tp->next = NULL;
tp->state = TIMER_STOPPED;
}
static void
-TimerService()
+TimerService(void)
{
struct pppTimer *tp, *exp, *wt;
- if (LogIsKept(LogDEBUG))
- ShowTimers();
+ if (log_IsKept(LogTIMER)) {
+ static time_t t;
+ time_t n = time(NULL); /* Only show timers every second */
+
+ if (n > t)
+ timer_Show(LogTIMER, NULL);
+ t = n;
+ }
tp = TimerList;
if (tp) {
tp->rest--;
@@ -162,22 +170,19 @@ TimerService()
wt = tp->next;
tp->enext = exp;
exp = tp;
- LogPrintf(LogDEBUG, "TimerService: Add %x to exp\n", tp);
tp = wt;
} while (tp && (tp->rest == 0));
TimerList = tp;
if (TimerList == NULL) /* No timers ? */
- TermTimerService(); /* Terminate Timer Service */
- LogPrintf(LogDEBUG, "TimerService: next is %x(%d)\n",
- TimerList, TimerList ? TimerList->rest : 0);
+ timer_TermService(); /* Terminate Timer Service */
/*
* Process all expired timers.
*/
while (exp) {
#ifdef notdef
- StopTimer(exp);
+ timer_Stop(exp);
#endif
if (exp->func)
(*exp->func) (exp->arg);
@@ -193,73 +198,31 @@ TimerService()
}
void
-ShowTimers()
+timer_Show(int LogLevel, struct prompt *prompt)
{
struct pppTimer *pt;
-
- LogPrintf(LogDEBUG, "---- Begin of Timer Service List---\n");
- for (pt = TimerList; pt; pt = pt->next)
- LogPrintf(LogDEBUG, "%x: load = %d, rest = %d, state =%x\n",
- pt, pt->load, pt->rest, pt->state);
- LogPrintf(LogDEBUG, "---- End of Timer Service List ---\n");
-}
-
-#ifdef SIGALRM
-
-static void
-nointr_dosleep(u_int sec, u_int usec)
-{
- struct timeval to, st, et;
-
- gettimeofday(&st, NULL);
- et.tv_sec = st.tv_sec + sec;
- et.tv_usec = st.tv_usec + usec;
- to.tv_sec = sec;
- to.tv_usec = usec;
- for (;;) {
- if (select(0, NULL, NULL, NULL, &to) == 0 ||
- errno != EINTR) {
- break;
- } else {
- gettimeofday(&to, NULL);
- if (to.tv_sec > et.tv_sec + 1 ||
- (to.tv_sec == et.tv_sec + 1 && to.tv_usec > et.tv_usec) ||
- to.tv_sec < st.tv_sec ||
- (to.tv_sec == st.tv_sec && to.tv_usec < st.tv_usec)) {
- LogPrintf(LogWARN, "Clock adjusted between %d and %d seconds "
- "during sleep !\n",
- to.tv_sec - st.tv_sec, sec + to.tv_sec - st.tv_sec);
- st.tv_sec = to.tv_sec;
- st.tv_usec = to.tv_usec;
- et.tv_sec = st.tv_sec + sec;
- et.tv_usec = st.tv_usec + usec;
- to.tv_sec = sec;
- to.tv_usec = usec;
- } else if (to.tv_sec > et.tv_sec ||
- (to.tv_sec == et.tv_sec && to.tv_usec >= et.tv_usec)) {
- break;
- } else {
- to.tv_sec = et.tv_sec - to.tv_sec;
- if (et.tv_usec < to.tv_usec) {
- to.tv_sec--;
- to.tv_usec = 1000000 + et.tv_usec - to.tv_usec;
- } else
- to.tv_usec = et.tv_usec - to.tv_usec;
- }
- }
+ int rest = 0;
+
+#define SECS(val) ((val) / SECTICKS)
+#define HSECS(val) (((val) % SECTICKS) * 100 / SECTICKS)
+#define DISP \
+ "%s timer[%p]: freq = %ld.%02lds, next = %d.%02ds, state = %s\n", \
+ pt->name, pt, SECS(pt->load), HSECS(pt->load), SECS(rest), \
+ HSECS(rest), tState2Nam(pt->state)
+
+ if (!prompt)
+ log_Printf(LogLevel, "---- Begin of Timer Service List---\n");
+
+ for (pt = TimerList; pt; pt = pt->next) {
+ rest += pt->rest;
+ if (prompt)
+ prompt_Printf(prompt, DISP);
+ else
+ log_Printf(LogLevel, DISP);
}
-}
-void
-nointr_sleep(u_int sec)
-{
- nointr_dosleep(sec, 0);
-}
-
-void
-nointr_usleep(u_int usec)
-{
- nointr_dosleep(0, usec);
+ if (!prompt)
+ log_Printf(LogLevel, "---- End of Timer Service List ---\n");
}
static void
@@ -267,23 +230,21 @@ InitTimerService()
{
struct itimerval itimer;
- pending_signal(SIGALRM, (void (*) (int)) TimerService);
+ sig_signal(SIGALRM, (void (*) (int)) TimerService);
itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0;
itimer.it_interval.tv_usec = itimer.it_value.tv_usec = TICKUNIT;
if (setitimer(ITIMER_REAL, &itimer, NULL) == -1)
- LogPrintf(LogERROR, "Unable to set itimer.\n");
+ log_Printf(LogERROR, "Unable to set itimer.\n");
}
void
-TermTimerService(void)
+timer_TermService(void)
{
struct itimerval itimer;
itimer.it_interval.tv_usec = itimer.it_interval.tv_sec = 0;
itimer.it_value.tv_usec = itimer.it_value.tv_sec = 0;
if (setitimer(ITIMER_REAL, &itimer, NULL) == -1)
- LogPrintf(LogERROR, "Unable to set itimer.\n");
- pending_signal(SIGALRM, SIG_IGN);
+ log_Printf(LogERROR, "Unable to set itimer.\n");
+ sig_signal(SIGALRM, SIG_IGN);
}
-
-#endif
diff --git a/usr.sbin/ppp/timer.h b/usr.sbin/ppp/timer.h
index e8df9b9387c7..0dcca5bedb32 100644
--- a/usr.sbin/ppp/timer.h
+++ b/usr.sbin/ppp/timer.h
@@ -15,16 +15,17 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: timer.h,v 1.4 1997/12/28 21:55:05 brian Exp $
+ * $Id: timer.h,v 1.5.4.5 1998/05/08 01:15:19 brian Exp $
*
* TODO:
*/
-#define TICKUNIT 100000 /* Unit in usec */
-#define SECTICKS (1000000/TICKUNIT)
+#define TICKUNIT 100000 /* usec's per Unit */
+#define SECTICKS (1000000/TICKUNIT) /* Units per second */
struct pppTimer {
int state;
+ const char *name;
u_long rest; /* Ticks to expire */
u_long load; /* Initial load value */
void (*func)(void *); /* Function called when timer is expired */
@@ -37,12 +38,9 @@ struct pppTimer {
#define TIMER_RUNNING 1
#define TIMER_EXPIRED 2
-extern void StartTimer(struct pppTimer *);
-extern void StopTimer(struct pppTimer *);
-extern void TermTimerService(void);
-extern void ShowTimers(void);
+struct prompt;
-#ifdef SIGALRM
-extern void nointr_sleep(u_int);
-extern void nointr_usleep(u_int);
-#endif
+extern void timer_Start(struct pppTimer *);
+extern void timer_Stop(struct pppTimer *);
+extern void timer_TermService(void);
+extern void timer_Show(int LogLevel, struct prompt *);
diff --git a/usr.sbin/ppp/tun.c b/usr.sbin/ppp/tun.c
index 5b94c8ebb66b..e0dd313736e2 100644
--- a/usr.sbin/ppp/tun.c
+++ b/usr.sbin/ppp/tun.c
@@ -23,44 +23,54 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: tun.c,v 1.5 1998/01/11 17:53:27 brian Exp $
+ * $Id: tun.c,v 1.6.4.18 1998/05/06 23:50:22 brian Exp $
*/
-#include <sys/param.h>
-#include <sys/time.h>
+#include <sys/types.h>
#include <sys/socket.h>
-#include <netinet/in.h>
#include <net/if.h>
+#include <netinet/in.h>
#include <net/if_tun.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
-#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
+#include "timer.h"
+#include "lqr.h"
#include "hdlc.h"
#include "defs.h"
-#include "loadalias.h"
-#include "vars.h"
+#include "fsm.h"
+#include "throughput.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
#include "tun.h"
void
-tun_configure(int mtu, int speed)
+tun_configure(struct bundle *bundle, int mtu)
{
struct tuninfo info;
info.type = 23;
info.mtu = mtu;
- if (VarPrefMTU != 0 && VarPrefMTU < mtu)
- info.mtu = VarPrefMTU;
- info.baudrate = speed;
+ info.baudrate = bundle->ifp.Speed;
#ifdef __OpenBSD__
info.flags = IFF_UP|IFF_POINTOPOINT;
#endif
- if (ioctl(tun_out, TUNSIFINFO, &info) < 0)
- LogPrintf(LogERROR, "tun_configure: ioctl(TUNSIFINFO): %s\n",
+ if (ioctl(bundle->dev.fd, TUNSIFINFO, &info) < 0)
+ log_Printf(LogERROR, "tun_configure: ioctl(TUNSIFINFO): %s\n",
strerror(errno));
}
diff --git a/usr.sbin/ppp/tun.h b/usr.sbin/ppp/tun.h
index 5848793f07c8..2745686f8e31 100644
--- a/usr.sbin/ppp/tun.h
+++ b/usr.sbin/ppp/tun.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: tun.h,v 1.3.4.3 1998/05/06 23:50:25 brian Exp $
*/
struct tun_data {
@@ -41,4 +41,6 @@ struct tun_data {
#define tun_check_header(f,proto) (1)
#endif
-extern void tun_configure(int, int);
+struct bundle;
+
+extern void tun_configure(struct bundle *, int);
diff --git a/usr.sbin/ppp/vars.c b/usr.sbin/ppp/vars.c
deleted file mode 100644
index 7cbd3b80aa91..000000000000
--- a/usr.sbin/ppp/vars.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * PPP configuration variables
- *
- * 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.
- *
- * $Id: vars.c,v 1.44 1998/01/20 22:47:48 brian Exp $
- *
- */
-#include <sys/param.h>
-#include <netinet/in.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include "command.h"
-#include "mbuf.h"
-#include "log.h"
-#include "defs.h"
-#include "timer.h"
-#include "fsm.h"
-#include "hdlc.h"
-#include "termios.h"
-#include "loadalias.h"
-#include "vars.h"
-#include "auth.h"
-
-char VarVersion[] = "PPP Version 1.65";
-char VarLocalVersion[] = "$Date: 1998/01/20 22:47:48 $";
-int Utmp = 0;
-int ipKeepAlive = 0;
-int reconnectState = RECON_UNKNOWN;
-int reconnectCount = 0;
-
-/*
- * Order of conf option is important. See vars.h.
- */
-struct confdesc pppConfs[] = {
- {"acfcomp", CONF_ENABLE, CONF_ACCEPT},
- {"chap", CONF_DISABLE, CONF_ACCEPT},
- {"deflate", CONF_ENABLE, CONF_ACCEPT},
- {"lqr", CONF_DISABLE, CONF_ACCEPT},
- {"pap", CONF_DISABLE, CONF_ACCEPT},
- {"pppd-deflate", CONF_DISABLE, CONF_DENY},
- {"pred1", CONF_ENABLE, CONF_ACCEPT},
- {"protocomp", CONF_ENABLE, CONF_ACCEPT},
- {"vjcomp", CONF_ENABLE, CONF_ACCEPT},
- {"msext", CONF_DISABLE, CONF_NONE},
- {"passwdauth", CONF_DISABLE, CONF_NONE},
- {"proxy", CONF_DISABLE, CONF_NONE},
- {"throughput", CONF_DISABLE, CONF_NONE},
- {"utmp", CONF_ENABLE, CONF_NONE},
- {NULL},
-};
-
-struct pppvars pppVars = {
- DEF_MRU, DEF_MTU, 0, MODEM_SPEED, CS8, MODEM_CTSRTS, 180, 30, 3,
- RECONNECT_TIMER, RECONNECT_TRIES, REDIAL_PERIOD,
- NEXT_REDIAL_PERIOD, 1, 1, MODEM_DEV, "", BASE_MODEM_DEV,
- 1, LOCAL_NO_AUTH, 0
-};
-
-int
-DisplayCommand(struct cmdargs const *arg)
-{
- struct confdesc *vp;
-
- if (!VarTerm)
- return 1;
-
- fprintf(VarTerm, "Current configuration option settings..\n\n");
- fprintf(VarTerm, "Name\t\tMy Side\t\tHis Side\n");
- fprintf(VarTerm, "----------------------------------------\n");
- for (vp = pppConfs; vp->name; vp++)
- fprintf(VarTerm, "%-10s\t%s\t\t%s\n", vp->name,
- (vp->myside == CONF_ENABLE) ? "enable" :
- (vp->myside == CONF_DISABLE ? "disable" : "N/A"),
- (vp->hisside == CONF_ACCEPT) ? "accept" :
- (vp->hisside == CONF_DENY ? "deny" : "N/A"));
-
- return 0;
-}
-
-static int
-ConfigCommand(struct cmdargs const *arg, int mine, int val)
-{
- struct confdesc *vp;
- int err;
- int narg = 0;
-
- if (arg->argc < 1)
- return -1;
-
- err = 0;
- do {
- for (vp = pppConfs; vp->name; vp++)
- if (strcasecmp(vp->name, arg->argv[narg]) == 0) {
- if (mine) {
- if (vp->myside == CONF_NONE) {
- LogPrintf(LogWARN, "Config: %s cannot be enabled or disabled\n",
- vp->name);
- err++;
- } else
- vp->myside = val;
- } else {
- if (vp->hisside == CONF_NONE) {
- LogPrintf(LogWARN, "Config: %s cannot be accepted or denied\n",
- vp->name);
- err++;
- } else
- vp->hisside = val;
- }
- break;
- }
- if (!vp->name) {
- LogPrintf(LogWARN, "Config: %s: No such key word\n", arg->argv[narg]);
- err++;
- }
- } while (++narg < arg->argc);
-
- return err;
-}
-
-int
-EnableCommand(struct cmdargs const *arg)
-{
- return ConfigCommand(arg, 1, CONF_ENABLE);
-}
-
-int
-DisableCommand(struct cmdargs const *arg)
-{
- return ConfigCommand(arg, 1, CONF_DISABLE);
-}
-
-int
-AcceptCommand(struct cmdargs const *arg)
-{
- return ConfigCommand(arg, 0, CONF_ACCEPT);
-}
-
-int
-DenyCommand(struct cmdargs const *arg)
-{
- return ConfigCommand(arg, 0, CONF_DENY);
-}
-
-int
-LocalAuthCommand(struct cmdargs const *arg)
-{
- const char *pass;
- if (arg->argc == 0)
- pass = "";
- else if (arg->argc > 1)
- return -1;
- else
- pass = *arg->argv;
-
- if (VarHaveLocalAuthKey)
- VarLocalAuth = strcmp(VarLocalAuthKey, pass) ? LOCAL_NO_AUTH : LOCAL_AUTH;
- else
- switch (LocalAuthValidate(SECRETFILE, VarShortHost, pass)) {
- case INVALID:
- VarLocalAuth = LOCAL_NO_AUTH;
- break;
- case VALID:
- VarLocalAuth = LOCAL_AUTH;
- break;
- case NOT_FOUND:
- VarLocalAuth = LOCAL_AUTH;
- LogPrintf(LogWARN, "WARNING: No Entry for this system\n");
- break;
- default:
- VarLocalAuth = LOCAL_NO_AUTH;
- LogPrintf(LogERROR, "LocalAuthCommand: Ooops?\n");
- return 1;
- }
- return 0;
-}
diff --git a/usr.sbin/ppp/vars.h b/usr.sbin/ppp/vars.h
deleted file mode 100644
index 70a406ae11b9..000000000000
--- a/usr.sbin/ppp/vars.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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. 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.
- *
- * $Id: vars.h,v 1.41 1998/01/20 22:47:48 brian Exp $
- *
- * TODO:
- */
-
-struct confdesc {
- const char *name;
- int myside, hisside;
-};
-
-#define CONF_NONE -1
-#define CONF_DISABLE 0
-#define CONF_ENABLE 1
-
-#define CONF_DENY 0
-#define CONF_ACCEPT 1
-
-#define ConfAcfcomp 0
-#define ConfChap 1
-#define ConfDeflate 2
-#define ConfLqr 3
-#define ConfPap 4
-#define ConfPppdDeflate 5
-#define ConfPred1 6
-#define ConfProtocomp 7
-#define ConfVjcomp 8
-
-#define ConfMSExt 9
-#define ConfPasswdAuth 10
-#define ConfProxy 11
-#define ConfThroughput 12
-#define ConfUtmp 13
-#define MAXCONFS 14
-
-#define Enabled(x) (pppConfs[x].myside & CONF_ENABLE)
-#define Acceptable(x) (pppConfs[x].hisside & CONF_ACCEPT)
-
-extern struct confdesc pppConfs[MAXCONFS + 1];
-
-struct pppvars {
- u_short var_mru; /* Initial MRU value */
- u_short pref_mtu; /* Preferred MTU value */
- int var_accmap; /* Initial ACCMAP value */
- int modem_speed; /* Current modem speed */
- int modem_parity; /* Parity setting */
- int modem_ctsrts; /* Use CTS/RTS on modem port? (boolean) */
- int idle_timeout; /* Idle timeout value */
- int lqr_timeout; /* LQR timeout value */
- int retry_timeout; /* Retry timeout value */
- int reconnect_timer; /* Timeout before reconnect on carrier loss */
- int reconnect_tries; /* Attempt reconnect on carrier loss */
- int redial_timeout; /* Redial timeout value */
- int redial_next_timeout; /* Redial next timeout value */
- int dial_tries; /* Dial attempts before giving up, 0 == inf */
- int loopback; /* Turn around packets addressed to me */
- char modem_devlist[LINE_LEN]; /* Comma-separated list of devices */
- char modem_dev[40]; /* Name of device / host:port */
- const char *base_modem_dev; /* Pointer to base of modem_dev */
- int open_mode; /* Delay before first LCP REQ (-1 = passive) */
-#define LOCAL_AUTH 0x01
-#define LOCAL_NO_AUTH 0x02
-#define LOCAL_DENY 0x03
- u_char lauth; /* Local Authorized status */
- FILE *termfp; /* The terminal */
-#define DIALUP_REQ 0x01
-#define DIALUP_DONE 0x02
- char dial_script[SCRIPT_LEN]; /* Dial script */
- char login_script[SCRIPT_LEN]; /* Login script */
- char auth_key[50]; /* PAP/CHAP key */
- char auth_name[50]; /* PAP/CHAP system name */
- char local_auth_key[50]; /* Local auth passwd */
- int have_local_auth_key; /* Local auth passwd specified ? */
-#ifdef HAVE_DES
- int use_MSChap; /* Use MSCHAP encryption */
-#endif
- char phone_numbers[200]; /* Telephone Numbers */
- char phone_copy[200]; /* copy for strsep() */
- char *next_phone; /* Next phone from the list */
- char *alt_phone; /* Next phone from the list */
- char shostname[MAXHOSTNAMELEN]; /* Local short Host Name */
- char hangup_script[SCRIPT_LEN]; /* Hangup script before modem is closed */
- struct aliasHandlers handler; /* Alias function pointers */
-};
-
-#define VarAccmap pppVars.var_accmap
-#define VarMRU pppVars.var_mru
-#define VarPrefMTU pppVars.pref_mtu
-#define VarDevice pppVars.modem_dev
-#define VarDeviceList pppVars.modem_devlist
-#define VarBaseDevice pppVars.base_modem_dev
-#define VarSpeed pppVars.modem_speed
-#define VarParity pppVars.modem_parity
-#define VarCtsRts pppVars.modem_ctsrts
-#define VarOpenMode pppVars.open_mode
-#define VarLocalAuth pppVars.lauth
-#define VarDialScript pppVars.dial_script
-#define VarHangupScript pppVars.hangup_script
-#define VarLoginScript pppVars.login_script
-#define VarIdleTimeout pppVars.idle_timeout
-#define VarLqrTimeout pppVars.lqr_timeout
-#define VarRetryTimeout pppVars.retry_timeout
-#define VarAuthKey pppVars.auth_key
-#define VarAuthName pppVars.auth_name
-#define VarLocalAuthKey pppVars.local_auth_key
-#define VarHaveLocalAuthKey pppVars.have_local_auth_key
-#ifdef HAVE_DES
-#define VarMSChap pppVars.use_MSChap
-#endif
-#define VarPhoneList pppVars.phone_numbers
-#define VarPhoneCopy pppVars.phone_copy
-#define VarNextPhone pppVars.next_phone
-#define VarAltPhone pppVars.alt_phone
-#define VarShortHost pppVars.shostname
-#define VarReconnectTimer pppVars.reconnect_timer
-#define VarReconnectTries pppVars.reconnect_tries
-#define VarRedialTimeout pppVars.redial_timeout
-#define VarRedialNextTimeout pppVars.redial_next_timeout
-#define VarDialTries pppVars.dial_tries
-#define VarLoopback pppVars.loopback
-#define VarTerm pppVars.termfp
-
-#define VarAliasHandlers pppVars.handler
-#define VarPacketAliasGetFragment (*pppVars.handler.PacketAliasGetFragment)
-#define VarPacketAliasGetFragment (*pppVars.handler.PacketAliasGetFragment)
-#define VarPacketAliasInit (*pppVars.handler.PacketAliasInit)
-#define VarPacketAliasIn (*pppVars.handler.PacketAliasIn)
-#define VarPacketAliasOut (*pppVars.handler.PacketAliasOut)
-#define VarPacketAliasRedirectAddr (*pppVars.handler.PacketAliasRedirectAddr)
-#define VarPacketAliasRedirectPort (*pppVars.handler.PacketAliasRedirectPort)
-#define VarPacketAliasSaveFragment (*pppVars.handler.PacketAliasSaveFragment)
-#define VarPacketAliasSetAddress (*pppVars.handler.PacketAliasSetAddress)
-#define VarPacketAliasSetMode (*pppVars.handler.PacketAliasSetMode)
-#define VarPacketAliasFragmentIn (*pppVars.handler.PacketAliasFragmentIn)
-
-#define DEV_IS_SYNC (VarSpeed == 0)
-
-extern struct pppvars pppVars;
-extern char VarVersion[];
-extern char VarLocalVersion[];
-
-extern int Utmp; /* Are we in /etc/utmp ? */
-extern int ipKeepAlive;
-extern int reconnectState;
-extern int reconnectCount;
-
-#define RECON_TRUE (1)
-#define RECON_FALSE (2)
-#define RECON_UNKNOWN (3)
-#define RECON_ENVOKED (4)
-#define reconnect(x) \
- do \
- if (reconnectState == RECON_UNKNOWN) { \
- reconnectState = x; \
- if (x == RECON_FALSE) \
- reconnectCount = 0; \
- } \
- while(0)
-
-
-/*
- * This is the logic behind the reconnect variables:
- * We have four reconnect "states". We start off not requiring anything
- * from the reconnect code (reconnectState == RECON_UNKNOWN). If the
- * line is brought down (via LcpClose() or LcpDown()), we have to decide
- * whether to set to RECON_TRUE or RECON_FALSE. It's only here that we
- * know the correct action. Once we've decided, we don't want that
- * decision to be overridden (hence the above reconnect() macro) - If we
- * call LcpClose, the ModemTimeout() still gets to "notice" that the line
- * is down. When it "notice"s, it should only set RECON_TRUE if a decision
- * hasn't already been made.
- *
- * In main.c, when we notice we have RECON_TRUE, we must only action
- * it once. The fourth "state" is where we're bringing the line up,
- * but if we call LcpClose for any reason (failed PAP/CHAP etc) we
- * don't want to set to RECON_{TRUE,FALSE}.
- *
- * If we get a connection or give up dialing, we go back to RECON_UNKNOWN.
- * If we get give up dialing or reconnecting or if we chose to down the
- * connection, we set reconnectCount back to zero.
- *
- */
-
-extern int EnableCommand(struct cmdargs const *);
-extern int DisableCommand(struct cmdargs const *);
-extern int AcceptCommand(struct cmdargs const *);
-extern int DenyCommand(struct cmdargs const *);
-extern int LocalAuthCommand(struct cmdargs const *);
-extern int DisplayCommand(struct cmdargs const *);
diff --git a/usr.sbin/ppp/vjcomp.c b/usr.sbin/ppp/vjcomp.c
index f9ef60db40fc..851ea2277293 100644
--- a/usr.sbin/ppp/vjcomp.c
+++ b/usr.sbin/ppp/vjcomp.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: vjcomp.c,v 1.15 1998/01/11 17:50:46 brian Exp $
+ * $Id: vjcomp.c,v 1.16.2.17 1998/05/04 03:00:09 brian Exp $
*
* TODO:
*/
@@ -25,44 +25,49 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <sys/un.h>
#include <stdio.h>
-#include <string.h>
-#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "timer.h"
#include "fsm.h"
#include "lcpproto.h"
#include "slcompress.h"
+#include "lqr.h"
#include "hdlc.h"
+#include "defs.h"
+#include "iplist.h"
+#include "throughput.h"
#include "ipcp.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "mp.h"
+#include "bundle.h"
#include "vjcomp.h"
#define MAX_VJHEADER 16 /* Maximum size of compressed header */
-static struct slcompress cslc;
-
-void
-VjInit(int max_state)
-{
- sl_compress_init(&cslc, max_state);
-}
-
void
-SendPppFrame(struct mbuf * bp)
+vj_SendFrame(struct link *l, struct mbuf * bp, struct bundle *bundle)
{
int type;
u_short proto;
- u_short cproto = IpcpInfo.his_compproto >> 16;
+ u_short cproto = bundle->ncp.ipcp.peer_compproto >> 16;
- LogPrintf(LogDEBUG, "SendPppFrame: proto = %x\n", IpcpInfo.his_compproto);
+ log_Printf(LogDEBUG, "vj_SendFrame: COMPPROTO = %x\n",
+ bundle->ncp.ipcp.peer_compproto);
if (((struct ip *) MBUF_CTOP(bp))->ip_p == IPPROTO_TCP
&& cproto == PROTO_VJCOMP) {
- type = sl_compress_tcp(bp, (struct ip *)MBUF_CTOP(bp), &cslc,
- IpcpInfo.his_compproto & 0xff);
- LogPrintf(LogDEBUG, "SendPppFrame: type = %x\n", type);
+ type = sl_compress_tcp(bp, (struct ip *)MBUF_CTOP(bp),
+ &bundle->ncp.ipcp.vj.cslc,
+ &bundle->ncp.ipcp.vj.slstat,
+ bundle->ncp.ipcp.peer_compproto & 0xff);
+ log_Printf(LogDEBUG, "vj_SendFrame: type = %x\n", type);
switch (type) {
case TYPE_IP:
proto = PROTO_IP;
@@ -74,24 +79,26 @@ SendPppFrame(struct mbuf * bp)
proto = PROTO_VJCOMP;
break;
default:
- LogPrintf(LogERROR, "Unknown frame type %x\n", type);
- pfree(bp);
+ log_Printf(LogERROR, "Unknown frame type %x\n", type);
+ mbuf_Free(bp);
return;
}
} else
proto = PROTO_IP;
- HdlcOutput(PRI_NORMAL, proto, bp);
+
+ if (!ccp_Compress(&l->ccp, l, PRI_NORMAL, proto, bp))
+ hdlc_Output(l, PRI_NORMAL, proto, bp);
}
static struct mbuf *
-VjUncompressTcp(struct mbuf * bp, u_char type)
+VjUncompressTcp(struct ipcp *ipcp, struct mbuf * bp, u_char type)
{
u_char *bufp;
int len, olen, rlen;
struct mbuf *nbp;
u_char work[MAX_HDR + MAX_VJHEADER]; /* enough to hold TCP/IP header */
- olen = len = plength(bp);
+ olen = len = mbuf_Length(bp);
if (type == TYPE_UNCOMPRESSED_TCP) {
/*
@@ -99,9 +106,9 @@ VjUncompressTcp(struct mbuf * bp, u_char type)
* space for uncompression job.
*/
bufp = MBUF_CTOP(bp);
- len = sl_uncompress_tcp(&bufp, len, type, &cslc);
+ len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat);
if (len <= 0) {
- pfree(bp);
+ mbuf_Free(bp);
bp = NULL;
}
return (bp);
@@ -116,27 +123,27 @@ VjUncompressTcp(struct mbuf * bp, u_char type)
len = MAX_VJHEADER;
rlen = len;
bufp = work + MAX_HDR;
- bp = mbread(bp, bufp, rlen);
- len = sl_uncompress_tcp(&bufp, olen, type, &cslc);
+ bp = mbuf_Read(bp, bufp, rlen);
+ len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat);
if (len <= 0) {
- pfree(bp);
+ mbuf_Free(bp);
return NULL;
}
len -= olen;
len += rlen;
- nbp = mballoc(len, MB_VJCOMP);
+ nbp = mbuf_Alloc(len, MB_VJCOMP);
memcpy(MBUF_CTOP(nbp), bufp, len);
nbp->next = bp;
return (nbp);
}
struct mbuf *
-VjCompInput(struct mbuf * bp, int proto)
+vj_Input(struct ipcp *ipcp, struct mbuf *bp, int proto)
{
u_char type;
- LogPrintf(LogDEBUG, "VjCompInput: proto %02x\n", proto);
- LogDumpBp(LogDEBUG, "Raw packet info:", bp);
+ log_Printf(LogDEBUG, "vj_Input: proto %02x\n", proto);
+ log_DumpBp(LogDEBUG, "Raw packet info:", bp);
switch (proto) {
case PROTO_VJCOMP:
@@ -146,10 +153,10 @@ VjCompInput(struct mbuf * bp, int proto)
type = TYPE_UNCOMPRESSED_TCP;
break;
default:
- LogPrintf(LogERROR, "VjCompInput...???\n");
+ log_Printf(LogERROR, "vj_Input...???\n");
return (bp);
}
- bp = VjUncompressTcp(bp, type);
+ bp = VjUncompressTcp(ipcp, bp, type);
return (bp);
}
@@ -158,7 +165,10 @@ vj2asc(u_int32_t val)
{
static char asc[50];
- sprintf(asc, "%d VJ slots %s slot compression",
- (int)((val>>8)&15)+1, val & 1 ? "with" : "without");
+ if (val)
+ snprintf(asc, sizeof asc, "%d VJ slots %s slot compression",
+ (int)((val>>8)&15)+1, val & 1 ? "with" : "without");
+ else
+ strcpy(asc, "VJ disabled");
return asc;
}
diff --git a/usr.sbin/ppp/vjcomp.h b/usr.sbin/ppp/vjcomp.h
index 615894cfc0c8..b33436eb8902 100644
--- a/usr.sbin/ppp/vjcomp.h
+++ b/usr.sbin/ppp/vjcomp.h
@@ -23,10 +23,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: vjcomp.h,v 1.4 1997/12/21 12:11:10 brian Exp $
+ * $Id: vjcomp.h,v 1.5.4.6 1998/05/01 19:26:12 brian Exp $
*/
-extern void VjInit(int);
-extern void SendPppFrame(struct mbuf *);
-extern struct mbuf *VjCompInput(struct mbuf *, int);
+struct mbuf;
+struct link;
+struct ipcp;
+struct bundle;
+
+extern void vj_SendFrame(struct link *, struct mbuf *, struct bundle *);
+extern struct mbuf *vj_Input(struct ipcp *, struct mbuf *, int);
extern const char *vj2asc(u_int32_t);