?? ipcp.c
字號:
/*****************************************************************************
* ipcp.c - Network PPP IP Control Protocol program file.
*
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
* portions Copyright (c) 1997 by Global Election Systems Inc.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY
*
* 03-01-01 Marc Boucher <marc@mbsi.ca>
* Ported to lwIP.
* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
* Original.
*****************************************************************************/
/*
* ipcp.c - PPP IP Control Protocol.
*
* Copyright (c) 1989 Carnegie Mellon University.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Carnegie Mellon University. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "pppconf.h"
#if PPP_SUPPORT > 0
#include "ppp.h"
#include "auth.h"
#include "fsm.h"
#include "vj.h"
#include "ipcp.h"
#include "pppdebug.h"
/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */
/*
* Lengths of configuration options.
*/
#define CILEN_VOID 2
#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
#define CILEN_ADDR 6 /* new-style single address option */
#define CILEN_ADDRS 10 /* old-style dual address option */
/***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
/*
* Callbacks for fsm code. (CI = Configuration Information)
*/
static void ipcp_resetci (fsm *); /* Reset our CI */
static int ipcp_cilen (fsm *); /* Return length of our CI */
static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */
static int ipcp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */
static int ipcp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */
static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */
static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
static void ipcp_up (fsm *); /* We're UP */
static void ipcp_down (fsm *); /* We're DOWN */
#if 0
static void ipcp_script (fsm *, char *); /* Run an up/down script */
#endif
static void ipcp_finished (fsm *); /* Don't need lower layer */
/*
* Protocol entry points from main code.
*/
static void ipcp_init (int);
static void ipcp_open (int);
static void ipcp_close (int, char *);
static void ipcp_lowerup (int);
static void ipcp_lowerdown (int);
static void ipcp_input (int, u_char *, int);
static void ipcp_protrej (int);
static void ipcp_clear_addrs (int);
#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
(x) == CONFNAK ? "NAK" : "REJ")
/******************************/
/*** PUBLIC DATA STRUCTURES ***/
/******************************/
/* global vars */
ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
struct protent ipcp_protent = {
PPP_IPCP,
ipcp_init,
ipcp_input,
ipcp_protrej,
ipcp_lowerup,
ipcp_lowerdown,
ipcp_open,
ipcp_close,
#if 0
ipcp_printpkt,
NULL,
#endif
1,
"IPCP",
#if 0
ip_check_options,
NULL,
ip_active_pkt
#endif
};
/*****************************/
/*** LOCAL DATA STRUCTURES ***/
/*****************************/
/* local vars */
static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
static int default_route_set[NUM_PPP]; /* Have set up a default route */
static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
ipcp_resetci, /* Reset our Configuration Information */
ipcp_cilen, /* Length of our Configuration Information */
ipcp_addci, /* Add our Configuration Information */
ipcp_ackci, /* ACK our Configuration Information */
ipcp_nakci, /* NAK our Configuration Information */
ipcp_rejci, /* Reject our Configuration Information */
ipcp_reqci, /* Request peer's Configuration Information */
ipcp_up, /* Called when fsm reaches OPENED state */
ipcp_down, /* Called when fsm leaves OPENED state */
NULL, /* Called when we want the lower layer up */
ipcp_finished, /* Called when we want the lower layer down */
NULL, /* Called when Protocol-Reject received */
NULL, /* Retransmission is necessary */
NULL, /* Called to handle protocol-specific codes */
"IPCP" /* String name of protocol */
};
/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
/*
* ipcp_init - Initialize IPCP.
*/
static void ipcp_init(int unit)
{
fsm *f = &ipcp_fsm[unit];
ipcp_options *wo = &ipcp_wantoptions[unit];
ipcp_options *ao = &ipcp_allowoptions[unit];
f->unit = unit;
f->protocol = PPP_IPCP;
f->callbacks = &ipcp_callbacks;
fsm_init(&ipcp_fsm[unit]);
memset(wo, 0, sizeof(*wo));
memset(ao, 0, sizeof(*ao));
wo->neg_addr = 1;
wo->ouraddr = 0;
#if VJ_SUPPORT > 0
wo->neg_vj = 1;
#else
wo->neg_vj = 0;
#endif
wo->vj_protocol = IPCP_VJ_COMP;
wo->maxslotindex = MAX_SLOTS - 1;
wo->cflag = 0;
wo->default_route = 1;
ao->neg_addr = 1;
#if VJ_SUPPORT > 0
ao->neg_vj = 1;
#else
ao->neg_vj = 0;
#endif
ao->maxslotindex = MAX_SLOTS - 1;
ao->cflag = 1;
ao->default_route = 1;
}
/*
* ipcp_open - IPCP is allowed to come up.
*/
static void ipcp_open(int unit)
{
fsm_open(&ipcp_fsm[unit]);
}
/*
* ipcp_close - Take IPCP down.
*/
static void ipcp_close(int unit, char *reason)
{
fsm_close(&ipcp_fsm[unit], reason);
}
/*
* ipcp_lowerup - The lower layer is up.
*/
static void ipcp_lowerup(int unit)
{
fsm_lowerup(&ipcp_fsm[unit]);
}
/*
* ipcp_lowerdown - The lower layer is down.
*/
static void ipcp_lowerdown(int unit)
{
fsm_lowerdown(&ipcp_fsm[unit]);
}
/*
* ipcp_input - Input IPCP packet.
*/
static void ipcp_input(int unit, u_char *p, int len)
{
fsm_input(&ipcp_fsm[unit], p, len);
}
/*
* ipcp_protrej - A Protocol-Reject was received for IPCP.
*
* Pretend the lower layer went down, so we shut up.
*/
static void ipcp_protrej(int unit)
{
fsm_lowerdown(&ipcp_fsm[unit]);
}
/*
* ipcp_resetci - Reset our CI.
*/
static void ipcp_resetci(fsm *f)
{
ipcp_options *wo = &ipcp_wantoptions[f->unit];
wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
if (wo->ouraddr == 0)
wo->accept_local = 1;
if (wo->hisaddr == 0)
wo->accept_remote = 1;
/* Request DNS addresses from the peer */
wo->req_dns1 = ppp_settings.usepeerdns;
wo->req_dns2 = ppp_settings.usepeerdns;
ipcp_gotoptions[f->unit] = *wo;
cis_received[f->unit] = 0;
}
/*
* ipcp_cilen - Return length of our CI.
*/
static int ipcp_cilen(fsm *f)
{
ipcp_options *go = &ipcp_gotoptions[f->unit];
ipcp_options *wo = &ipcp_wantoptions[f->unit];
ipcp_options *ho = &ipcp_hisoptions[f->unit];
#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0)
/*
* First see if we want to change our options to the old
* forms because we have received old forms from the peer.
*/
if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
/* use the old style of address negotiation */
go->neg_addr = 1;
go->old_addrs = 1;
}
if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
/* try an older style of VJ negotiation */
if (cis_received[f->unit] == 0) {
/* keep trying the new style until we see some CI from the peer */
go->neg_vj = 1;
} else {
/* use the old style only if the peer did */
if (ho->neg_vj && ho->old_vj) {
go->neg_vj = 1;
go->old_vj = 1;
go->vj_protocol = ho->vj_protocol;
}
}
}
return (LENCIADDR(go->neg_addr, go->old_addrs)
+ LENCIVJ(go->neg_vj, go->old_vj) +
LENCIDNS(go->req_dns1) +
LENCIDNS(go->req_dns2));
}
/*
* ipcp_addci - Add our desired CIs to a packet.
*/
static void ipcp_addci(fsm *f, u_char *ucp, int *lenp)
{
ipcp_options *go = &ipcp_gotoptions[f->unit];
int len = *lenp;
#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
if (neg) { \
int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
if (len >= vjlen) { \
PUTCHAR(opt, ucp); \
PUTCHAR(vjlen, ucp); \
PUTSHORT(val, ucp); \
if (!old) { \
PUTCHAR(maxslotindex, ucp); \
PUTCHAR(cflag, ucp); \
} \
len -= vjlen; \
} else \
neg = 0; \
}
#define ADDCIADDR(opt, neg, old, val1, val2) \
if (neg) { \
int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
if (len >= addrlen) { \
u32_t l; \
PUTCHAR(opt, ucp); \
PUTCHAR(addrlen, ucp); \
l = ntohl(val1); \
PUTLONG(l, ucp); \
if (old) { \
l = ntohl(val2); \
PUTLONG(l, ucp); \
} \
len -= addrlen; \
} else \
neg = 0; \
}
#define ADDCIDNS(opt, neg, addr) \
if (neg) { \
if (len >= CILEN_ADDR) { \
u32_t l; \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_ADDR, ucp); \
l = ntohl(addr); \
PUTLONG(l, ucp); \
len -= CILEN_ADDR; \
} else \
neg = 0; \
}
ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
go->old_addrs, go->ouraddr, go->hisaddr);
ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
go->maxslotindex, go->cflag);
ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
*lenp -= len;
}
/*
* ipcp_ackci - Ack our CIs.
*
* Returns:
* 0 - Ack was bad.
* 1 - Ack was good.
*/
static int ipcp_ackci(fsm *f, u_char *p, int len)
{
ipcp_options *go = &ipcp_gotoptions[f->unit];
u_short cilen, citype, cishort;
u32_t cilong;
u_char cimaxslotindex, cicflag;
/*
* CIs must be in exactly the same order that we sent...
* Check packet length and CI length at each step.
* If we find any deviations, then this packet is bad.
*/
#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
if (neg) { \
int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
if ((len -= vjlen) < 0) \
goto bad; \
GETCHAR(citype, p); \
GETCHAR(cilen, p); \
if (cilen != vjlen || \
citype != opt) \
goto bad; \
GETSHORT(cishort, p); \
if (cishort != val) \
goto bad; \
if (!old) { \
GETCHAR(cimaxslotindex, p); \
if (cimaxslotindex != maxslotindex) \
goto bad; \
GETCHAR(cicflag, p); \
if (cicflag != cflag) \
goto bad; \
} \
}
#define ACKCIADDR(opt, neg, old, val1, val2) \
if (neg) { \
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -