X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Ffsm.c;h=c200cc3a84387cefc952bdd37bac6650bf32161d;hb=4abe4296f0eddbb2b6ff11dbbd27100156c85f87;hp=387f7012928f0d2d7d9bab6a0c1ab3fccb34d143;hpb=428d4139c39999841f8ecc76a8b3414fd93edd3f;p=ppp.git diff --git a/pppd/fsm.c b/pppd/fsm.c index 387f701..c200cc3 100644 --- a/pppd/fsm.c +++ b/pppd/fsm.c @@ -40,7 +40,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define RCSID "$Id: fsm.c,v 1.21 2004/02/02 02:52:51 carlsonj Exp $" +#define RCSID "$Id: fsm.c,v 1.23 2004/11/13 02:28:15 paulus Exp $" /* * TODO: @@ -208,8 +208,9 @@ fsm_open(f) * send a terminate-request message as configured. */ static void -terminate_layer(f) +terminate_layer(f, nextstate) fsm *f; + int nextstate; { if( f->state != OPENED ) UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ @@ -227,7 +228,7 @@ terminate_layer(f) * We've already fired off one Terminate-Request just to be nice * to the peer, but we're not going to wait for a reply. */ - f->state = CLOSED; + f->state = nextstate == CLOSING ? CLOSED : STOPPED; if( f->callbacks->finished ) (*f->callbacks->finished)(f); return; @@ -236,7 +237,7 @@ terminate_layer(f) TIMEOUT(fsm_timeout, f, f->timeouttime); --f->retransmits; - f->state = CLOSING; + f->state = nextstate; } /* @@ -267,7 +268,7 @@ fsm_close(f, reason) case ACKRCVD: case ACKSENT: case OPENED: - terminate_layer(f); + terminate_layer(f, CLOSING); break; } } @@ -495,6 +496,7 @@ fsm_rconfack(f, id, inp, len) return; } f->seen_ack = 1; + f->rnakloops = 0; switch (f->state) { case CLOSED: @@ -543,17 +545,29 @@ fsm_rconfnakrej(f, code, id, inp, len) u_char *inp; int len; { - int (*proc) __P((fsm *, u_char *, int)); int ret; + int treat_as_reject; if (id != f->reqid || f->seen_ack) /* Expected id? */ return; /* Nope, toss... */ - proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; - if (!proc || !(ret = proc(f, inp, len))) { - /* Nak/reject is bad - ignore it */ - error("Received bad configure-nak/rej: %P", inp, len); - return; + + if (code == CONFNAK) { + ++f->rnakloops; + treat_as_reject = (f->rnakloops >= f->maxnakloops); + if (f->callbacks->nakci == NULL + || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { + error("Received bad configure-nak: %P", inp, len); + return; + } + } else { + f->rnakloops = 0; + if (f->callbacks->rejci == NULL + || !(ret = f->callbacks->rejci(f, inp, len))) { + error("Received bad configure-rej: %P", inp, len); + return; + } } + f->seen_ack = 1; switch (f->state) { @@ -714,7 +728,7 @@ fsm_protreject(f) break; case OPENED: - terminate_layer(f); + terminate_layer(f, STOPPING); break; default: @@ -740,6 +754,7 @@ fsm_sconfreq(f, retransmit) if( f->callbacks->resetci ) (*f->callbacks->resetci)(f); f->nakloops = 0; + f->rnakloops = 0; } if( !retransmit ){