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

Subversion Repositories openrisc

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

powered by: WebSVN 2.1.0

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