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
, int 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
< 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
< 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
< 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
, 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
;
811 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
817 lcp_SendIdentification(&fp
->link
->lcp
);
820 * Check and process easy case
825 log_Printf(fp
->LogLevel
, "%s: Oops, RCJ in %s.\n",
826 fp
->link
->name
, State2Nam(fp
->state
));
831 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
841 dec
.ackend
= dec
.ack
;
842 dec
.nakend
= dec
.nak
;
843 dec
.rejend
= dec
.rej
;
845 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_REJ
, &dec
);
846 if (flen
< sizeof(struct fsm_opt_hdr
))
847 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
852 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
853 FsmSendConfigReq(fp
);
856 (*fp
->fn
->LayerDown
)(fp
);
857 FsmSendConfigReq(fp
);
858 NewState(fp
, ST_REQSENT
);
859 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
862 FsmSendConfigReq(fp
);
863 NewState(fp
, ST_REQSENT
);
870 FsmRecvCodeRej(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
876 FsmRecvProtoRej(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
878 struct physical
*p
= link2physical(fp
->link
);
881 if (m_length(bp
) < 2) {
885 bp
= mbuf_Read(bp
, &proto
, 2);
886 proto
= ntohs(proto
);
887 log_Printf(fp
->LogLevel
, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
888 fp
->link
->name
, proto
, hdlc_Protocol2Nam(proto
));
893 lqr_Stop(p
, LQM_LQR
);
895 log_Printf(LogERROR
, "%s: FsmRecvProtoRej: Not a physical link !\n",
899 if (fp
->proto
== PROTO_LCP
) {
900 fp
= &fp
->link
->ccp
.fsm
;
901 /* Despite the RFC (1661), don't do an out-of-place TLF */
902 /* (*fp->fn->LayerFinish)(fp); */
906 NewState(fp
, ST_CLOSED
);
909 NewState(fp
, ST_STOPPED
);
913 /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */
917 if (fp
->proto
== PROTO_LCP
) {
918 log_Printf(LogPHASE
, "%s: IPCP protocol reject closes IPCP !\n",
920 fsm_Close(&fp
->bundle
->ncp
.ipcp
.fsm
);
925 if (fp
->proto
== PROTO_LCP
) {
926 log_Printf(LogPHASE
, "%s: IPV6CP protocol reject closes IPV6CP !\n",
928 fsm_Close(&fp
->bundle
->ncp
.ipv6cp
.fsm
);
933 if (fp
->proto
== PROTO_LCP
) {
934 struct lcp
*lcp
= fsm2lcp(fp
);
936 if (lcp
->want_mrru
&& lcp
->his_mrru
) {
937 log_Printf(LogPHASE
, "%s: MP protocol reject is fatal !\n",
948 FsmRecvEchoReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
950 struct lcp
*lcp
= fsm2lcp(fp
);
955 m_settype(bp
, MB_ECHOIN
);
957 if (lcp
&& ntohs(lhp
->length
) - sizeof *lhp
>= 4) {
959 ua_ntohl(cp
, &magic
);
960 if (magic
!= lcp
->his_magic
) {
961 log_Printf(fp
->LogLevel
, "%s: RecvEchoReq: magic 0x%08lx is wrong,"
962 " expecting 0x%08lx\n", fp
->link
->name
, (u_long
)magic
,
963 (u_long
)lcp
->his_magic
);
964 /* XXX: We should send terminate request */
966 if (fp
->state
== ST_OPENED
) {
967 ua_htonl(&lcp
->want_magic
, cp
); /* local magic */
968 fsm_Output(fp
, CODE_ECHOREP
, lhp
->id
, cp
,
969 ntohs(lhp
->length
) - sizeof *lhp
, MB_ECHOOUT
);
976 FsmRecvEchoRep(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
979 bp
= lqr_RecvEcho(fp
, bp
);
985 FsmRecvDiscReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
991 FsmRecvIdent(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
997 len
= ntohs(lhp
->length
) - sizeof *lhp
;
999 bp
= m_pullup(m_append(bp
, "", 1));
1001 ua_ntohl(cp
, &magic
);
1002 if (magic
!= fp
->link
->lcp
.his_magic
)
1003 log_Printf(fp
->LogLevel
, "%s: RecvIdent: magic 0x%08lx is wrong,"
1004 " expecting 0x%08lx\n", fp
->link
->name
, (u_long
)magic
,
1005 (u_long
)fp
->link
->lcp
.his_magic
);
1007 lcp_RecvIdentification(&fp
->link
->lcp
, cp
+ 4);
1013 FsmRecvTimeRemain(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1019 FsmRecvResetReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1021 if ((*fp
->fn
->RecvResetReq
)(fp
)) {
1023 * All sendable compressed packets are queued in the first (lowest
1024 * priority) modem output queue.... dump 'em to the priority queue
1025 * so that they arrive at the peer before our ResetAck.
1027 link_SequenceQueue(fp
->link
);
1028 fsm_Output(fp
, CODE_RESETACK
, lhp
->id
, NULL
, 0, MB_CCPOUT
);
1034 FsmRecvResetAck(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1036 (*fp
->fn
->RecvResetAck
)(fp
, lhp
->id
);
1041 fsm_Input(struct fsm
*fp
, struct mbuf
*bp
)
1044 struct fsmheader lh
;
1045 const struct fsmcodedesc
*codep
;
1048 if (len
< sizeof(struct fsmheader
)) {
1052 bp
= mbuf_Read(bp
, &lh
, sizeof lh
);
1054 if (ntohs(lh
.length
) > len
) {
1055 log_Printf(LogWARN
, "%s: Oops: Got %d bytes but %d byte payload "
1056 "- dropped\n", fp
->link
->name
, len
, (int)ntohs(lh
.length
));
1061 if (lh
.code
< fp
->min_code
|| lh
.code
> fp
->max_code
||
1062 lh
.code
> sizeof FsmCodes
/ sizeof *FsmCodes
) {
1064 * Use a private id. This is really a response-type packet, but we
1065 * MUST send a unique id for each REQ....
1069 bp
= m_prepend(bp
, &lh
, sizeof lh
, 0);
1071 fsm_Output(fp
, CODE_CODEREJ
, id
++, MBUF_CTOP(bp
), bp
->m_len
, MB_UNKNOWN
);
1076 codep
= FsmCodes
+ lh
.code
- 1;
1077 if (lh
.id
!= fp
->reqid
&& codep
->check_reqid
&&
1078 Enabled(fp
->bundle
, OPT_IDCHECK
)) {
1079 log_Printf(fp
->LogLevel
, "%s: Recv%s(%d), dropped (expected %d)\n",
1080 fp
->link
->name
, codep
->name
, lh
.id
, fp
->reqid
);
1084 log_Printf(fp
->LogLevel
, "%s: Recv%s(%d) state = %s\n",
1085 fp
->link
->name
, codep
->name
, lh
.id
, State2Nam(fp
->state
));
1087 if (codep
->inc_reqid
&& (lh
.id
== fp
->reqid
||
1088 (!Enabled(fp
->bundle
, OPT_IDCHECK
) && codep
->check_reqid
)))
1089 fp
->reqid
++; /* That's the end of that ``exchange''.... */
1091 (*codep
->recv
)(fp
, &lh
, bp
);
1095 fsm_NullRecvResetReq(struct fsm
*fp
)
1097 log_Printf(fp
->LogLevel
, "%s: Oops - received unexpected reset req\n",
1103 fsm_NullRecvResetAck(struct fsm
*fp
, u_char id
)
1105 log_Printf(fp
->LogLevel
, "%s: Oops - received unexpected reset ack\n",
1110 fsm_Reopen(struct fsm
*fp
)
1112 if (fp
->state
== ST_OPENED
) {
1113 (*fp
->fn
->LayerDown
)(fp
);
1114 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
1115 FsmSendConfigReq(fp
);
1116 NewState(fp
, ST_REQSENT
);
1117 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
1122 fsm2initial(struct fsm
*fp
)
1124 timer_Stop(&fp
->FsmTimer
);
1125 timer_Stop(&fp
->OpenTimer
);
1126 timer_Stop(&fp
->StoppedTimer
);
1127 if (fp
->state
== ST_STOPPED
)
1129 if (fp
->state
> ST_INITIAL
)
1131 if (fp
->state
> ST_INITIAL
)
1136 fsm_readopt(u_char
**cp
)
1138 struct fsm_opt
*o
= (struct fsm_opt
*)*cp
;
1140 if (o
->hdr
.len
< sizeof(struct fsm_opt_hdr
)) {
1141 log_Printf(LogERROR
, "Bad option length %d (out of phase?)\n", o
->hdr
.len
);
1147 if (o
->hdr
.len
> sizeof(struct fsm_opt
)) {
1148 log_Printf(LogERROR
, "Warning: Truncating option length from %d to %d\n",
1149 o
->hdr
.len
, (int)sizeof(struct fsm_opt
));
1150 o
->hdr
.len
= sizeof(struct fsm_opt
);
1157 fsm_opt(u_char
*opt
, int optlen
, const struct fsm_opt
*o
)
1159 int cplen
= o
->hdr
.len
;
1161 if (optlen
< sizeof(struct fsm_opt_hdr
))
1164 if (cplen
> optlen
) {
1165 log_Printf(LogERROR
, "Can't REJ length %d - trunating to %d\n",
1169 memcpy(opt
, o
, cplen
);
1177 fsm_rej(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1181 dec
->rejend
+= fsm_opt(dec
->rejend
, FSM_OPTLEN
- (dec
->rejend
- dec
->rej
), o
);
1185 fsm_ack(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1189 dec
->ackend
+= fsm_opt(dec
->ackend
, FSM_OPTLEN
- (dec
->ackend
- dec
->ack
), o
);
1193 fsm_nak(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1197 dec
->nakend
+= fsm_opt(dec
->nakend
, FSM_OPTLEN
- (dec
->nakend
- dec
->nak
), o
);
1201 fsm_opt_normalise(struct fsm_decode
*dec
)
1203 if (dec
->rejend
!= dec
->rej
) {
1204 /* rejects are preferred */
1205 dec
->ackend
= dec
->ack
;
1206 dec
->nakend
= dec
->nak
;
1207 } else if (dec
->nakend
!= dec
->nak
)
1209 dec
->ackend
= dec
->ack
;