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/] [lcp.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*****************************************************************************
2
* lcp.c - Network Link Control Protocol 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.
32
*****************************************************************************/
33
 
34
/*
35
 * lcp.c - PPP Link Control Protocol.
36
 *
37
 * Copyright (c) 1989 Carnegie Mellon University.
38
 * All rights reserved.
39
 *
40
 * Redistribution and use in source and binary forms are permitted
41
 * provided that the above copyright notice and this paragraph are
42
 * duplicated in all such forms and that any documentation,
43
 * advertising materials, and other materials related to such
44
 * distribution and use acknowledge that the software was developed
45
 * by Carnegie Mellon University.  The name of the
46
 * University may not be used to endorse or promote products derived
47
 * from this software without specific prior written permission.
48
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
49
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
50
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
51
 */
52
 
53
 
54
#include "lwip/opt.h"
55
 
56
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
57
 
58
#include "ppp.h"
59
#include "pppdebug.h"
60
 
61
#include "fsm.h"
62
#include "chap.h"
63
#include "magic.h"
64
#include "auth.h"
65
#include "lcp.h"
66
 
67
#include <string.h>
68
 
69
#if PPPOE_SUPPORT
70
#include "netif/ppp_oe.h"
71
#else
72
#define PPPOE_MAXMTU PPP_MAXMRU
73
#endif
74
 
75
 
76
/*************************/
77
/*** LOCAL DEFINITIONS ***/
78
/*************************/
79
/*
80
 * Length of each type of configuration option (in octets)
81
 */
82
#define CILEN_VOID  2
83
#define CILEN_CHAR  3
84
#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
85
#define CILEN_CHAP  5 /* CILEN_VOID + sizeof(short) + 1 */
86
#define CILEN_LONG  6 /* CILEN_VOID + sizeof(long) */
87
#define CILEN_LQR   8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
88
#define CILEN_CBCP  3
89
 
90
 
91
/***********************************/
92
/*** LOCAL FUNCTION DECLARATIONS ***/
93
/***********************************/
94
/*
95
 * Callbacks for fsm code.  (CI = Configuration Information)
96
 */
97
static void lcp_resetci (fsm*);                   /* Reset our CI */
98
static int  lcp_cilen (fsm*);                     /* Return length of our CI */
99
static void lcp_addci (fsm*, u_char*, int*);      /* Add our CI to pkt */
100
static int  lcp_ackci (fsm*, u_char*, int);       /* Peer ack'd our CI */
101
static int  lcp_nakci (fsm*, u_char*, int);       /* Peer nak'd our CI */
102
static int  lcp_rejci (fsm*, u_char*, int);       /* Peer rej'd our CI */
103
static int  lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */
104
static void lcp_up (fsm*);                        /* We're UP */
105
static void lcp_down (fsm*);                      /* We're DOWN */
106
static void lcp_starting (fsm*);                  /* We need lower layer up */
107
static void lcp_finished (fsm*);                  /* We need lower layer down */
108
static int  lcp_extcode (fsm*, int, u_char, u_char*, int);
109
 
110
static void lcp_rprotrej (fsm*, u_char*, int);
111
 
112
/*
113
 * routines to send LCP echos to peer
114
 */
115
static void lcp_echo_lowerup (int);
116
static void lcp_echo_lowerdown (int);
117
static void LcpEchoTimeout (void*);
118
static void lcp_received_echo_reply (fsm*, int, u_char*, int);
119
static void LcpSendEchoRequest (fsm*);
120
static void LcpLinkFailure (fsm*);
121
static void LcpEchoCheck (fsm*);
122
 
123
/*
124
 * Protocol entry points.
125
 * Some of these are called directly.
126
 */
127
static void lcp_input (int, u_char *, int);
128
static void lcp_protrej (int);
129
 
130
#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")
131
 
132
 
133
/******************************/
134
/*** PUBLIC DATA STRUCTURES ***/
135
/******************************/
136
/* global vars */
137
LinkPhase lcp_phase[NUM_PPP];          /* Phase of link session (RFC 1661) */
138
lcp_options lcp_wantoptions[NUM_PPP];  /* Options that we want to request */
139
lcp_options lcp_gotoptions[NUM_PPP];   /* Options that peer ack'd */
140
lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
141
lcp_options lcp_hisoptions[NUM_PPP];   /* Options that we ack'd */
142
ext_accm xmit_accm[NUM_PPP];           /* extended transmit ACCM */
143
 
144
 
145
 
146
/*****************************/
147
/*** LOCAL DATA STRUCTURES ***/
148
/*****************************/
149
static fsm lcp_fsm[NUM_PPP];                            /* LCP fsm structure (global)*/
150
static u_int lcp_echo_interval      = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
151
static u_int lcp_echo_fails         = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
152
static u32_t lcp_echos_pending      = 0;                /* Number of outstanding echo msgs */
153
static u32_t lcp_echo_number        = 0;                /* ID number of next echo frame */
154
static u32_t lcp_echo_timer_running = 0;                /* TRUE if a timer is running */
155
 
156
static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
157
 
158
static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
159
  lcp_resetci,  /* Reset our Configuration Information */
160
  lcp_cilen,    /* Length of our Configuration Information */
161
  lcp_addci,    /* Add our Configuration Information */
162
  lcp_ackci,    /* ACK our Configuration Information */
163
  lcp_nakci,    /* NAK our Configuration Information */
164
  lcp_rejci,    /* Reject our Configuration Information */
165
  lcp_reqci,    /* Request peer's Configuration Information */
166
  lcp_up,       /* Called when fsm reaches LS_OPENED state */
167
  lcp_down,     /* Called when fsm leaves LS_OPENED state */
168
  lcp_starting, /* Called when we want the lower layer up */
169
  lcp_finished, /* Called when we want the lower layer down */
170
  NULL,         /* Called when Protocol-Reject received */
171
  NULL,         /* Retransmission is necessary */
172
  lcp_extcode,  /* Called to handle LCP-specific codes */
173
  "LCP"         /* String name of protocol */
174
};
175
 
176
struct protent lcp_protent = {
177
    PPP_LCP,
178
    lcp_init,
179
    lcp_input,
180
    lcp_protrej,
181
    lcp_lowerup,
182
    lcp_lowerdown,
183
    lcp_open,
184
    lcp_close,
185
#if 0
186
    lcp_printpkt,
187
    NULL,
188
#endif
189
    1,
190
    "LCP",
191
#if 0
192
    NULL,
193
    NULL,
194
    NULL
195
#endif
196
};
197
 
198
int lcp_loopbackfail = DEFLOOPBACKFAIL;
199
 
200
 
201
 
202
/***********************************/
203
/*** PUBLIC FUNCTION DEFINITIONS ***/
204
/***********************************/
205
/*
206
 * lcp_init - Initialize LCP.
207
 */
208
void
209
lcp_init(int unit)
210
{
211
  fsm         *f  = &lcp_fsm[unit];
212
  lcp_options *wo = &lcp_wantoptions[unit];
213
  lcp_options *ao = &lcp_allowoptions[unit];
214
 
215
  f->unit      = unit;
216
  f->protocol  = PPP_LCP;
217
  f->callbacks = &lcp_callbacks;
218
 
219
  fsm_init(f);
220
 
221
  wo->passive           = 0;
222
  wo->silent            = 0;
223
  wo->restart           = 0;               /* Set to 1 in kernels or multi-line implementations */
224
  wo->neg_mru           = 1;
225
  wo->mru               = PPP_DEFMRU;
226
  wo->neg_asyncmap      = 1;
227
  wo->asyncmap          = 0x00000000l;     /* Assume don't need to escape any ctl chars. */
228
  wo->neg_chap          = 0;               /* Set to 1 on server */
229
  wo->neg_upap          = 0;               /* Set to 1 on server */
230
  wo->chap_mdtype       = CHAP_DIGEST_MD5;
231
  wo->neg_magicnumber   = 1;
232
  wo->neg_pcompression  = 1;
233
  wo->neg_accompression = 1;
234
  wo->neg_lqr           = 0;               /* no LQR implementation yet */
235
  wo->neg_cbcp          = 0;
236
 
237
  ao->neg_mru           = 1;
238
  ao->mru               = PPP_MAXMRU;
239
  ao->neg_asyncmap      = 1;
240
  ao->asyncmap          = 0x00000000l;     /* Assume don't need to escape any ctl chars. */
241
  ao->neg_chap          = (CHAP_SUPPORT != 0);
242
  ao->chap_mdtype       = CHAP_DIGEST_MD5;
243
  ao->neg_upap          = (PAP_SUPPORT != 0);
244
  ao->neg_magicnumber   = 1;
245
  ao->neg_pcompression  = 1;
246
  ao->neg_accompression = 1;
247
  ao->neg_lqr           = 0;               /* no LQR implementation yet */
248
  ao->neg_cbcp          = (CBCP_SUPPORT != 0);
249
 
250
  /*
251
   * Set transmit escape for the flag and escape characters plus anything
252
   * set for the allowable options.
253
   */
254
  memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
255
  xmit_accm[unit][15] = 0x60;
256
  xmit_accm[unit][0]  = (u_char)((ao->asyncmap        & 0xFF));
257
  xmit_accm[unit][1]  = (u_char)((ao->asyncmap >> 8)  & 0xFF);
258
  xmit_accm[unit][2]  = (u_char)((ao->asyncmap >> 16) & 0xFF);
259
  xmit_accm[unit][3]  = (u_char)((ao->asyncmap >> 24) & 0xFF);
260
  LCPDEBUG((LOG_INFO, "lcp_init: xmit_accm=%X %X %X %X\n",
261
        xmit_accm[unit][0],
262
        xmit_accm[unit][1],
263
        xmit_accm[unit][2],
264
        xmit_accm[unit][3]));
265
 
266
  lcp_phase[unit] = PHASE_INITIALIZE;
267
}
268
 
