1995-01-31 06:29:58 +00:00
|
|
|
/*
|
|
|
|
* PPP Finite State Machine for LCP/IPCP
|
|
|
|
*
|
|
|
|
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
|
|
|
|
*
|
|
|
|
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* provided that the above copyright notice and this paragraph are
|
|
|
|
* duplicated in all such forms and that any documentation,
|
|
|
|
* advertising materials, and other materials related to such
|
|
|
|
* distribution and use acknowledge that the software was developed
|
|
|
|
* by the Internet Initiative Japan, Inc. The name of the
|
|
|
|
* IIJ may not be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
1995-05-30 03:57:47 +00:00
|
|
|
*
|
1999-08-28 01:35:59 +00:00
|
|
|
* $FreeBSD$
|
1995-05-30 03:57:47 +00:00
|
|
|
*
|
1995-01-31 06:29:58 +00:00
|
|
|
* TODO:
|
|
|
|
*/
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1999-01-28 01:56:34 +00:00
|
|
|
#include <sys/param.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <netinet/in.h>
|
1998-05-21 21:49:08 +00:00
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <sys/un.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <termios.h>
|
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
#include "layer.h"
|
1998-09-04 18:26:00 +00:00
|
|
|
#include "ua.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
#include "mbuf.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "defs.h"
|
|
|
|
#include "timer.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "fsm.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "iplist.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "lqr.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "hdlc.h"
|
|
|
|
#include "throughput.h"
|
|
|
|
#include "slcompress.h"
|
|
|
|
#include "ipcp.h"
|
|
|
|
#include "filter.h"
|
|
|
|
#include "descriptor.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "lcp.h"
|
1996-01-11 17:48:59 +00:00
|
|
|
#include "ccp.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "link.h"
|
|
|
|
#include "mp.h"
|
1999-01-28 01:56:34 +00:00
|
|
|
#ifndef NORADIUS
|
|
|
|
#include "radius.h"
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "bundle.h"
|
|
|
|
#include "async.h"
|
|
|
|
#include "physical.h"
|
1999-05-08 11:07:56 +00:00
|
|
|
#include "proto.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
|
|
|
|
static void FsmSendConfigReq(struct fsm *);
|
|
|
|
static void FsmSendTerminateReq(struct fsm *);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
static void FsmInitRestartCounter(struct fsm *, int);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
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" },
|
2000-07-19 02:10:35 +00:00
|
|
|
{ FsmRecvIdent, 0, 1, "Ident" },
|
1998-05-21 21:49:08 +00:00
|
|
|
{ FsmRecvTimeRemain,0, 0, "TimeRemain" },
|
1999-05-08 11:07:56 +00:00
|
|
|
{ FsmRecvResetReq, 0, 0, "ResetReq" },
|
1998-05-21 21:49:08 +00:00
|
|
|
{ FsmRecvResetAck, 0, 1, "ResetAck" }
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
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)
|
|
|
|
{
|
1999-12-27 11:54:57 +00:00
|
|
|
static const char * const StateNames[] = {
|
1998-05-21 21:49:08 +00:00
|
|
|
"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];
|
|
|
|
}
|
|
|
|
|
1997-08-17 20:45:50 +00:00
|
|
|
static void
|
1997-11-22 03:37:54 +00:00
|
|
|
StoppedTimeout(void *v)
|
1997-08-17 20:45:50 +00:00
|
|
|
{
|
1997-11-22 03:37:54 +00:00
|
|
|
struct fsm *fp = (struct fsm *)v;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name);
|
1998-01-20 22:47:48 +00:00
|
|
|
if (fp->OpenTimer.state == TIMER_RUNNING) {
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n",
|
|
|
|
fp->link->name, fp->name);
|
|
|
|
timer_Stop(&fp->OpenTimer);
|
|
|
|
}
|
1998-06-20 00:19:42 +00:00
|
|
|
if (fp->state == ST_STOPPED)
|
|
|
|
fsm2initial(fp);
|
1997-08-17 20:45:50 +00:00
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
void
|
1998-05-21 21:49:08 +00:00
|
|
|
fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode,
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
int maxcode, int LogLevel, struct bundle *bundle,
|
1998-05-21 21:49:08 +00:00
|
|
|
struct link *l, const struct fsm_parent *parent,
|
1999-12-27 11:54:57 +00:00
|
|
|
struct fsm_callbacks *fn, const char * const timer_names[3])
|
1998-05-21 21:49:08 +00:00
|
|
|
{
|
|
|
|
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;
|
1995-01-31 06:29:58 +00:00
|
|
|
fp->reqid = 1;
|
|
|
|
fp->restart = 1;
|
1999-05-08 11:07:56 +00:00
|
|
|
fp->more.reqs = fp->more.naks = fp->more.rejs = 3;
|
1998-05-21 21:49:08 +00:00
|
|
|
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];
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1999-05-09 20:02:29 +00:00
|
|
|
NewState(struct fsm *fp, int new)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: State change %s --> %s\n",
|
|
|
|
fp->link->name, State2Nam(fp->state), State2Nam(new));
|
1997-08-20 23:47:53 +00:00
|
|
|
if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Stop(&fp->StoppedTimer);
|
1995-01-31 06:29:58 +00:00
|
|
|
fp->state = new;
|
1997-08-17 20:45:50 +00:00
|
|
|
if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Stop(&fp->FsmTimer);
|
1997-08-20 23:47:53 +00:00
|
|
|
if (new == ST_STOPPED && fp->StoppedTimer.load) {
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Stop(&fp->StoppedTimer);
|
1997-08-20 23:47:53 +00:00
|
|
|
fp->StoppedTimer.func = StoppedTimeout;
|
1997-08-25 00:29:32 +00:00
|
|
|
fp->StoppedTimer.arg = (void *) fp;
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Start(&fp->StoppedTimer);
|
1997-08-17 20:45:50 +00:00
|
|
|
}
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count,
|
|
|
|
int mtype)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
int plen;
|
|
|
|
struct fsmheader lh;
|
|
|
|
struct mbuf *bp;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-08-25 00:29:32 +00:00
|
|
|
plen = sizeof(struct fsmheader) + count;
|
1995-01-31 06:29:58 +00:00
|
|
|
lh.code = code;
|
|
|
|
lh.id = id;
|
|
|
|
lh.length = htons(plen);
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_get(plen, mtype);
|
1997-10-26 01:04:02 +00:00
|
|
|
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
|
1995-01-31 06:29:58 +00:00
|
|
|
if (count)
|
1997-10-26 01:04:02 +00:00
|
|
|
memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
|
1998-05-21 21:49:08 +00:00
|
|
|
log_DumpBp(LogDEBUG, "fsm_Output", bp);
|
1999-09-04 00:00:21 +00:00
|
|
|
link_PushPacket(fp->link, bp, fp->bundle, LINK_QUEUES(fp->link) - 1,
|
|
|
|
fp->proto);
|
2000-07-19 02:10:35 +00:00
|
|
|
|
|
|
|
if (code == CODE_CONFIGREJ)
|
|
|
|
lcp_SendIdentification(&fp->link->lcp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-01-20 22:47:48 +00:00
|
|
|
static void
|
|
|
|
FsmOpenNow(void *v)
|
|
|
|
{
|
|
|
|
struct fsm *fp = (struct fsm *)v;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Stop(&fp->OpenTimer);
|
1998-01-20 22:47:48 +00:00
|
|
|
if (fp->state <= ST_STOPPED) {
|
1998-06-27 23:48:54 +00:00
|
|
|
if (fp->state != ST_STARTING) {
|
|
|
|
/*
|
|
|
|
* In practice, we're only here in ST_STOPPED (when delaying the
|
|
|
|
* first config request) or ST_CLOSED (when openmode == 0).
|
|
|
|
*
|
|
|
|
* The ST_STOPPED bit is breaking the RFC already :-(
|
|
|
|
*
|
|
|
|
* According to the RFC (1661) state transition table, a TLS isn't
|
|
|
|
* required for an Open event when state == Closed, but the RFC
|
|
|
|
* must be wrong as TLS hasn't yet been called (since the last TLF)
|
|
|
|
* ie, Initial gets an `Up' event, Closing gets a RTA etc.
|
|
|
|
*/
|
|
|
|
(*fp->fn->LayerStart)(fp);
|
|
|
|
(*fp->parent->LayerStart)(fp->parent->object, fp);
|
|
|
|
}
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1998-01-20 22:47:48 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
void
|
1999-05-09 20:02:29 +00:00
|
|
|
fsm_Open(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
switch (fp->state) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case ST_INITIAL:
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_STARTING);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerStart)(fp);
|
|
|
|
(*fp->parent->LayerStart)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_CLOSED:
|
|
|
|
if (fp->open_mode == OPEN_PASSIVE) {
|
1998-06-27 23:48:54 +00:00
|
|
|
NewState(fp, ST_STOPPED); /* XXX: This is a hack ! */
|
1998-01-20 22:47:48 +00:00
|
|
|
} else if (fp->open_mode > 0) {
|
|
|
|
if (fp->open_mode > 1)
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n",
|
|
|
|
fp->link->name, fp->open_mode);
|
1998-06-27 23:48:54 +00:00
|
|
|
NewState(fp, ST_STOPPED); /* XXX: This is a not-so-bad hack ! */
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Stop(&fp->OpenTimer);
|
1998-01-20 22:47:48 +00:00
|
|
|
fp->OpenTimer.load = fp->open_mode * SECTICKS;
|
|
|
|
fp->OpenTimer.func = FsmOpenNow;
|
|
|
|
fp->OpenTimer.arg = (void *)fp;
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Start(&fp->OpenTimer);
|
1998-01-20 22:47:48 +00:00
|
|
|
} else
|
|
|
|
FsmOpenNow(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
1997-08-25 00:29:32 +00:00
|
|
|
case ST_STOPPED: /* XXX: restart option */
|
1995-01-31 06:29:58 +00:00
|
|
|
case ST_REQSENT:
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
case ST_ACKSENT:
|
1997-08-25 00:29:32 +00:00
|
|
|
case ST_OPENED: /* XXX: restart option */
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
1997-08-25 00:29:32 +00:00
|
|
|
case ST_CLOSING: /* XXX: restart option */
|
|
|
|
case ST_STOPPING: /* XXX: restart option */
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_STOPPING);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-05-09 20:02:29 +00:00
|
|
|
fsm_Up(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
switch (fp->state) {
|
1998-06-27 23:48:54 +00:00
|
|
|
case ST_INITIAL:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n",
|
|
|
|
fp->link->name);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_CLOSED);
|
|
|
|
break;
|
|
|
|
case ST_STARTING:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
default:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n",
|
|
|
|
fp->link->name, State2Nam(fp->state));
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-05-21 21:49:08 +00:00
|
|
|
fsm_Down(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
switch (fp->state) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case ST_CLOSED:
|
|
|
|
NewState(fp, ST_INITIAL);
|
|
|
|
break;
|
|
|
|
case ST_CLOSING:
|
1999-03-01 02:52:39 +00:00
|
|
|
/* This TLF contradicts the RFC (1661), which ``misses it out'' ! */
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerFinish)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_INITIAL);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerFinish)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_STOPPED:
|
1998-05-21 21:49:08 +00:00
|
|
|
NewState(fp, ST_STARTING);
|
|
|
|
(*fp->fn->LayerStart)(fp);
|
|
|
|
(*fp->parent->LayerStart)(fp->parent->object, fp);
|
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
case ST_STOPPING:
|
|
|
|
case ST_REQSENT:
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
case ST_ACKSENT:
|
|
|
|
NewState(fp, ST_STARTING);
|
|
|
|
break;
|
|
|
|
case ST_OPENED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerDown)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_STARTING);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-05-21 21:49:08 +00:00
|
|
|
fsm_Close(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
switch (fp->state) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case ST_STARTING:
|
|
|
|
(*fp->fn->LayerFinish)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_INITIAL);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerFinish)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_STOPPED:
|
|
|
|
NewState(fp, ST_CLOSED);
|
|
|
|
break;
|
|
|
|
case ST_STOPPING:
|
|
|
|
NewState(fp, ST_CLOSING);
|
|
|
|
break;
|
|
|
|
case ST_OPENED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerDown)(fp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_TRM_TIMER);
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmSendTerminateReq(fp);
|
|
|
|
NewState(fp, ST_CLOSING);
|
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
case ST_REQSENT:
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
case ST_ACKSENT:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_TRM_TIMER);
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendTerminateReq(fp);
|
|
|
|
NewState(fp, ST_CLOSING);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send functions
|
|
|
|
*/
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1999-05-09 20:02:29 +00:00
|
|
|
FsmSendConfigReq(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
if (fp->more.reqs-- > 0 && fp->restart-- > 0) {
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SendConfigReq)(fp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
timer_Start(&fp->FsmTimer); /* Start restart timer */
|
1995-01-31 06:29:58 +00:00
|
|
|
} else {
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
if (fp->more.reqs < 0)
|
|
|
|
log_Printf(LogPHASE, "%s: Too many %s REQs sent - abandoning "
|
|
|
|
"negotiation\n", fp->link->name, fp->name);
|
2000-07-19 02:10:35 +00:00
|
|
|
lcp_SendIdentification(&fp->link->lcp);
|
1998-05-21 21:49:08 +00:00
|
|
|
fsm_Close(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmSendTerminateReq(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0, MB_UNKNOWN);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SentTerminateReq)(fp);
|
|
|
|
timer_Start(&fp->FsmTimer); /* Start restart timer */
|
1995-01-31 06:29:58 +00:00
|
|
|
fp->restart--; /* Decrement restart counter */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Timeout actions
|
|
|
|
*/
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1997-11-22 03:37:54 +00:00
|
|
|
FsmTimeout(void *v)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1997-11-22 03:37:54 +00:00
|
|
|
struct fsm *fp = (struct fsm *)v;
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
if (fp->restart) {
|
|
|
|
switch (fp->state) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case ST_CLOSING:
|
|
|
|
case ST_STOPPING:
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendTerminateReq(fp);
|
|
|
|
break;
|
|
|
|
case ST_REQSENT:
|
|
|
|
case ST_ACKSENT:
|
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
break;
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Start(&fp->FsmTimer);
|
1995-01-31 06:29:58 +00:00
|
|
|
} else {
|
|
|
|
switch (fp->state) {
|
|
|
|
case ST_CLOSING:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerFinish)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_CLOSED);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerFinish)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_STOPPING:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerFinish)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_STOPPED);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerFinish)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_REQSENT: /* XXX: 3p */
|
|
|
|
case ST_ACKSENT:
|
|
|
|
case ST_ACKRCVD:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerFinish)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_STOPPED);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerFinish)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(struct fsm *fp, int what)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
timer_Stop(&fp->FsmTimer);
|
1995-01-31 06:29:58 +00:00
|
|
|
fp->FsmTimer.func = FsmTimeout;
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
fp->FsmTimer.arg = (void *)fp;
|
|
|
|
(*fp->fn->InitRestartCounter)(fp, what);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-05-09 20:02:29 +00:00
|
|
|
* Actions when receive packets
|
1995-01-31 06:29:58 +00:00
|
|
|
*/
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1997-08-25 00:29:32 +00:00
|
|
|
/* RCR */
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct fsm_decode dec;
|
1995-02-26 12:18:08 +00:00
|
|
|
int plen, flen;
|
1995-01-31 06:29:58 +00:00
|
|
|
int ackaction = 0;
|
1995-05-30 03:57:47 +00:00
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
plen = m_length(bp);
|
1997-12-24 09:29:17 +00:00
|
|
|
flen = ntohs(lhp->length) - sizeof *lhp;
|
1995-02-26 12:18:08 +00:00
|
|
|
if (plen < flen) {
|
1998-06-16 19:40:42 +00:00
|
|
|
log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
|
1998-05-21 21:49:08 +00:00
|
|
|
fp->link->name, plen, flen);
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-05-09 20:02:29 +00:00
|
|
|
/* Check and process easy case */
|
1995-01-31 06:29:58 +00:00
|
|
|
switch (fp->state) {
|
|
|
|
case ST_INITIAL:
|
1998-06-30 23:04:17 +00:00
|
|
|
if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) {
|
|
|
|
/*
|
|
|
|
* ccp_SetOpenMode() leaves us in initial if we're disabling
|
1999-05-08 11:07:56 +00:00
|
|
|
* & denying everything.
|
1998-06-30 23:04:17 +00:00
|
|
|
*/
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_prepend(bp, lhp, sizeof *lhp, 2);
|
1999-05-08 11:07:56 +00:00
|
|
|
bp = proto_Prepend(bp, fp->proto, 0, 0);
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_pullup(bp);
|
|
|
|
lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->m_len);
|
|
|
|
m_freem(bp);
|
1998-06-30 23:04:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Drop through */
|
1995-01-31 06:29:58 +00:00
|
|
|
case ST_STARTING:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n",
|
|
|
|
fp->link->name, State2Nam(fp->state));
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
case ST_CLOSED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SendTerminateAck)(fp, lhp->id);
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
case ST_CLOSING:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n",
|
|
|
|
fp->link->name, State2Nam(fp->state));
|
1997-11-11 23:23:11 +00:00
|
|
|
case ST_STOPPING:
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
1998-08-01 01:02:41 +00:00
|
|
|
case ST_OPENED:
|
|
|
|
(*fp->fn->LayerDown)(fp);
|
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_pullup(bp);
|
1998-05-21 21:49:08 +00:00
|
|
|
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");
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (dec.nakend == dec.nak && dec.rejend == dec.rej)
|
1995-01-31 06:29:58 +00:00
|
|
|
ackaction = 1;
|
|
|
|
|
|
|
|
switch (fp->state) {
|
|
|
|
case ST_STOPPED:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1998-08-01 01:02:41 +00:00
|
|
|
/* Fall through */
|
|
|
|
|
|
|
|
case ST_OPENED:
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (dec.rejend != dec.rej)
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej,
|
|
|
|
MB_UNKNOWN);
|
1998-05-21 21:49:08 +00:00
|
|
|
if (dec.nakend != dec.nak)
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak,
|
|
|
|
MB_UNKNOWN);
|
1995-01-31 06:29:58 +00:00
|
|
|
if (ackaction)
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack,
|
|
|
|
MB_UNKNOWN);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
switch (fp->state) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case ST_STOPPED:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
/*
|
|
|
|
* According to the RFC (1661) state transition table, a TLS isn't
|
|
|
|
* required for a RCR when state == ST_STOPPED, but the RFC
|
|
|
|
* must be wrong as TLS hasn't yet been called (since the last TLF)
|
|
|
|
*/
|
|
|
|
(*fp->fn->LayerStart)(fp);
|
|
|
|
(*fp->parent->LayerStart)(fp->parent->object, fp);
|
|
|
|
/* Fall through */
|
|
|
|
|
|
|
|
case ST_OPENED:
|
1995-01-31 06:29:58 +00:00
|
|
|
if (ackaction)
|
|
|
|
NewState(fp, ST_ACKSENT);
|
|
|
|
else
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
case ST_REQSENT:
|
|
|
|
if (ackaction)
|
|
|
|
NewState(fp, ST_ACKSENT);
|
|
|
|
break;
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
if (ackaction) {
|
|
|
|
NewState(fp, ST_OPENED);
|
1998-05-21 21:49:08 +00:00
|
|
|
if ((*fp->fn->LayerUp)(fp))
|
|
|
|
(*fp->parent->LayerUp)(fp->parent->object, fp);
|
|
|
|
else {
|
|
|
|
(*fp->fn->LayerDown)(fp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_TRM_TIMER);
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmSendTerminateReq(fp);
|
|
|
|
NewState(fp, ST_CLOSING);
|
2000-07-19 02:10:35 +00:00
|
|
|
lcp_SendIdentification(&fp->link->lcp);
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ST_ACKSENT:
|
|
|
|
if (!ackaction)
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
|
|
|
|
if (dec.rejend != dec.rej && --fp->more.rejs <= 0) {
|
|
|
|
log_Printf(LogPHASE, "%s: Too many %s REJs sent - abandoning negotiation\n",
|
|
|
|
fp->link->name, fp->name);
|
2000-07-19 02:10:35 +00:00
|
|
|
lcp_SendIdentification(&fp->link->lcp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
fsm_Close(fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dec.nakend != dec.nak && --fp->more.naks <= 0) {
|
|
|
|
log_Printf(LogPHASE, "%s: Too many %s NAKs sent - abandoning negotiation\n",
|
|
|
|
fp->link->name, fp->name);
|
2000-07-19 02:10:35 +00:00
|
|
|
lcp_SendIdentification(&fp->link->lcp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
fsm_Close(fp);
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1997-08-25 00:29:32 +00:00
|
|
|
/* RCA */
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
switch (fp->state) {
|
1997-08-25 00:29:32 +00:00
|
|
|
case ST_CLOSED:
|
|
|
|
case ST_STOPPED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SendTerminateAck)(fp, lhp->id);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_CLOSING:
|
|
|
|
case ST_STOPPING:
|
|
|
|
break;
|
|
|
|
case ST_REQSENT:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_ACKRCVD);
|
|
|
|
break;
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
case ST_ACKSENT:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_OPENED);
|
1998-05-21 21:49:08 +00:00
|
|
|
if ((*fp->fn->LayerUp)(fp))
|
|
|
|
(*fp->parent->LayerUp)(fp->parent->object, fp);
|
|
|
|
else {
|
|
|
|
(*fp->fn->LayerDown)(fp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_TRM_TIMER);
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmSendTerminateReq(fp);
|
|
|
|
NewState(fp, ST_CLOSING);
|
2000-07-19 02:10:35 +00:00
|
|
|
lcp_SendIdentification(&fp->link->lcp);
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_OPENED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerDown)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1997-08-25 00:29:32 +00:00
|
|
|
/* RCN */
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct fsm_decode dec;
|
1995-02-26 12:18:08 +00:00
|
|
|
int plen, flen;
|
1995-05-30 03:57:47 +00:00
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
plen = m_length(bp);
|
1997-12-24 09:29:17 +00:00
|
|
|
flen = ntohs(lhp->length) - sizeof *lhp;
|
1995-02-26 12:18:08 +00:00
|
|
|
if (plen < flen) {
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-08-25 00:29:32 +00:00
|
|
|
* Check and process easy case
|
1995-01-31 06:29:58 +00:00
|
|
|
*/
|
|
|
|
switch (fp->state) {
|
|
|
|
case ST_INITIAL:
|
|
|
|
case ST_STARTING:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n",
|
|
|
|
fp->link->name, State2Nam(fp->state));
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
case ST_CLOSED:
|
|
|
|
case ST_STOPPED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SendTerminateAck)(fp, lhp->id);
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
case ST_CLOSING:
|
|
|
|
case ST_STOPPING:
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_pullup(bp);
|
1998-05-21 21:49:08 +00:00
|
|
|
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");
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
switch (fp->state) {
|
|
|
|
case ST_REQSENT:
|
|
|
|
case ST_ACKSENT:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
break;
|
|
|
|
case ST_OPENED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerDown)(fp);
|
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
case ST_ACKRCVD:
|
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1997-08-25 00:29:32 +00:00
|
|
|
/* RTR */
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
switch (fp->state) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case ST_INITIAL:
|
|
|
|
case ST_STARTING:
|
|
|
|
log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n",
|
|
|
|
fp->link->name, State2Nam(fp->state));
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_CLOSED:
|
|
|
|
case ST_STOPPED:
|
|
|
|
case ST_CLOSING:
|
|
|
|
case ST_STOPPING:
|
|
|
|
case ST_REQSENT:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SendTerminateAck)(fp, lhp->id);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
case ST_ACKSENT:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SendTerminateAck)(fp, lhp->id);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
case ST_OPENED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerDown)(fp);
|
|
|
|
(*fp->fn->SendTerminateAck)(fp, lhp->id);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_TRM_TIMER);
|
|
|
|
timer_Start(&fp->FsmTimer); /* Start restart timer */
|
1997-06-02 00:04:40 +00:00
|
|
|
fp->restart = 0;
|
|
|
|
NewState(fp, ST_STOPPING);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
/* A delayed ST_STOPPED is now scheduled */
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1999-05-09 20:02:29 +00:00
|
|
|
FsmRecvTermAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1997-08-25 00:29:32 +00:00
|
|
|
/* RTA */
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
switch (fp->state) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case ST_CLOSING:
|
|
|
|
(*fp->fn->LayerFinish)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_CLOSED);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerFinish)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_STOPPING:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerFinish)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
NewState(fp, ST_STOPPED);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerFinish)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case ST_ACKRCVD:
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
case ST_OPENED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerDown)(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1997-08-25 00:29:32 +00:00
|
|
|
/* RCJ */
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct fsm_decode dec;
|
1995-02-26 12:18:08 +00:00
|
|
|
int plen, flen;
|
1995-05-30 03:57:47 +00:00
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
plen = m_length(bp);
|
1997-12-24 09:29:17 +00:00
|
|
|
flen = ntohs(lhp->length) - sizeof *lhp;
|
1995-02-26 12:18:08 +00:00
|
|
|
if (plen < flen) {
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-07-19 02:10:35 +00:00
|
|
|
lcp_SendIdentification(&fp->link->lcp);
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
/*
|
1997-08-25 00:29:32 +00:00
|
|
|
* Check and process easy case
|
1995-01-31 06:29:58 +00:00
|
|
|
*/
|
|
|
|
switch (fp->state) {
|
|
|
|
case ST_INITIAL:
|
|
|
|
case ST_STARTING:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n",
|
|
|
|
fp->link->name, State2Nam(fp->state));
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
case ST_CLOSED:
|
|
|
|
case ST_STOPPED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->SendTerminateAck)(fp, lhp->id);
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
case ST_CLOSING:
|
|
|
|
case ST_STOPPING:
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_pullup(bp);
|
1998-05-21 21:49:08 +00:00
|
|
|
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");
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
switch (fp->state) {
|
|
|
|
case ST_REQSENT:
|
|
|
|
case ST_ACKSENT:
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1995-01-31 06:29:58 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
break;
|
|
|
|
case ST_OPENED:
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->LayerDown)(fp);
|
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
case ST_ACKRCVD:
|
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
break;
|
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct physical *p = link2physical(fp->link);
|
1999-05-09 20:02:29 +00:00
|
|
|
u_short proto;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
if (m_length(bp) < 2) {
|
|
|
|
m_freem(bp);
|
1999-05-09 20:02:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
bp = mbuf_Read(bp, &proto, 2);
|
|
|
|
proto = ntohs(proto);
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
|
|
|
|
fp->link->name, proto, hdlc_Protocol2Nam(proto));
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
switch (proto) {
|
|
|
|
case PROTO_LQR:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (p)
|
|
|
|
lqr_Stop(p, LQM_LQR);
|
|
|
|
else
|
|
|
|
log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n",
|
|
|
|
fp->link->name);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case PROTO_CCP:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (fp->proto == PROTO_LCP) {
|
|
|
|
fp = &fp->link->ccp.fsm;
|
1999-03-01 02:52:39 +00:00
|
|
|
/* Despite the RFC (1661), don't do an out-of-place TLF */
|
|
|
|
/* (*fp->fn->LayerFinish)(fp); */
|
1998-05-21 21:49:08 +00:00
|
|
|
switch (fp->state) {
|
|
|
|
case ST_CLOSED:
|
|
|
|
case ST_CLOSING:
|
|
|
|
NewState(fp, ST_CLOSED);
|
|
|
|
default:
|
|
|
|
NewState(fp, ST_STOPPED);
|
|
|
|
break;
|
|
|
|
}
|
1999-03-01 02:52:39 +00:00
|
|
|
/* See above */
|
|
|
|
/* (*fp->parent->LayerFinish)(fp->parent->object, fp); */
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
|
|
|
break;
|
1999-08-10 08:42:20 +00:00
|
|
|
case PROTO_IPCP:
|
|
|
|
if (fp->proto == PROTO_LCP) {
|
|
|
|
log_Printf(LogPHASE, "%s: IPCP protocol reject closes IPCP !\n",
|
|
|
|
fp->link->name);
|
|
|
|
fsm_Close(&fp->bundle->ncp.ipcp.fsm);
|
|
|
|
}
|
|
|
|
break;
|
1998-05-21 21:49:08 +00:00
|
|
|
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);
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct lcp *lcp = fsm2lcp(fp);
|
1995-01-31 06:29:58 +00:00
|
|
|
u_char *cp;
|
1998-05-21 21:49:08 +00:00
|
|
|
u_int32_t magic;
|
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_pullup(bp);
|
|
|
|
m_settype(bp, MB_ECHOIN);
|
1999-11-06 22:50:59 +00:00
|
|
|
|
|
|
|
if (lcp && ntohs(lhp->length) - sizeof *lhp >= 4) {
|
1998-05-21 21:49:08 +00:00
|
|
|
cp = MBUF_CTOP(bp);
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_ntohl(cp, &magic);
|
1998-05-21 21:49:08 +00:00
|
|
|
if (magic != lcp->his_magic) {
|
1999-10-06 23:22:54 +00:00
|
|
|
log_Printf(fp->LogLevel, "%s: RecvEchoReq: magic 0x%08lx is wrong,"
|
|
|
|
" expecting 0x%08lx\n", fp->link->name, (u_long)magic,
|
|
|
|
(u_long)lcp->his_magic);
|
1998-05-21 21:49:08 +00:00
|
|
|
/* XXX: We should send terminate request */
|
|
|
|
}
|
|
|
|
if (fp->state == ST_OPENED) {
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_htonl(&lcp->want_magic, cp); /* local magic */
|
1999-11-06 22:50:59 +00:00
|
|
|
fsm_Output(fp, CODE_ECHOREP, lhp->id, cp,
|
|
|
|
ntohs(lhp->length) - sizeof *lhp, MB_ECHOOUT);
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
|
|
|
{
|
1999-05-14 09:36:06 +00:00
|
|
|
if (fsm2lcp(fp))
|
1999-05-09 20:02:29 +00:00
|
|
|
bp = lqr_RecvEcho(fp, bp);
|
1999-05-14 09:36:06 +00:00
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1999-05-09 20:02:29 +00:00
|
|
|
FsmRecvDiscReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1999-05-09 20:02:29 +00:00
|
|
|
FsmRecvIdent(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
2000-07-19 02:10:35 +00:00
|
|
|
u_int32_t magic;
|
|
|
|
u_short len;
|
|
|
|
u_char *cp;
|
|
|
|
|
|
|
|
len = ntohs(lhp->length) - sizeof *lhp;
|
|
|
|
if (len >= 4) {
|
|
|
|
bp = m_pullup(m_append(bp, "", 1));
|
|
|
|
cp = MBUF_CTOP(bp);
|
|
|
|
ua_ntohl(cp, &magic);
|
|
|
|
if (magic != fp->link->lcp.his_magic)
|
|
|
|
log_Printf(fp->LogLevel, "%s: RecvIdent: magic 0x%08lx is wrong,"
|
|
|
|
" expecting 0x%08lx\n", fp->link->name, (u_long)magic,
|
|
|
|
(u_long)fp->link->lcp.his_magic);
|
|
|
|
cp[len] = '\0';
|
|
|
|
lcp_RecvIdentification(&fp->link->lcp, cp + 4);
|
|
|
|
}
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1999-05-09 20:02:29 +00:00
|
|
|
FsmRecvTimeRemain(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
(*fp->fn->RecvResetReq)(fp);
|
Implement Reset{Req,Ack} properly, as per rfc 1962.
(I completely mis-read the rfc last time 'round!)
This means:
o Better CCP/WARN Reset diagnostics.
o After we've sent a REQ and before we've received an ACK, we drop
incoming compressed data and send another REQ.
o Before sending an ACK, re-sequence all pending PRI_NORMAL data in
the modem queue so that pending packets won't get to the peer
*after* the ResetAck.
o Send ACKs with the `identifier' from the REQ frame.
o After we've received a correct ACK, duplicate ACKs are ok (and will
reset our history).
o Incorrect ACKs (not matching the last REQ) are moaned about and dropped.
Also,
o Calculate the correct FCS after compressing a packet. DEFLATE
*may* produce an mbuf with more than a single link in the chain,
but HdlcOutput didn't know how to calculate the FCS :-(
o Make `struct fsm'::reqid a u_char, not an int.
This fix will prevent us from sending id `255' 2,000,000,000 times
before wrapping to `0' for another 2,000,000,000 sends :-/
o Bump the version number a little.
The end result: DEFLATE now works over an unreliable link layer.
I can txfr a 1.5Mb kernel over a (rather bad) null-modem
cable at an average of 21679 bytes per second using rcp.
Repeat after me: Don't test compression using a loopback ppp/tcp setup as
we never lose packets and therefore never have to reset!
1998-01-10 01:55:11 +00:00
|
|
|
/*
|
1999-09-04 00:00:21 +00:00
|
|
|
* All sendable compressed packets are queued in the first (lowest
|
|
|
|
* priority) modem output queue.... dump 'em to the priority queue
|
|
|
|
* so that they arrive at the peer before our ResetAck.
|
Implement Reset{Req,Ack} properly, as per rfc 1962.
(I completely mis-read the rfc last time 'round!)
This means:
o Better CCP/WARN Reset diagnostics.
o After we've sent a REQ and before we've received an ACK, we drop
incoming compressed data and send another REQ.
o Before sending an ACK, re-sequence all pending PRI_NORMAL data in
the modem queue so that pending packets won't get to the peer
*after* the ResetAck.
o Send ACKs with the `identifier' from the REQ frame.
o After we've received a correct ACK, duplicate ACKs are ok (and will
reset our history).
o Incorrect ACKs (not matching the last REQ) are moaned about and dropped.
Also,
o Calculate the correct FCS after compressing a packet. DEFLATE
*may* produce an mbuf with more than a single link in the chain,
but HdlcOutput didn't know how to calculate the FCS :-(
o Make `struct fsm'::reqid a u_char, not an int.
This fix will prevent us from sending id `255' 2,000,000,000 times
before wrapping to `0' for another 2,000,000,000 sends :-/
o Bump the version number a little.
The end result: DEFLATE now works over an unreliable link layer.
I can txfr a 1.5Mb kernel over a (rather bad) null-modem
cable at an average of 21679 bytes per second using rcp.
Repeat after me: Don't test compression using a loopback ppp/tcp setup as
we never lose packets and therefore never have to reset!
1998-01-10 01:55:11 +00:00
|
|
|
*/
|
1998-05-21 21:49:08 +00:00
|
|
|
link_SequenceQueue(fp->link);
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0, MB_CCPOUT);
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1997-10-26 01:04:02 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
|
|
|
{
|
|
|
|
(*fp->fn->RecvResetAck)(fp, lhp->id);
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
void
|
1998-05-21 21:49:08 +00:00
|
|
|
fsm_Input(struct fsm *fp, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
|
|
|
int len;
|
1999-05-08 11:07:56 +00:00
|
|
|
struct fsmheader lh;
|
1997-12-03 10:23:54 +00:00
|
|
|
const struct fsmcodedesc *codep;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
len = m_length(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
if (len < sizeof(struct fsmheader)) {
|
1999-12-20 20:29:47 +00:00
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-05-08 11:07:56 +00:00
|
|
|
bp = mbuf_Read(bp, &lh, sizeof lh);
|
1999-11-06 22:50:59 +00:00
|
|
|
|
2000-07-19 02:10:35 +00:00
|
|
|
if (ntohs(lh.length) > len) {
|
|
|
|
log_Printf(LogWARN, "%s: Oops: Got %d bytes but %d byte payload "
|
|
|
|
"- dropped\n", fp->link->name, len, (int)ntohs(lh.length));
|
|
|
|
m_freem(bp);
|
|
|
|
return;
|
2000-05-26 21:11:55 +00:00
|
|
|
}
|
1999-11-06 22:50:59 +00:00
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
if (lh.code < fp->min_code || lh.code > fp->max_code ||
|
|
|
|
lh.code > sizeof FsmCodes / sizeof *FsmCodes) {
|
1998-05-21 21:49:08 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
1998-06-15 19:06:58 +00:00
|
|
|
|
1999-12-20 20:29:47 +00:00
|
|
|
bp = m_prepend(bp, &lh, sizeof lh, 0);
|
|
|
|
bp = m_pullup(bp);
|
|
|
|
fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->m_len, MB_UNKNOWN);
|
|
|
|
m_freem(bp);
|
1995-01-31 06:29:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
codep = FsmCodes + lh.code - 1;
|
|
|
|
if (lh.id != fp->reqid && codep->check_reqid &&
|
1998-05-21 21:49:08 +00:00
|
|
|
Enabled(fp->bundle, OPT_IDCHECK)) {
|
|
|
|
log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n",
|
1999-05-08 11:07:56 +00:00
|
|
|
fp->link->name, codep->name, lh.id, fp->reqid);
|
1998-05-21 21:49:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n",
|
1999-05-08 11:07:56 +00:00
|
|
|
fp->link->name, codep->name, lh.id, State2Nam(fp->state));
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
if (codep->inc_reqid && (lh.id == fp->reqid ||
|
1998-05-21 21:49:08 +00:00
|
|
|
(!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid)))
|
|
|
|
fp->reqid++; /* That's the end of that ``exchange''.... */
|
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
(*codep->recv)(fp, &lh, bp);
|
1998-05-21 21:49:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1998-06-20 00:19:42 +00:00
|
|
|
|
1998-06-25 22:33:31 +00:00
|
|
|
void
|
|
|
|
fsm_Reopen(struct fsm *fp)
|
|
|
|
{
|
|
|
|
if (fp->state == ST_OPENED) {
|
|
|
|
(*fp->fn->LayerDown)(fp);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
|
1998-06-25 22:33:31 +00:00
|
|
|
FsmSendConfigReq(fp);
|
|
|
|
NewState(fp, ST_REQSENT);
|
|
|
|
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-06-20 00:19:42 +00:00
|
|
|
void
|
|
|
|
fsm2initial(struct fsm *fp)
|
|
|
|
{
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
timer_Stop(&fp->FsmTimer);
|
|
|
|
timer_Stop(&fp->OpenTimer);
|
|
|
|
timer_Stop(&fp->StoppedTimer);
|
1998-06-20 00:19:42 +00:00
|
|
|
if (fp->state == ST_STOPPED)
|
|
|
|
fsm_Close(fp);
|
|
|
|
if (fp->state > ST_INITIAL)
|
|
|
|
fsm_Down(fp);
|
|
|
|
if (fp->state > ST_INITIAL)
|
|
|
|
fsm_Close(fp);
|
|
|
|
}
|