GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/fsm.c Lines: 0 268 0.0 %
Date: 2017-11-07 Branches: 0 212 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: fsm.c,v 1.9 2017/05/30 17:22:00 yasuoka Exp $ */
2
3
/**@file
4
 * This file was adapted from NetBSD:/usr/src/usr.sbin/pppd/pppd/fsm.c
5
 */
6
/*
7
 * fsm.c is simple and it can be use without modifications.  So keep the
8
 * original as much as possible.  (2005/04 yasuoka)
9
 *
10
 * XXX: I think the same message for initial configure-request is a bad idea
11
 * XXX: on resending configure-request.(yasuoka)
12
 */
13
/*	$NetBSD: fsm.c,v 1.13 2000/09/23 22:39:35 christos Exp $	*/
14
15
/*
16
 * fsm.c - {Link, IP} Control Protocol Finite State Machine.
17
 *
18
 * Copyright (c) 1989 Carnegie Mellon University.
19
 * All rights reserved.
20
 *
21
 * Redistribution and use in source and binary forms are permitted
22
 * provided that the above copyright notice and this paragraph are
23
 * duplicated in all such forms and that any documentation,
24
 * advertising materials, and other materials related to such
25
 * distribution and use acknowledge that the software was developed
26
 * by Carnegie Mellon University.  The name of the
27
 * University may not be used to endorse or promote products derived
28
 * from this software without specific prior written permission.
29
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32
 */
33
34
/*
35
 * TODO:
36
 * Randomize fsm id on link/init.
37
 * Deal with variable outgoing MTU.
38
 */
39
40
#include <stdio.h>
41
#include <string.h>
42
#include <sys/types.h>
43
#include <stdarg.h>
44
#include <syslog.h>
45
#include <stdlib.h>
46
47
/* npppd related headers below */
48
#include <sys/time.h>
49
#include <sys/socket.h>
50
#include <netinet/in.h>
51
#include <net/if_dl.h>
52
#include <time.h>
53
#include <event.h>
54
#include "debugutil.h"
55
#include "slist.h"
56
#include "npppd.h"
57
#include "fsm.h"
58
59
#ifdef	FSM_DEBUG
60
#define	FSMDEBUG(x)	fsm_log x
61
#define	FSM_ASSERT(x)	ASSERT(x)
62
#else
63
#define	FSMDEBUG(x)
64
#define	FSM_ASSERT(x)
65
#endif
66
67
#define	HEADERLEN	4
68
69
#ifdef RCSID
70
static const char rcsid[] = RCSID;
71
#endif
72
73
static void fsm_timeout(void *);
74
static void fsm_rconfreq(fsm *, int, u_char *, int);
75
static void fsm_rconfack(fsm *, int, u_char *, int);
76
static void fsm_rconfnakrej(fsm *, int, int, u_char *, int);
77
static void fsm_rtermreq(fsm *, int, u_char *, int);
78
static void fsm_rtermack(fsm *);
79
static void fsm_rcoderej(fsm *, u_char *, int);
80
static void fsm_sconfreq(fsm *, int);
81
82
#define PROTO_NAME(f)	((f)->callbacks->proto_name)
83
84
void
85
fsm_evtimer_timeout(int fd, short evtype, void *ctx)
86
{
87
	struct evtimer_wrap *wrap;
88
89
	wrap = ctx;
90
	wrap->func(wrap->ctx);
91
}
92
93
94
/*
95
 * fsm_init - Initialize fsm.
96
 *
97
 * Initialize fsm state.
98
 */
99
void
100
fsm_init(f)
101
    fsm *f;
102
{
103
    f->state = INITIAL;
104
    f->flags = 0;
105
    f->id = 0;				/* XXX Start with random id? */
106
    f->timeouttime = DEFTIMEOUT;
107
    f->maxconfreqtransmits = DEFMAXCONFREQS;
108
    f->maxtermtransmits = DEFMAXTERMREQS;
109
    f->maxnakloops = DEFMAXNAKLOOPS;
110
    f->term_reason_len = 0;
111
    memset(&f->timerctx, 0, sizeof(f->timerctx));
112
    f->timerctx.ctx = f;
113
}
114
115
116
/*
117
 * fsm_lowerup - The lower layer is up.
118
 */
