fsm.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:17k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* fsm.c - {Link, IP} Control Protocol Finite State Machine */
  2. /* Copyright 1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1989 Carnegie Mellon University.
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by Carnegie Mellon University.  The name of the
  14.  * University may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20. /*
  21. modification history
  22. --------------------
  23. 01d,10sep98,sgv  Added fix for interoperating with Windows
  24. 01c,16jun95,dzb  header file consolidation.
  25.                  changed [UN]TIMEOUT macros to PPP_[UN]TIMEOUT.
  26. 01b,16jan95,dzb  warnings cleanup.
  27. 01a,21dec94,dab  VxWorks port - first WRS version.
  28.            +dzb  added: path for ppp header files, WRS copyright, strLib.h.
  29. */
  30. /*
  31.  * TODO:
  32.  * Deal with variable outgoing MTU.
  33.  */
  34. #include "vxWorks.h"
  35. #include "stdio.h"
  36. #include "strLib.h"
  37. #include "sys/types.h"
  38. #include "socket.h"
  39. #include "net/if.h"
  40. #include "pppLib.h"
  41. extern char *proto_name();
  42. static void fsm_timeout __ARGS((caddr_t));
  43. static void fsm_rconfreq __ARGS((fsm *, int, u_char *, int));
  44. static void fsm_rconfack __ARGS((fsm *, int, u_char *, int));
  45. static void fsm_rconfnakrej __ARGS((fsm *, int, int, u_char *, int));
  46. static void fsm_rtermreq __ARGS((fsm *, int));
  47. static void fsm_rtermack __ARGS((fsm *));
  48. static void fsm_rcoderej __ARGS((fsm *, u_char *, int));
  49. static void fsm_sconfreq __ARGS((fsm *, int));
  50. #define PROTO_NAME(f) ((f)->callbacks->proto_name)
  51. /*
  52.  * fsm_init - Initialize fsm.
  53.  *
  54.  * Initialize fsm state.
  55.  */
  56. void
  57. fsm_init(f)
  58.     fsm *f;
  59. {
  60.     f->state = INITIAL;
  61.     f->flags = 0;
  62.     f->id = (u_char)random();
  63.     f->timeouttime = DEFTIMEOUT;
  64.     f->maxconfreqtransmits = DEFMAXCONFREQS;
  65.     f->maxtermtransmits = DEFMAXTERMREQS;
  66.     f->maxnakloops = DEFMAXNAKLOOPS;
  67. }
  68. /*
  69.  * fsm_lowerup - The lower layer is up.
  70.  */
  71. void
  72. fsm_lowerup(f)
  73.     fsm *f;
  74. {
  75.     switch( f->state ){
  76.     case INITIAL:
  77. f->state = CLOSED;
  78. break;
  79.     case STARTING:
  80. if( f->flags & OPT_SILENT )
  81.     f->state = STOPPED;
  82. else {
  83.     /* Send an initial configure-request */
  84.     fsm_sconfreq(f, 0);
  85.     f->state = REQSENT;
  86. }
  87. break;
  88.     default:
  89. FSMDEBUG((LOG_INFO, "%s: Up event in state %d!",
  90.                   PROTO_NAME(f), f->state));
  91.     }
  92. }
  93. /*
  94.  * fsm_lowerdown - The lower layer is down.
  95.  *
  96.  * Cancel all timeouts and inform upper layers.
  97.  */
  98. void
  99. fsm_lowerdown(f)
  100.     fsm *f;
  101. {
  102.     switch( f->state ){
  103.     case CLOSED:
  104. f->state = INITIAL;
  105. break;
  106.     case STOPPED:
  107. f->state = STARTING;
  108. if( f->callbacks->starting )
  109.     (*f->callbacks->starting)(f);
  110. break;
  111.     case CLOSING:
  112. f->state = INITIAL;
  113. PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  114. break;
  115.     case STOPPING:
  116.     case REQSENT:
  117.     case ACKRCVD:
  118.     case ACKSENT:
  119. f->state = STARTING;
  120. PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  121. break;
  122.     case OPENED:
  123. if( f->callbacks->down )
  124.     (*f->callbacks->down)(f);
  125. f->state = STARTING;
  126. break;
  127.     default:
  128. FSMDEBUG((LOG_INFO, "%s: Down event in state %d!",
  129.                   PROTO_NAME(f), f->state));
  130.     }
  131. }
  132. /*
  133.  * fsm_open - Link is allowed to come up.
  134.  */
  135. void
  136. fsm_open(f)
  137.     fsm *f;
  138. {
  139.     switch( f->state ){
  140.     case INITIAL:
  141. f->state = STARTING;
  142. if( f->callbacks->starting )
  143.     (*f->callbacks->starting)(f);
  144. break;
  145.     case CLOSED:
  146. if( f->flags & OPT_SILENT )
  147.     f->state = STOPPED;
  148. else {
  149.     /* Send an initial configure-request */
  150.     fsm_sconfreq(f, 0);
  151.     f->state = REQSENT;
  152. }
  153. break;
  154.     case CLOSING:
  155. f->state = STOPPING;
  156. /* fall through */
  157.     case STOPPED:
  158.     case OPENED:
  159. if( f->flags & OPT_RESTART ){
  160.     fsm_lowerdown(f);
  161.     fsm_lowerup(f);
  162. }
  163. break;
  164.     }
  165. }
  166. /*
  167.  * fsm_close - Start closing connection.
  168.  *
  169.  * Cancel timeouts and either initiate close or possibly go directly to
  170.  * the CLOSED state.
  171.  */
  172. void
  173. fsm_close(f)
  174.     fsm *f;
  175. {
  176.     switch( f->state ){
  177.     case STARTING:
  178. f->state = INITIAL;
  179. break;
  180.     case STOPPED:
  181. f->state = CLOSED;
  182. break;
  183.     case STOPPING:
  184. f->state = CLOSING;
  185. break;
  186.     case REQSENT:
  187.     case ACKRCVD:
  188.     case ACKSENT:
  189.     case OPENED:
  190. if( f->state != OPENED )
  191.     PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  192. else if( f->callbacks->down )
  193.     (*f->callbacks->down)(f); /* Inform upper layers we're down */
  194. /* Init restart counter, send Terminate-Request */
  195. f->retransmits = f->maxtermtransmits;
  196. fsm_sdata(f, TERMREQ, f->reqid = ++f->id, NULL, 0);
  197. PPP_TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
  198. --f->retransmits;
  199. f->state = CLOSING;
  200. break;
  201.     }
  202. }
  203. /*
  204.  * fsm_timeout - Timeout expired.
  205.  */
  206. static void
  207. fsm_timeout(arg)
  208.     caddr_t arg;
  209. {
  210.     fsm *f = (fsm *) arg;
  211.     switch (f->state) {
  212.     case CLOSING:
  213.     case STOPPING:
  214. if( f->retransmits <= 0 ){
  215.     /*
  216.      * We've waited for an ack long enough.  Peer probably heard us.
  217.      */
  218.     f->state = (f->state == CLOSING)? CLOSED: STOPPED;
  219.     if( f->callbacks->finished )
  220. (*f->callbacks->finished)(f);
  221. } else {
  222.     /* Send Terminate-Request */
  223.     fsm_sdata(f, TERMREQ, f->reqid = ++f->id, NULL, 0);
  224.     PPP_TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
  225.     --f->retransmits;
  226. }
  227. break;
  228.     case REQSENT:
  229.     case ACKRCVD:
  230.     case ACKSENT:
  231. if (f->retransmits <= 0) {
  232.     syslog(LOG_WARNING, "%s: timeout sending Config-Requests",
  233.                    PROTO_NAME(f));
  234.     f->state = STOPPED;
  235.     if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
  236. (*f->callbacks->finished)(f);
  237. } else {
  238.     /* Retransmit the configure-request */
  239.     if (f->callbacks->retransmit)
  240. (*f->callbacks->retransmit)(f);
  241.     fsm_sconfreq(f, 1); /* Re-send Configure-Request */
  242.     if( f->state == ACKRCVD )
  243. f->state = REQSENT;
  244. }
  245. break;
  246.     default:
  247. FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d!",
  248.                   PROTO_NAME(f), f->state));
  249.     }
  250. }
  251. /*
  252.  * fsm_input - Input packet.
  253.  */
  254. void
  255. fsm_input(f, inpacket, l)
  256.     fsm *f;
  257.     u_char *inpacket;
  258.     int l;
  259. {
  260.     u_char *inp;
  261.     u_char code, id;
  262.     int len;
  263.     /*
  264.      * Parse header (code, id and length).
  265.      * If packet too short, drop it.
  266.      */
  267.     inp = inpacket;
  268.     if (l < HEADERLEN) {
  269. FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.",
  270.                   f->protocol));
  271. return;
  272.     }
  273.     GETCHAR(code, inp);
  274.     GETCHAR(id, inp);
  275.     GETSHORT(len, inp);
  276.     if (len < HEADERLEN) {
  277. FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.",
  278.                   f->protocol));
  279. return;
  280.     }
  281.     if (len > l) {
  282. FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.",
  283.                   f->protocol));
  284. return;
  285.     }
  286.     len -= HEADERLEN; /* subtract header length */
  287.     if( f->state == INITIAL || f->state == STARTING ){
  288. FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d.",
  289.   f->protocol, f->state));
  290. return;
  291.     }
  292.     /*
  293.      * Action depends on code.
  294.      */
  295.     switch (code) {
  296.     case CONFREQ:
  297. fsm_rconfreq(f, id, inp, len);
  298. break;
  299.     
  300.     case CONFACK:
  301. fsm_rconfack(f, id, inp, len);
  302. break;
  303.     
  304.     case CONFNAK:
  305.     case CONFREJ:
  306. fsm_rconfnakrej(f, code, id, inp, len);
  307. break;
  308.     
  309.     case TERMREQ:
  310. fsm_rtermreq(f, id);
  311. break;
  312.     
  313.     case TERMACK:
  314. fsm_rtermack(f);
  315. break;
  316.     
  317.     case CODEREJ:
  318. fsm_rcoderej(f, inp, len);
  319. break;
  320.     
  321.     default:
  322. if( !f->callbacks->extcode
  323.    || !(*f->callbacks->extcode)(f, code, id, inp, len) )
  324.     fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
  325. break;
  326.     }
  327. }
  328. /*
  329.  * fsm_rconfreq - Receive Configure-Request.
  330.  */
  331. static void
  332. fsm_rconfreq(f, id, inp, len)
  333.     fsm *f;
  334.     u_char id;
  335.     u_char *inp;
  336.     int len;
  337. {
  338.     int code = 0, reject_if_disagree;
  339.     FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d.", PROTO_NAME(f), id));
  340.     switch( f->state ){
  341.     case CLOSED:
  342. /* Go away, we're closed */
  343. fsm_sdata(f, TERMACK, id, NULL, 0);
  344. return;
  345.     case CLOSING:
  346.     case STOPPING:
  347. return;
  348.     case OPENED:
  349. /* Go down and restart negotiation */
  350. if( f->callbacks->down )
  351.     (*f->callbacks->down)(f); /* Inform upper layers */
  352. fsm_sconfreq(f, 0); /* Send initial Configure-Request */
  353. break;
  354.     case STOPPED:
  355. /* Negotiation started by our peer */
  356. fsm_sconfreq(f, 0); /* Send initial Configure-Request */
  357. f->state = REQSENT;
  358. break;
  359.     }
  360.     /*
  361.      * Pass the requested configuration options
  362.      * to protocol-specific code for checking.
  363.      */
  364.     if (f->callbacks->reqci){ /* Check CI */
  365. reject_if_disagree = (f->nakloops >= f->maxnakloops);
  366. code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
  367.     } else if (len)
  368. code = CONFREJ; /* Reject all CI */
  369.     else
  370.         code = CONFACK;
  371.     /* send the Ack, Nak or Rej to the peer */
  372.     fsm_sdata(f, code, id, inp, len);
  373.     if (code == CONFACK) {
  374. if (f->state == ACKRCVD) {
  375.     PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  376.     f->state = OPENED;
  377.     if (f->callbacks->up)
  378. (*f->callbacks->up)(f); /* Inform upper layers */
  379. } else
  380.     f->state = ACKSENT;
  381. f->nakloops = 0;
  382.     } else {
  383. /* we sent CONFACK or CONFREJ */
  384. if (f->state != ACKRCVD)
  385.     f->state = REQSENT;
  386. if( code == CONFNAK )
  387.     ++f->nakloops;
  388.     }
  389. }
  390. /*
  391.  * fsm_rconfack - Receive Configure-Ack.
  392.  */
  393. static void
  394. fsm_rconfack(f, id, inp, len)
  395.     fsm *f;
  396.     u_char id;
  397.     u_char *inp;
  398.     int len;
  399. {
  400.     FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d.",
  401.               PROTO_NAME(f), id));
  402.     if (id != f->reqid) /* Expected id? */
  403. return; /* Nope, toss... */
  404.     if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ){
  405. /* Ack is bad - ignore it */
  406. FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)",
  407.                   PROTO_NAME(f), len));
  408. return;
  409.     }
  410.     f->reqid = -1;
  411.     switch (f->state) {
  412.     case CLOSED:
  413.     case STOPPED:
  414. fsm_sdata(f, TERMACK, id, NULL, 0);
  415. break;
  416.     case REQSENT:
  417. f->state = ACKRCVD;
  418. f->retransmits = f->maxconfreqtransmits;
  419. break;
  420.     case ACKRCVD:
  421. /* Huh? an extra Ack? oh well... */
  422. fsm_sconfreq(f, 0);
  423. f->state = REQSENT;
  424. break;
  425.     case ACKSENT:
  426. PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  427. f->state = OPENED;
  428. f->retransmits = f->maxconfreqtransmits;
  429. if (f->callbacks->up)
  430.     (*f->callbacks->up)(f); /* Inform upper layers */
  431. break;
  432.     case OPENED:
  433. /* Go down and restart negotiation */
  434. if (f->callbacks->down)
  435.     (*f->callbacks->down)(f); /* Inform upper layers */
  436. fsm_sconfreq(f, 0); /* Send initial Configure-Request */
  437. f->state = REQSENT;
  438. break;
  439.     }
  440. }
  441. /*
  442.  * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
  443.  */
  444. static void
  445. fsm_rconfnakrej(f, code, id, inp, len)
  446.     fsm *f;
  447.     int code, id;
  448.     u_char *inp;
  449.     int len;
  450. {
  451.     int (*proc)();
  452.     FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d.",
  453.               PROTO_NAME(f), id));
  454.     if (id != f->reqid) /* Expected id? */
  455. return; /* Nope, toss... */
  456.     proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
  457.     if( !proc || !proc(f, inp, len) ){
  458. /* Nak/reject is bad - ignore it */
  459. FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)",
  460.   PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
  461. return;
  462.     }
  463.     f->reqid = -1;
  464.     switch (f->state) {
  465.     case CLOSED:
  466.     case STOPPED:
  467. fsm_sdata(f, TERMACK, id, NULL, 0);
  468. break;
  469.     case REQSENT:
  470.     case ACKSENT:
  471. /* They didn't agree to what we wanted - try another request */
  472. PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  473. fsm_sconfreq(f, 0); /* Send Configure-Request */
  474. break;
  475.     case ACKRCVD:
  476. /* Got a Nak/reject when we had already had an Ack?? oh well... */
  477. fsm_sconfreq(f, 0);
  478. f->state = REQSENT;
  479. break;
  480.     case OPENED:
  481. /* Go down and restart negotiation */
  482. if (f->callbacks->down)
  483.     (*f->callbacks->down)(f); /* Inform upper layers */
  484. fsm_sconfreq(f, 0); /* Send initial Configure-Request */
  485. f->state = REQSENT;
  486. break;
  487.     }
  488. }
  489. /*
  490.  * fsm_rtermreq - Receive Terminate-Req.
  491.  */
  492. static void
  493. fsm_rtermreq(f, id)
  494.     fsm *f;
  495.     int id;
  496. {
  497.     FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d.",
  498.               PROTO_NAME(f), id));
  499.     switch (f->state) {
  500.     case ACKRCVD:
  501.     case ACKSENT:
  502. f->state = REQSENT; /* Start over but keep trying */
  503. break;
  504.     case OPENED:
  505. syslog(LOG_INFO, "%s terminated at peer's request", PROTO_NAME(f));
  506. if (f->callbacks->down)
  507.     (*f->callbacks->down)(f); /* Inform upper layers */
  508. f->retransmits = 0;
  509. f->state = STOPPING;
  510. PPP_TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
  511. break;
  512.     }
  513.     fsm_sdata(f, TERMACK, id, NULL, 0);
  514. }
  515. /*
  516.  * fsm_rtermack - Receive Terminate-Ack.
  517.  */
  518. static void
  519. fsm_rtermack(f)
  520.     fsm *f;
  521. {
  522.     FSMDEBUG((LOG_INFO, "fsm_rtermack(%s).", PROTO_NAME(f)));
  523.     switch (f->state) {
  524.     case CLOSING:
  525. f->state = CLOSED;
  526. if( f->callbacks->finished )
  527.     (*f->callbacks->finished)(f);
  528. break;
  529.     case STOPPING:
  530. f->state = STOPPED;
  531. if( f->callbacks->finished )
  532.     (*f->callbacks->finished)(f);
  533. break;
  534.     case ACKRCVD:
  535. f->state = REQSENT;
  536. break;
  537.     case OPENED:
  538. if (f->callbacks->down)
  539.     (*f->callbacks->down)(f); /* Inform upper layers */
  540. fsm_sconfreq(f, 0);
  541. break;
  542.     }
  543. }
  544. /*
  545.  * fsm_rcoderej - Receive an Code-Reject.
  546.  */
  547. static void
  548. fsm_rcoderej(f, inp, len)
  549.     fsm *f;
  550.     u_char *inp;
  551.     int len;
  552. {
  553.     u_char code, id;
  554.     FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s).", PROTO_NAME(f)));
  555.     if (len < HEADERLEN) {
  556. FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!"));
  557. return;
  558.     }
  559.     GETCHAR(code, inp);
  560.     GETCHAR(id, inp);
  561.     syslog(LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d",
  562.            PROTO_NAME(f), code, id);
  563.     if( f->state == ACKRCVD )
  564. f->state = REQSENT;
  565. }
  566. /*
  567.  * fsm_protreject - Peer doesn't speak this protocol.
  568.  *
  569.  * Treat this as a catastrophic error (RXJ-).
  570.  */
  571. void
  572. fsm_protreject(f)
  573.     fsm *f;
  574. {
  575.     switch( f->state ){
  576.     case CLOSING:
  577. PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  578. /* fall through */
  579.     case CLOSED:
  580. f->state = CLOSED;
  581. if( f->callbacks->finished )
  582.     (*f->callbacks->finished)(f);
  583. break;
  584.     case STOPPING:
  585.     case REQSENT:
  586.     case ACKRCVD:
  587.     case ACKSENT:
  588. PPP_UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
  589. /* fall through */
  590.     case STOPPED:
  591. f->state = STOPPED;
  592. if( f->callbacks->finished )
  593.     (*f->callbacks->finished)(f);
  594. break;
  595.     case OPENED:
  596. if( f->callbacks->down )
  597.     (*f->callbacks->down)(f);
  598. /* Init restart counter, send Terminate-Request */
  599. f->retransmits = f->maxtermtransmits;
  600. fsm_sdata(f, TERMREQ, f->reqid = ++f->id, NULL, 0);
  601. PPP_TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
  602. --f->retransmits;
  603. f->state = STOPPING;
  604. break;
  605.     default:
  606. FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d!",
  607.   PROTO_NAME(f), f->state));
  608.     }
  609. }
  610. extern struct ppp_softc *ppp_softc[ ];
  611. /*
  612.  * fsm_sconfreq - Send a Configure-Request.
  613.  */
  614. static void
  615. fsm_sconfreq(f, retransmit)
  616.     fsm *f;
  617.     int retransmit;
  618. {
  619.     u_char *outp;
  620.     int cilen;
  621.     register struct ppp_softc *sc = ppp_softc[f->unit];
  622.     if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
  623. /* Not currently negotiating - reset options */
  624. if( f->callbacks->resetci )
  625.     (*f->callbacks->resetci)(f);
  626. f->nakloops = 0;
  627.     }
  628.     if( !retransmit ){
  629. /* New request - reset retransmission counter, use new ID */
  630. f->retransmits = f->maxconfreqtransmits;
  631. f->reqid = ++f->id;
  632.     }
  633.     /* Write the string "CLIENT" to the remote peer */
  634.     if (((ppp_if[ppp_unit]->lcp_wantoptions.passive) == 1) || 
  635.  (ppp_if[ppp_unit]->lcp_wantoptions.silent == 1))
  636. {
  637. char buf[7];
  638. strncpy(buf,"CLIENT",strlen("CLIENT"));
  639. output(f->unit, buf, strlen("CLIENT"));
  640. taskDelay(sysClkRateGet());
  641. }
  642.     /*
  643.      * Make up the request packet
  644.      */
  645.     outp = ppp_if[f->unit]->outpacket_buf + DLLHEADERLEN + HEADERLEN;
  646.     if( f->callbacks->cilen && f->callbacks->addci ){
  647. cilen = (*f->callbacks->cilen)(f);
  648. if( cilen > ppp_if[f->unit]->peer_mru - HEADERLEN )
  649.     cilen = ppp_if[f->unit]->peer_mru - HEADERLEN;
  650. if (f->callbacks->addci)
  651.     (*f->callbacks->addci)(f, outp, &cilen);
  652.     } else
  653. cilen = 0;
  654.     /* send the request to our peer */
  655.     fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
  656.     /* start the retransmit timer */
  657.     --f->retransmits;
  658.     PPP_TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime);
  659.     FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d",
  660.       PROTO_NAME(f), f->reqid));
  661. }
  662. /*
  663.  * fsm_sdata - Send some data.
  664.  *
  665.  * Used for all packets sent to our peer by this module.
  666.  */
  667. void
  668. fsm_sdata(f, code, id, data, datalen)
  669.     fsm *f;
  670.     u_char code, id;
  671.     u_char *data;
  672.     int datalen;
  673. {
  674.     u_char *outp;
  675.     int outlen;
  676.     /* Adjust length to be smaller than MTU */
  677.     outp = ppp_if[f->unit]->outpacket_buf;
  678.     if (datalen > ppp_if[f->unit]->peer_mru - HEADERLEN)
  679. datalen = ppp_if[f->unit]->peer_mru - HEADERLEN;
  680.     if (datalen && data != outp + DLLHEADERLEN + HEADERLEN)
  681. BCOPY((char *)data, (char *)(outp + DLLHEADERLEN + HEADERLEN), datalen);
  682.     outlen = datalen + HEADERLEN;
  683.     MAKEHEADER(outp, f->protocol);
  684.     PUTCHAR(code, outp);
  685.     PUTCHAR(id, outp);
  686.     PUTSHORT(outlen, outp);
  687.     output(f->unit, ppp_if[f->unit]->outpacket_buf, outlen + DLLHEADERLEN);
  688.     FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d, id %d.",
  689.       PROTO_NAME(f), code, id));
  690. }