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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [pppd/] [lcp.c] - Blame information for rev 173

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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