119
void
120
fsm_lowerup(f)
121
    fsm *f;
122
{
123
    switch( f->state ){
124
    case INITIAL:
125
	f->state = CLOSED;
126
	break;
127
128
    case STARTING:
129
	if( f->flags & OPT_SILENT )
130
	    f->state = STOPPED;
131
	else {
132
	    /* Send an initial configure-request */
133
	    fsm_sconfreq(f, 0);
134
	    f->state = REQSENT;
135
	}
136
	break;
137
138
    default:
139
	FSMDEBUG((f, LOG_DEBUG, "Up event in state %d!", f->state));
140
    }
141
}
142
143
144
/*
145
 * fsm_lowerdown - The lower layer is down.
146
 *
147
 * Cancel all timeouts and inform upper layers.
148
 */
149
void
150
fsm_lowerdown(f)
151
    fsm *f;
152
{
153
    switch( f->state ){
154
    case CLOSED:
155
	f->state = INITIAL;
156
	break;
157
158
    case STOPPED:
159
	f->state = STARTING;
160
	if( f->callbacks->starting )
161
	    (*f->callbacks->starting)(f);
162
	break;
163
164
    case CLOSING:
165
	f->state = INITIAL;
166
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
167
	break;
168
169
    case STOPPING:
170
    case REQSENT:
171
    case ACKRCVD:
172
    case ACKSENT:
173
	f->state = STARTING;
174
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
175
	break;
176
177
    case OPENED:
178
	if( f->callbacks->down )
179
	    (*f->callbacks->down)(f);
180
	f->state = STARTING;
181
	break;
182
183
    default:
184
	FSMDEBUG((f, LOG_DEBUG, "Down event in state %d!", f->state));
185
    }
186
}
187
188
189
/*
190
 * fsm_open - Link is allowed to come up.
191
 */
192
void
193
fsm_open(f)
194
    fsm *f;
195
{
196
    switch( f->state ){
197
    case INITIAL:
198
	f->state = STARTING;
199
	if( f->callbacks->starting )
200
	    (*f->callbacks->starting)(f);
201
	break;
202
203
    case CLOSED:
204
	if( f->flags & OPT_SILENT )
205
	    f->state = STOPPED;
206
	else {
207
	    /* Send an initial configure-request */
208
	    fsm_sconfreq(f, 0);
209
	    f->state = REQSENT;
210
	}
211
	break;
212
213
    case CLOSING:
214
	f->state = STOPPING;
215
	/* fall through */
216
    case STOPPED:
217
    case OPENED:
218
	if( f->flags & OPT_RESTART ){
219
	    fsm_lowerdown(f);
220
	    fsm_lowerup(f);
221
	}
222
	break;
223
    }
224
}
225
226
227
/*
228
 * fsm_close - Start closing connection.
229
 *
230
 * Cancel timeouts and either initiate close or possibly go directly to
231
 * the CLOSED state.
232
 */
233
void
234
fsm_close(f, reason)
235
    fsm *f;
236
    const char *reason;
237
{
238
    f->term_reason = (char *)reason;
239
    f->term_reason_len = (reason == NULL? 0: strlen(reason));
240
    switch( f->state ){
241
    case STARTING:
242
	f->state = INITIAL;
243
	break;
244
    case STOPPED:
245
	f->state = CLOSED;
246
	break;
247
    case STOPPING:
248
	f->state = CLOSING;
249
	break;
250
251
    case REQSENT:
252
    case ACKRCVD:
253
    case ACKSENT:
254
    case OPENED:
255
	if( f->state != OPENED )
256
	    UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
257
	else if( f->callbacks->down )
258
	    (*f->callbacks->down)(f);	/* Inform upper layers we're down */
259
260
	/* Init restart counter, send Terminate-Request */
261
	f->retransmits = f->maxtermtransmits;
262
	fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
263
		  (u_char *) f->term_reason, f->term_reason_len);
264
	TIMEOUT(fsm_timeout, f, f->timeouttime);
265
	--f->retransmits;
266
267
	f->state = CLOSING;
268
	break;
269
    }
