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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_130/] [src/] [netif/] [ppp/] [fsm.c] - Blame information for rev 606

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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