OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [ppp/] [current/] [src/] [fsm.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.