269
 
270
/*
271
 * lcp_open - LCP is allowed to come up.
272
 */
273
void
274
lcp_open(int unit)
275
{
276
  fsm         *f  = &lcp_fsm[unit];
277
  lcp_options *wo = &lcp_wantoptions[unit];
278
 
279
  f->flags = 0;
280
  if (wo->passive) {
281
    f->flags |= OPT_PASSIVE;
282
  }
283
  if (wo->silent) {
284
    f->flags |= OPT_SILENT;
285
  }
286
  fsm_open(f);
287
 
288
  lcp_phase[unit] = PHASE_ESTABLISH;
289
}
290
 
291
 
292
/*
293
 * lcp_close - Take LCP down.
294
 */
295
void
296
lcp_close(int unit, char *reason)
297
{
298
  fsm *f = &lcp_fsm[unit];
299
 
300
  if (lcp_phase[unit] != PHASE_DEAD) {
301
    lcp_phase[unit] = PHASE_TERMINATE;
302
  }
303
  if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
304
    /*
305
     * This action is not strictly according to the FSM in RFC1548,
306
     * but it does mean that the program terminates if you do an
307
     * lcp_close() in passive/silent mode when a connection hasn't
308
     * been established.
309
     */
310
    f->state = LS_CLOSED;
311
    lcp_finished(f);
312
  } else {
313
    fsm_close(&lcp_fsm[unit], reason);
314
  }
315
}
316
 
317
 
318
/*
319
 * lcp_lowerup - The lower layer is up.
320
 */
321
void
322
lcp_lowerup(int unit)
323
{
324
  lcp_options *wo = &lcp_wantoptions[unit];
325
 
326
  /*
327
   * Don't use A/C or protocol compression on transmission,
328
   * but accept A/C and protocol compressed packets
329
   * if we are going to ask for A/C and protocol compression.
330
   */
331
  ppp_set_xaccm(unit, &xmit_accm[unit]);
332
  ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0);
333
  ppp_recv_config(unit, PPP_MRU, 0x00000000l,
334
  wo->neg_pcompression, wo->neg_accompression);
335
  peer_mru[unit] = PPP_MRU;
336
  lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0]
337
                                 | ((u_long)xmit_accm[unit][1] << 8)
338
                                 | ((u_long)xmit_accm[unit][2] << 16)
339
                                 | ((u_long)xmit_accm[unit][3] << 24);
340
  LCPDEBUG((LOG_INFO, "lcp_lowerup: asyncmap=%X %X %X %X\n",
341
            xmit_accm[unit][3],
342
            xmit_accm[unit][2],
343
            xmit_accm[unit][1],
344
            xmit_accm[unit][0]));
345
 
346
  fsm_lowerup(&lcp_fsm[unit]);
347
}
348
 
349
 
350
/*
351
 * lcp_lowerdown - The lower layer is down.
352
 */
353
void
354
lcp_lowerdown(int unit)
355
{
356
  fsm_lowerdown(&lcp_fsm[unit]);
357
}
358
 
359
/*
360
 * lcp_sprotrej - Send a Protocol-Reject for some protocol.
361
 */
362
void
363
lcp_sprotrej(int unit, u_char *p, int len)
364
{
365
  /*
366
   * Send back the protocol and the information field of the
367
   * rejected packet.  We only get here if LCP is in the LS_OPENED state.
368
   */
369
 
370
  fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
371
}
372
 
373
 
374
 
375
/**********************************/
376
/*** LOCAL FUNCTION DEFINITIONS ***/
377
/**********************************/
378
/*
379
 * lcp_input - Input LCP packet.
380
 */
381
static void
382
lcp_input(int unit, u_char *p, int len)
383
{
384
  fsm *f = &lcp_fsm[unit];
385
 
386
  fsm_input(f, p, len);
387
}
388
 
389
 
390
/*
391
 * lcp_extcode - Handle a LCP-specific code.
392
 */
393
static int
394
lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len)
395
{
396
  u_char *magp;
397
 
398
  switch( code ){
399
    case PROTREJ:
400
      lcp_rprotrej(f, inp, len);
401
      break;
402
 
403
    case ECHOREQ:
404
      if (f->state != LS_OPENED) {
405
        break;
406
      }
407
      LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d\n", id));
408
      magp = inp;
409
      PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
410
      fsm_sdata(f, ECHOREP, id, inp, len);
411
      break;
412
 
413
    case ECHOREP:
414
      lcp_received_echo_reply(f, id, inp, len);
415
      break;
416
 
417
    case DISCREQ:
418
      break;
419
 
420
    default:
421
      return 0;
422
  }
423
  return 1;
424
}
425
 
426
 
427
/*
428
 * lcp_rprotrej - Receive an Protocol-Reject.
429
 *
430
 * Figure out which protocol is rejected and inform it.
431
 */
432
static void
433
lcp_rprotrej(fsm *f, u_char *inp, int len)
434
{
435
  int i;
436
  struct protent *protp;
437
  u_short prot;
438
 
439
  if (len < sizeof (u_short)) {
440
    LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!\n"));
441
    return;
442
  }
443
 
444
  GETSHORT(prot, inp);
445
 
446
  LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));
447
 
448
  /*
449
   * Protocol-Reject packets received in any state other than the LCP
450
   * LS_OPENED state SHOULD be silently discarded.
451
   */
452
  if( f->state != LS_OPENED ) {
453
    LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d\n", f->state));
454
    return;
455
  }
456
 
457
  /*
458
   * Upcall the proper Protocol-Reject routine.
459
   */
460
  for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
461
    if (protp->protocol == prot && protp->enabled_flag) {
462
      (*protp->protrej)(f->unit);
463
      return;
464
    }
465
  }
466
 
467
  LCPDEBUG((LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x\n", prot));
468
}
469
 
470
 
471
/*
472
 * lcp_protrej - A Protocol-Reject was received.
473
 */
474
static void
475
lcp_protrej(int unit)
476
{
477
  LWIP_UNUSED_ARG(unit);
478
  /*
479
   * Can't reject LCP!
480
   */
481
  LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!\n"));
482
  fsm_protreject(&lcp_fsm[unit]);
483
}
484
 
485
 
486
/*
487
 * lcp_resetci - Reset our CI.
488
 */
489
static void
490
lcp_resetci(fsm *f)
491
{
492
  lcp_wantoptions[f->unit].magicnumber = magic();
493
  lcp_wantoptions[f->unit].numloops = 0;
494
  lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
495
  peer_mru[f->unit] = PPP_MRU;
496
  auth_reset(f->unit);
497
}
498
 
499
 
500
/*
501
 * lcp_cilen - Return length of our CI.
502
 */
503
static int lcp_cilen(fsm *f)
504
{
505
  lcp_options *go = &lcp_gotoptions[f->unit];
506
 
507
#define LENCIVOID(neg)  ((neg) ? CILEN_VOID : 0)
508
#define LENCICHAP(neg)  ((neg) ? CILEN_CHAP : 0)
509
#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
510
#define LENCILONG(neg)  ((neg) ? CILEN_LONG : 0)
511
#define LENCILQR(neg)   ((neg) ? CILEN_LQR: 0)
512
#define LENCICBCP(neg)  ((neg) ? CILEN_CBCP: 0)
513
  /*
514
   * NB: we only ask for one of CHAP and UPAP, even if we will
515
   * accept either.
516
   */
517
  return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) +
518
          LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) +
519
          LENCICHAP(go->neg_chap) +
520
          LENCISHORT(!go->neg_chap && go->neg_upap) +
521
          LENCILQR(go->neg_lqr) +
522
          LENCICBCP(go->neg_cbcp) +
523
          LENCILONG(go->neg_magicnumber) +
524
          LENCIVOID(go->neg_pcompression) +
525
          LENCIVOID(go->neg_accompression));
526
}
527
 
528
 
529
/*
530
 * lcp_addci - Add our desired CIs to a packet.
531
 */
