From: Paul Mackerras Date: Sun, 7 Mar 2010 04:21:38 +0000 (+1100) Subject: pppd: Terminate correctly if lcp_lowerup delayed calling fsm_lowerup X-Git-Tag: ppp-2.4.7~53 X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=3eb9e810cfa515543655659b72dde30c54fea0a5 pppd: Terminate correctly if lcp_lowerup delayed calling fsm_lowerup 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 --- diff --git a/pppd/lcp.c b/pppd/lcp.c index 5c77490..8ed2778 100644 --- a/pppd/lcp.c +++ b/pppd/lcp.c @@ -397,21 +397,29 @@ lcp_close(unit, reason) char *reason; { fsm *f = &lcp_fsm[unit]; + int oldstate; 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 - * 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->state = CLOSED; + f->flags &= ~DELAYED_UP; lcp_finished(f); - - } else - fsm_close(f, reason); + } } @@ -453,9 +461,10 @@ lcp_lowerdown(unit) { fsm *f = &lcp_fsm[unit]; - if (f->flags & DELAYED_UP) + if (f->flags & DELAYED_UP) { f->flags &= ~DELAYED_UP; - else + untimeout(lcp_delayed_up, f); + } else fsm_lowerdown(&lcp_fsm[unit]); } @@ -489,6 +498,7 @@ lcp_input(unit, p, len) if (f->flags & DELAYED_UP) { f->flags &= ~DELAYED_UP; + untimeout(lcp_delayed_up, f); fsm_lowerup(f); } fsm_input(f, p, len);