270
}
271
272
273
/*
274
 * fsm_timeout - Timeout expired.
275
 */
276
static void
277
fsm_timeout(arg)
278
    void *arg;
279
{
280
    fsm *f = (fsm *) arg;
281
282
    switch (f->state) {
283
    case CLOSING:
284
    case STOPPING:
285
	if( f->retransmits <= 0 ){
286
	    /*
287
	     * We've waited for an ack long enough.  Peer probably heard us.
288
	     */
289
	    f->state = (f->state == CLOSING)? CLOSED: STOPPED;
290
	    if( f->callbacks->finished )
291
		(*f->callbacks->finished)(f);
292
	} else {
293
	    /* Send Terminate-Request */
294
	    fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
295
		      (u_char *) f->term_reason, f->term_reason_len);
296
	    TIMEOUT(fsm_timeout, f, f->timeouttime);
297
	    --f->retransmits;
298
	}
299
	break;
300
301
    case REQSENT:
302
    case ACKRCVD:
303
    case ACKSENT:
304
	if (f->retransmits <= 0) {
305
	    fsm_log(f, LOG_WARNING, "timeout sending Config-Requests\n");
306
	    f->state = STOPPED;
307
	    if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
308
		(*f->callbacks->finished)(f);
309
310
	} else {
311
	    /* Retransmit the configure-request */
312
	    if (f->callbacks->retransmit)
313
		(*f->callbacks->retransmit)(f);
314
	    fsm_sconfreq(f, 1);		/* Re-send Configure-Request */
315
	    if( f->state == ACKRCVD )
316
		f->state = REQSENT;
317
	}
318
	break;
319
320
    default:
321
	FSMDEBUG((f, LOG_DEBUG, "Timeout event in state %d!", f->state));
322
    }
323
}
324
325
326
/*
327
 * fsm_input - Input packet.
328
 */
329
void
330
fsm_input(f, inpacket, l)
331
    fsm *f;
332
    u_char *inpacket;
333
    int l;
334
{
335
    u_char *inp;
336
    u_char code, id;
337
    int len;
338
339
    /*
340
     * Parse header (code, id and length).
341
     * If packet too short, drop it.
342
     */
343
    inp = inpacket;
344
    if (l < HEADERLEN) {
345
	FSMDEBUG((f, LOG_DEBUG, "fsm_input(): Rcvd short header."));
346
	return;
347
    }
348
    GETCHAR(code, inp);
349
    GETCHAR(id, inp);
350
    GETSHORT(len, inp);
351
    if (len < HEADERLEN) {
352
	FSMDEBUG((f, LOG_DEBUG, "fsm_input(): Rcvd illegal length."));
353
	return;
354
    }
355
    if (len > l) {
356
	FSMDEBUG((f, LOG_DEBUG, "fsm_input(): Rcvd short packet."));
357
	return;
358
    }
359
    len -= HEADERLEN;		/* subtract header length */
360
361
    if( f->state == INITIAL || f->state == STARTING ){
362
	FSMDEBUG((f, LOG_DEBUG, "fsm_input(): Rcvd packet in state %d.",
363
	    f->state));
364
	return;
365
    }
366
367
    /*
368
     * Action depends on code.
369
     */
370
    switch (code) {
371
    case CONFREQ:
372
	fsm_rconfreq(f, id, inp, len);
373
	break;
374
375
    case CONFACK:
376
	fsm_rconfack(f, id, inp, len);
377
	break;
378
379
    case CONFNAK:
380
    case CONFREJ:
381
	fsm_rconfnakrej(f, code, id, inp, len);
382
	break;
383
384
    case TERMREQ:
385
	fsm_rtermreq(f, id, inp, len);
386
	break;
387
388
    case TERMACK:
389
	fsm_rtermack(f);
390
	break;
391
392
    case CODEREJ:
393
	fsm_rcoderej(f, inp, len);
394
	break;
395
396
    default:
397
	if( !f->callbacks->extcode
398
	   || !(*f->callbacks->extcode)(f, code, id, inp, len) )
399
	    fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
400
	break;
401
    }
402
}
403
404
405
/*
406
 * fsm_rconfreq - Receive Configure-Request.
407
 */