532
static void
533
lcp_addci(fsm *f, u_char *ucp, int *lenp)
534
{
535
  lcp_options *go = &lcp_gotoptions[f->unit];
536
  u_char *start_ucp = ucp;
537
 
538
#define ADDCIVOID(opt, neg) \
539
  if (neg) { \
540
    LCPDEBUG((LOG_INFO, "lcp_addci: opt=%d\n", opt)); \
541
    PUTCHAR(opt, ucp); \
542
    PUTCHAR(CILEN_VOID, ucp); \
543
  }
544
#define ADDCISHORT(opt, neg, val) \
545
  if (neg) { \
546
    LCPDEBUG((LOG_INFO, "lcp_addci: INT opt=%d %X\n", opt, val)); \
547
    PUTCHAR(opt, ucp); \
548
    PUTCHAR(CILEN_SHORT, ucp); \
549
    PUTSHORT(val, ucp); \
550
  }
551
#define ADDCICHAP(opt, neg, val, digest) \
552
  if (neg) { \
553
    LCPDEBUG((LOG_INFO, "lcp_addci: CHAP opt=%d %X\n", opt, val)); \
554
    PUTCHAR(opt, ucp); \
555
    PUTCHAR(CILEN_CHAP, ucp); \
556
    PUTSHORT(val, ucp); \
557
    PUTCHAR(digest, ucp); \
558
  }
559
#define ADDCILONG(opt, neg, val) \
560
  if (neg) { \
561
    LCPDEBUG((LOG_INFO, "lcp_addci: L opt=%d %lX\n", opt, val)); \
562
    PUTCHAR(opt, ucp); \
563
    PUTCHAR(CILEN_LONG, ucp); \
564
    PUTLONG(val, ucp); \
565
  }
566
#define ADDCILQR(opt, neg, val) \
567
  if (neg) { \
568
    LCPDEBUG((LOG_INFO, "lcp_addci: LQR opt=%d %lX\n", opt, val)); \
569
    PUTCHAR(opt, ucp); \
570
    PUTCHAR(CILEN_LQR, ucp); \
571
    PUTSHORT(PPP_LQR, ucp); \
572
    PUTLONG(val, ucp); \
573
  }
574
#define ADDCICHAR(opt, neg, val) \
575
  if (neg) { \
576
    LCPDEBUG((LOG_INFO, "lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \
577
    PUTCHAR(opt, ucp); \
578
    PUTCHAR(CILEN_CHAR, ucp); \
579
    PUTCHAR(val, ucp); \
580
  }
581
 
582
  ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
583
  ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap);
584
  ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
585
  ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
586
  ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
587
  ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
588
  ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
589
  ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
590
  ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
591
 
592
  if (ucp - start_ucp != *lenp) {
593
    /* this should never happen, because peer_mtu should be 1500 */
594
    LCPDEBUG((LOG_ERR, "Bug in lcp_addci: wrong length\n"));
595
  }
596
}
597
 
598
 
599
/*
600
 * lcp_ackci - Ack our CIs.
601
 * This should not modify any state if the Ack is bad.
602
 *
603
 * Returns:
604
 *  0 - Ack was bad.
605
 *  1 - Ack was good.
606
 */
607
static int
608
lcp_ackci(fsm *f, u_char *p, int len)
609
{
610
  lcp_options *go = &lcp_gotoptions[f->unit];
611
  u_char cilen, citype, cichar;
612
  u_short cishort;
613
  u32_t cilong;
614
 
615
  /*
616
   * CIs must be in exactly the same order that we sent.
617
   * Check packet length and CI length at each step.
618
   * If we find any deviations, then this packet is bad.
619
   */
620
#define ACKCIVOID(opt, neg) \
621
  if (neg) { \
622
    if ((len -= CILEN_VOID) < 0) \
623
      goto bad; \
624
    GETCHAR(citype, p); \
625
    GETCHAR(cilen, p); \
626
    if (cilen != CILEN_VOID || citype != opt) \
627
      goto bad; \
628
  }
629
#define ACKCISHORT(opt, neg, val) \
630
  if (neg) { \
631
    if ((len -= CILEN_SHORT) < 0) \
632
      goto bad; \
633
    GETCHAR(citype, p); \
634
    GETCHAR(cilen, p); \
635
    if (cilen != CILEN_SHORT || citype != opt) \
636
      goto bad; \
637
    GETSHORT(cishort, p); \
638
    if (cishort != val) \
639
      goto bad; \
640
  }
641
#define ACKCICHAR(opt, neg, val) \
642
  if (neg) { \
643
    if ((len -= CILEN_CHAR) < 0) \
644
      goto bad; \
645
    GETCHAR(citype, p); \
646
    GETCHAR(cilen, p); \
647
    if (cilen != CILEN_CHAR || citype != opt) \
648
      goto bad; \
649
    GETCHAR(cichar, p); \
650
    if (cichar != val) \
651
      goto bad; \
652
  }
653
#define ACKCICHAP(opt, neg, val, digest) \
654
  if (neg) { \
655
    if ((len -= CILEN_CHAP) < 0) \
656
      goto bad; \
657
    GETCHAR(citype, p); \
658
    GETCHAR(cilen, p); \
659
    if (cilen != CILEN_CHAP || citype != opt) \
660
      goto bad; \
661
    GETSHORT(cishort, p); \
662
    if (cishort != val) \
663
      goto bad; \
664
    GETCHAR(cichar, p); \
665
    if (cichar != digest) \
666
      goto bad; \
667
  }
668
#define ACKCILONG(opt, neg, val) \
669
  if (neg) { \
670
    if ((len -= CILEN_LONG) < 0) \
671
      goto bad; \
672
    GETCHAR(citype, p); \
673
    GETCHAR(cilen, p); \
674
    if (cilen != CILEN_LONG ||  citype != opt) \
675
      goto bad; \
676
    GETLONG(cilong, p); \
677
    if (cilong != val) \
678
      goto bad; \
679
  }
680
#define ACKCILQR(opt, neg, val) \
681
  if (neg) { \
682
    if ((len -= CILEN_LQR) < 0) \
683
      goto bad; \
684
    GETCHAR(citype, p); \
685
    GETCHAR(cilen, p); \
686
    if (cilen != CILEN_LQR || citype != opt) \
687
      goto bad; \
688
    GETSHORT(cishort, p); \
689
    if (cishort != PPP_LQR) \
690
      goto bad; \
691
    GETLONG(cilong, p); \
692
    if (cilong != val) \
693
      goto bad; \
694
  }
695
 
696
  ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
697
  ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap);
698
  ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
699
  ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
700
  ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
701
  ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
702
  ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
703
  ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
704
  ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
705
 
706
  /*
707
   * If there are any remaining CIs, then this packet is bad.
708
   */
709
  if (len != 0) {
710
    goto bad;
711
  }
712
  LCPDEBUG((LOG_INFO, "lcp_acki: Ack\n"));
713
  return (1);
714
bad:
715
  LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!\n"));
716
  return (0);
717
}
718
 
719
 
720
/*
721
 * lcp_nakci - Peer has sent a NAK for some of our CIs.
722
 * This should not modify any state if the Nak is bad
723
 * or if LCP is in the LS_OPENED state.
724
 *
725
 * Returns:
726
 *  0 - Nak was bad.
727
 *  1 - Nak was good.
728
 */
