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 $
31 #include <sys/param.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <sys/socket.h>
51 #include "throughput.h"
52 #include "slcompress.h"
56 #include "descriptor.h"
71 static void FsmSendConfigReq(struct fsm
*);
72 static void FsmSendTerminateReq(struct fsm
*);
73 static void FsmInitRestartCounter(struct fsm
*, int);
75 typedef void (recvfn
)(struct fsm
*, struct fsmheader
*, struct mbuf
*);
76 static recvfn FsmRecvConfigReq
, FsmRecvConfigAck
, FsmRecvConfigNak
,
77 FsmRecvConfigRej
, FsmRecvTermReq
, FsmRecvTermAck
,
78 FsmRecvCodeRej
, FsmRecvProtoRej
, FsmRecvEchoReq
,
79 FsmRecvEchoRep
, FsmRecvDiscReq
, FsmRecvIdent
,
80 FsmRecvTimeRemain
, FsmRecvResetReq
, FsmRecvResetAck
;
82 static const struct fsmcodedesc
{
84 unsigned check_reqid
: 1;
85 unsigned inc_reqid
: 1;
88 { FsmRecvConfigReq
, 0, 0, "ConfigReq" },
89 { FsmRecvConfigAck
, 1, 1, "ConfigAck" },
90 { FsmRecvConfigNak
, 1, 1, "ConfigNak" },
91 { FsmRecvConfigRej
, 1, 1, "ConfigRej" },
92 { FsmRecvTermReq
, 0, 0, "TerminateReq" },
93 { FsmRecvTermAck
, 1, 1, "TerminateAck" },
94 { FsmRecvCodeRej
, 0, 0, "CodeRej" },
95 { FsmRecvProtoRej
, 0, 0, "ProtocolRej" },
96 { FsmRecvEchoReq
, 0, 0, "EchoRequest" },
97 { FsmRecvEchoRep
, 0, 0, "EchoReply" },
98 { FsmRecvDiscReq
, 0, 0, "DiscardReq" },
99 { FsmRecvIdent
, 0, 1, "Ident" },
100 { FsmRecvTimeRemain
,0, 0, "TimeRemain" },
101 { FsmRecvResetReq
, 0, 0, "ResetReq" },
102 { FsmRecvResetAck
, 0, 1, "ResetAck" }
108 if (code
== 0 || code
> NELEM(FsmCodes
))
110 return FsmCodes
[code
-1].name
;
114 State2Nam(u_int state
)
116 static const char * const StateNames
[] = {
117 "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
118 "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
121 if (state
>= NELEM(StateNames
))
123 return StateNames
[state
];
127 StoppedTimeout(void *v
)
129 struct fsm
*fp
= (struct fsm
*)v
;
131 log_Printf(fp
->LogLevel
, "%s: Stopped timer expired\n", fp
->link
->name
);
132 if (fp
->OpenTimer
.state
== TIMER_RUNNING
) {
133 log_Printf(LogWARN
, "%s: %s: aborting open delay due to stopped timer\n",
134 fp
->link
->name
, fp
->name
);
135 timer_Stop(&fp
->OpenTimer
);
137 if (fp
->state
== ST_STOPPED
)
142 fsm_Init(struct fsm
*fp
, const char *name
, u_short proto
, int mincode
,
143 int maxcode
, int LogLevel
, struct bundle
*bundle
,
144 struct link
*l
, const struct fsm_parent
*parent
,
145 struct fsm_callbacks
*fn
, const char * const timer_names
[3])
149 fp
->min_code
= mincode
;
150 fp
->max_code
= maxcode
;
151 fp
->state
= fp
->min_code
> CODE_TERMACK
? ST_OPENED
: ST_INITIAL
;
154 fp
->more
.reqs
= fp
->more
.naks
= fp
->more
.rejs
= 3;
155 memset(&fp
->FsmTimer
, '\0', sizeof fp
->FsmTimer
);
156 memset(&fp
->OpenTimer
, '\0', sizeof fp
->OpenTimer
);
157 memset(&fp
->StoppedTimer
, '\0', sizeof fp
->StoppedTimer
);
158 fp
->LogLevel
= LogLevel
;
163 fp
->FsmTimer
.name
= timer_names
[0];
164 fp
->OpenTimer
.name
= timer_names
[1];
165 fp
->StoppedTimer
.name
= timer_names
[2];
169 NewState(struct fsm
*fp
, int new)
171 log_Printf(fp
->LogLevel
, "%s: State change %s --> %s\n",
172 fp
->link
->name
, State2Nam(fp
->state
), State2Nam(new));
173 if (fp
->state
== ST_STOPPED
&& fp
->StoppedTimer
.state
== TIMER_RUNNING
)
174 timer_Stop(&fp
->StoppedTimer
);
176 if ((new >= ST_INITIAL
&& new <= ST_STOPPED
) || (new == ST_OPENED
)) {
177 timer_Stop(&fp
->FsmTimer
);
178 if (new == ST_STOPPED
&& fp
->StoppedTimer
.load
) {
179 timer_Stop(&fp
->StoppedTimer
);
180 fp
->StoppedTimer
.func
= StoppedTimeout
;
181 fp
->StoppedTimer
.arg
= (void *) fp
;
182 timer_Start(&fp
->StoppedTimer
);
188 fsm_Output(struct fsm
*fp
, u_int code
, u_int id
, u_char
*ptr
, unsigned count
,
195 if (log_IsKept(fp
->LogLevel
)) {
196 log_Printf(fp
->LogLevel
, "%s: Send%s(%d) state = %s\n",
197 fp
->link
->name
, Code2Nam(code
), id
, State2Nam(fp
->state
));
203 (*fp
->fn
->DecodeConfig
)(fp
, ptr
, ptr
+ count
, MODE_NOP
, NULL
);
204 if (count
< sizeof(struct fsm_opt_hdr
))
205 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
210 plen
= sizeof(struct fsmheader
) + count
;
213 lh
.length
= htons(plen
);
214 bp
= m_get(plen
, mtype
);
215 memcpy(MBUF_CTOP(bp
), &lh
, sizeof(struct fsmheader
));
217 memcpy(MBUF_CTOP(bp
) + sizeof(struct fsmheader
), ptr
, count
);
218 log_DumpBp(LogDEBUG
, "fsm_Output", bp
);
219 link_PushPacket(fp
->link
, bp
, fp
->bundle
, LINK_QUEUES(fp
->link
) - 1,
222 if (code
== CODE_CONFIGREJ
)
223 lcp_SendIdentification(&fp
->link
->lcp
);
229 struct fsm
*fp
= (struct fsm
*)v
;
231 timer_Stop(&fp
->OpenTimer
);
232 if (fp
->state
<= ST_STOPPED
) {
233 if (fp
->state
!= ST_STARTING
) {
235 * In practice, we're only here in ST_STOPPED (when delaying the
236 * first config request) or ST_CLOSED (when openmode == 0).
238 * The ST_STOPPED bit is breaking the RFC already :-(
240 * According to the RFC (1661) state transition table, a TLS isn't
241 * required for an Open event when state == Closed, but the RFC
242 * must be wrong as TLS hasn't yet been called (since the last TLF)
243 * ie, Initial gets an `Up' event, Closing gets a RTA etc.
245 (*fp
->fn
->LayerStart
)(fp
);
246 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
248 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
249 FsmSendConfigReq(fp
);
250 NewState(fp
, ST_REQSENT
);
255 fsm_Open(struct fsm
*fp
)
259 NewState(fp
, ST_STARTING
);
260 (*fp
->fn
->LayerStart
)(fp
);
261 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
264 if (fp
->open_mode
== OPEN_PASSIVE
) {
265 NewState(fp
, ST_STOPPED
); /* XXX: This is a hack ! */
266 } else if (fp
->open_mode
> 0) {
267 if (fp
->open_mode
> 1)
268 log_Printf(LogPHASE
, "%s: Entering STOPPED state for %d seconds\n",
269 fp
->link
->name
, fp
->open_mode
);
270 NewState(fp
, ST_STOPPED
); /* XXX: This is a not-so-bad hack ! */
271 timer_Stop(&fp
->OpenTimer
);
272 fp
->OpenTimer
.load
= fp
->open_mode
* SECTICKS
;
273 fp
->OpenTimer
.func
= FsmOpenNow
;
274 fp
->OpenTimer
.arg
= (void *)fp
;
275 timer_Start(&fp
->OpenTimer
);
279 case ST_STOPPED
: /* XXX: restart option */
283 case ST_OPENED
: /* XXX: restart option */
285 case ST_CLOSING
: /* XXX: restart option */
286 case ST_STOPPING
: /* XXX: restart option */
287 NewState(fp
, ST_STOPPING
);
293 fsm_Up(struct fsm
*fp
)
297 log_Printf(fp
->LogLevel
, "FSM: Using \"%s\" as a transport\n",
299 NewState(fp
, ST_CLOSED
);
302 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
303 FsmSendConfigReq(fp
);
304 NewState(fp
, ST_REQSENT
);
307 log_Printf(fp
->LogLevel
, "%s: Oops, Up at %s\n",
308 fp
->link
->name
, State2Nam(fp
->state
));
314 fsm_Down(struct fsm
*fp
)
318 NewState(fp
, ST_INITIAL
);
321 /* This TLF contradicts the RFC (1661), which ``misses it out'' ! */
322 (*fp
->fn
->LayerFinish
)(fp
);
323 NewState(fp
, ST_INITIAL
);
324 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
327 NewState(fp
, ST_STARTING
);
328 (*fp
->fn
->LayerStart
)(fp
);
329 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
335 NewState(fp
, ST_STARTING
);
338 (*fp
->fn
->LayerDown
)(fp
);
339 NewState(fp
, ST_STARTING
);
340 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
346 fsm_Close(struct fsm
*fp
)
350 (*fp
->fn
->LayerFinish
)(fp
);
351 NewState(fp
, ST_INITIAL
);
352 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
355 NewState(fp
, ST_CLOSED
);
358 NewState(fp
, ST_CLOSING
);
361 (*fp
->fn
->LayerDown
)(fp
);
362 if (fp
->state
== ST_OPENED
) {
363 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
364 FsmSendTerminateReq(fp
);
365 NewState(fp
, ST_CLOSING
);
366 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
372 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
373 FsmSendTerminateReq(fp
);
374 NewState(fp
, ST_CLOSING
);
383 FsmSendConfigReq(struct fsm
*fp
)
385 if (fp
->more
.reqs
-- > 0 && fp
->restart
-- > 0) {
386 (*fp
->fn
->SendConfigReq
)(fp
);
387 timer_Start(&fp
->FsmTimer
); /* Start restart timer */
389 if (fp
->more
.reqs
< 0)
390 log_Printf(LogPHASE
, "%s: Too many %s REQs sent - abandoning "
391 "negotiation\n", fp
->link
->name
, fp
->name
);
392 lcp_SendIdentification(&fp
->link
->lcp
);
398 FsmSendTerminateReq(struct fsm
*fp
)
400 fsm_Output(fp
, CODE_TERMREQ
, fp
->reqid
, NULL
, 0, MB_UNKNOWN
);
401 (*fp
->fn
->SentTerminateReq
)(fp
);
402 timer_Start(&fp
->FsmTimer
); /* Start restart timer */
403 fp
->restart
--; /* Decrement restart counter */
412 struct fsm
*fp
= (struct fsm
*)v
;
418 FsmSendTerminateReq(fp
);
422 FsmSendConfigReq(fp
);
425 FsmSendConfigReq(fp
);
426 NewState(fp
, ST_REQSENT
);
429 timer_Start(&fp
->FsmTimer
);
433 (*fp
->fn
->LayerFinish
)(fp
);
434 NewState(fp
, ST_CLOSED
);
435 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
438 (*fp
->fn
->LayerFinish
)(fp
);
439 NewState(fp
, ST_STOPPED
);
440 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
442 case ST_REQSENT
: /* XXX: 3p */
445 (*fp
->fn
->LayerFinish
)(fp
);
446 NewState(fp
, ST_STOPPED
);
447 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
454 FsmInitRestartCounter(struct fsm
*fp
, int what
)
456 timer_Stop(&fp
->FsmTimer
);
457 fp
->FsmTimer
.func
= FsmTimeout
;
458 fp
->FsmTimer
.arg
= (void *)fp
;
459 (*fp
->fn
->InitRestartCounter
)(fp
, what
);
463 * Actions when receive packets
466 FsmRecvConfigReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
469 struct fsm_decode dec
;
476 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
478 log_Printf(LogWARN
, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
479 fp
->link
->name
, plen
, flen
);
484 /* Some things must be done before we Decode the packet */
487 (*fp
->fn
->LayerDown
)(fp
);
490 dec
.ackend
= dec
.ack
;
491 dec
.nakend
= dec
.nak
;
492 dec
.rejend
= dec
.rej
;
494 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_REQ
, &dec
);
495 if (flen
< (int)sizeof(struct fsm_opt_hdr
))
496 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
498 if (dec
.nakend
== dec
.nak
&& dec
.rejend
== dec
.rej
)
501 /* Check and process easy case */
504 if (fp
->proto
== PROTO_CCP
&& fp
->link
->lcp
.fsm
.state
== ST_OPENED
) {
506 * ccp_SetOpenMode() leaves us in initial if we're disabling
507 * & denying everything.
509 bp
= m_prepend(bp
, lhp
, sizeof *lhp
, 2);
510 bp
= proto_Prepend(bp
, fp
->proto
, 0, 0);
512 lcp_SendProtoRej(&fp
->link
->lcp
, MBUF_CTOP(bp
), bp
->m_len
);
518 log_Printf(fp
->LogLevel
, "%s: Oops, RCR in %s.\n",
519 fp
->link
->name
, State2Nam(fp
->state
));
523 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
527 log_Printf(fp
->LogLevel
, "%s: Error: Got ConfigReq while state = %s\n",
528 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
> NELEM(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
;