165309e5cSBrian Somers /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 465309e5cSBrian Somers * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 565309e5cSBrian Somers * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 665309e5cSBrian Somers * Internet Initiative Japan, Inc (IIJ) 765309e5cSBrian Somers * All rights reserved. 8af57ed9fSAtsushi Murai * 965309e5cSBrian Somers * Redistribution and use in source and binary forms, with or without 1065309e5cSBrian Somers * modification, are permitted provided that the following conditions 1165309e5cSBrian Somers * are met: 1265309e5cSBrian Somers * 1. Redistributions of source code must retain the above copyright 1365309e5cSBrian Somers * notice, this list of conditions and the following disclaimer. 1465309e5cSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 1565309e5cSBrian Somers * notice, this list of conditions and the following disclaimer in the 1665309e5cSBrian Somers * documentation and/or other materials provided with the distribution. 17af57ed9fSAtsushi Murai * 1865309e5cSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1965309e5cSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2065309e5cSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2165309e5cSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2265309e5cSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2365309e5cSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2465309e5cSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2565309e5cSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2665309e5cSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2765309e5cSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2865309e5cSBrian Somers * SUCH DAMAGE. 29af57ed9fSAtsushi Murai */ 3053c9f6c0SAtsushi Murai 31af57ed9fSAtsushi Murai /* 32af57ed9fSAtsushi Murai * State of machine 33af57ed9fSAtsushi Murai */ 34af57ed9fSAtsushi Murai #define ST_INITIAL 0 35af57ed9fSAtsushi Murai #define ST_STARTING 1 36af57ed9fSAtsushi Murai #define ST_CLOSED 2 37af57ed9fSAtsushi Murai #define ST_STOPPED 3 38af57ed9fSAtsushi Murai #define ST_CLOSING 4 39af57ed9fSAtsushi Murai #define ST_STOPPING 5 40af57ed9fSAtsushi Murai #define ST_REQSENT 6 41af57ed9fSAtsushi Murai #define ST_ACKRCVD 7 42af57ed9fSAtsushi Murai #define ST_ACKSENT 8 43af57ed9fSAtsushi Murai #define ST_OPENED 9 44af57ed9fSAtsushi Murai 45af57ed9fSAtsushi Murai #define ST_MAX 10 46af57ed9fSAtsushi Murai #define ST_UNDEF -1 47af57ed9fSAtsushi Murai 48af57ed9fSAtsushi Murai #define MODE_REQ 0 49af57ed9fSAtsushi Murai #define MODE_NAK 1 50af57ed9fSAtsushi Murai #define MODE_REJ 2 5153c9f6c0SAtsushi Murai #define MODE_NOP 3 520053cc58SBrian Somers #define MODE_ACK 4 /* pseudo mode for ccp negotiations */ 53af57ed9fSAtsushi Murai 5449b239e0SBrian Somers #define OPEN_PASSIVE -1 55af57ed9fSAtsushi Murai 56479508cfSBrian Somers #define FSM_REQ_TIMER 1 57479508cfSBrian Somers #define FSM_TRM_TIMER 2 58479508cfSBrian Somers 59ff360cc9SBrian Somers #define FSM_OPTLEN 100 60ff360cc9SBrian Somers 6183d1af55SBrian Somers struct fsm; 6283d1af55SBrian Somers 63479508cfSBrian Somers struct fsm_retry { 64479508cfSBrian Somers u_int timeout; /* FSM retry frequency */ 65479508cfSBrian Somers u_int maxreq; /* Max Config REQ retries */ 66479508cfSBrian Somers u_int maxtrm; /* Max Term REQ retries */ 67479508cfSBrian Somers }; 68479508cfSBrian Somers 6930c2f2ffSBrian Somers struct fsm_decode { 70ff360cc9SBrian Somers u_char ack[FSM_OPTLEN], *ackend; 71ff360cc9SBrian Somers u_char nak[FSM_OPTLEN], *nakend; 72ff360cc9SBrian Somers u_char rej[FSM_OPTLEN], *rejend; 7330c2f2ffSBrian Somers }; 7430c2f2ffSBrian Somers 756d666775SBrian Somers struct fsm_callbacks { 766f384573SBrian Somers int (*LayerUp)(struct fsm *); /* Layer is now up (tlu) */ 7783d1af55SBrian Somers void (*LayerDown)(struct fsm *); /* About to come down (tld) */ 78ff360cc9SBrian Somers void (*LayerStart)(struct fsm *); /* Layer about to start (tls) */ 7983d1af55SBrian Somers void (*LayerFinish)(struct fsm *); /* Layer now down (tlf) */ 80479508cfSBrian Somers void (*InitRestartCounter)(struct fsm *, int);/* Set fsm timer load */ 8183d1af55SBrian Somers void (*SendConfigReq)(struct fsm *); /* Send REQ please */ 822267893fSBrian Somers void (*SentTerminateReq)(struct fsm *); /* Term REQ just sent */ 832267893fSBrian Somers void (*SendTerminateAck)(struct fsm *, u_char); /* Send Term ACK please */ 84ff360cc9SBrian Somers void (*DecodeConfig)(struct fsm *, u_char *, u_char *, int, 85ff360cc9SBrian Somers struct fsm_decode *); /* Deal with incoming data */ 866cf6ee76SBrian Somers int (*RecvResetReq)(struct fsm *fp); /* Reset output */ 87503a7782SBrian Somers void (*RecvResetAck)(struct fsm *fp, u_char); /* Reset input */ 8883d1af55SBrian Somers }; 8983d1af55SBrian Somers 906d666775SBrian Somers struct fsm_parent { 916d666775SBrian Somers void (*LayerStart) (void *, struct fsm *); /* tls */ 926d666775SBrian Somers void (*LayerUp) (void *, struct fsm *); /* tlu */ 936d666775SBrian Somers void (*LayerDown) (void *, struct fsm *); /* tld */ 946d666775SBrian Somers void (*LayerFinish) (void *, struct fsm *); /* tlf */ 956d666775SBrian Somers void *object; 966d666775SBrian Somers }; 976d666775SBrian Somers 982764b86aSBrian Somers struct link; 992764b86aSBrian Somers struct bundle; 1002764b86aSBrian Somers 101af57ed9fSAtsushi Murai struct fsm { 102b6e82f33SBrian Somers const char *name; /* Name of protocol */ 103af57ed9fSAtsushi Murai u_short proto; /* Protocol number */ 1043b0f8d2eSBrian Somers u_short min_code; 105af57ed9fSAtsushi Murai u_short max_code; 1067308ec68SBrian Somers int open_mode; /* Delay before config REQ (-1 forever) */ 107057f1760SBrian Somers unsigned state; /* State of the machine */ 10898baf7c8SBrian Somers u_char reqid; /* Next request id */ 109af57ed9fSAtsushi Murai int restart; /* Restart counter value */ 110479508cfSBrian Somers 111479508cfSBrian Somers struct { 112479508cfSBrian Somers int reqs; /* Max config REQs before a close() */ 113479508cfSBrian Somers int naks; /* Max config NAKs before a close() */ 114479508cfSBrian Somers int rejs; /* Max config REJs before a close() */ 115479508cfSBrian Somers } more; 116af57ed9fSAtsushi Murai 117af57ed9fSAtsushi Murai struct pppTimer FsmTimer; /* Restart Timer */ 11849b239e0SBrian Somers struct pppTimer OpenTimer; /* Delay before opening */ 119af57ed9fSAtsushi Murai 120cb611434SBrian Somers /* 121cb611434SBrian Somers * This timer times the ST_STOPPED state out after the given value 122944f7098SBrian Somers * (specified via "set stopped ..."). Although this isn't specified in the 123944f7098SBrian Somers * rfc, the rfc *does* say that "the application may use higher level 124944f7098SBrian Somers * timers to avoid deadlock". The StoppedTimer takes effect when the other 125944f7098SBrian Somers * side ABENDs rather than going into ST_ACKSENT (and sending the ACK), 126944f7098SBrian Somers * causing ppp to time out and drop into ST_STOPPED. At this point, 127944f7098SBrian Somers * nothing will change this state :-( 128cb611434SBrian Somers */ 129cb611434SBrian Somers struct pppTimer StoppedTimer; 130cb611434SBrian Somers int LogLevel; 131cb611434SBrian Somers 1327a6f8720SBrian Somers /* The link layer active with this FSM (may be our bundle below) */ 1338c07a7b2SBrian Somers struct link *link; 13463b73463SBrian Somers 1357a6f8720SBrian Somers /* Our high-level link */ 1367a6f8720SBrian Somers struct bundle *bundle; 1377a6f8720SBrian Somers 1386d666775SBrian Somers const struct fsm_parent *parent; 13983d1af55SBrian Somers const struct fsm_callbacks *fn; 140af57ed9fSAtsushi Murai }; 141af57ed9fSAtsushi Murai 142af57ed9fSAtsushi Murai struct fsmheader { 143af57ed9fSAtsushi Murai u_char code; /* Request code */ 144af57ed9fSAtsushi Murai u_char id; /* Identification */ 145af57ed9fSAtsushi Murai u_short length; /* Length of packet */ 146af57ed9fSAtsushi Murai }; 147af57ed9fSAtsushi Murai 148af57ed9fSAtsushi Murai #define CODE_CONFIGREQ 1 149af57ed9fSAtsushi Murai #define CODE_CONFIGACK 2 150af57ed9fSAtsushi Murai #define CODE_CONFIGNAK 3 151af57ed9fSAtsushi Murai #define CODE_CONFIGREJ 4 152af57ed9fSAtsushi Murai #define CODE_TERMREQ 5 153af57ed9fSAtsushi Murai #define CODE_TERMACK 6 154af57ed9fSAtsushi Murai #define CODE_CODEREJ 7 155af57ed9fSAtsushi Murai #define CODE_PROTOREJ 8 156af57ed9fSAtsushi Murai #define CODE_ECHOREQ 9 /* Used in LCP */ 157af57ed9fSAtsushi Murai #define CODE_ECHOREP 10 /* Used in LCP */ 158af57ed9fSAtsushi Murai #define CODE_DISCREQ 11 159af57ed9fSAtsushi Murai #define CODE_IDENT 12 /* Used in LCP Extension */ 160af57ed9fSAtsushi Murai #define CODE_TIMEREM 13 /* Used in LCP Extension */ 161af57ed9fSAtsushi Murai #define CODE_RESETREQ 14 /* Used in CCP */ 162af57ed9fSAtsushi Murai #define CODE_RESETACK 15 /* Used in CCP */ 163af57ed9fSAtsushi Murai 164ff360cc9SBrian Somers struct fsm_opt_hdr { 165ff360cc9SBrian Somers u_char id; 166ff360cc9SBrian Somers u_char len; 167f219cbb7SBernd Walter } __packed; 168af57ed9fSAtsushi Murai 169d4ff125fSBrian Somers #define MAX_FSM_OPT_LEN 52 170ff360cc9SBrian Somers struct fsm_opt { 171ff360cc9SBrian Somers struct fsm_opt_hdr hdr; 172ff360cc9SBrian Somers u_char data[MAX_FSM_OPT_LEN-2]; 173ff360cc9SBrian Somers }; 174ff360cc9SBrian Somers 175ff360cc9SBrian Somers #define INC_FSM_OPT(ty, length, o) \ 176ff360cc9SBrian Somers do { \ 177ff360cc9SBrian Somers (o)->hdr.id = (ty); \ 178ff360cc9SBrian Somers (o)->hdr.len = (length); \ 179ff360cc9SBrian Somers (o) = (struct fsm_opt *)((u_char *)(o) + (length)); \ 180ff360cc9SBrian Somers } while (0) 181ff360cc9SBrian Somers 182ff360cc9SBrian Somers 183479508cfSBrian Somers extern void fsm_Init(struct fsm *, const char *, u_short, int, int, int, 1846d666775SBrian Somers struct bundle *, struct link *, const struct fsm_parent *, 185182c898aSBrian Somers struct fsm_callbacks *, const char * const [3]); 186057f1760SBrian Somers extern void fsm_Output(struct fsm *, u_int, u_int, u_char *, unsigned, int); 187dd7e2610SBrian Somers extern void fsm_Open(struct fsm *); 188dd7e2610SBrian Somers extern void fsm_Up(struct fsm *); 189dd7e2610SBrian Somers extern void fsm_Down(struct fsm *); 190dd7e2610SBrian Somers extern void fsm_Input(struct fsm *, struct mbuf *); 191dd7e2610SBrian Somers extern void fsm_Close(struct fsm *); 1926cf6ee76SBrian Somers extern int fsm_NullRecvResetReq(struct fsm *); 19309206a6fSBrian Somers extern void fsm_NullRecvResetAck(struct fsm *, u_char); 194897f9429SBrian Somers extern void fsm_Reopen(struct fsm *); 19509206a6fSBrian Somers extern void fsm2initial(struct fsm *); 1961e991daaSBrian Somers extern const char *State2Nam(u_int); 197ff360cc9SBrian Somers extern struct fsm_opt *fsm_readopt(u_char **); 198ff360cc9SBrian Somers extern void fsm_rej(struct fsm_decode *, const struct fsm_opt *); 199ff360cc9SBrian Somers extern void fsm_ack(struct fsm_decode *, const struct fsm_opt *); 200ff360cc9SBrian Somers extern void fsm_nak(struct fsm_decode *, const struct fsm_opt *); 201ff360cc9SBrian Somers extern void fsm_opt_normalise(struct fsm_decode *); 202