408
static void
409
fsm_rconfreq(f, id, inp, len)
410
    fsm *f;
411
    u_char id;
412
    u_char *inp;
413
    int len;
414
{
415
    int code, reject_if_disagree;
416
417
    switch( f->state ){
418
    case CLOSED:
419
	/* Go away, we're closed */
420
	fsm_sdata(f, TERMACK, id, NULL, 0);
421
	return;
422
    case CLOSING:
423
    case STOPPING:
424
	return;
425
426
    case OPENED:
427
	/* Go down and restart negotiation */
428
	if( f->callbacks->down )
429
	    (*f->callbacks->down)(f);	/* Inform upper layers */
430
	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
431
	break;
432
433
    case STOPPED:
434
	/* Negotiation started by our peer */
435
	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
436
	f->state = REQSENT;
437
	break;
438
    }
439
440
    /*
441
     * Pass the requested configuration options
442
     * to protocol-specific code for checking.
443
     */
444
    if (f->callbacks->reqci){		/* Check CI */
445
	reject_if_disagree = (f->nakloops >= f->maxnakloops);
446
	code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
447
    } else if (len)
448
	code = CONFREJ;			/* Reject all CI */
449
    else
450
	code = CONFACK;
451
452
    /* send the Ack, Nak or Rej to the peer */
453
    fsm_sdata(f, code, id, inp, len);
454
455
    if (code == CONFACK) {
456
	if (f->state == ACKRCVD) {
457
	    UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
458
	    f->state = OPENED;
459
	    if (f->callbacks->up)
460
		(*f->callbacks->up)(f);	/* Inform upper layers */
461
	} else
462
	    f->state = ACKSENT;
463
	f->nakloops = 0;
464
465
    } else {
466
	/* we sent CONFNAK or CONFREJ */
467
	if (f->state != ACKRCVD)
468
	    f->state = REQSENT;
469
	if( code == CONFNAK )
470
	    ++f->nakloops;
471
    }
472
}
473
474
475
/*
476
 * fsm_rconfack - Receive Configure-Ack.
477
 */
478
static void
479
fsm_rconfack(f, id, inp, len)
480
    fsm *f;
481
    int id;
482
    u_char *inp;
483
    int len;
484
{
485
    if (id != f->reqid || f->seen_ack)		/* Expected id? */
486
	return;					/* Nope, toss... */
487
    if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
488
	  (len == 0)) ){
489
	/* Ack is bad - ignore it */
490
	fsm_log(f, LOG_ERR, "Received bad configure-ack: %p(%d)", inp, len);
491
	return;
492
    }
493
    f->seen_ack = 1;
494
495
    switch (f->state) {
496
    case CLOSED:
497
    case STOPPED:
498
	fsm_sdata(f, TERMACK, id, NULL, 0);
499
	break;
500
501
    case REQSENT:
502
	f->state = ACKRCVD;
503
	f->retransmits = f->maxconfreqtransmits;
504
	break;
505
506
    case ACKRCVD:
507
	/* Huh? an extra valid Ack? oh well... */
508
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
509
	fsm_sconfreq(f, 0);
510
	f->state = REQSENT;
511
	break;
512
513
    case ACKSENT:
514
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
515
	f->state = OPENED;
516
	f->retransmits = f->maxconfreqtransmits;
517
	if (f->callbacks->up)
518
	    (*f->callbacks->up)(f);	/* Inform upper layers */
519
	break;
520
521
    case OPENED:
522
	/* Go down and restart negotiation */
523
	if (f->callbacks->down)
524
	    (*f->callbacks->down)(f);	/* Inform upper layers */
525
	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
526
	f->state = REQSENT;
527
	break;
528
    }
529
}
530
531
532
/*
533
 * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
534
 */
535
static void
536
fsm_rconfnakrej(f, code, id, inp, len)
537
    fsm *f;
538
    int code, id;
539
    u_char *inp;
540
    int len;
