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
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
> sizeof FsmCodes
/ sizeof FsmCodes
[0])
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
>= sizeof StateNames
/ sizeof StateNames
[0])
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
));
533 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
536 FsmSendConfigReq(fp
);
540 if (dec
.rejend
!= dec
.rej
)
541 fsm_Output(fp
, CODE_CONFIGREJ
, lhp
->id
, dec
.rej
, dec
.rejend
- dec
.rej
,
543 if (dec
.nakend
!= dec
.nak
)
544 fsm_Output(fp
, CODE_CONFIGNAK
, lhp
->id
, dec
.nak
, dec
.nakend
- dec
.nak
,
547 fsm_Output(fp
, CODE_CONFIGACK
, lhp
->id
, dec
.ack
, dec
.ackend
- dec
.ack
,
553 * According to the RFC (1661) state transition table, a TLS isn't
554 * required for a RCR when state == ST_STOPPED, but the RFC
555 * must be wrong as TLS hasn't yet been called (since the last TLF)
557 (*fp
->fn
->LayerStart
)(fp
);
558 (*fp
->parent
->LayerStart
)(fp
->parent
->object
, fp
);
563 NewState(fp
, ST_ACKSENT
);
565 NewState(fp
, ST_REQSENT
);
566 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
570 NewState(fp
, ST_ACKSENT
);
574 NewState(fp
, ST_OPENED
);
575 if ((*fp
->fn
->LayerUp
)(fp
))
576 (*fp
->parent
->LayerUp
)(fp
->parent
->object
, fp
);
578 (*fp
->fn
->LayerDown
)(fp
);
579 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
580 FsmSendTerminateReq(fp
);
581 NewState(fp
, ST_CLOSING
);
582 lcp_SendIdentification(&fp
->link
->lcp
);
588 NewState(fp
, ST_REQSENT
);
593 if (dec
.rejend
!= dec
.rej
&& --fp
->more
.rejs
<= 0) {
594 log_Printf(LogPHASE
, "%s: Too many %s REJs sent - abandoning negotiation\n",
595 fp
->link
->name
, fp
->name
);
596 lcp_SendIdentification(&fp
->link
->lcp
);
600 if (dec
.nakend
!= dec
.nak
&& --fp
->more
.naks
<= 0) {
601 log_Printf(LogPHASE
, "%s: Too many %s NAKs sent - abandoning negotiation\n",
602 fp
->link
->name
, fp
->name
);
603 lcp_SendIdentification(&fp
->link
->lcp
);
609 FsmRecvConfigAck(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
612 struct fsm_decode dec
;
617 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
624 dec
.ackend
= dec
.ack
;
625 dec
.nakend
= dec
.nak
;
626 dec
.rejend
= dec
.rej
;
628 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_ACK
, &dec
);
629 if (flen
< (int)sizeof(struct fsm_opt_hdr
))
630 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
635 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
641 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
642 NewState(fp
, ST_ACKRCVD
);
645 FsmSendConfigReq(fp
);
646 NewState(fp
, ST_REQSENT
);
649 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
650 NewState(fp
, ST_OPENED
);
651 if ((*fp
->fn
->LayerUp
)(fp
))
652 (*fp
->parent
->LayerUp
)(fp
->parent
->object
, fp
);
654 (*fp
->fn
->LayerDown
)(fp
);
655 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
656 FsmSendTerminateReq(fp
);
657 NewState(fp
, ST_CLOSING
);
658 lcp_SendIdentification(&fp
->link
->lcp
);
662 (*fp
->fn
->LayerDown
)(fp
);
663 FsmSendConfigReq(fp
);
664 NewState(fp
, ST_REQSENT
);
665 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
672 FsmRecvConfigNak(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
675 struct fsm_decode dec
;
680 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
687 * Check and process easy case
692 log_Printf(fp
->LogLevel
, "%s: Oops, RCN in %s.\n",
693 fp
->link
->name
, State2Nam(fp
->state
));
698 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
708 dec
.ackend
= dec
.ack
;
709 dec
.nakend
= dec
.nak
;
710 dec
.rejend
= dec
.rej
;
712 (*fp
->fn
->DecodeConfig
)(fp
, cp
, cp
+ flen
, MODE_NAK
, &dec
);
713 if (flen
< (int)sizeof(struct fsm_opt_hdr
))
714 log_Printf(fp
->LogLevel
, " [EMPTY]\n");
719 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
720 FsmSendConfigReq(fp
);
723 (*fp
->fn
->LayerDown
)(fp
);
724 FsmSendConfigReq(fp
);
725 NewState(fp
, ST_REQSENT
);
726 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
729 FsmSendConfigReq(fp
);
730 NewState(fp
, ST_REQSENT
);
738 FsmRecvTermReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
744 log_Printf(fp
->LogLevel
, "%s: Oops, RTR in %s\n",
745 fp
->link
->name
, State2Nam(fp
->state
));
752 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
756 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
757 NewState(fp
, ST_REQSENT
);
760 (*fp
->fn
->LayerDown
)(fp
);
761 (*fp
->fn
->SendTerminateAck
)(fp
, lhp
->id
);
762 FsmInitRestartCounter(fp
, FSM_TRM_TIMER
);
763 timer_Start(&fp
->FsmTimer
); /* Start restart timer */
765 NewState(fp
, ST_STOPPING
);
766 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
767 /* A delayed ST_STOPPED is now scheduled */
774 FsmRecvTermAck(struct fsm
*fp
, struct fsmheader
*lhp __unused
, struct mbuf
*bp
)
779 (*fp
->fn
->LayerFinish
)(fp
);
780 NewState(fp
, ST_CLOSED
);
781 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
784 (*fp
->fn
->LayerFinish
)(fp
);
785 NewState(fp
, ST_STOPPED
);
786 (*fp
->parent
->LayerFinish
)(fp
->parent
->object
, fp
);
789 NewState(fp
, ST_REQSENT
);
792 (*fp
->fn
->LayerDown
)(fp
);
793 FsmSendConfigReq(fp
);
794 NewState(fp
, ST_REQSENT
);
795 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
802 FsmRecvConfigRej(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
805 struct fsm_decode dec
;
811 flen
= ntohs(lhp
->length
) - sizeof *lhp
;
812 if ((int)plen
< flen
) {
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
< (int)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 __unused
, struct fsmheader
*lhp __unused
,
877 FsmRecvProtoRej(struct fsm
*fp
, struct fsmheader
*lhp __unused
, struct mbuf
*bp
)
879 struct physical
*p
= link2physical(fp
->link
);
882 if (m_length(bp
) < 2) {
886 bp
= mbuf_Read(bp
, &proto
, 2);
887 proto
= ntohs(proto
);
888 log_Printf(fp
->LogLevel
, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
889 fp
->link
->name
, proto
, hdlc_Protocol2Nam(proto
));
894 lqr_Stop(p
, LQM_LQR
);
896 log_Printf(LogERROR
, "%s: FsmRecvProtoRej: Not a physical link !\n",
900 if (fp
->proto
== PROTO_LCP
) {
901 fp
= &fp
->link
->ccp
.fsm
;
902 /* Despite the RFC (1661), don't do an out-of-place TLF */
903 /* (*fp->fn->LayerFinish)(fp); */
907 NewState(fp
, ST_CLOSED
);
910 NewState(fp
, ST_STOPPED
);
914 /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */
918 if (fp
->proto
== PROTO_LCP
) {
919 log_Printf(LogPHASE
, "%s: IPCP protocol reject closes IPCP !\n",
921 fsm_Close(&fp
->bundle
->ncp
.ipcp
.fsm
);
926 if (fp
->proto
== PROTO_LCP
) {
927 log_Printf(LogPHASE
, "%s: IPV6CP protocol reject closes IPV6CP !\n",
929 fsm_Close(&fp
->bundle
->ncp
.ipv6cp
.fsm
);
934 if (fp
->proto
== PROTO_LCP
) {
935 struct lcp
*lcp
= fsm2lcp(fp
);
937 if (lcp
->want_mrru
&& lcp
->his_mrru
) {
938 log_Printf(LogPHASE
, "%s: MP protocol reject is fatal !\n",
949 FsmRecvEchoReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
951 struct lcp
*lcp
= fsm2lcp(fp
);
956 m_settype(bp
, MB_ECHOIN
);
958 if (lcp
&& ntohs(lhp
->length
) - sizeof *lhp
>= 4) {
960 ua_ntohl(cp
, &magic
);
961 if (magic
!= lcp
->his_magic
) {
962 log_Printf(fp
->LogLevel
, "%s: RecvEchoReq: magic 0x%08lx is wrong,"
963 " expecting 0x%08lx\n", fp
->link
->name
, (u_long
)magic
,
964 (u_long
)lcp
->his_magic
);
965 /* XXX: We should send terminate request */
967 if (fp
->state
== ST_OPENED
) {
968 ua_htonl(&lcp
->want_magic
, cp
); /* local magic */
969 fsm_Output(fp
, CODE_ECHOREP
, lhp
->id
, cp
,
970 ntohs(lhp
->length
) - sizeof *lhp
, MB_ECHOOUT
);
977 FsmRecvEchoRep(struct fsm
*fp
, struct fsmheader
*lhp __unused
, struct mbuf
*bp
)
980 bp
= lqr_RecvEcho(fp
, bp
);
986 FsmRecvDiscReq(struct fsm
*fp __unused
, struct fsmheader
*lhp __unused
,
993 FsmRecvIdent(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
999 len
= ntohs(lhp
->length
) - sizeof *lhp
;
1001 bp
= m_pullup(m_append(bp
, "", 1));
1003 ua_ntohl(cp
, &magic
);
1004 if (magic
!= fp
->link
->lcp
.his_magic
)
1005 log_Printf(fp
->LogLevel
, "%s: RecvIdent: magic 0x%08lx is wrong,"
1006 " expecting 0x%08lx\n", fp
->link
->name
, (u_long
)magic
,
1007 (u_long
)fp
->link
->lcp
.his_magic
);
1009 lcp_RecvIdentification(&fp
->link
->lcp
, cp
+ 4);
1015 FsmRecvTimeRemain(struct fsm
*fp __unused
, struct fsmheader
*lhp __unused
,
1022 FsmRecvResetReq(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1024 if ((*fp
->fn
->RecvResetReq
)(fp
)) {
1026 * All sendable compressed packets are queued in the first (lowest
1027 * priority) modem output queue.... dump 'em to the priority queue
1028 * so that they arrive at the peer before our ResetAck.
1030 link_SequenceQueue(fp
->link
);
1031 fsm_Output(fp
, CODE_RESETACK
, lhp
->id
, NULL
, 0, MB_CCPOUT
);
1037 FsmRecvResetAck(struct fsm
*fp
, struct fsmheader
*lhp
, struct mbuf
*bp
)
1039 (*fp
->fn
->RecvResetAck
)(fp
, lhp
->id
);
1044 fsm_Input(struct fsm
*fp
, struct mbuf
*bp
)
1047 struct fsmheader lh
;
1048 const struct fsmcodedesc
*codep
;
1051 if (len
< sizeof(struct fsmheader
)) {
1055 bp
= mbuf_Read(bp
, &lh
, sizeof lh
);
1057 if (ntohs(lh
.length
) > len
) {
1058 log_Printf(LogWARN
, "%s: Oops: Got %zu bytes but %d byte payload "
1059 "- dropped\n", fp
->link
->name
, len
, (int)ntohs(lh
.length
));
1064 if (lh
.code
< fp
->min_code
|| lh
.code
> fp
->max_code
||
1065 lh
.code
> sizeof FsmCodes
/ sizeof *FsmCodes
) {
1067 * Use a private id. This is really a response-type packet, but we
1068 * MUST send a unique id for each REQ....
1072 bp
= m_prepend(bp
, &lh
, sizeof lh
, 0);
1074 fsm_Output(fp
, CODE_CODEREJ
, id
++, MBUF_CTOP(bp
), bp
->m_len
, MB_UNKNOWN
);
1079 codep
= FsmCodes
+ lh
.code
- 1;
1080 if (lh
.id
!= fp
->reqid
&& codep
->check_reqid
&&
1081 Enabled(fp
->bundle
, OPT_IDCHECK
)) {
1082 log_Printf(fp
->LogLevel
, "%s: Recv%s(%d), dropped (expected %d)\n",
1083 fp
->link
->name
, codep
->name
, lh
.id
, fp
->reqid
);
1087 log_Printf(fp
->LogLevel
, "%s: Recv%s(%d) state = %s\n",
1088 fp
->link
->name
, codep
->name
, lh
.id
, State2Nam(fp
->state
));
1090 if (codep
->inc_reqid
&& (lh
.id
== fp
->reqid
||
1091 (!Enabled(fp
->bundle
, OPT_IDCHECK
) && codep
->check_reqid
)))
1092 fp
->reqid
++; /* That's the end of that ``exchange''.... */
1094 (*codep
->recv
)(fp
, &lh
, bp
);
1098 fsm_NullRecvResetReq(struct fsm
*fp
)
1100 log_Printf(fp
->LogLevel
, "%s: Oops - received unexpected reset req\n",
1106 fsm_NullRecvResetAck(struct fsm
*fp
, u_char id __unused
)
1108 log_Printf(fp
->LogLevel
, "%s: Oops - received unexpected reset ack\n",
1113 fsm_Reopen(struct fsm
*fp
)
1115 if (fp
->state
== ST_OPENED
) {
1116 (*fp
->fn
->LayerDown
)(fp
);
1117 FsmInitRestartCounter(fp
, FSM_REQ_TIMER
);
1118 FsmSendConfigReq(fp
);
1119 NewState(fp
, ST_REQSENT
);
1120 (*fp
->parent
->LayerDown
)(fp
->parent
->object
, fp
);
1125 fsm2initial(struct fsm
*fp
)
1127 timer_Stop(&fp
->FsmTimer
);
1128 timer_Stop(&fp
->OpenTimer
);
1129 timer_Stop(&fp
->StoppedTimer
);
1130 if (fp
->state
== ST_STOPPED
)
1132 if (fp
->state
> ST_INITIAL
)
1134 if (fp
->state
> ST_INITIAL
)
1139 fsm_readopt(u_char
**cp
)
1141 struct fsm_opt
*o
= (struct fsm_opt
*)*cp
;
1143 if (o
->hdr
.len
< sizeof(struct fsm_opt_hdr
)) {
1144 log_Printf(LogERROR
, "Bad option length %d (out of phase?)\n", o
->hdr
.len
);
1150 if (o
->hdr
.len
> sizeof(struct fsm_opt
)) {
1151 log_Printf(LogERROR
, "Warning: Truncating option length from %d to %d\n",
1152 o
->hdr
.len
, (int)sizeof(struct fsm_opt
));
1153 o
->hdr
.len
= sizeof(struct fsm_opt
);
1160 fsm_opt(u_char
*opt
, int optlen
, const struct fsm_opt
*o
)
1162 unsigned cplen
= o
->hdr
.len
;
1164 if (optlen
< (int)sizeof(struct fsm_opt_hdr
))
1167 if ((int)cplen
> optlen
) {
1168 log_Printf(LogERROR
, "Can't REJ length %d - trunating to %d\n",
1172 memcpy(opt
, o
, cplen
);
1180 fsm_rej(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1184 dec
->rejend
+= fsm_opt(dec
->rejend
, FSM_OPTLEN
- (dec
->rejend
- dec
->rej
), o
);
1188 fsm_ack(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1192 dec
->ackend
+= fsm_opt(dec
->ackend
, FSM_OPTLEN
- (dec
->ackend
- dec
->ack
), o
);
1196 fsm_nak(struct fsm_decode
*dec
, const struct fsm_opt
*o
)
1200 dec
->nakend
+= fsm_opt(dec
->nakend
, FSM_OPTLEN
- (dec
->nakend
- dec
->nak
), o
);
1204 fsm_opt_normalise(struct fsm_decode
*dec
)
1206 if (dec
->rejend
!= dec
->rej
) {
1207 /* rejects are preferred */
1208 dec
->ackend
= dec
->ack
;
1209 dec
->nakend
= dec
->nak
;
1210 } else if (dec
->nakend
!= dec
->nak
)
1212 dec
->ackend
= dec
->ack
;