2001-06-13 21:52:19 +00:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
|
|
|
|
* based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
|
|
|
|
* Internet Initiative Japan, Inc (IIJ)
|
|
|
|
* All rights reserved.
|
1995-01-31 06:29:58 +00:00
|
|
|
*
|
2001-06-13 21:52:19 +00:00
|
|
|
* 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.
|
1995-01-31 06:29:58 +00:00
|
|
|
*
|
2001-06-13 21:52:19 +00:00
|
|
|
* 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.
|
1995-01-31 06:29:58 +00:00
|
|
|
*
|
1999-08-28 01:35:59 +00:00
|
|
|
* $FreeBSD$
|
1995-01-31 06:29:58 +00:00
|
|
|
*/
|
1995-02-26 12:18:08 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
/*
|
|
|
|
* State of machine
|
|
|
|
*/
|
|
|
|
#define ST_INITIAL 0
|
|
|
|
#define ST_STARTING 1
|
|
|
|
#define ST_CLOSED 2
|
|
|
|
#define ST_STOPPED 3
|
|
|
|
#define ST_CLOSING 4
|
|
|
|
#define ST_STOPPING 5
|
|
|
|
#define ST_REQSENT 6
|
|
|
|
#define ST_ACKRCVD 7
|
|
|
|
#define ST_ACKSENT 8
|
|
|
|
#define ST_OPENED 9
|
|
|
|
|
|
|
|
#define ST_MAX 10
|
|
|
|
#define ST_UNDEF -1
|
|
|
|
|
|
|
|
#define MODE_REQ 0
|
|
|
|
#define MODE_NAK 1
|
|
|
|
#define MODE_REJ 2
|
1995-02-26 12:18:08 +00:00
|
|
|
#define MODE_NOP 3
|
1997-12-03 10:23:54 +00:00
|
|
|
#define MODE_ACK 4 /* pseudo mode for ccp negotiations */
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-01-20 22:47:48 +00:00
|
|
|
#define OPEN_PASSIVE -1
|
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
|
|
|
#define FSM_REQ_TIMER 1
|
|
|
|
#define FSM_TRM_TIMER 2
|
|
|
|
|
2002-04-16 23:57:09 +00:00
|
|
|
#define FSM_OPTLEN 100
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
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
|
|
|
struct fsm_retry {
|
|
|
|
u_int timeout; /* FSM retry frequency */
|
|
|
|
u_int maxreq; /* Max Config REQ retries */
|
|
|
|
u_int maxtrm; /* Max Term REQ retries */
|
|
|
|
};
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
struct fsm_decode {
|
2002-04-16 23:57:09 +00:00
|
|
|
u_char ack[FSM_OPTLEN], *ackend;
|
|
|
|
u_char nak[FSM_OPTLEN], *nakend;
|
|
|
|
u_char rej[FSM_OPTLEN], *rejend;
|
1998-05-21 21:49:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct fsm_callbacks {
|
2002-04-16 23:57:09 +00:00
|
|
|
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 (tls) */
|
|
|
|
void (*LayerFinish)(struct fsm *); /* Layer now down (tlf) */
|
|
|
|
void (*InitRestartCounter)(struct fsm *, int);/* 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 *, u_char *, int,
|
|
|
|
struct fsm_decode *); /* Deal with incoming data */
|
|
|
|
int (*RecvResetReq)(struct fsm *fp); /* Reset output */
|
|
|
|
void (*RecvResetAck)(struct fsm *fp, u_char); /* Reset input */
|
1998-05-21 21:49:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
struct fsm {
|
1997-11-22 03:37:54 +00:00
|
|
|
const char *name; /* Name of protocol */
|
1995-01-31 06:29:58 +00:00
|
|
|
u_short proto; /* Protocol number */
|
1998-05-21 21:49:08 +00:00
|
|
|
u_short min_code;
|
1995-01-31 06:29:58 +00:00
|
|
|
u_short max_code;
|
1998-05-21 21:49:08 +00:00
|
|
|
int open_mode; /* Delay before config REQ (-1 forever) */
|
1997-08-25 00:29:32 +00:00
|
|
|
int state; /* State of the machine */
|
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
|
|
|
u_char reqid; /* Next request id */
|
1997-08-25 00:29:32 +00:00
|
|
|
int restart; /* Restart counter value */
|
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
|
|
|
|
|
|
|
struct {
|
|
|
|
int reqs; /* Max config REQs before a close() */
|
|
|
|
int naks; /* Max config NAKs before a close() */
|
|
|
|
int rejs; /* Max config REJs before a close() */
|
|
|
|
} more;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
|
|
|
struct pppTimer FsmTimer; /* Restart Timer */
|
1998-01-20 22:47:48 +00:00
|
|
|
struct pppTimer OpenTimer; /* Delay before opening */
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-08-20 23:47:53 +00:00
|
|
|
/*
|
|
|
|
* This timer times the ST_STOPPED state out after the given value
|
1997-08-25 00:29:32 +00:00
|
|
|
* (specified via "set stopped ..."). Although this isn't specified in the
|
|
|
|
* rfc, the rfc *does* say that "the application may use higher level
|
|
|
|
* timers to avoid deadlock". The StoppedTimer takes effect when the other
|
|
|
|
* side ABENDs rather than going into ST_ACKSENT (and sending the ACK),
|
|
|
|
* causing ppp to time out and drop into ST_STOPPED. At this point,
|
|
|
|
* nothing will change this state :-(
|
1997-08-20 23:47:53 +00:00
|
|
|
*/
|
|
|
|
struct pppTimer StoppedTimer;
|
|
|
|
int LogLevel;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
/* 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;
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct fsmheader {
|
1997-08-25 00:29:32 +00:00
|
|
|
u_char code; /* Request code */
|
|
|
|
u_char id; /* Identification */
|
|
|
|
u_short length; /* Length of packet */
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define CODE_CONFIGREQ 1
|
|
|
|
#define CODE_CONFIGACK 2
|
|
|
|
#define CODE_CONFIGNAK 3
|
|
|
|
#define CODE_CONFIGREJ 4
|
|
|
|
#define CODE_TERMREQ 5
|
|
|
|
#define CODE_TERMACK 6
|
|
|
|
#define CODE_CODEREJ 7
|
|
|
|
#define CODE_PROTOREJ 8
|
1997-08-25 00:29:32 +00:00
|
|
|
#define CODE_ECHOREQ 9 /* Used in LCP */
|
|
|
|
#define CODE_ECHOREP 10 /* Used in LCP */
|
1995-01-31 06:29:58 +00:00
|
|
|
#define CODE_DISCREQ 11
|
1997-08-25 00:29:32 +00:00
|
|
|
#define CODE_IDENT 12 /* Used in LCP Extension */
|
|
|
|
#define CODE_TIMEREM 13 /* Used in LCP Extension */
|
|
|
|
#define CODE_RESETREQ 14 /* Used in CCP */
|
|
|
|
#define CODE_RESETACK 15 /* Used in CCP */
|
1995-01-31 06:29:58 +00:00
|
|
|
|
2002-04-16 23:57:09 +00:00
|
|
|
struct fsm_opt_hdr {
|
|
|
|
u_char id;
|
|
|
|
u_char len;
|
|
|
|
};
|
|
|
|
|
2002-05-22 21:17:13 +00:00
|
|
|
#define MAX_FSM_OPT_LEN 52
|
2002-04-16 23:57:09 +00:00
|
|
|
struct fsm_opt {
|
|
|
|
struct fsm_opt_hdr hdr;
|
|
|
|
u_char data[MAX_FSM_OPT_LEN-2];
|
1995-01-31 06:29:58 +00:00
|
|
|
};
|
|
|
|
|
2002-04-16 23:57:09 +00:00
|
|
|
#define INC_FSM_OPT(ty, length, o) \
|
|
|
|
do { \
|
|
|
|
(o)->hdr.id = (ty); \
|
|
|
|
(o)->hdr.len = (length); \
|
|
|
|
(o) = (struct fsm_opt *)((u_char *)(o) + (length)); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
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
|
|
|
extern void fsm_Init(struct fsm *, const char *, u_short, int, int, int,
|
1998-05-21 21:49:08 +00:00
|
|
|
struct bundle *, struct link *, const struct fsm_parent *,
|
1999-12-27 11:54:57 +00:00
|
|
|
struct fsm_callbacks *, const char * const [3]);
|
1999-06-02 15:59:09 +00:00
|
|
|
extern void fsm_Output(struct fsm *, u_int, u_int, u_char *, int, int);
|
1998-05-21 21:49:08 +00:00
|
|
|
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 *);
|
2001-06-18 15:00:22 +00:00
|
|
|
extern int fsm_NullRecvResetReq(struct fsm *);
|
1998-06-20 00:19:42 +00:00
|
|
|
extern void fsm_NullRecvResetAck(struct fsm *, u_char);
|
1998-06-25 22:33:31 +00:00
|
|
|
extern void fsm_Reopen(struct fsm *);
|
1998-06-20 00:19:42 +00:00
|
|
|
extern void fsm2initial(struct fsm *);
|
1998-05-21 21:49:08 +00:00
|
|
|
extern const char *State2Nam(u_int);
|
2002-04-16 23:57:09 +00:00
|
|
|
extern struct fsm_opt *fsm_readopt(u_char **);
|
|
|
|
extern void fsm_rej(struct fsm_decode *, const struct fsm_opt *);
|
|
|
|
extern void fsm_ack(struct fsm_decode *, const struct fsm_opt *);
|
|
|
|
extern void fsm_nak(struct fsm_decode *, const struct fsm_opt *);
|
|
|
|
extern void fsm_opt_normalise(struct fsm_decode *);
|