541
{
542
    int (*proc)(fsm *, u_char *, int);
543
    int ret;
544
545
    if (id != f->reqid || f->seen_ack)	/* Expected id? */
546
	return;				/* Nope, toss... */
547
    proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
548
    if (!proc || !(ret = proc(f, inp, len))) {
549
	/* Nak/reject is bad - ignore it */
550
	fsm_log(f, LOG_INFO, "Received bad configure-%s: %p(%d)",
551
	    (code == CONFNAK)? "nak" : "rej", inp, len);
552
	return;
553
    }
554
    f->seen_ack = 1;
555
556
    switch (f->state) {
557
    case CLOSED:
558
    case STOPPED:
559
	fsm_sdata(f, TERMACK, id, NULL, 0);
560
	break;
561
562
    case REQSENT:
563
    case ACKSENT:
564
	/* They didn't agree to what we wanted - try another request */
565
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
566
	if (ret < 0)
567
	    f->state = STOPPED;		/* kludge for stopping CCP */
568
	else
569
	    fsm_sconfreq(f, 0);		/* Send Configure-Request */
570
	break;
571
572
    case ACKRCVD:
573
	/* Got a Nak/reject when we had already had an Ack?? oh well... */
574
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
575
	fsm_sconfreq(f, 0);
576
	f->state = REQSENT;
577
	break;
578
579
    case OPENED:
580
	/* Go down and restart negotiation */
581
	if (f->callbacks->down)
582
	    (*f->callbacks->down)(f);	/* Inform upper layers */
583
	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
584
	f->state = REQSENT;
585
	break;
586
    }
587
}
588
589
590
/*
591
 * fsm_rtermreq - Receive Terminate-Req.
592
 */
593
static void
594
fsm_rtermreq(f, id, p, len)
595
    fsm *f;
596
    int id;
597
    u_char *p;
598
    int len;
599
{
600
    switch (f->state) {
601
    case ACKRCVD:
602
    case ACKSENT:
603
	f->state = REQSENT;		/* Start over but keep trying */
604
	break;
605
606
    case OPENED:
607
	fsm_log(f, LOG_INFO, "terminated by peer");
608
	if (f->callbacks->down)
609
	    (*f->callbacks->down)(f);	/* Inform upper layers */
610
	f->retransmits = 0;
611
	f->state = STOPPING;
612
	TIMEOUT(fsm_timeout, f, f->timeouttime);
613
	break;
614
    }
615
616
    fsm_sdata(f, TERMACK, id, NULL, 0);
617
}
618
619
620
/*
621
 * fsm_rtermack - Receive Terminate-Ack.
622
 */
623
static void
624
fsm_rtermack(f)
625
    fsm *f;
626
{
627
    switch (f->state) {
628
    case CLOSING:
629
	UNTIMEOUT(fsm_timeout, f);
630
	f->state = CLOSED;
631
	if( f->callbacks->finished )
632
	    (*f->callbacks->finished)(f);
633
	break;
634
    case STOPPING:
635
	UNTIMEOUT(fsm_timeout, f);
636
	f->state = STOPPED;
637
	if( f->callbacks->finished )
638
	    (*f->callbacks->finished)(f);
639
	break;
640
641
    case ACKRCVD:
642
	f->state = REQSENT;
643
	break;
644
645
    case OPENED:
646
	if (f->callbacks->down)
647
	    (*f->callbacks->down)(f);	/* Inform upper layers */
648
	fsm_sconfreq(f, 0);
649
	f->state = REQSENT;
650
	break;
651
    }
652
}
653
654
655
/*
656
 * fsm_rcoderej - Receive an Code-Reject.
657
 */
658
static void
659
fsm_rcoderej(f, inp, len)
660
    fsm *f;
661
    u_char *inp;
662
    int len;
