1 /*****************************************************************************
2 * fsm.c - Network Control Protocol Finite State Machine program file.
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5 * portions Copyright (c) 1997 by Global Election Systems Inc.
7 * The authors hereby grant permission to use, copy, modify, distribute,
8 * and license this software and its documentation for any purpose, provided
9 * that existing copyright notices are retained in all copies and that this
10 * notice and the following disclaimer are included verbatim in any
11 * distributions. No written agreement, license, or royalty fee is required
12 * for any of the authorized uses.
14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 ******************************************************************************
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
30 * 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
31 * Original based on BSD fsm.c.
32 *****************************************************************************/
34 * fsm.c - {Link, IP} Control Protocol Finite State Machine.
36 * Copyright (c) 1989 Carnegie Mellon University.
37 * All rights reserved.
39 * Redistribution and use in source and binary forms are permitted
40 * provided that the above copyright notice and this paragraph are
41 * duplicated in all such forms and that any documentation,
42 * advertising materials, and other materials related to such
43 * distribution and use acknowledge that the software was developed
44 * by Carnegie Mellon University. The name of the
45 * University may not be used to endorse or promote products derived
46 * from this software without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
54 * Randomize fsm id on link/init.
55 * Deal with variable outgoing MTU.
60 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
70 static const char *ppperr_strerr
[] = {
71 "LS_INITIAL", /* LS_INITIAL 0 */
72 "LS_STARTING", /* LS_STARTING 1 */
73 "LS_CLOSED", /* LS_CLOSED 2 */
74 "LS_STOPPED", /* LS_STOPPED 3 */
75 "LS_CLOSING", /* LS_CLOSING 4 */
76 "LS_STOPPING", /* LS_STOPPING 5 */
77 "LS_REQSENT", /* LS_REQSENT 6 */
78 "LS_ACKRCVD", /* LS_ACKRCVD 7 */
79 "LS_ACKSENT", /* LS_ACKSENT 8 */
80 "LS_OPENED" /* LS_OPENED 9 */
82 #endif /* PPP_DEBUG */
84 static void fsm_timeout (void *);
85 static void fsm_rconfreq (fsm
*, u_char
, u_char
*, int);
86 static void fsm_rconfack (fsm
*, int, u_char
*, int);
87 static void fsm_rconfnakrej (fsm
*, int, int, u_char
*, int);
88 static void fsm_rtermreq (fsm
*, int, u_char
*, int);
89 static void fsm_rtermack (fsm
*);
90 static void fsm_rcoderej (fsm
*, u_char
*, int);
91 static void fsm_sconfreq (fsm
*, int);
93 #define PROTO_NAME(f) ((f)->callbacks->proto_name)
95 int peer_mru
[NUM_PPP
];
99 * fsm_init - Initialize fsm.
101 * Initialize fsm state.
106 f
->state
= LS_INITIAL
;
108 f
->id
= 0; /* XXX Start with random id? */
109 f
->timeouttime
= FSM_DEFTIMEOUT
;
110 f
->maxconfreqtransmits
= FSM_DEFMAXCONFREQS
;
111 f
->maxtermtransmits
= FSM_DEFMAXTERMREQS
;
112 f
->maxnakloops
= FSM_DEFMAXNAKLOOPS
;
113 f
->term_reason_len
= 0;
118 * fsm_lowerup - The lower layer is up.
123 int oldState
= f
->state
;
125 LWIP_UNUSED_ARG(oldState
);
129 f
->state
= LS_CLOSED
;
133 if( f
->flags
& OPT_SILENT
) {
134 f
->state
= LS_STOPPED
;
136 /* Send an initial configure-request */
138 f
->state
= LS_REQSENT
;
143 FSMDEBUG(LOG_INFO
, ("%s: Up event in state %d (%s)!\n",
144 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
147 FSMDEBUG(LOG_INFO
, ("%s: lowerup state %d (%s) -> %d (%s)\n",
148 PROTO_NAME(f
), oldState
, ppperr_strerr
[oldState
], f
->state
, ppperr_strerr
[f
->state
]));
153 * fsm_lowerdown - The lower layer is down.
155 * Cancel all timeouts and inform upper layers.
158 fsm_lowerdown(fsm
*f
)
160 int oldState
= f
->state
;
162 LWIP_UNUSED_ARG(oldState
);
166 f
->state
= LS_INITIAL
;
170 f
->state
= LS_STARTING
;
171 if( f
->callbacks
->starting
) {
172 (*f
->callbacks
->starting
)(f
);
177 f
->state
= LS_INITIAL
;
178 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
185 f
->state
= LS_STARTING
;
186 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
190 if( f
->callbacks
->down
) {
191 (*f
->callbacks
->down
)(f
);
193 f
->state
= LS_STARTING
;
197 FSMDEBUG(LOG_INFO
, ("%s: Down event in state %d (%s)!\n",
198 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
201 FSMDEBUG(LOG_INFO
, ("%s: lowerdown state %d (%s) -> %d (%s)\n",
202 PROTO_NAME(f
), oldState
, ppperr_strerr
[oldState
], f
->state
, ppperr_strerr
[f
->state
]));
207 * fsm_open - Link is allowed to come up.
212 int oldState
= f
->state
;
214 LWIP_UNUSED_ARG(oldState
);
218 f
->state
= LS_STARTING
;
219 if( f
->callbacks
->starting
) {
220 (*f
->callbacks
->starting
)(f
);
225 if( f
->flags
& OPT_SILENT
) {
226 f
->state
= LS_STOPPED
;
228 /* Send an initial configure-request */
230 f
->state
= LS_REQSENT
;
235 f
->state
= LS_STOPPING
;
239 if( f
->flags
& OPT_RESTART
) {
246 FSMDEBUG(LOG_INFO
, ("%s: open state %d (%s) -> %d (%s)\n",
247 PROTO_NAME(f
), oldState
, ppperr_strerr
[oldState
], f
->state
, ppperr_strerr
[f
->state
]));
250 #if 0 /* backport pppd 2.4.4b1; */
252 * terminate_layer - Start process of shutting down the FSM
254 * Cancel any timeout running, notify upper layers we're done, and
255 * send a terminate-request message as configured.
258 terminate_layer(fsm
*f
, int nextstate
)
265 * fsm_close - Start closing connection.
267 * Cancel timeouts and either initiate close or possibly go directly to
268 * the LS_CLOSED state.
271 fsm_close(fsm
*f
, char *reason
)
273 int oldState
= f
->state
;
275 LWIP_UNUSED_ARG(oldState
);
277 f
->term_reason
= reason
;
278 f
->term_reason_len
= (reason
== NULL
? 0 : (int)strlen(reason
));
281 f
->state
= LS_INITIAL
;
284 f
->state
= LS_CLOSED
;
287 f
->state
= LS_CLOSING
;
294 if( f
->state
!= LS_OPENED
) {
295 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
296 } else if( f
->callbacks
->down
) {
297 (*f
->callbacks
->down
)(f
); /* Inform upper layers we're down */
299 /* Init restart counter, send Terminate-Request */
300 f
->retransmits
= f
->maxtermtransmits
;
301 fsm_sdata(f
, TERMREQ
, f
->reqid
= ++f
->id
,
302 (u_char
*) f
->term_reason
, f
->term_reason_len
);
303 TIMEOUT(fsm_timeout
, f
, f
->timeouttime
);
306 f
->state
= LS_CLOSING
;
310 FSMDEBUG(LOG_INFO
, ("%s: close reason=%s state %d (%s) -> %d (%s)\n",
311 PROTO_NAME(f
), reason
, oldState
, ppperr_strerr
[oldState
], f
->state
, ppperr_strerr
[f
->state
]));
316 * fsm_timeout - Timeout expired.
319 fsm_timeout(void *arg
)
321 fsm
*f
= (fsm
*) arg
;
326 if( f
->retransmits
<= 0 ) {
327 FSMDEBUG(LOG_WARNING
, ("%s: timeout sending Terminate-Request state=%d (%s)\n",
328 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
330 * We've waited for an ack long enough. Peer probably heard us.
332 f
->state
= (f
->state
== LS_CLOSING
)? LS_CLOSED
: LS_STOPPED
;
333 if( f
->callbacks
->finished
) {
334 (*f
->callbacks
->finished
)(f
);
337 FSMDEBUG(LOG_WARNING
, ("%s: timeout resending Terminate-Requests state=%d (%s)\n",
338 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
339 /* Send Terminate-Request */
340 fsm_sdata(f
, TERMREQ
, f
->reqid
= ++f
->id
,
341 (u_char
*) f
->term_reason
, f
->term_reason_len
);
342 TIMEOUT(fsm_timeout
, f
, f
->timeouttime
);
350 if (f
->retransmits
<= 0) {
351 FSMDEBUG(LOG_WARNING
, ("%s: timeout sending Config-Requests state=%d (%s)\n",
352 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
353 f
->state
= LS_STOPPED
;
354 if( (f
->flags
& OPT_PASSIVE
) == 0 && f
->callbacks
->finished
) {
355 (*f
->callbacks
->finished
)(f
);
358 FSMDEBUG(LOG_WARNING
, ("%s: timeout resending Config-Request state=%d (%s)\n",
359 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
360 /* Retransmit the configure-request */
361 if (f
->callbacks
->retransmit
) {
362 (*f
->callbacks
->retransmit
)(f
);
364 fsm_sconfreq(f
, 1); /* Re-send Configure-Request */
365 if( f
->state
== LS_ACKRCVD
) {
366 f
->state
= LS_REQSENT
;
372 FSMDEBUG(LOG_INFO
, ("%s: UNHANDLED timeout event in state %d (%s)!\n",
373 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
379 * fsm_input - Input packet.
382 fsm_input(fsm
*f
, u_char
*inpacket
, int l
)
384 u_char
*inp
= inpacket
;
389 * Parse header (code, id and length).
390 * If packet too short, drop it.
393 FSMDEBUG(LOG_WARNING
, ("fsm_input(%x): Rcvd short header.\n",
400 if (len
< HEADERLEN
) {
401 FSMDEBUG(LOG_INFO
, ("fsm_input(%x): Rcvd illegal length.\n",
406 FSMDEBUG(LOG_INFO
, ("fsm_input(%x): Rcvd short packet.\n",
410 len
-= HEADERLEN
; /* subtract header length */
412 if( f
->state
== LS_INITIAL
|| f
->state
== LS_STARTING
) {
413 FSMDEBUG(LOG_INFO
, ("fsm_input(%x): Rcvd packet in state %d (%s).\n",
414 f
->protocol
, f
->state
, ppperr_strerr
[f
->state
]));
417 FSMDEBUG(LOG_INFO
, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f
), code
, id
, l
));
419 * Action depends on code.
423 fsm_rconfreq(f
, id
, inp
, len
);
427 fsm_rconfack(f
, id
, inp
, len
);
432 fsm_rconfnakrej(f
, code
, id
, inp
, len
);
436 fsm_rtermreq(f
, id
, inp
, len
);
444 fsm_rcoderej(f
, inp
, len
);
448 FSMDEBUG(LOG_INFO
, ("fsm_input(%s): default: \n", PROTO_NAME(f
)));
449 if( !f
->callbacks
->extcode
||
450 !(*f
->callbacks
->extcode
)(f
, code
, id
, inp
, len
) ) {
451 fsm_sdata(f
, CODEREJ
, ++f
->id
, inpacket
, len
+ HEADERLEN
);
459 * fsm_rconfreq - Receive Configure-Request.
462 fsm_rconfreq(fsm
*f
, u_char id
, u_char
*inp
, int len
)
464 int code
, reject_if_disagree
;
466 FSMDEBUG(LOG_INFO
, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
467 PROTO_NAME(f
), id
, f
->state
, ppperr_strerr
[f
->state
]));
470 /* Go away, we're closed */
471 fsm_sdata(f
, TERMACK
, id
, NULL
, 0);
478 /* Go down and restart negotiation */
479 if( f
->callbacks
->down
) {
480 (*f
->callbacks
->down
)(f
); /* Inform upper layers */
482 fsm_sconfreq(f
, 0); /* Send initial Configure-Request */
486 /* Negotiation started by our peer */
487 fsm_sconfreq(f
, 0); /* Send initial Configure-Request */
488 f
->state
= LS_REQSENT
;
493 * Pass the requested configuration options
494 * to protocol-specific code for checking.
496 if (f
->callbacks
->reqci
) { /* Check CI */
497 reject_if_disagree
= (f
->nakloops
>= f
->maxnakloops
);
498 code
= (*f
->callbacks
->reqci
)(f
, inp
, &len
, reject_if_disagree
);
500 code
= CONFREJ
; /* Reject all CI */
505 /* send the Ack, Nak or Rej to the peer */
506 fsm_sdata(f
, (u_char
)code
, id
, inp
, len
);
508 if (code
== CONFACK
) {
509 if (f
->state
== LS_ACKRCVD
) {
510 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
511 f
->state
= LS_OPENED
;
512 if (f
->callbacks
->up
) {
513 (*f
->callbacks
->up
)(f
); /* Inform upper layers */
516 f
->state
= LS_ACKSENT
;
520 /* we sent CONFACK or CONFREJ */
521 if (f
->state
!= LS_ACKRCVD
) {
522 f
->state
= LS_REQSENT
;
524 if( code
== CONFNAK
) {
532 * fsm_rconfack - Receive Configure-Ack.
535 fsm_rconfack(fsm
*f
, int id
, u_char
*inp
, int len
)
537 FSMDEBUG(LOG_INFO
, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
538 PROTO_NAME(f
), id
, f
->state
, ppperr_strerr
[f
->state
]));
540 if (id
!= f
->reqid
|| f
->seen_ack
) { /* Expected id? */
541 return; /* Nope, toss... */
543 if( !(f
->callbacks
->ackci
? (*f
->callbacks
->ackci
)(f
, inp
, len
): (len
== 0)) ) {
544 /* Ack is bad - ignore it */
545 FSMDEBUG(LOG_INFO
, ("%s: received bad Ack (length %d)\n",
546 PROTO_NAME(f
), len
));
554 fsm_sdata(f
, TERMACK
, (u_char
)id
, NULL
, 0);
558 f
->state
= LS_ACKRCVD
;
559 f
->retransmits
= f
->maxconfreqtransmits
;
563 /* Huh? an extra valid Ack? oh well... */
564 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
566 f
->state
= LS_REQSENT
;
570 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
571 f
->state
= LS_OPENED
;
572 f
->retransmits
= f
->maxconfreqtransmits
;
573 if (f
->callbacks
->up
) {
574 (*f
->callbacks
->up
)(f
); /* Inform upper layers */
579 /* Go down and restart negotiation */
580 if (f
->callbacks
->down
) {
581 (*f
->callbacks
->down
)(f
); /* Inform upper layers */
583 fsm_sconfreq(f
, 0); /* Send initial Configure-Request */
584 f
->state
= LS_REQSENT
;
591 * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
594 fsm_rconfnakrej(fsm
*f
, int code
, int id
, u_char
*inp
, int len
)
596 int (*proc
) (fsm
*, u_char
*, int);
599 FSMDEBUG(LOG_INFO
, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
600 PROTO_NAME(f
), id
, f
->state
, ppperr_strerr
[f
->state
]));
602 if (id
!= f
->reqid
|| f
->seen_ack
) { /* Expected id? */
603 return; /* Nope, toss... */
605 proc
= (code
== CONFNAK
)? f
->callbacks
->nakci
: f
->callbacks
->rejci
;
606 if (!proc
|| !((ret
= proc(f
, inp
, len
)))) {
607 /* Nak/reject is bad - ignore it */
608 FSMDEBUG(LOG_INFO
, ("%s: received bad %s (length %d)\n",
609 PROTO_NAME(f
), (code
==CONFNAK
? "Nak": "reject"), len
));
617 fsm_sdata(f
, TERMACK
, (u_char
)id
, NULL
, 0);
622 /* They didn't agree to what we wanted - try another request */
623 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
625 f
->state
= LS_STOPPED
; /* kludge for stopping CCP */
627 fsm_sconfreq(f
, 0); /* Send Configure-Request */
632 /* Got a Nak/reject when we had already had an Ack?? oh well... */
633 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
635 f
->state
= LS_REQSENT
;
639 /* Go down and restart negotiation */
640 if (f
->callbacks
->down
) {
641 (*f
->callbacks
->down
)(f
); /* Inform upper layers */
643 fsm_sconfreq(f
, 0); /* Send initial Configure-Request */
644 f
->state
= LS_REQSENT
;
651 * fsm_rtermreq - Receive Terminate-Req.
654 fsm_rtermreq(fsm
*f
, int id
, u_char
*p
, int len
)
658 FSMDEBUG(LOG_INFO
, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
659 PROTO_NAME(f
), id
, f
->state
, ppperr_strerr
[f
->state
]));
664 f
->state
= LS_REQSENT
; /* Start over but keep trying */
669 FSMDEBUG(LOG_INFO
, ("%s terminated by peer (%p)\n", PROTO_NAME(f
), p
));
671 FSMDEBUG(LOG_INFO
, ("%s terminated by peer\n", PROTO_NAME(f
)));
673 if (f
->callbacks
->down
) {
674 (*f
->callbacks
->down
)(f
); /* Inform upper layers */
677 f
->state
= LS_STOPPING
;
678 TIMEOUT(fsm_timeout
, f
, f
->timeouttime
);
682 fsm_sdata(f
, TERMACK
, (u_char
)id
, NULL
, 0);
687 * fsm_rtermack - Receive Terminate-Ack.
692 FSMDEBUG(LOG_INFO
, ("fsm_rtermack(%s): state=%d (%s)\n",
693 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
697 UNTIMEOUT(fsm_timeout
, f
);
698 f
->state
= LS_CLOSED
;
699 if( f
->callbacks
->finished
) {
700 (*f
->callbacks
->finished
)(f
);
705 UNTIMEOUT(fsm_timeout
, f
);
706 f
->state
= LS_STOPPED
;
707 if( f
->callbacks
->finished
) {
708 (*f
->callbacks
->finished
)(f
);
713 f
->state
= LS_REQSENT
;
717 if (f
->callbacks
->down
) {
718 (*f
->callbacks
->down
)(f
); /* Inform upper layers */
723 FSMDEBUG(LOG_INFO
, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n",
724 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
730 * fsm_rcoderej - Receive an Code-Reject.
733 fsm_rcoderej(fsm
*f
, u_char
*inp
, int len
)
737 FSMDEBUG(LOG_INFO
, ("fsm_rcoderej(%s): state=%d (%s)\n",
738 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
740 if (len
< HEADERLEN
) {
741 FSMDEBUG(LOG_INFO
, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
746 FSMDEBUG(LOG_WARNING
, ("%s: Rcvd Code-Reject for code %d, id %d\n",
747 PROTO_NAME(f
), code
, id
));
749 if( f
->state
== LS_ACKRCVD
) {
750 f
->state
= LS_REQSENT
;
756 * fsm_protreject - Peer doesn't speak this protocol.
758 * Treat this as a catastrophic error (RXJ-).
761 fsm_protreject(fsm
*f
)
765 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
768 f
->state
= LS_CLOSED
;
769 if( f
->callbacks
->finished
) {
770 (*f
->callbacks
->finished
)(f
);
778 UNTIMEOUT(fsm_timeout
, f
); /* Cancel timeout */
781 f
->state
= LS_STOPPED
;
782 if( f
->callbacks
->finished
) {
783 (*f
->callbacks
->finished
)(f
);
788 if( f
->callbacks
->down
) {
789 (*f
->callbacks
->down
)(f
);
791 /* Init restart counter, send Terminate-Request */
792 f
->retransmits
= f
->maxtermtransmits
;
793 fsm_sdata(f
, TERMREQ
, f
->reqid
= ++f
->id
,
794 (u_char
*) f
->term_reason
, f
->term_reason_len
);
795 TIMEOUT(fsm_timeout
, f
, f
->timeouttime
);
798 f
->state
= LS_STOPPING
;
802 FSMDEBUG(LOG_INFO
, ("%s: Protocol-reject event in state %d (%s)!\n",
803 PROTO_NAME(f
), f
->state
, ppperr_strerr
[f
->state
]));
809 * fsm_sconfreq - Send a Configure-Request.
812 fsm_sconfreq(fsm
*f
, int retransmit
)
817 if( f
->state
!= LS_REQSENT
&& f
->state
!= LS_ACKRCVD
&& f
->state
!= LS_ACKSENT
) {
818 /* Not currently negotiating - reset options */
819 if( f
->callbacks
->resetci
) {
820 (*f
->callbacks
->resetci
)(f
);
826 /* New request - reset retransmission counter, use new ID */
827 f
->retransmits
= f
->maxconfreqtransmits
;
834 * Make up the request packet
836 outp
= outpacket_buf
[f
->unit
] + PPP_HDRLEN
+ HEADERLEN
;
837 if( f
->callbacks
->cilen
&& f
->callbacks
->addci
) {
838 cilen
= (*f
->callbacks
->cilen
)(f
);
839 if( cilen
> peer_mru
[f
->unit
] - (int)HEADERLEN
) {
840 cilen
= peer_mru
[f
->unit
] - HEADERLEN
;
842 if (f
->callbacks
->addci
) {
843 (*f
->callbacks
->addci
)(f
, outp
, &cilen
);
849 /* send the request to our peer */
850 fsm_sdata(f
, CONFREQ
, f
->reqid
, outp
, cilen
);
852 /* start the retransmit timer */
854 TIMEOUT(fsm_timeout
, f
, f
->timeouttime
);
856 FSMDEBUG(LOG_INFO
, ("%s: sending Configure-Request, id %d\n",
857 PROTO_NAME(f
), f
->reqid
));
862 * fsm_sdata - Send some data.
864 * Used for all packets sent to our peer by this module.
867 fsm_sdata( fsm
*f
, u_char code
, u_char id
, u_char
*data
, int datalen
)
872 /* Adjust length to be smaller than MTU */
873 outp
= outpacket_buf
[f
->unit
];
874 if (datalen
> peer_mru
[f
->unit
] - (int)HEADERLEN
) {
875 datalen
= peer_mru
[f
->unit
] - HEADERLEN
;
877 if (datalen
&& data
!= outp
+ PPP_HDRLEN
+ HEADERLEN
) {
878 BCOPY(data
, outp
+ PPP_HDRLEN
+ HEADERLEN
, datalen
);
880 outlen
= datalen
+ HEADERLEN
;
881 MAKEHEADER(outp
, f
->protocol
);
884 PUTSHORT(outlen
, outp
);
885 pppWrite(f
->unit
, outpacket_buf
[f
->unit
], outlen
+ PPP_HDRLEN
);
886 FSMDEBUG(LOG_INFO
, ("fsm_sdata(%s): Sent code %d,%d,%d.\n",
887 PROTO_NAME(f
), code
, id
, outlen
));
890 #endif /* PPP_SUPPORT */