00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #include "lwip/opt.h"
00059
00060 #if PPP_SUPPORT
00061
00062 #include "ppp.h"
00063 #include "pppdebug.h"
00064
00065 #include "fsm.h"
00066
00067 #include <string.h>
00068
00069
00070
00071
00072
00073
00074 #if PPP_DEBUG
00075
00076 static const char *ppperr_strerr[] = {
00077 "LS_INITIAL",
00078 "LS_STARTING",
00079 "LS_CLOSED",
00080 "LS_STOPPED",
00081 "LS_CLOSING",
00082 "LS_STOPPING",
00083 "LS_REQSENT",
00084 "LS_ACKRCVD",
00085 "LS_ACKSENT",
00086 "LS_OPENED"
00087 };
00088
00089 #endif
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 static void fsm_timeout (void *);
00100 static void fsm_rconfreq (fsm *, u_char, u_char *, int);
00101 static void fsm_rconfack (fsm *, int, u_char *, int);
00102 static void fsm_rconfnakrej (fsm *, int, int, u_char *, int);
00103 static void fsm_rtermreq (fsm *, int, u_char *, int);
00104 static void fsm_rtermack (fsm *);
00105 static void fsm_rcoderej (fsm *, u_char *, int);
00106 static void fsm_sconfreq (fsm *, int);
00107
00108 #define PROTO_NAME(f) ((f)->callbacks->proto_name)
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 int peer_mru[NUM_PPP];
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 void
00132 fsm_init(fsm *f)
00133 {
00134 f->state = LS_INITIAL;
00135 f->flags = 0;
00136 f->id = 0;
00137 f->timeouttime = FSM_DEFTIMEOUT;
00138 f->maxconfreqtransmits = FSM_DEFMAXCONFREQS;
00139 f->maxtermtransmits = FSM_DEFMAXTERMREQS;
00140 f->maxnakloops = FSM_DEFMAXNAKLOOPS;
00141 f->term_reason_len = 0;
00142 }
00143
00144
00145
00146
00147
00148 void
00149 fsm_lowerup(fsm *f)
00150 {
00151 int oldState = f->state;
00152
00153 LWIP_UNUSED_ARG(oldState);
00154
00155 switch( f->state ) {
00156 case LS_INITIAL:
00157 f->state = LS_CLOSED;
00158 break;
00159
00160 case LS_STARTING:
00161 if( f->flags & OPT_SILENT ) {
00162 f->state = LS_STOPPED;
00163 } else {
00164
00165 fsm_sconfreq(f, 0);
00166 f->state = LS_REQSENT;
00167 }
00168 break;
00169
00170 default:
00171 FSMDEBUG((LOG_INFO, "%s: Up event in state %d (%s)!\n",
00172 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00173 }
00174
00175 FSMDEBUG((LOG_INFO, "%s: lowerup state %d (%s) -> %d (%s)\n",
00176 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 void
00186 fsm_lowerdown(fsm *f)
00187 {
00188 int oldState = f->state;
00189
00190 LWIP_UNUSED_ARG(oldState);
00191
00192 switch( f->state ) {
00193 case LS_CLOSED:
00194 f->state = LS_INITIAL;
00195 break;
00196
00197 case LS_STOPPED:
00198 f->state = LS_STARTING;
00199 if( f->callbacks->starting ) {
00200 (*f->callbacks->starting)(f);
00201 }
00202 break;
00203
00204 case LS_CLOSING:
00205 f->state = LS_INITIAL;
00206 UNTIMEOUT(fsm_timeout, f);
00207 break;
00208
00209 case LS_STOPPING:
00210 case LS_REQSENT:
00211 case LS_ACKRCVD:
00212 case LS_ACKSENT:
00213 f->state = LS_STARTING;
00214 UNTIMEOUT(fsm_timeout, f);
00215 break;
00216
00217 case LS_OPENED:
00218 if( f->callbacks->down ) {
00219 (*f->callbacks->down)(f);
00220 }
00221 f->state = LS_STARTING;
00222 break;
00223
00224 default:
00225 FSMDEBUG((LOG_INFO, "%s: Down event in state %d (%s)!\n",
00226 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00227 }
00228
00229 FSMDEBUG((LOG_INFO, "%s: lowerdown state %d (%s) -> %d (%s)\n",
00230 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
00231 }
00232
00233
00234
00235
00236
00237 void
00238 fsm_open(fsm *f)
00239 {
00240 int oldState = f->state;
00241
00242 LWIP_UNUSED_ARG(oldState);
00243
00244 switch( f->state ) {
00245 case LS_INITIAL:
00246 f->state = LS_STARTING;
00247 if( f->callbacks->starting ) {
00248 (*f->callbacks->starting)(f);
00249 }
00250 break;
00251
00252 case LS_CLOSED:
00253 if( f->flags & OPT_SILENT ) {
00254 f->state = LS_STOPPED;
00255 } else {
00256
00257 fsm_sconfreq(f, 0);
00258 f->state = LS_REQSENT;
00259 }
00260 break;
00261
00262 case LS_CLOSING:
00263 f->state = LS_STOPPING;
00264
00265 case LS_STOPPED:
00266 case LS_OPENED:
00267 if( f->flags & OPT_RESTART ) {
00268 fsm_lowerdown(f);
00269 fsm_lowerup(f);
00270 }
00271 break;
00272 }
00273
00274 FSMDEBUG((LOG_INFO, "%s: open state %d (%s) -> %d (%s)\n",
00275 PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285 void
00286 fsm_close(fsm *f, char *reason)
00287 {
00288 int oldState = f->state;
00289
00290 LWIP_UNUSED_ARG(oldState);
00291
00292 f->term_reason = reason;
00293 f->term_reason_len = (reason == NULL? 0: strlen(reason));
00294 switch( f->state ) {
00295 case LS_STARTING:
00296 f->state = LS_INITIAL;
00297 break;
00298 case LS_STOPPED:
00299 f->state = LS_CLOSED;
00300 break;
00301 case LS_STOPPING:
00302 f->state = LS_CLOSING;
00303 break;
00304
00305 case LS_REQSENT:
00306 case LS_ACKRCVD:
00307 case LS_ACKSENT:
00308 case LS_OPENED:
00309 if( f->state != LS_OPENED ) {
00310 UNTIMEOUT(fsm_timeout, f);
00311 } else if( f->callbacks->down ) {
00312 (*f->callbacks->down)(f);
00313 }
00314
00315 f->retransmits = f->maxtermtransmits;
00316 fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
00317 (u_char *) f->term_reason, f->term_reason_len);
00318 TIMEOUT(fsm_timeout, f, f->timeouttime);
00319 --f->retransmits;
00320
00321 f->state = LS_CLOSING;
00322 break;
00323 }
00324
00325 FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d (%s) -> %d (%s)\n",
00326 PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 void
00336 fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen)
00337 {
00338 u_char *outp;
00339 int outlen;
00340
00341
00342 outp = outpacket_buf[f->unit];
00343 if (datalen > peer_mru[f->unit] - (int)HEADERLEN) {
00344 datalen = peer_mru[f->unit] - HEADERLEN;
00345 }
00346 if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) {
00347 BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
00348 }
00349 outlen = datalen + HEADERLEN;
00350 MAKEHEADER(outp, f->protocol);
00351 PUTCHAR(code, outp);
00352 PUTCHAR(id, outp);
00353 PUTSHORT(outlen, outp);
00354 pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
00355 FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d.\n",
00356 PROTO_NAME(f), code, id, outlen));
00357 }
00358
00359
00360
00361
00362
00363 void
00364 fsm_input(fsm *f, u_char *inpacket, int l)
00365 {
00366 u_char *inp = inpacket;
00367 u_char code, id;
00368 int len;
00369
00370
00371
00372
00373
00374 if (l < HEADERLEN) {
00375 FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n",
00376 f->protocol));
00377 return;
00378 }
00379 GETCHAR(code, inp);
00380 GETCHAR(id, inp);
00381 GETSHORT(len, inp);
00382 if (len < HEADERLEN) {
00383 FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n",
00384 f->protocol));
00385 return;
00386 }
00387 if (len > l) {
00388 FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n",
00389 f->protocol));
00390 return;
00391 }
00392 len -= HEADERLEN;
00393
00394 if( f->state == LS_INITIAL || f->state == LS_STARTING ) {
00395 FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d (%s).\n",
00396 f->protocol, f->state, ppperr_strerr[f->state]));
00397 return;
00398 }
00399 FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
00400
00401
00402
00403 switch (code) {
00404 case CONFREQ:
00405 fsm_rconfreq(f, id, inp, len);
00406 break;
00407
00408 case CONFACK:
00409 fsm_rconfack(f, id, inp, len);
00410 break;
00411
00412 case CONFNAK:
00413 case CONFREJ:
00414 fsm_rconfnakrej(f, code, id, inp, len);
00415 break;
00416
00417 case TERMREQ:
00418 fsm_rtermreq(f, id, inp, len);
00419 break;
00420
00421 case TERMACK:
00422 fsm_rtermack(f);
00423 break;
00424
00425 case CODEREJ:
00426 fsm_rcoderej(f, inp, len);
00427 break;
00428
00429 default:
00430 if( !f->callbacks->extcode ||
00431 !(*f->callbacks->extcode)(f, code, id, inp, len) ) {
00432 fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
00433 }
00434 break;
00435 }
00436 }
00437
00438
00439
00440
00441
00442
00443
00444 void
00445 fsm_protreject(fsm *f)
00446 {
00447 switch( f->state ) {
00448 case LS_CLOSING:
00449 UNTIMEOUT(fsm_timeout, f);
00450
00451 case LS_CLOSED:
00452 f->state = LS_CLOSED;
00453 if( f->callbacks->finished ) {
00454 (*f->callbacks->finished)(f);
00455 }
00456 break;
00457
00458 case LS_STOPPING:
00459 case LS_REQSENT:
00460 case LS_ACKRCVD:
00461 case LS_ACKSENT:
00462 UNTIMEOUT(fsm_timeout, f);
00463
00464 case LS_STOPPED:
00465 f->state = LS_STOPPED;
00466 if( f->callbacks->finished ) {
00467 (*f->callbacks->finished)(f);
00468 }
00469 break;
00470
00471 case LS_OPENED:
00472 if( f->callbacks->down ) {
00473 (*f->callbacks->down)(f);
00474 }
00475
00476 f->retransmits = f->maxtermtransmits;
00477 fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
00478 (u_char *) f->term_reason, f->term_reason_len);
00479 TIMEOUT(fsm_timeout, f, f->timeouttime);
00480 --f->retransmits;
00481
00482 f->state = LS_STOPPING;
00483 break;
00484
00485 default:
00486 FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d (%s)!\n",
00487 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00488 }
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 static void
00503 fsm_timeout(void *arg)
00504 {
00505 fsm *f = (fsm *) arg;
00506
00507 switch (f->state) {
00508 case LS_CLOSING:
00509 case LS_STOPPING:
00510 if( f->retransmits <= 0 ) {
00511 FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d (%s)\n",
00512 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00513
00514
00515
00516 f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED;
00517 if( f->callbacks->finished ) {
00518 (*f->callbacks->finished)(f);
00519 }
00520 } else {
00521 FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d (%s)\n",
00522 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00523
00524 fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
00525 (u_char *) f->term_reason, f->term_reason_len);
00526 TIMEOUT(fsm_timeout, f, f->timeouttime);
00527 --f->retransmits;
00528 }
00529 break;
00530
00531 case LS_REQSENT:
00532 case LS_ACKRCVD:
00533 case LS_ACKSENT:
00534 if (f->retransmits <= 0) {
00535 FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d (%s)\n",
00536 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00537 f->state = LS_STOPPED;
00538 if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) {
00539 (*f->callbacks->finished)(f);
00540 }
00541 } else {
00542 FSMDEBUG((LOG_WARNING, "%s: timeout resending Config-Request state=%d (%s)\n",
00543 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00544
00545 if (f->callbacks->retransmit) {
00546 (*f->callbacks->retransmit)(f);
00547 }
00548 fsm_sconfreq(f, 1);
00549 if( f->state == LS_ACKRCVD ) {
00550 f->state = LS_REQSENT;
00551 }
00552 }
00553 break;
00554
00555 default:
00556 FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n",
00557 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00558 }
00559 }
00560
00561
00562
00563
00564
00565 static void
00566 fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
00567 {
00568 int code, reject_if_disagree;
00569
00570 FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
00571 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
00572 switch( f->state ) {
00573 case LS_CLOSED:
00574
00575 fsm_sdata(f, TERMACK, id, NULL, 0);
00576 return;
00577 case LS_CLOSING:
00578 case LS_STOPPING:
00579 return;
00580
00581 case LS_OPENED:
00582
00583 if( f->callbacks->down ) {
00584 (*f->callbacks->down)(f);
00585 }
00586 fsm_sconfreq(f, 0);
00587 break;
00588
00589 case LS_STOPPED:
00590
00591 fsm_sconfreq(f, 0);
00592 f->state = LS_REQSENT;
00593 break;
00594 }
00595
00596
00597
00598
00599
00600 if (f->callbacks->reqci) {
00601 reject_if_disagree = (f->nakloops >= f->maxnakloops);
00602 code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
00603 } else if (len) {
00604 code = CONFREJ;
00605 } else {
00606 code = CONFACK;
00607 }
00608
00609
00610 fsm_sdata(f, (u_char)code, id, inp, len);
00611
00612 if (code == CONFACK) {
00613 if (f->state == LS_ACKRCVD) {
00614 UNTIMEOUT(fsm_timeout, f);
00615 f->state = LS_OPENED;
00616 if (f->callbacks->up) {
00617 (*f->callbacks->up)(f);
00618 }
00619 } else {
00620 f->state = LS_ACKSENT;
00621 }
00622 f->nakloops = 0;
00623 } else {
00624
00625 if (f->state != LS_ACKRCVD) {
00626 f->state = LS_REQSENT;
00627 }
00628 if( code == CONFNAK ) {
00629 ++f->nakloops;
00630 }
00631 }
00632 }
00633
00634
00635
00636
00637
00638 static void
00639 fsm_rconfack(fsm *f, int id, u_char *inp, int len)
00640 {
00641 FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
00642 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
00643
00644 if (id != f->reqid || f->seen_ack) {
00645 return;
00646 }
00647 if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) {
00648
00649 FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)\n",
00650 PROTO_NAME(f), len));
00651 return;
00652 }
00653 f->seen_ack = 1;
00654
00655 switch (f->state) {
00656 case LS_CLOSED:
00657 case LS_STOPPED:
00658 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
00659 break;
00660
00661 case LS_REQSENT:
00662 f->state = LS_ACKRCVD;
00663 f->retransmits = f->maxconfreqtransmits;
00664 break;
00665
00666 case LS_ACKRCVD:
00667
00668 UNTIMEOUT(fsm_timeout, f);
00669 fsm_sconfreq(f, 0);
00670 f->state = LS_REQSENT;
00671 break;
00672
00673 case LS_ACKSENT:
00674 UNTIMEOUT(fsm_timeout, f);
00675 f->state = LS_OPENED;
00676 f->retransmits = f->maxconfreqtransmits;
00677 if (f->callbacks->up) {
00678 (*f->callbacks->up)(f);
00679 }
00680 break;
00681
00682 case LS_OPENED:
00683
00684 if (f->callbacks->down) {
00685 (*f->callbacks->down)(f);
00686 }
00687 fsm_sconfreq(f, 0);
00688 f->state = LS_REQSENT;
00689 break;
00690 }
00691 }
00692
00693
00694
00695
00696
00697 static void
00698 fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
00699 {
00700 int (*proc) (fsm *, u_char *, int);
00701 int ret;
00702
00703 FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
00704 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
00705
00706 if (id != f->reqid || f->seen_ack) {
00707 return;
00708 }
00709 proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
00710 if (!proc || !((ret = proc(f, inp, len)))) {
00711
00712 FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n",
00713 PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
00714 return;
00715 }
00716 f->seen_ack = 1;
00717
00718 switch (f->state) {
00719 case LS_CLOSED:
00720 case LS_STOPPED:
00721 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
00722 break;
00723
00724 case LS_REQSENT:
00725 case LS_ACKSENT:
00726
00727 UNTIMEOUT(fsm_timeout, f);
00728 if (ret < 0) {
00729 f->state = LS_STOPPED;
00730 } else {
00731 fsm_sconfreq(f, 0);
00732 }
00733 break;
00734
00735 case LS_ACKRCVD:
00736
00737 UNTIMEOUT(fsm_timeout, f);
00738 fsm_sconfreq(f, 0);
00739 f->state = LS_REQSENT;
00740 break;
00741
00742 case LS_OPENED:
00743
00744 if (f->callbacks->down) {
00745 (*f->callbacks->down)(f);
00746 }
00747 fsm_sconfreq(f, 0);
00748 f->state = LS_REQSENT;
00749 break;
00750 }
00751 }
00752
00753
00754
00755
00756
00757 static void
00758 fsm_rtermreq(fsm *f, int id, u_char *p, int len)
00759 {
00760 LWIP_UNUSED_ARG(p);
00761
00762 FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
00763 PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
00764
00765 switch (f->state) {
00766 case LS_ACKRCVD:
00767 case LS_ACKSENT:
00768 f->state = LS_REQSENT;
00769 break;
00770
00771 case LS_OPENED:
00772 if (len > 0) {
00773 FSMDEBUG((LOG_INFO, "%s terminated by peer (%x)\n", PROTO_NAME(f), p));
00774 } else {
00775 FSMDEBUG((LOG_INFO, "%s terminated by peer\n", PROTO_NAME(f)));
00776 }
00777 if (f->callbacks->down) {
00778 (*f->callbacks->down)(f);
00779 }
00780 f->retransmits = 0;
00781 f->state = LS_STOPPING;
00782 TIMEOUT(fsm_timeout, f, f->timeouttime);
00783 break;
00784 }
00785
00786 fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
00787 }
00788
00789
00790
00791
00792
00793 static void
00794 fsm_rtermack(fsm *f)
00795 {
00796 FSMDEBUG((LOG_INFO, "fsm_rtermack(%s): state=%d (%s)\n",
00797 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00798
00799 switch (f->state) {
00800 case LS_CLOSING:
00801 UNTIMEOUT(fsm_timeout, f);
00802 f->state = LS_CLOSED;
00803 if( f->callbacks->finished ) {
00804 (*f->callbacks->finished)(f);
00805 }
00806 break;
00807
00808 case LS_STOPPING:
00809 UNTIMEOUT(fsm_timeout, f);
00810 f->state = LS_STOPPED;
00811 if( f->callbacks->finished ) {
00812 (*f->callbacks->finished)(f);
00813 }
00814 break;
00815
00816 case LS_ACKRCVD:
00817 f->state = LS_REQSENT;
00818 break;
00819
00820 case LS_OPENED:
00821 if (f->callbacks->down) {
00822 (*f->callbacks->down)(f);
00823 }
00824 fsm_sconfreq(f, 0);
00825 break;
00826 }
00827 }
00828
00829
00830
00831
00832
00833 static void
00834 fsm_rcoderej(fsm *f, u_char *inp, int len)
00835 {
00836 u_char code, id;
00837
00838 FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d (%s)\n",
00839 PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
00840
00841 if (len < HEADERLEN) {
00842 FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
00843 return;
00844 }
00845 GETCHAR(code, inp);
00846 GETCHAR(id, inp);
00847 FSMDEBUG((LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d\n",
00848 PROTO_NAME(f), code, id));
00849
00850 if( f->state == LS_ACKRCVD ) {
00851 f->state = LS_REQSENT;
00852 }
00853 }
00854
00855
00856
00857
00858
00859 static void
00860 fsm_sconfreq(fsm *f, int retransmit)
00861 {
00862 u_char *outp;
00863 int cilen;
00864
00865 if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) {
00866
00867 if( f->callbacks->resetci ) {
00868 (*f->callbacks->resetci)(f);
00869 }
00870 f->nakloops = 0;
00871 }
00872
00873 if( !retransmit ) {
00874
00875 f->retransmits = f->maxconfreqtransmits;
00876 f->reqid = ++f->id;
00877 }
00878
00879 f->seen_ack = 0;
00880
00881
00882
00883
00884 outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN;
00885 if( f->callbacks->cilen && f->callbacks->addci ) {
00886 cilen = (*f->callbacks->cilen)(f);
00887 if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) {
00888 cilen = peer_mru[f->unit] - HEADERLEN;
00889 }
00890 if (f->callbacks->addci) {
00891 (*f->callbacks->addci)(f, outp, &cilen);
00892 }
00893 } else {
00894 cilen = 0;
00895 }
00896
00897
00898 fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
00899
00900
00901 --f->retransmits;
00902 TIMEOUT(fsm_timeout, f, f->timeouttime);
00903
00904 FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d\n",
00905 PROTO_NAME(f), f->reqid));
00906 }
00907
00908 #endif