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

Subversion Repositories openrisc

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

powered by: WebSVN 2.1.0

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