2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $FreeBSD: src/usr.sbin/ppp/fsm.c,v 1.52.2.8 2002/09/01 02:12:27 brian Exp $
29 * $DragonFly: src/usr.sbin/ppp/fsm.c,v 1.2 2003/06/17 04:30:00 dillon Exp $
32 #include <sys/param.h>
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #include <sys/socket.h>
52 #include "throughput.h"
53 #include "slcompress.h"
57 #include "descriptor.h"
72 static void FsmSendConfigReq(struct fsm
*);
73 static void FsmSendTerminateReq(struct fsm
*);
74 static void FsmInitRestartCounter(struct fsm
*, int);
76 typedef void (recvfn
)(struct fsm
*, struct fsmheader
*, struct mbuf
*);
77 static recvfn FsmRecvConfigReq
, FsmRecvConfigAck
, FsmRecvConfigNak
,
78 FsmRecvConfigRej
, FsmRecvTermReq
, FsmRecvTermAck
,
79 FsmRecvCodeRej
, FsmRecvProtoRej
, FsmRecvEchoReq
,
80 FsmRecvEchoRep
, FsmRecvDiscReq
, FsmRecvIdent
,
81 FsmRecvTimeRemain
, FsmRecvResetReq
, FsmRecvResetAck
;
83 static const struct fsmcodedesc
{
85 unsigned check_reqid
: 1;
86 unsigned inc_reqid
: 1;
89 { FsmRecvConfigReq
, 0, 0, "ConfigReq" },
90 { FsmRecvConfigAck
, 1, 1, "ConfigAck" },
91 { FsmRecvConfigNak
, 1, 1, "ConfigNak" },
92 { FsmRecvConfigRej
, 1, 1, "ConfigRej" },
93 { FsmRecvTermReq
, 0, 0, "TerminateReq" },
94 { FsmRecvTermAck
, 1, 1, "TerminateAck" },
95 { FsmRecvCodeRej
, 0, 0, "CodeRej" },
96 { FsmRecvProtoRej
, 0, 0, "ProtocolRej" },
97 { FsmRecvEchoReq
, 0, 0, "EchoRequest" },
98 { FsmRecvEchoRep
, 0, 0, "EchoReply" },
99 { FsmRecvDiscReq
, 0, 0, "DiscardReq" },
100 { FsmRecvIdent
, 0, 1, "Ident" },
101 { FsmRecvTimeRemain
,0, 0, "TimeRemain" },
102 { FsmRecvResetReq
, 0, 0, "ResetReq" },
103 { FsmRecvResetAck
, 0, 1, "ResetAck" }
109 if (code
== 0 || code
> sizeof FsmCodes
/ sizeof FsmCodes
[0])
111 return FsmCodes
[code
-1].name
;
115 State2Nam(u_int state
)
117 static const char * const StateNames
[] = {
118 "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
119 "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
122 if (state
>= sizeof StateNames
/ sizeof StateNames
[0])
124 return StateNames
[state
];
128 StoppedTimeout(void *v
)
130 struct fsm
*fp
= (struct fsm
*)v
;
132 log_Printf(fp
->LogLevel
, "%s: Stopped timer expired\n", fp
->link
->name
);
133 if (fp
->OpenTimer
.state
== TIMER_RUNNING
) {
134 log_Printf(LogWARN
, "%s: %s: aborting open delay due to stopped timer\n",
135 fp
->link
->name
, fp
->name
);
136 timer_Stop(&fp
->OpenTimer
);
138 if (fp
->state
== ST_STOPPED
)
143 fsm_Init(struct fsm
*fp
, const char *name
, u_short proto
, int mincode
,
144 int maxcode
, int LogLevel
, struct bundle
*bundle
,
145 struct link
*l
, const struct fsm_parent
*parent
,
146 struct fsm_callbacks
*fn
, const char * const timer_names
[3])
150 fp
->min_code
= mincode
;
151 fp
->max_code
= maxcode
;
152 fp
->state
= fp
->min_code
> CODE_TERMACK
? ST_OPENED
: ST_INITIAL
;
155 fp
->more
.reqs
= fp
->more
.naks
= fp
->more
.rejs
= 3;
156 memset(&fp
->FsmTimer
, '\0', sizeof fp
->FsmTimer
);
157 memset(&fp
->OpenTimer
, '\0', sizeof fp
->OpenTimer
);
158 memset(&fp
->StoppedTimer
, '\0', sizeof fp
->StoppedTimer
);
159 fp
->LogLevel
= LogLevel
;
164 fp
->FsmTimer
.name
= timer_names
[0];
165 fp
->OpenTimer
.name
= timer_names
[1];
166 fp
->StoppedTimer
.name
= timer_names
[2];
170 NewState(struct fsm
*fp
, int new)
172 log_Printf(fp
->LogLevel
, "%s: State change %s --> %s\n",
173 fp
->link
->name
, State2Nam(fp
->state
), State2Nam(new));
174 if (fp
->state
== ST_STOPPED
&& fp
->StoppedTimer
.state
== TIMER_RUNNING
)
175 timer_Stop(&fp
->StoppedTimer
);
177 if ((new >= ST_INITIAL
&& new <= ST_STOPPED
) || (new == ST_OPENED
)) {
178 timer_Stop(&fp
->FsmTimer
);
179 if (new == ST_STOPPED
&& fp
->StoppedTimer
.load
) {
180 timer_Stop(&fp
->StoppedTimer
);
181 fp
->StoppedTimer
.func
= StoppedTimeout
;
182 fp
->StoppedTimer
.arg
= (void *) fp
;
183 timer_Start(&fp
->StoppedTimer
);
189 fsm_Output(struct fsm
*fp
, u_int code
, u_int id
, u_char
*ptr
, unsigned count
,
196 if (log_IsKept(fp
->LogLevel
)) {
197 log_Printf(fp
->LogLevel
, "%s: Send%s(%d) state = %s\n",
198 fp
->link
->name
, Code2Nam(code
), id
, State2Nam(fp
->state
));
204 (*fp
->fn
->DecodeConfig
)(fp
, ptr
, ptr
+ count
, MODE_NOP
, NULL
);
205 if (count
< sizeof(struct fsm_opt_hdr
))
206 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
211 plen
= sizeof(struct fsmheader
) + count
;
214 lh
.length
= htons(plen
);
215 bp
= m_get(plen
, mtype
);
216 memcpy(MBUF_CTOP(bp
), &lh
, sizeof(struct fsmheader
));
218 memcpy(MBUF_CTOP(bp
) + sizeof(struct fsmheader
), ptr
, count
);
219 log_DumpBp(LogDEBUG
, "fsm_Output", bp
);
220 link_PushPacket(fp
->link
, bp
, fp
->bundle
, LINK_QUEUES(fp
->link
) - 1,
223 if (code
== CODE_CONFIGREJ
)
224 lcp_SendIdentification(&fp
->link
->lcp
);
230 struct fsm
*fp
= (struct fsm
*)v
;
232 timer_Stop(&fp
->OpenTimer
);
233 if (fp
->state
<= ST_STOPPED
) {
234 if (fp
->state
!= ST_STARTING
) {
236 * In practice, we're only here in ST_STOPPED (when delaying the
237 * first config request) or ST_CLOSED (when openmode == 0).
239 * The ST_STOPPED bit is breaking the RFC already :-(
241 * According to the RFC (1661) state transition table, a TLS isn't
242 * required for an Open event when state == Closed, but the RFC
243 * must be wrong as TLS hasn't yet been called (since the last TLF)
244 * ie, Initial gets an `Up' event, Closing gets a RTA etc.
246 (*fp
->fn
->LayerStart
)(fp
);
247 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
249 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
250 FsmSendConfigReq(fp
);
251 NewState(fp
, ST_REQSENT
);
256 fsm_Open(struct fsm
*fp
)
260 NewState(fp
, ST_STARTING
);
261 (*fp
->fn
->LayerStart
)(fp
);
262 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
265 if (fp
->open_mode
== OPEN_PASSIVE
) {
266 NewState(fp
, ST_STOPPED
); /* XXX: This is a hack ! */
267 } else if (fp
->open_mode
> 0) {
268 if (fp
->open_mode
> 1)
269 log_Printf(LogPHASE
, "%s: Entering STOPPED state for %d seconds\n",
270 fp
->link
->name
, fp
->open_mode
);
271 NewState(fp
, ST_STOPPED
); /* XXX: This is a not-so-bad hack ! */
272 timer_Stop(&fp
->OpenTimer
);
273 fp
->OpenTimer
.load
= fp
->open_mode
* SECTICKS
;
274 fp
->OpenTimer
.func
= FsmOpenNow
;
275 fp
->OpenTimer
.arg
= (void *)fp
;
276 timer_Start(&fp
->OpenTimer
);
280 case ST_STOPPED
: /* XXX: restart option */
284 case ST_OPENED
: /* XXX: restart option */
286 case ST_CLOSING
: /* XXX: restart option */
287 case ST_STOPPING
: /* XXX: restart option */
288 NewState(fp
, ST_STOPPING
);
294 fsm_Up(struct fsm
*fp
)
298 log_Printf(fp
->LogLevel
, "FSM: Using \"%s\" as a transport\n",
300 NewState(fp
, ST_CLOSED
);
303 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
304 FsmSendConfigReq(fp
);
305 NewState(fp
, ST_REQSENT
);
308 log_Printf(fp
->LogLevel
, "%s: Oops, Up at %s\n",
309 fp
->link
->name
, State2Nam(fp
->state
));
315 fsm_Down(struct fsm
*fp
)
319 NewState(fp
, ST_INITIAL
);
322 /* This TLF contradicts the RFC (1661), which ``misses it out'' ! */
323 (*fp
->fn
->LayerFinish
)(fp
);
324 NewState(fp
, ST_INITIAL
);
325 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
328 NewState(fp
, ST_STARTING
);
329 (*fp
->fn
->LayerStart
)(fp
);
330 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
336 NewState(fp
, ST_STARTING
);
339 (*fp
->fn
->LayerDown
)(fp
);
340 NewState(fp
, ST_STARTING
);
341 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
347 fsm_Close(struct fsm
*fp
)
351 (*fp
->fn
->LayerFinish
)(fp
);
352 NewState(fp
, ST_INITIAL
);
353 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
356 NewState(fp
, ST_CLOSED
);
359 NewState(fp
, ST_CLOSING
);
362 (*fp
->fn
->LayerDown
)(fp
);
363 if (fp
->state
== ST_OPENED
) {
364 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
365 FsmSendTerminateReq(fp
);
366 NewState(fp
, ST_CLOSING
);
367 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
373 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
374 FsmSendTerminateReq(fp
);
375 NewState(fp
, ST_CLOSING
);
384 FsmSendConfigReq(struct fsm
*fp
)
386 if (fp
->more
.reqs
-- > 0 && fp
->restart
-- > 0) {
387 (*fp
->fn
->SendConfigReq
)(fp
);
388 timer_Start(&fp
->FsmTimer
); /* Start restart timer */
390 if (fp
->more
.reqs
< 0)
391 log_Printf(LogPHASE
, "%s: Too many %s REQs sent - abandoning "
392 "negotiation\n", fp
->link
->name
, fp
->name
);
393 lcp_SendIdentification(&fp
->link
->lcp
);
399 FsmSendTerminateReq(struct fsm
*fp
)
401 fsm_Output(fp
, CODE_TERMREQ
, fp
->reqid
, NULL
, 0, MB_UNKNOWN
);
402 (*fp
->fn
->SentTerminateReq
)(fp
);
403 timer_Start(&fp
->FsmTimer
); /* Start restart timer */
404 fp
->restart
--; /* Decrement restart counter */
413 struct fsm
*fp
= (struct fsm
*)v
;
419 FsmSendTerminateReq(fp
);
423 FsmSendConfigReq(fp
);
426 FsmSendConfigReq(fp
);
427 NewState(fp
, ST_REQSENT
);
430 timer_Start(&fp
->FsmTimer
);
434 (*fp
->fn
->LayerFinish
)(fp
);
435 NewState(fp
, ST_CLOSED
);
436 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
439 (*fp
->fn
->LayerFinish
)(fp
);
440 NewState(fp
, ST_STOPPED
);
441 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
443 case ST_REQSENT
: /* XXX: 3p */
446 (*fp
->fn
->LayerFinish
)(fp
);
447 NewState(fp
, ST_STOPPED
);
448 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
455 FsmInitRestartCounter(struct fsm
*fp
, int what
)
457 timer_Stop(&fp
->FsmTimer
);
458 fp
->FsmTimer
.func
= FsmTimeout
;
459 fp
->FsmTimer
.arg
= (void *)fp
;
460 (*fp
->fn
->InitRestartCounter
)(fp
, what
);
464 * Actions when receive packets
467 FsmRecvConfigReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
470 struct fsm_decode dec
;
477 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
479 log_Printf(LogWARN
, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
480 fp
->link
->name
, plen
, flen
);
485 /* Some things must be done before we Decode the packet */
488 (*fp
->fn
->LayerDown
)(fp
);
491 dec
.ackend
= dec
.ack
;
492 dec
.nakend
= dec
.nak
;
493 dec
.rejend
= dec
.rej
;
495 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_REQ
, &dec
);
496 if (flen
< (int)sizeof(struct fsm_opt_hdr
))
497 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
499 if (dec
.nakend
== dec
.nak
&& dec
.rejend
== dec
.rej
)
502 /* Check and process easy case */
505 if (fp
->proto
== PROTO_CCP
&& fp
->link
->lcp
.fsm
.state
== ST_OPENED
) {
507 * ccp_SetOpenMode() leaves us in initial if we're disabling
508 * & denying everything.
510 bp
= m_prepend(bp
, lhp
, sizeof *lhp
, 2);
511 bp
= proto_Prepend(bp
, fp
->proto
, 0, 0);
513 lcp_SendProtoRej(&fp
->link
->lcp
, MBUF_CTOP(bp
), bp
->m_len
);
519 log_Printf(fp
->LogLevel
, "%s: Oops, RCR in %s.\n",
520 fp
->link
->name
, State2Nam(fp
->state
));
524 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
528 log_Printf(fp
->LogLevel
, "%s: Error: Got ConfigReq while state = %s\n",
529 fp
->link
->name
, State2Nam(fp
->state
));
534 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
537 FsmSendConfigReq(fp
);
541 if (dec
.rejend
!= dec
.rej
)
542 fsm_Output(fp
, CODE_CONFIGREJ
, lhp
->id
, dec
.rej
, dec
.rejend
- dec
.rej
,
544 if (dec
.nakend
!= dec
.nak
)
545 fsm_Output(fp
, CODE_CONFIGNAK
, lhp
->id
, dec
.nak
, dec
.nakend
- dec
.nak
,
548 fsm_Output(fp
, CODE_CONFIGACK
, lhp
->id
, dec
.ack
, dec
.ackend
- dec
.ack
,
554 * According to the RFC (1661) state transition table, a TLS isn't
555 * required for a RCR when state == ST_STOPPED, but the RFC
556 * must be wrong as TLS hasn't yet been called (since the last TLF)
558 (*fp
->fn
->LayerStart
)(fp
);
559 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
564 NewState(fp
, ST_ACKSENT
);
566 NewState(fp
, ST_REQSENT
);
567 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
571 NewState(fp
, ST_ACKSENT
);
575 NewState(fp
, ST_OPENED
);
576 if ((*fp
->fn
->LayerUp
)(fp
))
577 (*fp
->parent
->LayerUp
)(fp
->parent
->object
, fp
);
579 (*fp
->fn
->LayerDown
)(fp
);
580 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
581 FsmSendTerminateReq(fp
);
582 NewState(fp
, ST_CLOSING
);
583 lcp_SendIdentification(&fp
->link
->lcp
);
589 NewState(fp
, ST_REQSENT
);
594 if (dec
.rejend
!= dec
.rej
&& --fp
->more
.rejs
<= 0) {
595 log_Printf(LogPHASE
, "%s: Too many %s REJs sent - abandoning negotiation\n",
596 fp
->link
->name
, fp
->name
);
597 lcp_SendIdentification(&fp
->link
->lcp
);
601 if (dec
.nakend
!= dec
.nak
&& --fp
->more
.naks
<= 0) {
602 log_Printf(LogPHASE
, "%s: Too many %s NAKs sent - abandoning negotiation\n",
603 fp
->link
->name
, fp
->name
);
604 lcp_SendIdentification(&fp
->link
->lcp
);
610 FsmRecvConfigAck(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
613 struct fsm_decode dec
;
618 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
625 dec
.ackend
= dec
.ack
;
626 dec
.nakend
= dec
.nak
;
627 dec
.rejend
= dec
.rej
;
629 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_ACK
, &dec
);
630 if (flen
< (int)sizeof(struct fsm_opt_hdr
))
631 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
636 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
642 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
643 NewState(fp
, ST_ACKRCVD
);
646 FsmSendConfigReq(fp
);
647 NewState(fp
, ST_REQSENT
);
650 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
651 NewState(fp
, ST_OPENED
);
652 if ((*fp
->fn
->LayerUp
)(fp
))
653 (*fp
->parent
->LayerUp
)(fp
->parent
->object
, fp
);
655 (*fp
->fn
->LayerDown
)(fp
);
656 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
657 FsmSendTerminateReq(fp
);
658 NewState(fp
, ST_CLOSING
);
659 lcp_SendIdentification(&fp
->link
->lcp
);
663 (*fp
->fn
->LayerDown
)(fp
);
664 FsmSendConfigReq(fp
);
665 NewState(fp
, ST_REQSENT
);
666 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
673 FsmRecvConfigNak(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
676 struct fsm_decode dec
;
681 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
688 * Check and process easy case
693 log_Printf(fp
->LogLevel
, "%s: Oops, RCN in %s.\n",
694 fp
->link
->name
, State2Nam(fp
->state
));
699 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
709 dec
.ackend
= dec
.ack
;
710 dec
.nakend
= dec
.nak
;
711 dec
.rejend
= dec
.rej
;
713 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_NAK
, &dec
);
714 if (flen
< (int)sizeof(struct fsm_opt_hdr
))
715 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
720 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
721 FsmSendConfigReq(fp
);
724 (*fp
->fn
->LayerDown
)(fp
);
725 FsmSendConfigReq(fp
);
726 NewState(fp
, ST_REQSENT
);
727 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
730 FsmSendConfigReq(fp
);
731 NewState(fp
, ST_REQSENT
);
739 FsmRecvTermReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
745 log_Printf(fp
->LogLevel
, "%s: Oops, RTR in %s\n",
746 fp
->link
->name
, State2Nam(fp
->state
));
753 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
757 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
758 NewState(fp
, ST_REQSENT
);
761 (*fp
->fn
->LayerDown
)(fp
);
762 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
763 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
764 timer_Start(&fp
->FsmTimer
); /* Start restart timer */
766 NewState(fp
, ST_STOPPING
);
767 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
768 /* A delayed ST_STOPPED is now scheduled */
775 FsmRecvTermAck(struct fsm
*fp
, struct fsmheader
*lhp __unused
, struct mbuf
*bp
)
780 (*fp
->fn
->LayerFinish
)(fp
);
781 NewState(fp
, ST_CLOSED
);
782 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
785 (*fp
->fn
->LayerFinish
)(fp
);
786 NewState(fp
, ST_STOPPED
);
787 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
790 NewState(fp
, ST_REQSENT
);
793 (*fp
->fn
->LayerDown
)(fp
);
794 FsmSendConfigReq(fp
);
795 NewState(fp
, ST_REQSENT
);
796 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
803 FsmRecvConfigRej(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
806 struct fsm_decode dec
;
812 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
813 if ((int)plen
< flen
) {
818 lcp_SendIdentification(&fp
->link
->lcp
);
821 * Check and process easy case
826 log_Printf(fp
->LogLevel
, "%s: Oops, RCJ in %s.\n",
827 fp
->link
->name
, State2Nam(fp
->state
));
832 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
842 dec
.ackend
= dec
.ack
;
843 dec
.nakend
= dec
.nak
;
844 dec
.rejend
= dec
.rej
;
846 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_REJ
, &dec
);
847 if (flen
< (int)sizeof(struct fsm_opt_hdr
))
848 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
853 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
854 FsmSendConfigReq(fp
);
857 (*fp
->fn
->LayerDown
)(fp
);
858 FsmSendConfigReq(fp
);
859 NewState(fp
, ST_REQSENT
);
860 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
863 FsmSendConfigReq(fp
);
864 NewState(fp
, ST_REQSENT
);
871 FsmRecvCodeRej(struct fsm
*fp __unused
, struct fsmheader
*lhp __unused
,
878 FsmRecvProtoRej(struct fsm
*fp
, struct fsmheader
*lhp __unused
, struct mbuf
*bp
)
880 struct physical
*p
= link2physical(fp
->link
);
883 if (m_length(bp
) < 2) {
887 bp
= mbuf_Read(bp
, &proto
, 2);
888 proto
= ntohs(proto
);
889 log_Printf(fp
->LogLevel
, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
890 fp
->link
->name
, proto
, hdlc_Protocol2Nam(proto
));
895 lqr_Stop(p
, LQM_LQR
);
897 log_Printf(LogERROR
, "%s: FsmRecvProtoRej: Not a physical link !\n",
901 if (fp
->proto
== PROTO_LCP
) {
902 fp
= &fp
->link
->ccp
.fsm
;
903 /* Despite the RFC (1661), don't do an out-of-place TLF */
904 /* (*fp->fn->LayerFinish)(fp); */
908 NewState(fp
, ST_CLOSED
);
911 NewState(fp
, ST_STOPPED
);
915 /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */
919 if (fp
->proto
== PROTO_LCP
) {
920 log_Printf(LogPHASE
, "%s: IPCP protocol reject closes IPCP !\n",
922 fsm_Close(&fp
->bundle
->ncp
.ipcp
.fsm
);
927 if (fp
->proto
== PROTO_LCP
) {
928 log_Printf(LogPHASE
, "%s: IPV6CP protocol reject closes IPV6CP !\n",
930 fsm_Close(&fp
->bundle
->ncp
.ipv6cp
.fsm
);
935 if (fp
->proto
== PROTO_LCP
) {
936 struct lcp
*lcp
= fsm2lcp(fp
);
938 if (lcp
->want_mrru
&& lcp
->his_mrru
) {
939 log_Printf(LogPHASE
, "%s: MP protocol reject is fatal !\n",
950 FsmRecvEchoReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
952 struct lcp
*lcp
= fsm2lcp(fp
);
957 m_settype(bp
, MB_ECHOIN
);
959 if (lcp
&& ntohs(lhp
->length
) - sizeof *lhp
>= 4) {
961 ua_ntohl(cp
, &magic
);
962 if (magic
!= lcp
->his_magic
) {
963 log_Printf(fp
->LogLevel
, "%s: RecvEchoReq: magic 0x%08lx is wrong,"
964 " expecting 0x%08lx\n", fp
->link
->name
, (u_long
)magic
,
965 (u_long
)lcp
->his_magic
);
966 /* XXX: We should send terminate request */
968 if (fp
->state
== ST_OPENED
) {
969 ua_htonl(&lcp
->want_magic
, cp
); /* local magic */
970 fsm_Output(fp
, CODE_ECHOREP
, lhp
->id
, cp
,
971 ntohs(lhp
->length
) - sizeof *lhp
, MB_ECHOOUT
);
978 FsmRecvEchoRep(struct fsm
*fp
, struct fsmheader
*lhp __unused
, struct mbuf
*bp
)
981 bp
= lqr_RecvEcho(fp
, bp
);
987 FsmRecvDiscReq(struct fsm
*fp __unused
, struct fsmheader
*lhp __unused
,
994 FsmRecvIdent(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1000 len
= ntohs(lhp
->length
) - sizeof *lhp
;
1002 bp
= m_pullup(m_append(bp
, "", 1));
1004 ua_ntohl(cp
, &magic
);
1005 if (magic
!= fp
->link
->lcp
.his_magic
)
1006 log_Printf(fp
->LogLevel
, "%s: RecvIdent: magic 0x%08lx is wrong,"
1007 " expecting 0x%08lx\n", fp
->link
->name
, (u_long
)magic
,
1008 (u_long
)fp
->link
->lcp
.his_magic
);
1010 lcp_RecvIdentification(&fp
->link
->lcp
, cp
+ 4);
1016 FsmRecvTimeRemain(struct fsm
*fp __unused
, struct fsmheader
*lhp __unused
,
1023 FsmRecvResetReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1025 if ((*fp
->fn
->RecvResetReq
)(fp
)) {
1027 * All sendable compressed packets are queued in the first (lowest
1028 * priority) modem output queue.... dump 'em to the priority queue
1029 * so that they arrive at the peer before our ResetAck.
1031 link_SequenceQueue(fp
->link
);
1032 fsm_Output(fp
, CODE_RESETACK
, lhp
->id
, NULL
, 0, MB_CCPOUT
);
1038 FsmRecvResetAck(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1040 (*fp
->fn
->RecvResetAck
)(fp
, lhp
->id
);
1045 fsm_Input(struct fsm
*fp
, struct mbuf
*bp
)
1048 struct fsmheader lh
;
1049 const struct fsmcodedesc
*codep
;
1052 if (len
< sizeof(struct fsmheader
)) {
1056 bp
= mbuf_Read(bp
, &lh
, sizeof lh
);
1058 if (ntohs(lh
.length
) > len
) {
1059 log_Printf(LogWARN
, "%s: Oops: Got %zu bytes but %d byte payload "
1060 "- dropped\n", fp
->link
->name
, len
, (int)ntohs(lh
.length
));
1065 if (lh
.code
< fp
->min_code
|| lh
.code
> fp
->max_code
||
1066 lh
.code
> sizeof FsmCodes
/ sizeof *FsmCodes
) {
1068 * Use a private id. This is really a response-type packet, but we
1069 * MUST send a unique id for each REQ....
1073 bp
= m_prepend(bp
, &lh
, sizeof lh
, 0);
1075 fsm_Output(fp
, CODE_CODEREJ
, id
++, MBUF_CTOP(bp
), bp
->m_len
, MB_UNKNOWN
);
1080 codep
= FsmCodes
+ lh
.code
- 1;
1081 if (lh
.id
!= fp
->reqid
&& codep
->check_reqid
&&
1082 Enabled(fp
->bundle
, OPT_IDCHECK
)) {
1083 log_Printf(fp
->LogLevel
, "%s: Recv%s(%d), dropped (expected %d)\n",
1084 fp
->link
->name
, codep
->name
, lh
.id
, fp
->reqid
);
1088 log_Printf(fp
->LogLevel
, "%s: Recv%s(%d) state = %s\n",
1089 fp
->link
->name
, codep
->name
, lh
.id
, State2Nam(fp
->state
));
1091 if (codep
->inc_reqid
&& (lh
.id
== fp
->reqid
||
1092 (!Enabled(fp
->bundle
, OPT_IDCHECK
) && codep
->check_reqid
)))
1093 fp
->reqid
++; /* That's the end of that ``exchange''.... */
1095 (*codep
->recv
)(fp
, &lh
, bp
);
1099 fsm_NullRecvResetReq(struct fsm
*fp
)
1101 log_Printf(fp
->LogLevel
, "%s: Oops - received unexpected reset req\n",
1107 fsm_NullRecvResetAck(struct fsm
*fp
, u_char id __unused
)
1109 log_Printf(fp
->LogLevel
, "%s: Oops - received unexpected reset ack\n",
1114 fsm_Reopen(struct fsm
*fp
)
1116 if (fp
->state
== ST_OPENED
) {
1117 (*fp
->fn
->LayerDown
)(fp
);
1118 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
1119 FsmSendConfigReq(fp
);
1120 NewState(fp
, ST_REQSENT
);
1121 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
1126 fsm2initial(struct fsm
*fp
)
1128 timer_Stop(&fp
->FsmTimer
);
1129 timer_Stop(&fp
->OpenTimer
);
1130 timer_Stop(&fp
->StoppedTimer
);
1131 if (fp
->state
== ST_STOPPED
)
1133 if (fp
->state
> ST_INITIAL
)
1135 if (fp
->state
> ST_INITIAL
)
1140 fsm_readopt(u_char
**cp
)
1142 struct fsm_opt
*o
= (struct fsm_opt
*)*cp
;
1144 if (o
->hdr
.len
< sizeof(struct fsm_opt_hdr
)) {
1145 log_Printf(LogERROR
, "Bad option length %d (out of phase?)\n", o
->hdr
.len
);
1151 if (o
->hdr
.len
> sizeof(struct fsm_opt
)) {
1152 log_Printf(LogERROR
, "Warning: Truncating option length from %d to %d\n",
1153 o
->hdr
.len
, (int)sizeof(struct fsm_opt
));
1154 o
->hdr
.len
= sizeof(struct fsm_opt
);
1161 fsm_opt(u_char
*opt
, int optlen
, const struct fsm_opt
*o
)
1163 unsigned cplen
= o
->hdr
.len
;
1165 if (optlen
< (int)sizeof(struct fsm_opt_hdr
))
1168 if ((int)cplen
> optlen
) {
1169 log_Printf(LogERROR
, "Can't REJ length %d - trunating to %d\n",
1173 memcpy(opt
, o
, cplen
);
1181 fsm_rej(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1185 dec
->rejend
+= fsm_opt(dec
->rejend
, FSM_OPTLEN
- (dec
->rejend
- dec
->rej
), o
);
1189 fsm_ack(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1193 dec
->ackend
+= fsm_opt(dec
->ackend
, FSM_OPTLEN
- (dec
->ackend
- dec
->ack
), o
);
1197 fsm_nak(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1201 dec
->nakend
+= fsm_opt(dec
->nakend
, FSM_OPTLEN
- (dec
->nakend
- dec
->nak
), o
);
1205 fsm_opt_normalise(struct fsm_decode
*dec
)
1207 if (dec
->rejend
!= dec
->rej
) {
1208 /* rejects are preferred */
1209 dec
->ackend
= dec
->ack
;
1210 dec
->nakend
= dec
->nak
;
1211 } else if (dec
->nakend
!= dec
->nak
)
1213 dec
->ackend
= dec
->ack
;