729
static int
730
lcp_nakci(fsm *f, u_char *p, int len)
731
{
732
  lcp_options *go = &lcp_gotoptions[f->unit];
733
  lcp_options *wo = &lcp_wantoptions[f->unit];
734
  u_char citype, cichar, *next;
735
  u_short cishort;
736
  u32_t cilong;
737
  lcp_options no;     /* options we've seen Naks for */
738
  lcp_options try;    /* options to request next time */
739
  int looped_back = 0;
740
  int cilen;
741
 
742
  BZERO(&no, sizeof(no));
743
  try = *go;
744
 
745
  /*
746
   * Any Nak'd CIs must be in exactly the same order that we sent.
747
   * Check packet length and CI length at each step.
748
   * If we find any deviations, then this packet is bad.
749
   */
750
#define NAKCIVOID(opt, neg, code) \
751
  if (go->neg && \
752
      len >= CILEN_VOID && \
753
      p[1] == CILEN_VOID && \
754
      p[0] == opt) { \
755
    len -= CILEN_VOID; \
756
    INCPTR(CILEN_VOID, p); \
757
    no.neg = 1; \
758
    code \
759
  }
760
#define NAKCICHAP(opt, neg, code) \
761
  if (go->neg && \
762
      len >= CILEN_CHAP && \
763
      p[1] == CILEN_CHAP && \
764
      p[0] == opt) { \
765
    len -= CILEN_CHAP; \
766
    INCPTR(2, p); \
767
    GETSHORT(cishort, p); \
768
    GETCHAR(cichar, p); \
769
    no.neg = 1; \
770
    code \
771
  }
772
#define NAKCICHAR(opt, neg, code) \
773
  if (go->neg && \
774
      len >= CILEN_CHAR && \
775
      p[1] == CILEN_CHAR && \
776
      p[0] == opt) { \
777
    len -= CILEN_CHAR; \
778
    INCPTR(2, p); \
779
    GETCHAR(cichar, p); \
780
    no.neg = 1; \
781
    code \
782
  }
783
#define NAKCISHORT(opt, neg, code) \
784
  if (go->neg && \
785
      len >= CILEN_SHORT && \
786
      p[1] == CILEN_SHORT && \
787
      p[0] == opt) { \
788
    len -= CILEN_SHORT; \
789
    INCPTR(2, p); \
790
    GETSHORT(cishort, p); \
791
    no.neg = 1; \
792
    code \
793
  }
794
#define NAKCILONG(opt, neg, code) \
795
  if (go->neg && \
796
      len >= CILEN_LONG && \
797
      p[1] == CILEN_LONG && \
798
      p[0] == opt) { \
799
    len -= CILEN_LONG; \
800
    INCPTR(2, p); \
801
    GETLONG(cilong, p); \
802
    no.neg = 1; \
803
    code \
804
  }
805
#define NAKCILQR(opt, neg, code) \
806
  if (go->neg && \
807
      len >= CILEN_LQR && \
808
      p[1] == CILEN_LQR && \
809
      p[0] == opt) { \
810
    len -= CILEN_LQR; \
811
    INCPTR(2, p); \
812
    GETSHORT(cishort, p); \
813
    GETLONG(cilong, p); \
814
    no.neg = 1; \
815
    code \
816
  }
817
 
818
  /*
819
   * We don't care if they want to send us smaller packets than
820
   * we want.  Therefore, accept any MRU less than what we asked for,
821
   * but then ignore the new value when setting the MRU in the kernel.
822
   * If they send us a bigger MRU than what we asked, accept it, up to
823
   * the limit of the default MRU we'd get if we didn't negotiate.
824
   */
825
  if (go->neg_mru && go->mru != PPP_DEFMRU) {
826
    NAKCISHORT(CI_MRU, neg_mru,
827
      if (cishort <= wo->mru || cishort < PPP_DEFMRU) {
828
        try.mru = cishort;
829
      }
830
    );
831
  }
832
 
833
  /*
834
   * Add any characters they want to our (receive-side) asyncmap.
835
   */
836
  if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) {
837
    NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
838
      try.asyncmap = go->asyncmap | cilong;
839
    );
840
  }
841
 
842
  /*
843
   * If they've nak'd our authentication-protocol, check whether
844
   * they are proposing a different protocol, or a different
845
   * hash algorithm for CHAP.
846
   */
847
  if ((go->neg_chap || go->neg_upap)
848
      && len >= CILEN_SHORT
849
      && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
850
    cilen = p[1];
851
    len -= cilen;
852
    no.neg_chap = go->neg_chap;
853
    no.neg_upap = go->neg_upap;
854
    INCPTR(2, p);
855
    GETSHORT(cishort, p);
856
    if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
857
      /*
858
       * If we were asking for CHAP, they obviously don't want to do it.
859
       * If we weren't asking for CHAP, then we were asking for PAP,
860
       * in which case this Nak is bad.
861
       */
862
      if (!go->neg_chap) {
863
        goto bad;
864
      }
865
      try.neg_chap = 0;
866
 
867
    } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
868
      GETCHAR(cichar, p);
869
      if (go->neg_chap) {
870
        /*
871
         * We were asking for CHAP/MD5; they must want a different
872
         * algorithm.  If they can't do MD5, we'll have to stop
873
         * asking for CHAP.
874
         */
875
        if (cichar != go->chap_mdtype) {
876
          try.neg_chap = 0;
877
        }
878
      } else {
879
        /*
880
         * Stop asking for PAP if we were asking for it.
881
         */
882
        try.neg_upap = 0;
883
      }
884
 
885
    } else {
886
      /*
887
       * We don't recognize what they're suggesting.
888
       * Stop asking for what we were asking for.
889
       */
890
      if (go->neg_chap) {
891
        try.neg_chap = 0;
892
      } else {
893
        try.neg_upap = 0;
894
      }
895
      p += cilen - CILEN_SHORT;
896
    }
897
  }
898
 
899
  /*
900
   * If they can't cope with our link quality protocol, we'll have
901
   * to stop asking for LQR.  We haven't got any other protocol.
902
   * If they Nak the reporting period, take their value XXX ?
903
   */
904
  NAKCILQR(CI_QUALITY, neg_lqr,
905
    if (cishort != PPP_LQR) {
906
      try.neg_lqr = 0;
907
    } else {
908
      try.lqr_period = cilong;
909
    }
910
  );
911
 
912
  /*
913
   * Only implementing CBCP...not the rest of the callback options
914
   */
915
  NAKCICHAR(CI_CALLBACK, neg_cbcp,
916
    try.neg_cbcp = 0;
917
  );
918
 
919
  /*
920
   * Check for a looped-back line.
921
   */
922
  NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
923
    try.magicnumber = magic();
924
    looped_back = 1;
925
  );
926
 
927
  /*
928
   * Peer shouldn't send Nak for protocol compression or
929
   * address/control compression requests; they should send
930
   * a Reject instead.  If they send a Nak, treat it as a Reject.
931
   */
932
  NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
933
    try.neg_pcompression = 0;
934
  );
935
  NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
936
    try.neg_accompression = 0;
937
  );
938
 
939
  /*
940
   * There may be remaining CIs, if the peer is requesting negotiation
941
   * on an option that we didn't include in our request packet.
942
   * If we see an option that we requested, or one we've already seen
943
   * in this packet, then this packet is bad.
944
   * If we wanted to respond by starting to negotiate on the requested
945
   * option(s), we could, but we don't, because except for the
946
   * authentication type and quality protocol, if we are not negotiating
947
   * an option, it is because we were told not to.
948
   * For the authentication type, the Nak from the peer means
949
   * `let me authenticate myself with you' which is a bit pointless.
950
   * For the quality protocol, the Nak means `ask me to send you quality
951
   * reports', but if we didn't ask for them, we don't want them.
952
   * An option we don't recognize represents the peer asking to
953
   * negotiate some option we don't support, so ignore it.
954
   */
955
  while (len > CILEN_VOID) {
956
    GETCHAR(citype, p);
957
    GETCHAR(cilen, p);
958
    if (cilen < CILEN_VOID || (len -= cilen) < 0) {
959
      goto bad;
960
    }
961
    next = p + cilen - 2;
962
 
963
    switch (citype) {
964
      case CI_MRU:
965
        if ((go->neg_mru && go->mru != PPP_DEFMRU)
966
            || no.neg_mru || cilen != CILEN_SHORT) {
967
          goto bad;
968
        }
969
        GETSHORT(cishort, p);
970
        if (cishort < PPP_DEFMRU) {
971
          try.mru = cishort;
972
        }
973
        break;
974
      case CI_ASYNCMAP:
975
        if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl)
976
            || no.neg_asyncmap || cilen != CILEN_LONG) {
977
          goto bad;
978
        }
979
        break;
980
      case CI_AUTHTYPE:
981
        if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) {
982
          goto bad;
983
        }
984
        break;
985
      case CI_MAGICNUMBER:
986
        if (go->neg_magicnumber || no.neg_magicnumber ||
987
            cilen != CILEN_LONG) {
988
          goto bad;
989
        }
990
        break;
991
      case CI_PCOMPRESSION:
992
        if (go->neg_pcompression || no.neg_pcompression
993
            || cilen != CILEN_VOID) {
994
          goto bad;
995
        }
996
        break;
997
      case CI_ACCOMPRESSION:
998
        if (go->neg_accompression || no.neg_accompression
999
            || cilen != CILEN_VOID) {
1000
          goto bad;
1001
        }
1002
        break;
1003
      case CI_QUALITY:
1004
        if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) {
1005
          goto bad;
1006
        }
1007
        break;
1008
    }
1009
    p = next;
1010
  }
1011
 
1012
  /* If there is still anything left, this packet is bad. */
1013
  if (len != 0) {
1014
    goto bad;
1015
  }
1016
 
1017
  /*
1018
  * OK, the Nak is good.  Now we can update state.
1019
  */
1020
  if (f->state != LS_OPENED) {
1021
    if (looped_back) {
1022
      if (++try.numloops >= lcp_loopbackfail) {
1023
        LCPDEBUG((LOG_NOTICE, "Serial line is looped back.\n"));
1024
        lcp_close(f->unit, "Loopback detected");
1025
      }
1026
    } else {
1027
      try.numloops = 0;
1028
    }
1029
    *go = try;
1030
  }
1031
 
1032
  return 1;
1033
 
1034
bad:
1035
  LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!\n"));
1036
  return 0;
1037
}
1038
 
1039
 
