📄 ipcp.c
字号:
/*
* FILENAME: ipcp.c
*
* Copyright 1997- 2001 By InterNiche Technologies Inc. All rights reserved
*
* PPP IP Control Protocol
*
* MODULE: PPP
*
* ROUTINES: ipcp_resetci(), ipcp_addci(), ipcp_ackci(),
* ROUTINES: ipcp_nakci(), ipcp_rejci(), ipcp_reqci(), ipcp_up(),
* ROUTINES: ipcp_down(), ipcp_started(), ipcp_finished
*
* PORTABLE: yes
*/
/* Additional Copyrights: */
/* Portions Copyright 1996 by NetPort Software.
* Portions 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 "ipport.h"
#ifdef USE_PPP /* whole C file can be ifdeffed */
#include "ppp_port.h"
#include "mppp.h"
#define IPCP_DEBUG 0
#if IPCP_DEBUG > 0
#include "ZPrint.h"
#endif
int allow_ipset = TRUE;
/* 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 */
#define CILEN_DNSADDR 6 /* RFC 1877 domain name server address length */
#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
(x) == CONFNAK ? "NAK" : "REJ")
/* FUNCTION: ipcp_resetci()
*
* ipcp_resetci - Reset our CI.
*
*
* PARAM1: M_PPP mppp
*
* RETURNS:
*/
void
ipcp_resetci(M_PPP mppp)
{
ipcp_options * wo = &mppp->ipcp_wantoptions;
/* Fill in the ipcp_options we will try for */
wo->neg_addr = 1;
wo->old_addrs = 0;
if(mppp->ifp)
wo->ouraddr = mppp->ifp->n_ipaddr; /* in net endian */
else
wo->ouraddr = 0;
wo->hisaddr = 0;
wo->old_vj = 0;
wo->vj_protocol = IPCP_VJ_COMP;
wo->maxslotindex = MAX_STATES - 1; /* really max index */
wo->cflag = 1;
#ifdef PPP_VJC
wo->neg_vj = 1; /* ask for VJ compression if build supports it */
#else
wo->neg_vj = 0; /* else don't ask */
#endif
#if defined (USE_PPPOE) && defined (PPP_VJC)
if(mppp->line.lower_type == LN_PPPOE)
{
/* VJ over PPPOE is legal, but it's really slow */
//ConPrintf("Disabling VJ over PPPOE link %lx\n", mppp);
wo->neg_vj = 0;
}
#endif /* USE_PPPOE */
wo->req_addr = wo->neg_addr;
/* allow our IP address to be set if it is 0.0.0.0 OR we are client */
if ((wo->ouraddr == 0) || ((mppp->pppflags & PPP_SERVER) == FALSE ))
{
wo->accept_local = 1;
}
if (wo->hisaddr == 0)
wo->accept_remote = 1;
MEMCPY(&mppp->ipcp_gotoptions, wo, sizeof(*wo));
mppp->cis_received[IPCP_STATE] = 0;
}
/* FUNCTION: ipcp_addci()
*
* ipcp_addci - Build our desired CIs in mppp->lastci buffer. The buffer
* should be at least MAX_CILEN long.
*
* PARAM1: M_PPP mppp
*
* RETURNS: length of config option string
*/
#ifdef NPDEBUG
/* Macro to make sure passed buffer has room for this option */
#define CHECK_CI_LEN(cilen) \
if (len < cilen) {dtrap("ipcp 1\n"); goto addci_done; }
#else
#define CHECK_CI_LEN(fu) /* define away to nothing */
#endif /* NPDEBUG */
int
ipcp_addci(M_PPP mppp)
{
int len; /* space left in passed buffer */
int optlen; /* length of current option string */
u_char opt;
u_char * ucp;
u_long longval;
ipcp_options * go = &mppp->ipcp_gotoptions;
#if IPCP_DEBUG
Printu("ipcp_addci\r\n");
#endif
#ifdef PPP_OLDFORMS
ipcp_options * wo = &mppp->ipcp_wantoptions;
ipcp_options * ho = &mppp->ipcp_hisoptions;
/*
* 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 (mppp->cis_received[IPCP_STATE] == 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;
}
}
}
if (go->old_addrs)
{
/* set up for older form of addr option */
opt = CI_ADDRS;
optlen = CILEN_ADDRS;
}
else
#endif /* PPP_OLDFORMS */
{
/* set up for current form of addr option */
opt = CI_ADDR;
optlen = CILEN_ADDR;
}
/* build reply in mppp's scratch buffer */
ucp = mppp->lastci;
len = MAX_CILEN;
if (go->ouraddr == 0L) { /*ConPrintf("ipcp_addci: ouraddr==0.0.0.0\n");*/ }
/* start building the IPCP ci list in passed buffer. Address first.
* "optlen" was set above.
*/
if (go->neg_addr)
{
CHECK_CI_LEN(optlen);
*ucp++ = opt;
*ucp++ = (u_char)optlen;
/* convert IP address to local endian for putlong() call */
longval = ntohl(go->ouraddr);
ppp_putlong(ucp, longval);
ucp += 4;
#ifdef PPP_OLDFORMS
if (go->old_addrs)
{
longval = ntohl(go->hisaddr);
ppp_putlong(ucp, longval);
ucp += 4;
}
#endif /* PPP_OLDFORMS */
len -= optlen;
}
if(go->neg_vj)
{
#ifdef PPP_OLDFORMS
optlen = go->old_vj? CILEN_COMPRESS : CILEN_VJ;
#else
optlen = CILEN_VJ;
#endif
CHECK_CI_LEN(optlen);
*ucp++ = CI_COMPRESSTYPE;
*ucp++ = (u_char)optlen;
ppp_putshort(ucp, go->vj_protocol);
ucp += 2;
if (!go->old_vj)
{
*ucp++ = go->maxslotindex;
*ucp++ = go->cflag;
}
len -= optlen;
}
#ifdef PPP_DNS
if (go->neg_dnsaddr_pri)
{
CHECK_CI_LEN(CILEN_DNSADDR);
*ucp++ = CI_DNSADDR_PRI;
*ucp++ = CILEN_DNSADDR;
longval = ntohl(go->dnsaddr_pri);
ppp_putlong(ucp, longval);
ucp += 4;
len -= CILEN_DNSADDR;
}
if (go->neg_dnsaddr_sec)
{
CHECK_CI_LEN(CILEN_DNSADDR);
*ucp++ = CI_DNSADDR_SEC;
*ucp++ = CILEN_DNSADDR;
longval = ntohl(go->dnsaddr_sec);
ppp_putlong(ucp, longval);
ucp += 4;
len -= CILEN_DNSADDR;
}
#endif /* PPP_DNS */
#ifdef NPDEBUG
addci_done:
#endif
#ifdef NPDEBUG
if(len > MAX_CILEN)
{
dtrap("ipcp 0\n"); /* reserved mppp->lastci[] buffer too small */
}
#endif
return(MAX_CILEN - len); /* size of options */
}
/* FUNCTION: ipcp_ackci()
*
* ipcp_ackci - Check an Ack our our previous CIs.
*
*
* PARAM1: M_PPP mppp
* PARAM2: u_char * p
* PARAM3: int len
*
* RETURNS: 0 - Ack was good, or 1 - Ack was bad.
*/
int
ipcp_ackci(M_PPP mppp, u_char * p, int len)
{
if(MEMCMP(p, mppp->lastci, len) == 0)
return 0;
else
return 1;
}
/* FUNCTION: ipcp_nakci()
*
* ipcp_nakci - Peer has sent a NAK for some of our CIs.
* This should not modify any state if the Nak is bad
* or if IPCP is in the OPENED state.
*
* PARAM1: M_PPP mppp
* PARAM2: u_char * p
* PARAM3: int len
*
* RETURNS: 0 if Nak was good or 1 if Nak was bad.
*/
int
ipcp_nakci(M_PPP mppp, u_char * p, int len)
{
u_char cimaxslotindex = 0;
u_char cicflag = 0;
u_char cilen;
u_short cishort;
u_long ciaddr1;
u_long ciaddr2;
ulong longval;
ipcp_options tryfor; /* options to request next time */
/* options we have currently (i.e. got last time) */
ipcp_options * go = &mppp->ipcp_gotoptions;
#if IPCP_DEBUG
Printu("ipcp_nakci\r\n");
#endif
MEMCPY(&tryfor, go, sizeof(*go) ); /* init "tryfor" to "go" */
while(len > 0)
{
cilen = *(p + 1);
switch(*p)
{
case CI_ADDR:
if(go->neg_addr == 0)
tryfor.neg_addr = 1;
/* Accept the peer's idea of {our,his} address, if different
* from our idea, only if the accept_{local,remote} flag is set.
*/
longval = ppp_getlong(p + 2); /* extract our address */
/* convert getlong() result back to net endian for storage */
ciaddr1 = htonl(longval);
#if IPCP_DEBUG
Printu("ciaddr1:%xc\tilen:%x\r\n",ciaddr1,cilen);
#endif
#ifdef PPP_OLDFORMS
if (go->old_addrs) /* old address command? */
{
tryfor.old_addrs = 1;
longval = ppp_getlong(p);
p += 4;
ciaddr2 = htonl(longval); /* extract his address */
if(cilen != CILEN_ADDRS)
return 1; /* bad packet */
}
else /* new address command, sets our address only */
#endif /* PPP_OLDFORMS */
{
if(cilen != CILEN_ADDR)
return 1; /* bad packet */
ciaddr2 = 0; /* flag his as 0 for now */
}
if (ciaddr1 && go->accept_local) /* Will we allow this? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -