176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    dial-on-demand has been stripped. */
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*****************************************************************************
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* ipcp.c - Network PPP IP Control Protocol program file.
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* portions Copyright (c) 1997 by Global Election Systems Inc.
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* The authors hereby grant permission to use, copy, modify, distribute,
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* and license this software and its documentation for any purpose, provided
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* that existing copyright notices are retained in all copies and that this
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* notice and the following disclaimer are included verbatim in any
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* distributions. No written agreement, license, or royalty fee is required
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* for any of the authorized uses.
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman******************************************************************************
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* REVISION HISTORY
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 03-01-01 Marc Boucher <marc@mbsi.ca>
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*   Ported to lwIP.
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*   Original.
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*****************************************************************************/
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp.c - PPP IP Control Protocol.
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (c) 1989 Carnegie Mellon University.
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * All rights reserved.
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Redistribution and use in source and binary forms are permitted
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * provided that the above copyright notice and this paragraph are
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * duplicated in all such forms and that any documentation,
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * advertising materials, and other materials related to such
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * distribution and use acknowledge that the software was developed
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * by Carnegie Mellon University.  The name of the
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * University may not be used to endorse or promote products derived
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * from this software without specific prior written permission.
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lwip/opt.h"
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "ppp.h"
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "pppdebug.h"
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "auth.h"
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "fsm.h"
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "vj.h"
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "ipcp.h"
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lwip/inet.h"
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* global vars */
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_options ipcp_wantoptions[NUM_PPP];  /* Options that we want to request */
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_options ipcp_gotoptions[NUM_PPP];   /* Options that peer ack'd */
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_options ipcp_hisoptions[NUM_PPP];   /* Options that we ack'd */
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* local vars */
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int default_route_set[NUM_PPP]; /* Have set up a default route */
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int cis_received[NUM_PPP];      /* # Conf-Reqs received */
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Callbacks for fsm code.  (CI = Configuration Information)
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_resetci (fsm *);                     /* Reset our CI */
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int  ipcp_cilen (fsm *);                       /* Return length of our CI */
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_addci (fsm *, u_char *, int *);      /* Add our CI */
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int  ipcp_ackci (fsm *, u_char *, int);        /* Peer ack'd our CI */
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int  ipcp_nakci (fsm *, u_char *, int);        /* Peer nak'd our CI */
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int  ipcp_rejci (fsm *, u_char *, int);        /* Peer rej'd our CI */
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int  ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_up (fsm *);                          /* We're UP */
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_down (fsm *);                        /* We're DOWN */
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if PPP_ADDITIONAL_CALLBACKS
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_script (fsm *, char *); /* Run an up/down script */
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_finished (fsm *);                    /* Don't need lower layer */
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_resetci,  /* Reset our Configuration Information */
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_cilen,    /* Length of our Configuration Information */
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_addci,    /* Add our Configuration Information */
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_ackci,    /* ACK our Configuration Information */
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_nakci,    /* NAK our Configuration Information */
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_rejci,    /* Reject our Configuration Information */
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_reqci,    /* Request peer's Configuration Information */
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_up,       /* Called when fsm reaches LS_OPENED state */
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_down,     /* Called when fsm leaves LS_OPENED state */
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NULL,          /* Called when we want the lower layer up */
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_finished, /* Called when we want the lower layer down */
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NULL,          /* Called when Protocol-Reject received */
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NULL,          /* Retransmission is necessary */
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NULL,          /* Called to handle protocol-specific codes */
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  "IPCP"         /* String name of protocol */
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Protocol entry points from main code.
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_init (int);
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_open (int);
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_close (int, char *);
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_lowerup (int);
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_lowerdown (int);
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_input (int, u_char *, int);
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_protrej (int);
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct protent ipcp_protent = {
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  PPP_IPCP,
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_init,
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_input,
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_protrej,
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_lowerup,
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_lowerdown,
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_open,
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_close,
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if PPP_ADDITIONAL_CALLBACKS
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_printpkt,
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NULL,
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PPP_ADDITIONAL_CALLBACKS */
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  1,
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  "IPCP",
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if PPP_ADDITIONAL_CALLBACKS
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ip_check_options,
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NULL,
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ip_active_pkt
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PPP_ADDITIONAL_CALLBACKS */
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ipcp_clear_addrs (int);
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Lengths of configuration options.
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define CILEN_VOID     2
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define CILEN_COMPRESS 4  /* min length for compression protocol opt. */
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define CILEN_VJ       6  /* length for RFC1332 Van-Jacobson opt. */
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define CILEN_ADDR     6  /* new-style single address option */
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define CILEN_ADDRS    10 /* old-style dual address option */
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     (x) == CONFNAK ? "NAK" : "REJ")
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_init - Initialize IPCP.
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_init(int unit)
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm           *f = &ipcp_fsm[unit];
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *wo = &ipcp_wantoptions[unit];
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *ao = &ipcp_allowoptions[unit];
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  f->unit      = unit;
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  f->protocol  = PPP_IPCP;
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  f->callbacks = &ipcp_callbacks;
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm_init(&ipcp_fsm[unit]);
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  memset(wo, 0, sizeof(*wo));
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  memset(ao, 0, sizeof(*ao));
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->neg_addr      = 1;
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->ouraddr       = 0;
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if VJ_SUPPORT
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->neg_vj        = 1;
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else  /* VJ_SUPPORT */
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->neg_vj        = 0;
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* VJ_SUPPORT */
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->vj_protocol   = IPCP_VJ_COMP;
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->maxslotindex  = MAX_SLOTS - 1;
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->cflag         = 0;
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->default_route = 1;
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ao->neg_addr      = 1;
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if VJ_SUPPORT
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ao->neg_vj        = 1;
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else  /* VJ_SUPPORT */
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ao->neg_vj        = 0;
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* VJ_SUPPORT */
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ao->maxslotindex  = MAX_SLOTS - 1;
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ao->cflag         = 1;
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ao->default_route = 1;
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_open - IPCP is allowed to come up.
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_open(int unit)
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm_open(&ipcp_fsm[unit]);
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_close - Take IPCP down.
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_close(int unit, char *reason)
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm_close(&ipcp_fsm[unit], reason);
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_lowerup - The lower layer is up.
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_lowerup(int unit)
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm_lowerup(&ipcp_fsm[unit]);
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_lowerdown - The lower layer is down.
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_lowerdown(int unit)
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm_lowerdown(&ipcp_fsm[unit]);
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_input - Input IPCP packet.
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_input(int unit, u_char *p, int len)
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm_input(&ipcp_fsm[unit], p, len);
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_protrej - A Protocol-Reject was received for IPCP.
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Pretend the lower layer went down, so we shut up.
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_protrej(int unit)
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  fsm_lowerdown(&ipcp_fsm[unit]);
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_resetci - Reset our CI.
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_resetci(fsm *f)
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *wo = &ipcp_wantoptions[f->unit];
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (wo->ouraddr == 0) {
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    wo->accept_local = 1;
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (wo->hisaddr == 0) {
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    wo->accept_remote = 1;
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* Request DNS addresses from the peer */
29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->req_dns1 = ppp_settings.usepeerdns;
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  wo->req_dns2 = ppp_settings.usepeerdns;
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_gotoptions[f->unit] = *wo;
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  cis_received[f->unit] = 0;
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_cilen - Return length of our CI.
30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int
30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_cilen(fsm *f)
30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *go = &ipcp_gotoptions[f->unit];
30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *wo = &ipcp_wantoptions[f->unit];
30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *ho = &ipcp_hisoptions[f->unit];
30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LENCIVJ(neg, old)   (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LENCIDNS(neg)       (neg ? (CILEN_ADDR) : 0)
31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * First see if we want to change our options to the old
31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * forms because we have received old forms from the peer.
31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* use the old style of address negotiation */
31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    go->neg_addr = 1;
32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    go->old_addrs = 1;
32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* try an older style of VJ negotiation */
32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cis_received[f->unit] == 0) {
32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* keep trying the new style until we see some CI from the peer */
32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      go->neg_vj = 1;
32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else {
32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* use the old style only if the peer did */
32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (ho->neg_vj && ho->old_vj) {
33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        go->neg_vj = 1;
33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        go->old_vj = 1;
33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        go->vj_protocol = ho->vj_protocol;
33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return (LENCIADDR(go->neg_addr, go->old_addrs) +
33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          LENCIVJ(go->neg_vj, go->old_vj) +
33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          LENCIDNS(go->req_dns1) +
34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          LENCIDNS(go->req_dns2));
34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_addci - Add our desired CIs to a packet.
34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_addci(fsm *f, u_char *ucp, int *lenp)
34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *go = &ipcp_gotoptions[f->unit];
35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int len = *lenp;
35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (neg) { \
35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (len >= vjlen) { \
35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTCHAR(opt, ucp); \
35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTCHAR(vjlen, ucp); \
35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTSHORT(val, ucp); \
36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (!old) { \
36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        PUTCHAR(maxslotindex, ucp); \
36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        PUTCHAR(cflag, ucp); \
36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len -= vjlen; \
36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else { \
36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      neg = 0; \
36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define ADDCIADDR(opt, neg, old, val1, val2) \
37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (neg) { \
37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (len >= addrlen) { \
37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      u32_t l; \
37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTCHAR(opt, ucp); \
37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTCHAR(addrlen, ucp); \
37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      l = ntohl(val1); \
37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTLONG(l, ucp); \
37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (old) { \
38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        l = ntohl(val2); \
38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        PUTLONG(l, ucp); \
38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len -= addrlen; \
38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else { \
38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      neg = 0; \
38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define ADDCIDNS(opt, neg, addr) \
39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (neg) { \
39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (len >= CILEN_ADDR) { \
39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      u32_t l; \
39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTCHAR(opt, ucp); \
39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTCHAR(CILEN_ADDR, ucp); \
39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      l = ntohl(addr); \
39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      PUTLONG(l, ucp); \
39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len -= CILEN_ADDR; \
39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else { \
39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      neg = 0; \
40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      go->old_addrs, go->ouraddr, go->hisaddr);
40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      go->maxslotindex, go->cflag);
40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  *lenp -= len;
41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_ackci - Ack our CIs.
41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns:
42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  0 - Ack was bad.
42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  1 - Ack was good.
42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int
42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_ackci(fsm *f, u_char *p, int len)
42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *go = &ipcp_gotoptions[f->unit];
42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_short cilen, citype, cishort;
42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t cilong;
43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char cimaxslotindex, cicflag;
43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * CIs must be in exactly the same order that we sent...
43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Check packet length and CI length at each step.
43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * If we find any deviations, then this packet is bad.
43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (neg) { \
44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if ((len -= vjlen) < 0) { \
44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(citype, p); \
44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(cilen, p); \
44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cilen != vjlen || \
44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        citype != opt) { \
44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETSHORT(cishort, p); \
45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cishort != val) { \
45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!old) { \
45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETCHAR(cimaxslotindex, p); \
45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (cimaxslotindex != maxslotindex) { \
45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto bad; \
45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETCHAR(cicflag, p); \
46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (cicflag != cflag) { \
46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto bad; \
46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define ACKCIADDR(opt, neg, old, val1, val2) \
46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (neg) { \
46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32_t l; \
47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if ((len -= addrlen) < 0) { \
47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(citype, p); \
47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(cilen, p); \
47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cilen != addrlen || \
47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        citype != opt) { \
47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETLONG(l, p); \
48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cilong = htonl(l); \
48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (val1 != cilong) { \
48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (old) { \
48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETLONG(l, p); \
48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      cilong = htonl(l); \
48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (val2 != cilong) { \
48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto bad; \
48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define ACKCIDNS(opt, neg, addr) \
49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (neg) { \
49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32_t l; \
49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if ((len -= CILEN_ADDR) < 0) { \
49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(citype, p); \
50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(cilen, p); \
50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cilen != CILEN_ADDR || \
50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        citype != opt) { \
50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETLONG(l, p); \
50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cilong = htonl(l); \
50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (addr != cilong) { \
50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        go->old_addrs, go->ouraddr, go->hisaddr);
51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      go->maxslotindex, go->cflag);
51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * If there are any remaining CIs, then this packet is bad.
52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (len != 0) {
52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    goto bad;
52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return (1);
52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbad:
53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n"));
53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return (0);
53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_nakci - Peer has sent a NAK for some of our CIs.
53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This should not modify any state if the Nak is bad
53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * or if IPCP is in the LS_OPENED state.
53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns:
54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  0 - Nak was bad.
54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  1 - Nak was good.
54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int
54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_nakci(fsm *f, u_char *p, int len)
54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *go = &ipcp_gotoptions[f->unit];
54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char cimaxslotindex, cicflag;
54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char citype, cilen, *next;
55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_short cishort;
55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t ciaddr1, ciaddr2, l, cidnsaddr;
55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options no;    /* options we've seen Naks for */
55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options try;    /* options to request next time */
55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  BZERO(&no, sizeof(no));
55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  try = *go;
55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Any Nak'd CIs must be in exactly the same order that we sent.
56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Check packet length and CI length at each step.
56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * If we find any deviations, then this packet is bad.
56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define NAKCIADDR(opt, neg, old, code) \
56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->neg && \
56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[1] == cilen && \
56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[0] == opt) { \
56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    len -= cilen; \
56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    INCPTR(2, p); \
57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETLONG(l, p); \
57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ciaddr1 = htonl(l); \
57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (old) { \
57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETLONG(l, p); \
57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ciaddr2 = htonl(l); \
57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      no.old_addrs = 1; \
57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else { \
57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ciaddr2 = 0; \
57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    no.neg = 1; \
58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    code \
58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define NAKCIVJ(opt, neg, code) \
58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->neg && \
58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len >= cilen && \
58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[0] == opt) { \
58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    len -= cilen; \
58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    INCPTR(2, p); \
59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETSHORT(cishort, p); \
59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    no.neg = 1; \
59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    code \
59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define NAKCIDNS(opt, neg, code) \
59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->neg && \
59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((cilen = p[1]) == CILEN_ADDR) && \
59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len >= cilen && \
59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[0] == opt) { \
60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    len -= cilen; \
60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    INCPTR(2, p); \
60276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETLONG(l, p); \
60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cidnsaddr = htonl(l); \
60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    no.neg = 1; \
60576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    code \
60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Accept the peer's idea of {our,his} address, if different
61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * from our idea, only if the accept_{local,remote} flag is set.
61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (go->accept_local && ciaddr1) { /* Do we know our address? */
61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      try.ouraddr = ciaddr1;
61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      IPCPDEBUG(LOG_INFO, ("local IP address %s\n",
61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           inet_ntoa(ciaddr1)));
61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (go->accept_remote && ciaddr2) { /* Does he know his? */
61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      try.hisaddr = ciaddr2;
62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      IPCPDEBUG(LOG_INFO, ("remote IP address %s\n",
62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           inet_ntoa(ciaddr2)));
62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  );
62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Accept the peer's value of maxslotindex provided that it
62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * is less than what we asked for.  Turn off slot-ID compression
62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * if the peer wants.  Send old-style compress-type option if
62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * the peer wants.
63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cilen == CILEN_VJ) {
63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETCHAR(cimaxslotindex, p);
63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETCHAR(cicflag, p);
63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (cishort == IPCP_VJ_COMP) {
63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.old_vj = 0;
63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (cimaxslotindex < go->maxslotindex) {
63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          try.maxslotindex = cimaxslotindex;
63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (!cicflag) {
64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          try.cflag = 0;
64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } else {
64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.neg_vj = 0;
64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else {
64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.old_vj = 1;
64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.vj_protocol = cishort;
65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } else {
65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.neg_vj = 0;
65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  );
65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NAKCIDNS(CI_MS_DNS1, req_dns1,
65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      try.dnsaddr[0] = cidnsaddr;
65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr)));
65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      );
66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  NAKCIDNS(CI_MS_DNS2, req_dns2,
66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      try.dnsaddr[1] = cidnsaddr;
66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      );
66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  * There may be remaining CIs, if the peer is requesting negotiation
66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  * on an option that we didn't include in our request packet.
66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  * If they want to negotiate about IP addresses, we comply.
67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  * If they want us to ask for compression, we refuse.
67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  */
67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  while (len > CILEN_VOID) {
67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(citype, p);
67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(cilen, p);
67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if( (len -= cilen) < 0 ) {
67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad;
67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    next = p + cilen - 2;
67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    switch (citype) {
68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_COMPRESSTYPE:
68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (go->neg_vj || no.neg_vj ||
68376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
68476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          goto bad;
68576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
68676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        no.neg_vj = 1;
68776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
68876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_ADDRS:
68976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if ((go->neg_addr && go->old_addrs) || no.old_addrs
69076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            || cilen != CILEN_ADDRS) {
69176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          goto bad;
69276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
69376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.neg_addr = 1;
69476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.old_addrs = 1;
69576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(l, p);
69676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ciaddr1 = htonl(l);
69776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ciaddr1 && go->accept_local) {
69876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          try.ouraddr = ciaddr1;
69976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
70076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(l, p);
70176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ciaddr2 = htonl(l);
70276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ciaddr2 && go->accept_remote) {
70376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          try.hisaddr = ciaddr2;
70476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
70576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        no.old_addrs = 1;
70676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
70776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_ADDR:
70876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) {
70976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          goto bad;
71076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
71176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        try.old_addrs = 0;
71276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(l, p);
71376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ciaddr1 = htonl(l);
71476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ciaddr1 && go->accept_local) {
71576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          try.ouraddr = ciaddr1;
71676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
71776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (try.ouraddr != 0) {
71876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          try.neg_addr = 1;
71976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
72076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        no.neg_addr = 1;
72176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
72276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
72376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    p = next;
72476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
72576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
72676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* If there is still anything left, this packet is bad. */
72776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (len != 0) {
72876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    goto bad;
72976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
73076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
73176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
73276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * OK, the Nak is good.  Now we can update state.
73376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
73476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (f->state != LS_OPENED) {
73576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    *go = try;
73676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
73776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
73876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
73976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
74076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbad:
74176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n"));
74276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 0;
74376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
74476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
74576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
74676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
74776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_rejci - Reject some of our CIs.
74876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
74976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int
75076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_rejci(fsm *f, u_char *p, int len)
75176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
75276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *go = &ipcp_gotoptions[f->unit];
75376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char cimaxslotindex, ciflag, cilen;
75476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_short cishort;
75576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t cilong;
75676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options try;    /* options to request next time */
75776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
75876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  try = *go;
75976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
76076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Any Rejected CIs must be in exactly the same order that we sent.
76176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Check packet length and CI length at each step.
76276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * If we find any deviations, then this packet is bad.
76376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
76476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define REJCIADDR(opt, neg, old, val1, val2) \
76576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->neg && \
76676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
76776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[1] == cilen && \
76876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[0] == opt) { \
76976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32_t l; \
77076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    len -= cilen; \
77176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    INCPTR(2, p); \
77276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETLONG(l, p); \
77376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cilong = htonl(l); \
77476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Check rejected value. */ \
77576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cilong != val1) { \
77676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
77776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
77876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (old) { \
77976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETLONG(l, p); \
78076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      cilong = htonl(l); \
78176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* Check rejected value. */ \
78276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (cilong != val2) { \
78376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto bad; \
78476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
78576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
78676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    try.neg = 0; \
78776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
78876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
78976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
79076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->neg && \
79176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
79276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len >= p[1] && \
79376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[0] == opt) { \
79476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    len -= p[1]; \
79576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    INCPTR(2, p); \
79676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETSHORT(cishort, p); \
79776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Check rejected value. */  \
79876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cishort != val) { \
79976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
80076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
80176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!old) { \
80276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETCHAR(cimaxslotindex, p); \
80376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (cimaxslotindex != maxslot) { \
80476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto bad; \
80576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
80676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      GETCHAR(ciflag, p); \
80776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (ciflag != cflag) { \
80876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto bad; \
80976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } \
81076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
81176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    try.neg = 0; \
81276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
81376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
81476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define REJCIDNS(opt, neg, dnsaddr) \
81576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->neg && \
81676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ((cilen = p[1]) == CILEN_ADDR) && \
81776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      len >= cilen && \
81876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      p[0] == opt) { \
81976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32_t l; \
82076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    len -= cilen; \
82176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    INCPTR(2, p); \
82276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETLONG(l, p); \
82376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cilong = htonl(l); \
82476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Check rejected value. */ \
82576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (cilong != dnsaddr) { \
82676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto bad; \
82776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } \
82876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    try.neg = 0; \
82976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
83076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
83276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        go->old_addrs, go->ouraddr, go->hisaddr);
83376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
83576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      go->maxslotindex, go->cflag);
83676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
83876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
84076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
84176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
84276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * If there are any remaining CIs, then this packet is bad.
84376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
84476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (len != 0) {
84576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    goto bad;
84676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
84776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
84876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Now we can update state.
84976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
85076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (f->state != LS_OPENED) {
85176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    *go = try;
85276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
85376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
85476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
85576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbad:
85676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n"));
85776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 0;
85876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
85976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
86076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
86176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
86276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
86376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
86476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
86576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * appropriately.  If reject_if_disagree is non-zero, doesn't return
86676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * CONFNAK; returns CONFREJ if it can't return CONFACK.
86776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
86876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int
86976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree)
87076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
87176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *wo = &ipcp_wantoptions[f->unit];
87276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *ho = &ipcp_hisoptions[f->unit];
87376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *ao = &ipcp_allowoptions[f->unit];
87476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef OLD_CI_ADDRS
87576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *go = &ipcp_gotoptions[f->unit];
87676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
87776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char *cip, *next;     /* Pointer to current and next CIs */
87876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_short cilen, citype;  /* Parsed len, type */
87976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_short cishort;        /* Parsed short value */
88076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t tl, ciaddr1;      /* Parsed address values */
88176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef OLD_CI_ADDRS
88276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t ciaddr2;          /* Parsed address values */
88376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
88476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int rc = CONFACK;       /* Final packet return code */
88576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int orc;                /* Individual option return code */
88676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char *p;              /* Pointer to next char to parse */
88776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char *ucp = inp;      /* Pointer to current output char */
88876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int l = *len;           /* Length left */
88976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char maxslotindex, cflag;
89076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int d;
89176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
89276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  cis_received[f->unit] = 1;
89376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
89476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
89576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Reset all his options.
89676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
89776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  BZERO(ho, sizeof(*ho));
89876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
89976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
90076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Process all his options.
90176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
90276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  next = inp;
90376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  while (l) {
90476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    orc = CONFACK;       /* Assume success */
90576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cip = p = next;      /* Remember begining of CI */
90676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (l < 2 ||         /* Not enough data for CI header or */
90776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        p[1] < 2 ||      /*  CI length too small or */
90876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        p[1] > l) {      /*  CI length too big? */
90976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n"));
91076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      orc = CONFREJ;     /* Reject bad CI */
91176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      cilen = (u_short)l;/* Reject till end of packet */
91276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      l = 0;             /* Don't loop again */
91376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      goto endswitch;
91476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
91576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(citype, p);  /* Parse CI type */
91676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    GETCHAR(cilen, p);   /* Parse CI length */
91776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    l -= cilen;          /* Adjust remaining length */
91876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    next += cilen;       /* Step to next CI */
91976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
92076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    switch (citype) {      /* Check CI type */
92176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef OLD_CI_ADDRS /* Need to save space... */
92276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_ADDRS:
92376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n"));
92476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (!ao->neg_addr ||
92576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            cilen != CILEN_ADDRS) {  /* Check CI length */
92676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;    /* Reject CI */
92776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
92876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
92976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
93076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /*
93176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * If he has no address, or if we both have his address but
93276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * disagree about it, then NAK it with our idea.
93376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * In particular, if we don't know his address, but he does,
93476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * then accept it.
93576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         */
93676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(tl, p);    /* Parse source address (his) */
93776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ciaddr1 = htonl(tl);
93876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1)));
93976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ciaddr1 != wo->hisaddr
94076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            && (ciaddr1 == 0 || !wo->accept_remote)) {
94176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFNAK;
94276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (!reject_if_disagree) {
94376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            DECPTR(sizeof(u32_t), p);
94476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            tl = ntohl(wo->hisaddr);
94576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            PUTLONG(tl, p);
94676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          }
94776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
94876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          /*
94976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           * If neither we nor he knows his address, reject the option.
95076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           */
95176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;
95276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
95376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
95476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
95576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
95676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /*
95776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * If he doesn't know our address, or if we both have our address
95876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * but disagree about it, then NAK it with our idea.
95976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         */
96076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(tl, p);    /* Parse desination address (ours) */
96176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ciaddr2 = htonl(tl);
96276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2)));
96376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ciaddr2 != wo->ouraddr) {
96476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (ciaddr2 == 0 || !wo->accept_local) {
96576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            orc = CONFNAK;
96676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (!reject_if_disagree) {
96776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              DECPTR(sizeof(u32_t), p);
96876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              tl = ntohl(wo->ouraddr);
96976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              PUTLONG(tl, p);
97076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
97176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          } else {
97276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            go->ouraddr = ciaddr2;  /* accept peer's idea */
97376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          }
97476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
97576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
97676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->neg_addr = 1;
97776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->old_addrs = 1;
97876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->hisaddr = ciaddr1;
97976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->ouraddr = ciaddr2;
98076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
98176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
98276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
98376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_ADDR:
98476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (!ao->neg_addr) {
98576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n"));
98676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;        /* Reject CI */
98776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
98876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else if (cilen != CILEN_ADDR) {  /* Check CI length */
98976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n"));
99076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;        /* Reject CI */
99176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
99276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
99376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
99476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /*
99576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * If he has no address, or if we both have his address but
99676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * disagree about it, then NAK it with our idea.
99776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * In particular, if we don't know his address, but he does,
99876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         * then accept it.
99976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         */
100076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(tl, p);  /* Parse source address (his) */
100176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ciaddr1 = htonl(tl);
100276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ciaddr1 != wo->hisaddr
100376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            && (ciaddr1 == 0 || !wo->accept_remote)) {
100476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFNAK;
100576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (!reject_if_disagree) {
100676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            DECPTR(sizeof(u32_t), p);
100776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            tl = ntohl(wo->hisaddr);
100876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            PUTLONG(tl, p);
100976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          }
101076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
101176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
101276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          /*
101376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           * Don't ACK an address of 0.0.0.0 - reject it instead.
101476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           */
101576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
101676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;
101776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
101876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
101976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
102076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
102176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->neg_addr = 1;
102276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->hisaddr = ciaddr1;
102376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
102476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
102576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
102676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_MS_DNS1:
102776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_MS_DNS2:
102876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* Microsoft primary or secondary DNS request */
102976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        d = citype == CI_MS_DNS2;
103076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
103176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* If we do not have a DNS address then we cannot send it */
103276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ao->dnsaddr[d] == 0 ||
103376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            cilen != CILEN_ADDR) {  /* Check CI length */
103476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1));
103576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;        /* Reject CI */
103676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
103776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
103876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(tl, p);
103976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (htonl(tl) != ao->dnsaddr[d]) {
104076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n",
104176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                d+1, inet_ntoa(tl)));
104276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          DECPTR(sizeof(u32_t), p);
104376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          tl = ntohl(ao->dnsaddr[d]);
104476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PUTLONG(tl, p);
104576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFNAK;
104676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
104776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1));
104876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
104976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
105076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_MS_WINS1:
105176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_MS_WINS2:
105276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* Microsoft primary or secondary WINS request */
105376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        d = citype == CI_MS_WINS2;
105476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1));
105576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
105676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* If we do not have a DNS address then we cannot send it */
105776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (ao->winsaddr[d] == 0 ||
105876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          cilen != CILEN_ADDR) {  /* Check CI length */
105976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;      /* Reject CI */
106076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
106176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
106276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETLONG(tl, p);
106376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (htonl(tl) != ao->winsaddr[d]) {
106476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          DECPTR(sizeof(u32_t), p);
106576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          tl = ntohl(ao->winsaddr[d]);
106676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          PUTLONG(tl, p);
106776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFNAK;
106876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
106976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
107076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
107176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      case CI_COMPRESSTYPE:
107276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (!ao->neg_vj) {
107376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
107476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;
107576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
107676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
107776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
107876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;
107976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
108076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
108176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        GETSHORT(cishort, p);
108276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
108376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (!(cishort == IPCP_VJ_COMP ||
108476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
108576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
108676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          orc = CONFREJ;
108776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          break;
108876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
108976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
109076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->neg_vj = 1;
109176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ho->vj_protocol = cishort;
109276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (cilen == CILEN_VJ) {
109376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          GETCHAR(maxslotindex, p);
109476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (maxslotindex > ao->maxslotindex) {
109576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
109676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            orc = CONFNAK;
109776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (!reject_if_disagree) {
109876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              DECPTR(1, p);
109976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              PUTCHAR(ao->maxslotindex, p);
110076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
110176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          }
110276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          GETCHAR(cflag, p);
110376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          if (cflag && !ao->cflag) {
110476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag));
110576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            orc = CONFNAK;
110676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (!reject_if_disagree) {
110776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              DECPTR(1, p);
110876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              PUTCHAR(wo->cflag, p);
110976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
111076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          }
111176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          ho->maxslotindex = maxslotindex;
111276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          ho->cflag = cflag;
111376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else {
111476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          ho->old_vj = 1;
111576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          ho->maxslotindex = MAX_SLOTS - 1;
111676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          ho->cflag = 1;
111776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
111876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, (
111976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",
112076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman              ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
112176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
112276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
112376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      default:
112476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype));
112576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        orc = CONFREJ;
112676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
112776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
112876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
112976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanendswitch:
113076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (orc == CONFACK &&    /* Good CI */
113176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        rc != CONFACK) {     /*  but prior CI wasnt? */
113276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      continue;              /* Don't send this one */
113376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
113476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
113576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (orc == CONFNAK) {    /* Nak this CI? */
113676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (reject_if_disagree) {  /* Getting fed up with sending NAKs? */
113776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n"));
113876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        orc = CONFREJ;       /* Get tough if so */
113976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } else {
114076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (rc == CONFREJ) { /* Rejecting prior CI? */
114176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          continue;          /* Don't send this one */
114276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
114376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (rc == CONFACK) { /* Ack'd all prior CIs? */
114476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          rc = CONFNAK;      /* Not anymore... */
114576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          ucp = inp;         /* Backup */
114676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
114776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
114876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
114976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
115076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (orc == CONFREJ &&    /* Reject this CI */
115176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        rc != CONFREJ) {  /*  but no prior ones? */
115276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      rc = CONFREJ;
115376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ucp = inp;        /* Backup */
115476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
115576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
115676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Need to move CI? */
115776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (ucp != cip) {
115876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      BCOPY(cip, ucp, cilen);  /* Move it */
115976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
116076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
116176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Update output pointer */
116276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    INCPTR(cilen, ucp);
116376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
116476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
116576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
116676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * If we aren't rejecting this packet, and we want to negotiate
116776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * their address, and they didn't send their address, then we
116876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * send a NAK with a CI_ADDR option appended.  We assume the
116976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * input buffer is long enough that we can append the extra
117076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * option safely.
117176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
117276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (rc != CONFREJ && !ho->neg_addr &&
117376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      wo->req_addr && !reject_if_disagree) {
117476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n"));
117576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (rc == CONFACK) {
117676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      rc = CONFNAK;
117776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      ucp = inp;        /* reset pointer */
117876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      wo->req_addr = 0;    /* don't ask again */
117976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
118076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PUTCHAR(CI_ADDR, ucp);
118176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PUTCHAR(CILEN_ADDR, ucp);
118276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    tl = ntohl(wo->hisaddr);
118376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PUTLONG(tl, ucp);
118476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
118576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
118676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  *len = (int)(ucp - inp);    /* Compute output length */
118776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
118876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return (rc);      /* Return final code */
118976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
119076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
119176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
119276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0
119376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
119476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ip_check_options - check that any IP-related options are OK,
119576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and assign appropriate defaults.
119676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
119776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
119876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanip_check_options(u_long localAddr)
119976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
120076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *wo = &ipcp_wantoptions[0];
120176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
120276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
120376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Load our default IP address but allow the remote host to give us
120476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * a new address.
120576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
120676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) {
120776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    wo->accept_local = 1;  /* don't insist on this default value */
120876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    wo->ouraddr = htonl(localAddr);
120976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
121076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
121176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
121276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
121376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
121476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
121576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_up - IPCP has come UP.
121676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
121776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Configure the IP network interface appropriately and bring it up.
121876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
121976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
122076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_up(fsm *f)
122176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
122276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t mask;
122376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *ho = &ipcp_hisoptions[f->unit];
122476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *go = &ipcp_gotoptions[f->unit];
122576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_options *wo = &ipcp_wantoptions[f->unit];
122676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
122776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  np_up(f->unit, PPP_IP);
122876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_INFO, ("ipcp: up\n"));
122976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
123076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
123176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * We must have a non-zero IP address for both ends of the link.
123276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
123376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!ho->neg_addr) {
123476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ho->hisaddr = wo->hisaddr;
123576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
123676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
123776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (ho->hisaddr == 0) {
123876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n"));
123976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ipcp_close(f->unit, "Could not determine remote IP address");
124076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
124176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
124276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->ouraddr == 0) {
124376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n"));
124476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ipcp_close(f->unit, "Could not determine local IP address");
124576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
124676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
124776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
124876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
124976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/
125076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
125176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
125276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
125376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Check that the peer is allowed to use the IP address it wants.
125476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
125576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!auth_ip_addr(f->unit, ho->hisaddr)) {
125676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n",
125776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        inet_ntoa(ho->hisaddr)));
125876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ipcp_close(f->unit, "Unauthorized remote IP address");
125976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
126076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
126176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
126276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* set tcp compression */
126376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
126476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
126576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
126676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Set IP addresses and (if specified) netmask.
126776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
126876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  mask = GetMask(go->ouraddr);
126976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
127076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {
127176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n"));
127276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ipcp_close(f->unit, "Interface configuration failed");
127376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
127476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
127576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
127676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* bring the interface up for IP */
127776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!sifup(f->unit)) {
127876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_WARNING, ("sifup failed\n"));
127976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ipcp_close(f->unit, "Interface configuration failed");
128076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
128176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
128276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
128376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
128476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
128576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* assign a default route through the interface if required */
128676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (ipcp_wantoptions[f->unit].default_route) {
128776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) {
128876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      default_route_set[f->unit] = 1;
128976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
129076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
129176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
129276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_NOTICE, ("local  IP address %s\n", inet_ntoa(go->ouraddr)));
129376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr)));
129476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->dnsaddr[0]) {
129576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_NOTICE, ("primary   DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
129676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
129776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (go->dnsaddr[1]) {
129876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
129976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
130076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
130176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
130276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
130376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
130476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_down - IPCP has gone DOWN.
130576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
130676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Take the IP network interface down, clear its addresses
130776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and delete routes through it.
130876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
130976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
131076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_down(fsm *f)
131176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
131276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  IPCPDEBUG(LOG_INFO, ("ipcp: down\n"));
131376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  np_down(f->unit, PPP_IP);
131476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  sifvjcomp(f->unit, 0, 0, 0);
131576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
131676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  sifdown(f->unit);
131776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ipcp_clear_addrs(f->unit);
131876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
131976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
132076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
132176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
132276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_clear_addrs() - clear the interface addresses, routes, etc.
132376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
132476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
132576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_clear_addrs(int unit)
132676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
132776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t ouraddr, hisaddr;
132876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
132976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ouraddr = ipcp_gotoptions[unit].ouraddr;
133076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  hisaddr = ipcp_hisoptions[unit].hisaddr;
133176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (default_route_set[unit]) {
133276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cifdefaultroute(unit, ouraddr, hisaddr);
133376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    default_route_set[unit] = 0;
133476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
133576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  cifaddr(unit, ouraddr, hisaddr);
133676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
133776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
133876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
133976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
134076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ipcp_finished - possibly shut down the lower layers.
134176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
134276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void
134376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_finished(fsm *f)
134476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
134576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  np_finished(f->unit, PPP_IP);
134676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
134776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
134876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if PPP_ADDITIONAL_CALLBACKS
134976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int
135076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
135176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
135276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  LWIP_UNUSED_ARG(p);
135376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  LWIP_UNUSED_ARG(plen);
135476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  LWIP_UNUSED_ARG(printer);
135576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  LWIP_UNUSED_ARG(arg);
135676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 0;
135776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
135876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
135976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
136076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ip_active_pkt - see if this IP packet is worth bringing the link up for.
136176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We don't bring the link up for IP fragments or for TCP FIN packets
136276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * with no data.
136376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
136476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define IP_HDRLEN   20  /* bytes */
136576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define IP_OFFMASK  0x1fff
136676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define IPPROTO_TCP 6
136776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TCP_HDRLEN  20
136876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TH_FIN      0x01
136976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
137076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
137176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We use these macros because the IP header may be at an odd address,
137276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and some compilers might use word loads to get th_off or ip_hl.
137376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
137476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
137576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define net_short(x)    (((x)[0] << 8) + (x)[1])
137676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define get_iphl(x)     (((unsigned char *)(x))[0] & 0xF)
137776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define get_ipoff(x)    net_short((unsigned char *)(x) + 6)
137876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define get_ipproto(x)  (((unsigned char *)(x))[9])
137976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define get_tcpoff(x)   (((unsigned char *)(x))[12] >> 4)
138076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define get_tcpflags(x) (((unsigned char *)(x))[13])
138176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
138276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int
138376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanip_active_pkt(u_char *pkt, int len)
138476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
138576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u_char *tcp;
138676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int hlen;
138776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
138876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  len -= PPP_HDRLEN;
138976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  pkt += PPP_HDRLEN;
139076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (len < IP_HDRLEN) {
139176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
139276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
139376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
139476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
139576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
139676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (get_ipproto(pkt) != IPPROTO_TCP) {
139776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 1;
139876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
139976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  hlen = get_iphl(pkt) * 4;
140076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (len < hlen + TCP_HDRLEN) {
140176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
140276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
140376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  tcp = pkt + hlen;
140476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) {
140576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
140676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
140776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
140876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
140976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PPP_ADDITIONAL_CALLBACKS */
141076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
141176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PPP_SUPPORT */
1412