1040
/*
1041
 * lcp_rejci - Peer has Rejected some of our CIs.
1042
 * This should not modify any state if the Reject is bad
1043
 * or if LCP is in the LS_OPENED state.
1044
 *
1045
 * Returns:
1046
 *  0 - Reject was bad.
1047
 *  1 - Reject was good.
1048
 */
1049
static int
1050
lcp_rejci(fsm *f, u_char *p, int len)
1051
{
1052
  lcp_options *go = &lcp_gotoptions[f->unit];
1053
  u_char cichar;
1054
  u_short cishort;
1055
  u32_t cilong;
1056
  lcp_options try; /* options to request next time */
1057
 
1058
  try = *go;
1059
 
1060
  /*
1061
   * Any Rejected CIs must be in exactly the same order that we sent.
1062
   * Check packet length and CI length at each step.
1063
   * If we find any deviations, then this packet is bad.
1064
   */
1065
#define REJCIVOID(opt, neg) \
1066
  if (go->neg && \
1067
      len >= CILEN_VOID && \
1068
      p[1] == CILEN_VOID && \
1069
      p[0] == opt) { \
1070
    len -= CILEN_VOID; \
1071
    INCPTR(CILEN_VOID, p); \
1072
    try.neg = 0; \
1073
    LCPDEBUG((LOG_INFO, "lcp_rejci: void opt %d rejected\n", opt)); \
1074
  }
1075
#define REJCISHORT(opt, neg, val) \
1076
  if (go->neg && \
1077
      len >= CILEN_SHORT && \
1078
      p[1] == CILEN_SHORT && \
1079
      p[0] == opt) { \
1080
    len -= CILEN_SHORT; \
1081
    INCPTR(2, p); \
1082
    GETSHORT(cishort, p); \
1083
    /* Check rejected value. */ \
1084
    if (cishort != val) { \
1085
      goto bad; \
1086
    } \
1087
    try.neg = 0; \
1088
    LCPDEBUG((LOG_INFO,"lcp_rejci: short opt %d rejected\n", opt)); \
1089
  }
1090
#define REJCICHAP(opt, neg, val, digest) \
1091
  if (go->neg && \
1092
      len >= CILEN_CHAP && \
1093
      p[1] == CILEN_CHAP && \
1094
      p[0] == opt) { \
1095
    len -= CILEN_CHAP; \
1096
    INCPTR(2, p); \
1097
    GETSHORT(cishort, p); \
1098
    GETCHAR(cichar, p); \
1099
    /* Check rejected value. */ \
1100
    if (cishort != val || cichar != digest) { \
1101
      goto bad; \
1102
    } \
1103
    try.neg = 0; \
1104
    try.neg_upap = 0; \
1105
    LCPDEBUG((LOG_INFO,"lcp_rejci: chap opt %d rejected\n", opt)); \
1106
  }
1107
#define REJCILONG(opt, neg, val) \
1108
  if (go->neg && \
1109
      len >= CILEN_LONG && \
1110
      p[1] == CILEN_LONG && \
1111
      p[0] == opt) { \
1112
    len -= CILEN_LONG; \
1113
    INCPTR(2, p); \
1114
    GETLONG(cilong, p); \
1115
    /* Check rejected value. */ \
1116
    if (cilong != val) { \
1117
      goto bad; \
1118
    } \
1119
    try.neg = 0; \
1120
    LCPDEBUG((LOG_INFO,"lcp_rejci: long opt %d rejected\n", opt)); \
1121
  }
1122
#define REJCILQR(opt, neg, val) \
1123
  if (go->neg && \
1124
      len >= CILEN_LQR && \
1125
      p[1] == CILEN_LQR && \
1126
      p[0] == opt) { \
1127
    len -= CILEN_LQR; \
1128
    INCPTR(2, p); \
1129
    GETSHORT(cishort, p); \
1130
    GETLONG(cilong, p); \
1131
    /* Check rejected value. */ \
1132
    if (cishort != PPP_LQR || cilong != val) { \
1133
      goto bad; \
1134
    } \
1135
    try.neg = 0; \
1136
    LCPDEBUG((LOG_INFO,"lcp_rejci: LQR opt %d rejected\n", opt)); \
1137
  }
1138
#define REJCICBCP(opt, neg, val) \
1139
  if (go->neg && \
1140
      len >= CILEN_CBCP && \
1141
      p[1] == CILEN_CBCP && \
1142
      p[0] == opt) { \
1143
    len -= CILEN_CBCP; \
1144
    INCPTR(2, p); \
1145
    GETCHAR(cichar, p); \
1146
    /* Check rejected value. */ \
1147
    if (cichar != val) { \
1148
      goto bad; \
1149
    } \
1150
    try.neg = 0; \
1151
    LCPDEBUG((LOG_INFO,"lcp_rejci: Callback opt %d rejected\n", opt)); \
1152
  }
1153
 
1154
  REJCISHORT(CI_MRU, neg_mru, go->mru);
1155
  REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1156
  REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
1157
  if (!go->neg_chap) {
1158
    REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1159
  }
1160
  REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1161
  REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1162
  REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1163
  REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1164
  REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1165
 
1166
  /*
1167
   * If there are any remaining CIs, then this packet is bad.
1168
   */
1169
  if (len != 0) {
1170
    goto bad;
1171
  }
1172
  /*
1173
   * Now we can update state.
1174
   */
1175
  if (f->state != LS_OPENED) {
1176
    *go = try;
1177
  }
1178
  return 1;
1179
 
1180
bad:
1181
  LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!\n"));
1182
  return 0;
1183
}
1184
 
1185
 
1186
/*
1187
 * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1188
 *
1189
 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1190
 * appropriately.  If reject_if_disagree is non-zero, doesn't return
1191
 * CONFNAK; returns CONFREJ if it can't return CONFACK.
1192
 */
1193
static int
1194
lcp_reqci(fsm *f,
1195
          u_char *inp,    /* Requested CIs */
1196
          int *lenp,      /* Length of requested CIs */
1197
          int reject_if_disagree)
