📄 ipcp.c
字号:
{
/* got here because he's trying to set our address */
tryfor.ouraddr = ciaddr1;
//ConPrintf("local IP address %u.%u.%u.%u\n",
//PUSH_IPADDR(ciaddr1));
#if IPCP_DEBUG
Printu("local IP address %u.%u.%u.%u\n",
PUSH_IPADDR(ciaddr1));
#endif
}
else {
#if IPCP_DEBUG
Printu("no acceptr_local\r\n");
#endif
}
if (go->accept_remote && ciaddr2) /* Does he know his? */
{
tryfor.hisaddr = ciaddr2;
// ConPrintf("remote IP address %u.%u.%u.%u\n",
// PUSH_IPADDR(ciaddr2) );
}
/*if (mppp->states[IPCP_STATE] != ST_OPENED)
MEMCPY(go, &tryfor, sizeof(tryfor) );
*/
break;
case CI_COMPRESSTYPE:
/* Accept the peer's value of maxslotindex provided that it
* is less than what we asked for. Turn off slot-ID compression
* if the peer wants. Send old-style compress-type option if
* the peer wants.
*/
if(go->neg_vj == 0)
tryfor.neg_vj = 1;
cishort = ppp_getshort(p + 2);
if(cilen == CILEN_VJ)
{
if (cishort == IPCP_VJ_COMP)
{
cimaxslotindex = *(p + 4);
cicflag = *(p + 5);
tryfor.old_vj = 0;
if (cimaxslotindex < go->maxslotindex)
tryfor.maxslotindex = cimaxslotindex;
if (!cicflag)
tryfor.cflag = 0;
}
else
{
tryfor.neg_vj = 0;
}
}
else if(cilen == CILEN_COMPRESS)
{
if((cishort == IPCP_VJ_COMP) || (cishort == IPCP_VJ_COMP_OLD))
{
tryfor.old_vj = 1;
tryfor.vj_protocol = cishort;
}
else
{
tryfor.neg_vj = 0;
}
}
else
{
// ConPrintf("ipcp rcv NAK: bad VJ length %d\n", cilen);
return 1;
}
break;
#ifdef PPP_DNS
case CI_DNSADDR_PRI:
if(go->neg_dnsaddr_pri == 0)
tryfor.neg_dnsaddr_pri = 1;
goto set_dns_addr;
case CI_DNSADDR_SEC:
if(go->neg_dnsaddr_sec == 0)
tryfor.neg_dnsaddr_sec = 1;
set_dns_addr:
/* most of the rest of this case code is common to the primary
* DNS server address option and the secondary DNS server address
* option.
*/
longval = ppp_getlong(p + 2); /* extract DNS server address */
ciaddr1 = htonl(longval); /* make net endian for storage */
/* Accept the nameserver addresses only if the
* accept_dnsaddrs flag is set.
*/
if (ciaddr1 && go->accept_dnsaddrs) /* Will we allow this? */
{
/* got here because he's trying to set our address */
if(*p == CI_DNSADDR_PRI) /* primary or secondary? */
tryfor.dnsaddr_pri = ciaddr1;
else
tryfor.dnsaddr_sec = ciaddr1;
//ConPrintf("ipcp NAK: DNS (0x%x) address %u.%u.%u.%u \n",
//(unsigned)(*p), PUSH_IPADDR(ciaddr1) );
}
break;
#else
case CI_DNSADDR_PRI:
case CI_DNSADDR_SEC:
break;
#endif /* PPP_DNS */
default:
// ConPrintf("ipcp rcv NAK: unknown option 0x%x\n", *p);
return 1;
}
p += cilen; /* bump pointer to NAK options */
len -= cilen;
}
/*if(len != 0)
{
//ConPrintf("ipcp odd NAK len\n");
return 1;
} */
/* Nak pkt seems OK. Update "go" from tmp "tryfor" */
if (mppp->states[IPCP_STATE] != ST_OPENED)
MEMCPY(go, &tryfor, sizeof(tryfor) );
return 0;
}
/* FUNCTION: ipcp_rejci()
*
* ipcp_rejci - Peer rejected some of our CIs.
*
*
* PARAM1: M_PPP mppp
* PARAM2: u_char *p
* PARAM3: int len
*
* RETURNS: One of the CI reject events:
* EV_RXJC - unrecoverable rejection, kill session.
* EV_RXJP - tolerable rejection, try other option.
* EV_NOEVENT - packet was badly formed, ignore it.
*/
int
ipcp_rejci(M_PPP mppp, u_char * p, int len)
{
u_char cimaxslotindex;
u_char ciflag;
u_char cilen;
u_short cishort;
u_long cilong;
ipcp_options tryfor; /* options to request next time */
ipcp_options * go;
#ifdef PPP_OLDFORMS
u_long l;
#endif
go = &mppp->ipcp_gotoptions;
/* Initialize "tryfor" options from last set received */
MEMCPY(&tryfor, go, sizeof(*go));
while (len > 0)
{
cilen = *(p + 1);
switch(*p)
{
case CI_ADDRS:
case CI_ADDR:
if (go->neg_addr == 0)
break;
cilong = ppp_getlong(p + 2);
cilong = htonl(cilong);
/* Check rejected value. */
if (cilong != (u_long)go->ouraddr)
goto bad_rej;
#ifdef PPP_OLDFORMS
if (go->old_addrs && (*p == CI_ADDRS))
{
/* Extract and check rejected value. */
l = ppp_getlong(p);
cilong = htonl(l);
if (cilong != go->hisaddr)
goto bad_rej;
}
#endif /* PPP_OLDFORMS */
/* He rejected our IP assignment. Don't negotiate this anymore */
tryfor.neg_addr = 0;
break;
case CI_COMPRESSTYPE:
if(go->neg_vj == 0)
goto bad_rej;
cishort = ppp_getshort(p + 2);
/* Check rejected value. */
if (cishort != go->vj_protocol) /* we only support VJ header compression */
goto bad_rej;
if (go->old_vj == 0)
{
cimaxslotindex = *(p + 4);
if (cimaxslotindex != go->maxslotindex)
goto bad_rej;
ciflag = *(p + 5);
if (ciflag != go->cflag)
goto bad_rej;
}
tryfor.neg_vj = 0; /* don't ask for this anymore */
break;
#ifdef PPP_DNS
case CI_DNSADDR_PRI:
if (go->neg_dnsaddr_pri == 0)
goto bad_rej;
cilong = ppp_getlong(p + 2);
if (cilong != (u_long)go->dnsaddr_pri)
goto bad_rej;
tryfor.neg_dnsaddr_pri = 0;
break;
case CI_DNSADDR_SEC:
if (go->neg_dnsaddr_sec == 0)
return EV_NOEVENT;
cilong = ppp_getlong(p + 2);
if (cilong != (u_long)go->dnsaddr_sec)
goto bad_rej;
tryfor.neg_dnsaddr_sec = 0;
break;
#endif /* PPP_DNS */
default:
goto bad_rej;
}
p += cilen;
len -= cilen;
}
if(len != 0)
{
//ConPrintf("ipcp_rejci: bad Rej pkt len\n");
return EV_NOEVENT;
}
/* Make "tryfor" list the current "got" list */
if (mppp->states[IPCP_STATE] != ST_OPENED)
MEMCPY(go, &tryfor, sizeof(tryfor));
return EV_RXJP;
bad_rej:
// ConPrintf("ipcp_rejci: bad Rej pkt at opt 0x%x\n", *p);
return EV_NOEVENT;
}
/* FUNCTION: ipcp_reqci()
*
* ipcp_reqci - Check the peer's requested CIs and build appropriate
* response in input packet. If reject_if_disagree is non-zero, doesn't
* return CONFNAK; returns CONFREJ if it can't return CONFACK.
*
* PARAM1: M_PPP mppp
* PARAM2: u_char * inp - recevied REQ data
* PARAM3: int * len - (IN/OUT) length of buffer
* PARAM4: int reject_if_disagree
*
* RETURNS: CONFACK, CONFNAK or CONFREJ
*/
int
ipcp_reqci(M_PPP mppp,
u_char * inp, /* received option list (CIs) */
int * lenp, /* Length of inp */
int reject_if_disagree)
{
u_short cilen, citype; /* Parsed len, type */
u_long tl; /* Parsed address values */
u_long ciaddr1;
int rc = CONFACK; /* Final packet return code */
int orc; /* Individual option return code */
u_char * p; /* Pointer to next char to parse */
u_char * ucp; /* Pointer to current output char */
int len = *lenp; /* Length left */
u_char nakaddrdone = 0; /* flag: have nak'ed (his) address */
ipcp_options * wo = &mppp->ipcp_wantoptions;
ipcp_options * ho = &mppp->ipcp_hisoptions;
#ifdef PPP_OLDFORMS
ipcp_options * go = &mppp->ipcp_gotoptions;
#endif /* PPP_OLDFORMS */
#ifdef PPP_VJC
u_char maxslotindex;
u_char cflag;
u_short cishort; /* Parsed short value */
#endif /* PPP_VJC */
#if IPCP_DEBUG
Printu("ipcp_reqci\r\n");
#endif
/* Reset all his options. */
MEMSET(ho, 0, sizeof(*ho));
p = ucp = inp;
/* loop through received options list. */
while (len)
{
orc = CONFACK; /* Assume success */
citype = *p; /* Parse CI type */
cilen = *(p+1); /* Parse CI length */
if ((len < 2) || /* Not enough data for CI header or */
(cilen < 2) || /* CI length too small or */
(cilen > (u_short)len)) /* CI length too big? */
{
// ConPrintf("ipcp_reqci: bad CI length on opt 0x%x", citype);
orc = CONFREJ; /* Reject bad CI */
cilen = (u_char)len; /* Reject till end of packet */
len = 0; /* Don't loop again */
goto endswitch;
}
len -= cilen; /* Adjust remaining length */
switch (citype) /* Check CI type */
{
case CI_ADDR:
case CI_ADDRS:
//ConPrintf("ipcp: received ADDR ");
tl = ppp_getlong(p + 2); /* Parse source address (his) */
ciaddr1 = htonl(tl);
//ConPrintf("IP:%u.%u.%u.%u:", PUSH_IPADDR(ciaddr1));
/* If he has no address and we have no address to give him,
* reject this CI -- we can't help.
*/
if((ciaddr1 == 0) &&
(wo->hisaddr == 0))
{
wo->req_addr = 0; /* and don't ask for his address later */
orc = CONFREJ;
break;
}
/*
* If we have an address for the peer, and either he disagrees
* with us and we don't want to accept his address, or he
* doesn't have an address, then NAK it with our idea.
* In particular, if we don't know his address, but he does,
* then accept it.
*/
if((wo->hisaddr != 0) &&
(((ciaddr1 != wo->hisaddr) && (!wo->accept_remote)) ||
(ciaddr1 == 0)))
{
orc = CONFNAK;
if (!reject_if_disagree)
{
tl = ntohl(wo->hisaddr);
ppp_putlong(p + 2, tl);
}
nakaddrdone = 1;
break;
}
#ifdef PPP_OLDFORMS
if(citype == CI_ADDRS)
{
u_long ciaddr2;
/* If he doesn't know our address, or if we both have our address
* but disagree about it, then NAK it with our idea.
*/
tl = ppp_getlong(p + 6); /* Parse desination address (ours) */
ciaddr2 = htonl(tl);
//ConPrintf("%u.%u.%u.%u", PUSH_IPADDR(ciaddr2) );
if (ciaddr2 != wo->ouraddr)
{
if (ciaddr2 == 0 || !wo->accept_local)
{
orc = CONFNAK;
if (!reject_if_disagree)
{
tl = ntohl(wo->ouraddr);
ppp_putlong(p + 6, tl);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -