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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_MCF5235_GCC/] [lwip/] [src/] [netif/] [ppp/] [fsm.c] - Blame information for rev 583

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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