1198
{
1199
  lcp_options *go = &lcp_gotoptions[f->unit];
1200
  lcp_options *ho = &lcp_hisoptions[f->unit];
1201
  lcp_options *ao = &lcp_allowoptions[f->unit];
1202
  u_char *cip, *next;         /* Pointer to current and next CIs */
1203
  int cilen, citype, cichar;  /* Parsed len, type, char value */
1204
  u_short cishort;            /* Parsed short value */
1205
  u32_t cilong;               /* Parse long value */
1206
  int rc = CONFACK;           /* Final packet return code */
1207
  int orc;                    /* Individual option return code */
1208
  u_char *p;                  /* Pointer to next char to parse */
1209
  u_char *rejp;               /* Pointer to next char in reject frame */
1210
  u_char *nakp;               /* Pointer to next char in Nak frame */
1211
  int l = *lenp;              /* Length left */
1212
#if TRACELCP > 0
1213
  char traceBuf[80];
1214
  int traceNdx = 0;
1215
#endif
1216
 
1217
  /*
1218
   * Reset all his options.
1219
   */
1220
  BZERO(ho, sizeof(*ho));
1221
 
1222
  /*
1223
   * Process all his options.
1224
   */
1225
  next = inp;
1226
  nakp = nak_buffer;
1227
  rejp = inp;
1228
  while (l) {
1229
    orc = CONFACK;      /* Assume success */
1230
    cip = p = next;     /* Remember begining of CI */
1231
    if (l < 2 ||        /* Not enough data for CI header or */
1232
        p[1] < 2 ||     /*  CI length too small or */
1233
        p[1] > l) {     /*  CI length too big? */
1234
      LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!\n"));
1235
      orc = CONFREJ;    /* Reject bad CI */
1236
      cilen = l;        /* Reject till end of packet */
1237
      l = 0;            /* Don't loop again */
1238
      citype = 0;
1239
      goto endswitch;
1240
    }
1241
    GETCHAR(citype, p); /* Parse CI type */
1242
    GETCHAR(cilen, p);  /* Parse CI length */
1243
    l -= cilen;         /* Adjust remaining length */
1244
    next += cilen;      /* Step to next CI */
1245
 
1246
    switch (citype) {   /* Check CI type */
1247
      case CI_MRU:
1248
        if (!ao->neg_mru) {    /* Allow option? */
1249
          LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - not allowed\n"));
1250
          orc = CONFREJ;    /* Reject CI */
1251
          break;
1252
        } else if (cilen != CILEN_SHORT) {  /* Check CI length */
1253
          LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - bad length\n"));
1254
          orc = CONFREJ;    /* Reject CI */
1255
          break;
1256
        }
1257
        GETSHORT(cishort, p);  /* Parse MRU */
1258
 
1259
        /*
1260
         * He must be able to receive at least our minimum.
1261
         * No need to check a maximum.  If he sends a large number,
1262
         * we'll just ignore it.
1263
         */
1264
        if (cishort < PPP_MINMRU) {
1265
          LCPDEBUG((LOG_INFO, "lcp_reqci: Nak - MRU too small\n"));
1266
          orc = CONFNAK;    /* Nak CI */
1267
          PUTCHAR(CI_MRU, nakp);
1268
          PUTCHAR(CILEN_SHORT, nakp);
1269
          PUTSHORT(PPP_MINMRU, nakp);  /* Give him a hint */
1270
          break;
1271
        }
1272
        ho->neg_mru = 1;    /* Remember he sent MRU */
1273
        ho->mru = cishort;    /* And remember value */
1274
#if TRACELCP > 0
1275
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort);
1276
        traceNdx = strlen(traceBuf);
1277
#endif
1278
        break;
1279
 
1280
      case CI_ASYNCMAP:
1281
        if (!ao->neg_asyncmap) {
1282
          LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP not allowed\n"));
1283
          orc = CONFREJ;
1284
          break;
1285
        } else if (cilen != CILEN_LONG) {
1286
          LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP bad length\n"));
1287
          orc = CONFREJ;
1288
          break;
1289
        }
1290
        GETLONG(cilong, p);
1291
 
1292
        /*
1293
         * Asyncmap must have set at least the bits
1294
         * which are set in lcp_allowoptions[unit].asyncmap.
1295
         */
1296
        if ((ao->asyncmap & ~cilong) != 0) {
1297
          LCPDEBUG((LOG_INFO, "lcp_reqci: Nak ASYNCMAP %lX missing %lX\n",
1298
                    cilong, ao->asyncmap));
1299
          orc = CONFNAK;
1300
          PUTCHAR(CI_ASYNCMAP, nakp);
1301
          PUTCHAR(CILEN_LONG, nakp);
1302
          PUTLONG(ao->asyncmap | cilong, nakp);
1303
          break;
1304
        }
1305
        ho->neg_asyncmap = 1;
1306
        ho->asyncmap = cilong;
1307
#if TRACELCP > 0
1308
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong);
1309
        traceNdx = strlen(traceBuf);
1310
#endif
1311
        break;
1312
 
1313
      case CI_AUTHTYPE:
1314
        if (cilen < CILEN_SHORT) {
1315
          LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE missing arg\n"));
1316
          orc = CONFREJ;
1317
          break;
1318
        } else if (!(ao->neg_upap || ao->neg_chap)) {
1319
          /*
1320
           * Reject the option if we're not willing to authenticate.
1321
           */
1322
          LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE not allowed\n"));
1323
          orc = CONFREJ;
1324
          break;
1325
        }
1326
        GETSHORT(cishort, p);
1327
 
1328
        /*
1329
         * Authtype must be UPAP or CHAP.
1330
         *
1331
         * Note: if both ao->neg_upap and ao->neg_chap are set,
1332
         * and the peer sends a Configure-Request with two
1333
         * authenticate-protocol requests, one for CHAP and one
1334
         * for UPAP, then we will reject the second request.
1335
         * Whether we end up doing CHAP or UPAP depends then on
1336
         * the ordering of the CIs in the peer's Configure-Request.
1337
         */
1338
 
1339
        if (cishort == PPP_PAP) {
1340
          if (ho->neg_chap) {  /* we've already accepted CHAP */
1341
            LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP already accepted\n"));
1342
            orc = CONFREJ;
1343
            break;
1344
          } else if (cilen != CILEN_SHORT) {
1345
            LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP bad len\n"));
1346
            orc = CONFREJ;
1347
            break;
1348
          }
1349
          if (!ao->neg_upap) {  /* we don't want to do PAP */
1350
            LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE PAP not allowed\n"));
1351
            orc = CONFNAK;  /* NAK it and suggest CHAP */
1352
            PUTCHAR(CI_AUTHTYPE, nakp);
1353
            PUTCHAR(CILEN_CHAP, nakp);
1354
            PUTSHORT(PPP_CHAP, nakp);
1355
            PUTCHAR(ao->chap_mdtype, nakp);
1356
            break;
1357
          }
1358
          ho->neg_upap = 1;
1359
#if TRACELCP > 0
1360
          snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort);
1361
          traceNdx = strlen(traceBuf);
1362
#endif
1363
          break;
1364
        }
1365
        if (cishort == PPP_CHAP) {
1366
          if (ho->neg_upap) {  /* we've already accepted PAP */
1367
            LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n"));
1368
            orc = CONFREJ;
1369
            break;
1370
          } else if (cilen != CILEN_CHAP) {
1371
            LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP bad len\n"));
1372
            orc = CONFREJ;
1373
            break;
1374
          }
1375
          if (!ao->neg_chap) {  /* we don't want to do CHAP */
1376
            LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP not allowed\n"));
1377
            orc = CONFNAK;  /* NAK it and suggest PAP */
1378
            PUTCHAR(CI_AUTHTYPE, nakp);
1379
            PUTCHAR(CILEN_SHORT, nakp);
1380
            PUTSHORT(PPP_PAP, nakp);
1381
            break;
1382
          }
1383
          GETCHAR(cichar, p);  /* get digest type*/
1384
          if (cichar != CHAP_DIGEST_MD5
1385
#ifdef CHAPMS
1386
              && cichar != CHAP_MICROSOFT
1387
#endif
1388
          ) {
1389
            LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", cichar));
1390
            orc = CONFNAK;
1391
            PUTCHAR(CI_AUTHTYPE, nakp);
1392
            PUTCHAR(CILEN_CHAP, nakp);
1393
            PUTSHORT(PPP_CHAP, nakp);
1394
            PUTCHAR(ao->chap_mdtype, nakp);
1395
            break;
1396
          }
1397
#if TRACELCP > 0
1398
          snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
1399
          traceNdx = strlen(traceBuf);
1400
#endif
1401
          ho->chap_mdtype = cichar; /* save md type */
1402
          ho->neg_chap = 1;
1403
          break;
1404
        }
1405
 
1406
        /*
1407
         * We don't recognize the protocol they're asking for.
1408
         * Nak it with something we're willing to do.
1409
         * (At this point we know ao->neg_upap || ao->neg_chap.)
1410
         */
1411
        orc = CONFNAK;
1412
        PUTCHAR(CI_AUTHTYPE, nakp);
1413
        if (ao->neg_chap) {
1414
          LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort));
1415
          PUTCHAR(CILEN_CHAP, nakp);
1416
          PUTSHORT(PPP_CHAP, nakp);
1417
          PUTCHAR(ao->chap_mdtype, nakp);
1418
        } else {
1419
          LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort));
1420
          PUTCHAR(CILEN_SHORT, nakp);
1421
          PUTSHORT(PPP_PAP, nakp);
1422
        }
1423
        break;
1424
 
1425
      case CI_QUALITY:
1426
        GETSHORT(cishort, p);
1427
        GETLONG(cilong, p);
1428
#if TRACELCP > 0
1429
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong);
1430
        traceNdx = strlen(traceBuf);
1431
#endif
1432
 
1433
        if (!ao->neg_lqr ||
1434
            cilen != CILEN_LQR) {
1435
          orc = CONFREJ;
1436
          break;
1437
        }
1438
 
1439
        /*
1440
         * Check the protocol and the reporting period.
1441
         * XXX When should we Nak this, and what with?
1442
         */
1443
        if (cishort != PPP_LQR) {
1444
          orc = CONFNAK;
1445
          PUTCHAR(CI_QUALITY, nakp);
1446
          PUTCHAR(CILEN_LQR, nakp);
1447
          PUTSHORT(PPP_LQR, nakp);
1448
          PUTLONG(ao->lqr_period, nakp);
1449
          break;
1450
        }
1451
        break;
1452
 
1453
      case CI_MAGICNUMBER:
1454
        if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
1455
            cilen != CILEN_LONG) {
1456
          orc = CONFREJ;
1457
          break;
1458
        }
1459
        GETLONG(cilong, p);
1460
#if TRACELCP > 0
1461
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong);
1462
        traceNdx = strlen(traceBuf);
1463
#endif
1464
 
1465
        /*
1466
         * He must have a different magic number.
1467
         */
1468
        if (go->neg_magicnumber &&
1469
            cilong == go->magicnumber) {
1470
          cilong = magic();  /* Don't put magic() inside macro! */
1471
          orc = CONFNAK;
1472
          PUTCHAR(CI_MAGICNUMBER, nakp);
1473
          PUTCHAR(CILEN_LONG, nakp);
1474
          PUTLONG(cilong, nakp);
1475
          break;
1476
        }
1477
        ho->neg_magicnumber = 1;
1478
        ho->magicnumber = cilong;
1479
        break;
1480
 
1481
 
1482
      case CI_PCOMPRESSION:
1483
#if TRACELCP > 0
1484
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION");
1485
        traceNdx = strlen(traceBuf);
