source: rtems/cpukit/pppd/lcp.c @ 660db8c8

5
Last change on this file since 660db8c8 was 33a1a4db, checked in by Peng Fan <van.freenix@…>, on 04/05/16 at 12:45:55

cpukit: pppd: fix compile warning

rcsid is defined, but not used. So discard it.

Signed-off-by: Peng Fan <van.freenix@…>

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