663
{
664
    u_char code, id;
665
666
    if (len < HEADERLEN) {
667
	FSMDEBUG((f, LOG_DEBUG,
668
	    "fsm_rcoderej: Rcvd short Code-Reject packet!"));
669
	return;
670
    }
671
    GETCHAR(code, inp);
672
    GETCHAR(id, inp);
673
    fsm_log(f, LOG_INFO,
674
	"%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id);
675
676
    if( f->state == ACKRCVD )
677
	f->state = REQSENT;
678
}
679
680
681
/*
682
 * fsm_protreject - Peer doesn't speak this protocol.
683
 *
684
 * Treat this as a catastrophic error (RXJ-).
685
 */
686
void
687
fsm_protreject(f)
688
    fsm *f;
689
{
690
    switch( f->state ){
691
    case CLOSING:
692
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
693
	/* fall through */
694
    case CLOSED:
695
	f->state = CLOSED;
696
	if( f->callbacks->finished )
697
	    (*f->callbacks->finished)(f);
698
	break;
699
700
    case STOPPING:
701
    case REQSENT:
702
    case ACKRCVD:
703
    case ACKSENT:
704
	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
705
	/* fall through */
706
    case STOPPED:
707
	f->state = STOPPED;
708
	if( f->callbacks->finished )
709
	    (*f->callbacks->finished)(f);
710
	break;
711
712
    case OPENED:
713
	if( f->callbacks->down )
714
	    (*f->callbacks->down)(f);
715
716
	/* Init restart counter, send Terminate-Request */
717
	f->retransmits = f->maxtermtransmits;
718
	fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
719
		  (u_char *) f->term_reason, f->term_reason_len);
720
	TIMEOUT(fsm_timeout, f, f->timeouttime);
721
	--f->retransmits;
722
723
	f->state = STOPPING;
724
	break;
725
726
    default:
727
	FSMDEBUG((f, LOG_DEBUG,
728
	    "Protocol-reject event in state %d!", f->state));
729
    }
730
}
731
732
733
/*
734
 * fsm_sconfreq - Send a Configure-Request.
735
 */
736
static void
737
fsm_sconfreq(f, retransmit)
738
    fsm *f;
739
    int retransmit;
740
{
741
    u_char *outp;
742
    int cilen;
743
744
    if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
745
	/* Not currently negotiating - reset options */
746
	if( f->callbacks->resetci )
747
	    (*f->callbacks->resetci)(f);
748
	f->nakloops = 0;
749
    }
750
751
    if( !retransmit ){
752
	/* New request - reset retransmission counter, use new ID */
753
	f->retransmits = f->maxconfreqtransmits;
754
	f->reqid = ++f->id;
755
    }
756
757
    f->seen_ack = 0;
758
759
    /*
760
     * Make up the request packet
761
     */
762
    outp = f->ppp->outpacket_buf + PPP_HDRLEN + HEADERLEN;
763
    if( f->callbacks->cilen && f->callbacks->addci ){
764
	cilen = (*f->callbacks->cilen)(f);
765
	if( cilen > f->ppp->mru - HEADERLEN )
766
	    cilen = f->ppp->mru - HEADERLEN;
767
	if (f->callbacks->addci)
768
	    (*f->callbacks->addci)(f, outp, &cilen);
769
    } else
770
	cilen = 0;
771
772
    /* send the request to our peer */
773
    fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
774
775
    /* start the retransmit timer */
776
    --f->retransmits;
777
    TIMEOUT(fsm_timeout, f, f->timeouttime);
778
}
779
780
781
/*
782
 * fsm_sdata - Send some data.
783
 *
784
 * Used for all packets sent to our peer by this module.
785
 */
786
void
787
fsm_sdata(f, code, id, data, datalen)
788
    fsm *f;
789
    u_char code, id;
790
    u_char *data;
791
    int datalen;
792
{
793
    ppp_output(f->ppp, f->protocol, code, id, data, datalen);
794
}
795
796
797
void
798
fsm_log(fsm *f, uint32_t prio, const char *fmt, ...)
799
{
800
    char logbuf[BUFSIZ];
801
    va_list ap;
802
803
    FSM_ASSERT(f != NULL);
804
    FSM_ASSERT(f->callbacks != NULL);
805
806
    va_start(ap, fmt);
807
    snprintf(logbuf, sizeof(logbuf), "ppp id=%u layer=%s %s", f->ppp->id,
808
	PROTO_NAME(f), fmt);
809
    vlog_printf(prio, logbuf, ap);
810
    va_end(ap);
811
}