1486
#endif
1487
        if (!ao->neg_pcompression ||
1488
            cilen != CILEN_VOID) {
1489
          orc = CONFREJ;
1490
          break;
1491
        }
1492
        ho->neg_pcompression = 1;
1493
        break;
1494
 
1495
      case CI_ACCOMPRESSION:
1496
#if TRACELCP > 0
1497
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION");
1498
        traceNdx = strlen(traceBuf);
1499
#endif
1500
        if (!ao->neg_accompression ||
1501
            cilen != CILEN_VOID) {
1502
          orc = CONFREJ;
1503
          break;
1504
        }
1505
        ho->neg_accompression = 1;
1506
        break;
1507
 
1508
      case CI_MRRU:
1509
#if TRACELCP > 0
1510
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU");
1511
        traceNdx = strlen(traceBuf);
1512
#endif
1513
        orc = CONFREJ;
1514
        break;
1515
 
1516
      case CI_SSNHF:
1517
#if TRACELCP > 0
1518
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF");
1519
        traceNdx = strlen(traceBuf);
1520
#endif
1521
        orc = CONFREJ;
1522
        break;
1523
 
1524
      case CI_EPDISC:
1525
#if TRACELCP > 0
1526
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC");
1527
        traceNdx = strlen(traceBuf);
1528
#endif
1529
        orc = CONFREJ;
1530
        break;
1531
 
1532
      default:
1533
#if TRACELCP
1534
        snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype);
1535
        traceNdx = strlen(traceBuf);
1536
#endif
1537
        orc = CONFREJ;
1538
        break;
1539
    }
1540
 
1541
  endswitch:
1542
#if TRACELCP
1543
    if (traceNdx >= 80 - 32) {
1544
      LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd%s\n", traceBuf));
1545
      traceNdx = 0;
1546
    }
1547
#endif
1548
    if (orc == CONFACK && /* Good CI */
1549
        rc != CONFACK) {  /*  but prior CI wasnt? */
1550
      continue;           /* Don't send this one */
1551
    }
1552
 
1553
    if (orc == CONFNAK) {     /* Nak this CI? */
1554
      if (reject_if_disagree  /* Getting fed up with sending NAKs? */
1555
          && citype != CI_MAGICNUMBER) {
1556
        orc = CONFREJ;        /* Get tough if so */
1557
      } else {
1558
        if (rc == CONFREJ) {  /* Rejecting prior CI? */
1559
          continue;           /* Don't send this one */
1560
        }
1561
        rc = CONFNAK;
1562
      }
1563
    }
1564
    if (orc == CONFREJ) {        /* Reject this CI */
1565
      rc = CONFREJ;
1566
      if (cip != rejp) {         /* Need to move rejected CI? */
1567
        BCOPY(cip, rejp, cilen); /* Move it */
1568
      }
1569
      INCPTR(cilen, rejp);       /* Update output pointer */
1570
    }
1571
  }
1572
 
1573
  /*
1574
   * If we wanted to send additional NAKs (for unsent CIs), the
1575
   * code would go here.  The extra NAKs would go at *nakp.
1576
   * At present there are no cases where we want to ask the
1577
   * peer to negotiate an option.
1578
   */
1579
 
1580
  switch (rc) {
1581
    case CONFACK:
1582
      *lenp = (int)(next - inp);
1583
      break;
1584
    case CONFNAK:
1585
      /*
1586
       * Copy the Nak'd options from the nak_buffer to the caller's buffer.
1587
       */
1588
      *lenp = (int)(nakp - nak_buffer);
1589
      BCOPY(nak_buffer, inp, *lenp);
1590
      break;
1591
    case CONFREJ:
1592
      *lenp = (int)(rejp - inp);
1593
      break;
1594
  }
1595
 
1596
#if TRACELCP > 0
1597
  if (traceNdx > 0) {
1598
    LCPDEBUG((LOG_INFO, "lcp_reqci: %s\n", traceBuf));
1599
  }
1600
#endif
1601
  LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.\n", CODENAME(rc)));
1602
  return (rc);      /* Return final code */
1603
}
1604
 
1605
 
1606
/*
1607
 * lcp_up - LCP has come UP.
1608
 */
1609
static void
1610
lcp_up(fsm *f)
1611
{
1612
  lcp_options *wo = &lcp_wantoptions[f->unit];
1613
  lcp_options *ho = &lcp_hisoptions[f->unit];
1614
  lcp_options *go = &lcp_gotoptions[f->unit];
1615
  lcp_options *ao = &lcp_allowoptions[f->unit];
1616
 
1617
  if (!go->neg_magicnumber) {
1618
    go->magicnumber = 0;
1619
  }
1620
  if (!ho->neg_magicnumber) {
1621
    ho->magicnumber = 0;
1622
  }
1623
 
1624
  /*
1625
   * Set our MTU to the smaller of the MTU we wanted and
1626
   * the MRU our peer wanted.  If we negotiated an MRU,
1627
   * set our MRU to the larger of value we wanted and
1628
   * the value we got in the negotiation.
1629
   */
1630
  ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
1631
                 (ho->neg_asyncmap? ho->asyncmap: 0xffffffffl),
1632
                  ho->neg_pcompression, ho->neg_accompression);
1633
  /*
1634
   * If the asyncmap hasn't been negotiated, we really should
1635
   * set the receive asyncmap to ffffffff, but we set it to 0
1636
   * for backwards contemptibility.
1637
   */
1638
  ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU),
1639
                 (go->neg_asyncmap? go->asyncmap: 0x00000000),
1640
                  go->neg_pcompression, go->neg_accompression);
1641
 
1642
  if (ho->neg_mru) {
1643
    peer_mru[f->unit] = ho->mru;
1644
  }
1645
 
1646
  lcp_echo_lowerup(f->unit); /* Enable echo messages */
1647
 
1648
  link_established(f->unit);
1649
}
1650
 
1651
 
1652
/*
1653
 * lcp_down - LCP has gone DOWN.
1654
 *
1655
 * Alert other protocols.
1656
 */
1657
static void
1658
lcp_down(fsm *f)
1659
{
1660
  lcp_options *go = &lcp_gotoptions[f->unit];
1661
 
1662
  lcp_echo_lowerdown(f->unit);
1663
 
1664
  link_down(f->unit);
1665
 
1666
  ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0);
1667
  ppp_recv_config(f->unit, PPP_MRU,
1668
                  (go->neg_asyncmap? go->asyncmap: 0x00000000),
1669
                   go->neg_pcompression, go->neg_accompression);
1670
  peer_mru[f->unit] = PPP_MRU;
1671
}
1672
 
1673
 
1674
/*
1675
 * lcp_starting - LCP needs the lower layer up.
1676
 */
1677
static void
1678
lcp_starting(fsm *f)
1679
{
1680
  link_required(f->unit);
1681
}
1682
 
1683
 
1684
/*
1685
 * lcp_finished - LCP has finished with the lower layer.
1686
 */
1687
static void
1688
lcp_finished(fsm *f)
1689
{
1690
  link_terminated(f->unit);
1691
}
1692
 
1693
 
1694
#if 0
1695
/*
1696
 * print_string - print a readable representation of a string using
1697
 * printer.
1698
 */
1699
static void
1700
print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg)
1701
{
1702
  int c;
1703
 
1704
  printer(arg, "\"");
1705
  for (; len > 0; --len) {
1706
    c = *p++;
1707
    if (' ' <= c && c <= '~') {
1708
        if (c == '\\' || c == '"') {
1709
          printer(arg, "\\");
1710
        }
1711
        printer(arg, "%c", c);
1712
    } else {
1713
      switch (c) {
1714
        case '\n':
1715
          printer(arg, "\\n");
1716
          break;
1717
        case '\r':
1718
          printer(arg, "\\r");
1719
          break;
1720
        case '\t':
1721
          printer(arg, "\\t");
1722
          break;
1723
        default:
1724
          printer(arg, "\\%.3o", c);
1725
        }
1726
    }
1727
  }
1728
  printer(arg, "\"");
1729
}
1730
 
1731
 
1732
/*
1733
 * lcp_printpkt - print the contents of an LCP packet.
1734
 */
1735
static char *lcp_codenames[] = {
1736
  "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1737
  "TermReq", "TermAck", "CodeRej", "ProtRej",
1738
  "EchoReq", "EchoRep", "DiscReq"
1739
};
1740
 
1741
static int
1742
lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
1743
{
1744
  int code, id, len, olen;
1745
  u_char *pstart, *optend;
1746
  u_short cishort;
1747
  u32_t cilong;
1748
 
1749
  if (plen < HEADERLEN) {
1750
    return 0;
1751
  }
1752
  pstart = p;
1753
  GETCHAR(code, p);
1754
  GETCHAR(id, p);
1755
  GETSHORT(len, p);
1756
  if (len < HEADERLEN || len > plen) {
1757
    return 0;
1758
  }
1759
 
1760
  if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) {
1761
    printer(arg, " %s", lcp_codenames[code-1]);
1762
  } else {
1763
    printer(arg, " code=0x%x", code);
1764
  }
