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