Cameron Hutchison noticed that if pppd gets asked to terminate the
link in the period between when lcp_lowerup() is called and when
fsm_lowerup() is called from lcp_delayed_up() (i.e. when listen_time
is non-zero), pppd never exits.
The reason is that lcp_close() doesn't handle the delayed-up case
properly. Since the FSM is still in STOPPED state, we don't call
lcp_finished() and therefore never exit the main event loop.
This fixes it by handling the delayed-up case in lcp_close() as if
we had done the lowerup but the OPT_SILENT bit was set. We use the
silent case because we don't want to actually send a configure-request
at this point.
Signed-off-by: Paul Mackerras <paulus@samba.org>
char *reason;
{
fsm *f = &lcp_fsm[unit];
char *reason;
{
fsm *f = &lcp_fsm[unit];
if (phase != PHASE_DEAD && phase != PHASE_MASTER)
new_phase(PHASE_TERMINATE);
if (phase != PHASE_DEAD && phase != PHASE_MASTER)
new_phase(PHASE_TERMINATE);
- if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
+
+ if (f->flags & DELAYED_UP) {
+ untimeout(lcp_delayed_up, f);
+ f->state = STOPPED;
+ }
+ oldstate = f->state;
+
+ fsm_close(f, reason);
+ if (oldstate == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP)) {
/*
* This action is not strictly according to the FSM in RFC1548,
* but it does mean that the program terminates if you do a
/*
* This action is not strictly according to the FSM in RFC1548,
* but it does mean that the program terminates if you do a
- * lcp_close() in passive/silent mode when a connection hasn't
- * been established.
+ * lcp_close() when a connection hasn't been established
+ * because we are in passive/silent mode or because we have
+ * delayed the fsm_lowerup() call and it hasn't happened yet.
+ f->flags &= ~DELAYED_UP;
-
- } else
- fsm_close(f, reason);
{
fsm *f = &lcp_fsm[unit];
{
fsm *f = &lcp_fsm[unit];
- if (f->flags & DELAYED_UP)
+ if (f->flags & DELAYED_UP) {
+ untimeout(lcp_delayed_up, f);
+ } else
fsm_lowerdown(&lcp_fsm[unit]);
}
fsm_lowerdown(&lcp_fsm[unit]);
}
if (f->flags & DELAYED_UP) {
f->flags &= ~DELAYED_UP;
if (f->flags & DELAYED_UP) {
f->flags &= ~DELAYED_UP;
+ untimeout(lcp_delayed_up, f);
fsm_lowerup(f);
}
fsm_input(f, p, len);
fsm_lowerup(f);
}
fsm_input(f, p, len);