1765
  printer(arg, " id=0x%x", id);
1766
  len -= HEADERLEN;
1767
  switch (code) {
1768
    case CONFREQ:
1769
    case CONFACK:
1770
    case CONFNAK:
1771
    case CONFREJ:
1772
      /* print option list */
1773
      while (len >= 2) {
1774
        GETCHAR(code, p);
1775
        GETCHAR(olen, p);
1776
        p -= 2;
1777
        if (olen < 2 || olen > len) {
1778
          break;
1779
        }
1780
        printer(arg, " <");
1781
        len -= olen;
1782
        optend = p + olen;
1783
        switch (code) {
1784
          case CI_MRU:
1785
            if (olen == CILEN_SHORT) {
1786
              p += 2;
1787
              GETSHORT(cishort, p);
1788
              printer(arg, "mru %d", cishort);
1789
            }
1790
            break;
1791
          case CI_ASYNCMAP:
1792
            if (olen == CILEN_LONG) {
1793
              p += 2;
1794
              GETLONG(cilong, p);
1795
              printer(arg, "asyncmap 0x%lx", cilong);
1796
            }
1797
            break;
1798
          case CI_AUTHTYPE:
1799
            if (olen >= CILEN_SHORT) {
1800
              p += 2;
1801
              printer(arg, "auth ");
1802
              GETSHORT(cishort, p);
1803
              switch (cishort) {
1804
                case PPP_PAP:
1805
                  printer(arg, "pap");
1806
                  break;
1807
                case PPP_CHAP:
1808
                  printer(arg, "chap");
1809
                  break;
1810
                default:
1811
                  printer(arg, "0x%x", cishort);
1812
              }
1813
            }
1814
            break;
1815
          case CI_QUALITY:
1816
            if (olen >= CILEN_SHORT) {
1817
              p += 2;
1818
              printer(arg, "quality ");
1819
              GETSHORT(cishort, p);
1820
              switch (cishort) {
1821
                case PPP_LQR:
1822
                  printer(arg, "lqr");
1823
                  break;
1824
                default:
1825
                  printer(arg, "0x%x", cishort);
1826
              }
1827
            }
1828
            break;
1829
          case CI_CALLBACK:
1830
            if (olen >= CILEN_CHAR) {
1831
              p += 2;
1832
              printer(arg, "callback ");
1833
              GETSHORT(cishort, p);
1834
              switch (cishort) {
1835
                case CBCP_OPT:
1836
                  printer(arg, "CBCP");
1837
                  break;
1838
                default:
1839
                  printer(arg, "0x%x", cishort);
1840
              }
1841
            }
1842
            break;
1843
          case CI_MAGICNUMBER:
1844
            if (olen == CILEN_LONG) {
1845
              p += 2;
1846
              GETLONG(cilong, p);
1847
              printer(arg, "magic 0x%x", cilong);
1848
            }
1849
            break;
1850
          case CI_PCOMPRESSION:
1851
            if (olen == CILEN_VOID) {
1852
              p += 2;
1853
              printer(arg, "pcomp");
1854
            }
1855
            break;
1856
          case CI_ACCOMPRESSION:
1857
            if (olen == CILEN_VOID) {
1858
              p += 2;
1859
              printer(arg, "accomp");
1860
            }
1861
            break;
1862
        }
1863
        while (p < optend) {
1864
          GETCHAR(code, p);
1865
          printer(arg, " %.2x", code);
1866
        }
1867
        printer(arg, ">");
1868
      }
1869
      break;
1870
 
1871
    case TERMACK:
1872
    case TERMREQ:
1873
      if (len > 0 && *p >= ' ' && *p < 0x7f) {
1874
        printer(arg, " ");
1875
        print_string((char*)p, len, printer, arg);
1876
        p += len;
1877
        len = 0;
1878
      }
1879
      break;
1880
 
1881
    case ECHOREQ:
1882
    case ECHOREP:
1883
    case DISCREQ:
1884
      if (len >= 4) {
1885
        GETLONG(cilong, p);
1886
        printer(arg, " magic=0x%x", cilong);
1887
        p += 4;
1888
        len -= 4;
1889
      }
1890
      break;
1891
  }
1892
 
1893
  /* print the rest of the bytes in the packet */
1894
  for (; len > 0; --len) {
1895
    GETCHAR(code, p);
1896
    printer(arg, " %.2x", code);
1897
  }
1898
 
1899
  return (int)(p - pstart);
1900
}
1901
#endif
1902
 
1903
/*
1904
 * Time to shut down the link because there is nothing out there.
1905
 */
1906
static void
1907
LcpLinkFailure (fsm *f)
1908
{
1909
  if (f->state == LS_OPENED) {
1910
    LCPDEBUG((LOG_INFO, "No response to %d echo-requests\n", lcp_echos_pending));
1911
    LCPDEBUG((LOG_NOTICE, "Serial link appears to be disconnected.\n"));
1912
    lcp_close(f->unit, "Peer not responding");
1913
  }
1914
}
1915
 
1916
/*
1917
 * Timer expired for the LCP echo requests from this process.
1918
 */
1919
static void
1920
LcpEchoCheck (fsm *f)
1921
{
1922
  LcpSendEchoRequest (f);
1923
 
1924
  /*
1925
   * Start the timer for the next interval.
1926
   */
1927
  LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0);
1928
 
1929
  TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
1930
  lcp_echo_timer_running = 1;
1931
}
1932
 
1933
/*
1934
 * LcpEchoTimeout - Timer expired on the LCP echo
1935
 */
1936
static void
1937
LcpEchoTimeout (void *arg)
1938
{
1939
  if (lcp_echo_timer_running != 0) {
1940
    lcp_echo_timer_running = 0;
1941
    LcpEchoCheck ((fsm *) arg);
1942
  }
1943
}
1944
 
1945
/*
1946
 * LcpEchoReply - LCP has received a reply to the echo
1947
 */
1948
static void
1949
lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len)
1950
{
1951
  u32_t magic;
1952
 
1953
  LWIP_UNUSED_ARG(id);
1954
 
1955
  /* Check the magic number - don't count replies from ourselves. */
1956
  if (len < 4) {
1957
    LCPDEBUG((LOG_WARNING, "lcp: received short Echo-Reply, length %d\n", len));
1958
    return;
1959
  }
1960
  GETLONG(magic, inp);
1961
  if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) {
1962
    LCPDEBUG((LOG_WARNING, "appear to have received our own echo-reply!\n"));
1963
    return;
1964
  }
1965
 
1966
  /* Reset the number of outstanding echo frames */
1967
  lcp_echos_pending = 0;
1968
}
1969
 
1970
/*
1971
 * LcpSendEchoRequest - Send an echo request frame to the peer
1972
 */
1973
static void
1974
LcpSendEchoRequest (fsm *f)
1975
{
1976
  u32_t lcp_magic;
1977
  u_char pkt[4], *pktp;
1978
 
1979
  /*
1980
   * Detect the failure of the peer at this point.
1981
   */
1982
  if (lcp_echo_fails != 0) {
1983
    if (lcp_echos_pending++ >= lcp_echo_fails) {
1984
      LcpLinkFailure(f);
1985
      lcp_echos_pending = 0;
1986
    }
1987
  }
1988
 
1989
  /*
1990
   * Make and send the echo request frame.
1991
   */
1992
  if (f->state == LS_OPENED) {
1993
    lcp_magic = lcp_gotoptions[f->unit].magicnumber;
1994
    pktp = pkt;
1995
    PUTLONG(lcp_magic, pktp);
1996
    fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt));
1997
  }
1998
}
1999
 
2000
/*
2001
 * lcp_echo_lowerup - Start the timer for the LCP frame
2002
 */
2003
 
2004
static void
2005
lcp_echo_lowerup (int unit)
2006
{
2007
  fsm *f = &lcp_fsm[unit];
2008
 
2009
  /* Clear the parameters for generating echo frames */
2010
  lcp_echos_pending      = 0;
2011
  lcp_echo_number        = 0;
2012
  lcp_echo_timer_running = 0;
2013
 
2014
  /* If a timeout interval is specified then start the timer */
2015
  if (lcp_echo_interval != 0) {
2016
    LcpEchoCheck (f);
2017
  }
2018
}
2019
 
2020
/*
2021
 * lcp_echo_lowerdown - Stop the timer for the LCP frame
2022
 */
2023
 
2024
static void
2025
lcp_echo_lowerdown (int unit)
2026
{
2027
  fsm *f = &lcp_fsm[unit];
2028
 
2029
  if (lcp_echo_timer_running != 0) {
2030
    UNTIMEOUT (LcpEchoTimeout, f);
2031
    lcp_echo_timer_running = 0;
2032
  }
2033
}
2034
 
2035
#endif /* PPP_SUPPORT */

powered by: WebSVN 2.1.0

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