lcp.c
来自「在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LE」· C语言 代码 · 共 1,350 行 · 第 1/3 页
C
1,350 行
{
/* We can only use our single global MLED */
*ucp++ = CI_ML_ENDP;
*ucp++ = (u_char)(3 + ml_endplen); /* length of option field */
*ucp++ = (u_char)(ml_endpclass);
/* If class is IP address, and data is not set; then set it now */
if((ml_endpclass == MLEDCLASS_IP) &&
(*(ip_addr*)(&ml_endp[0]) == 0) &&
(mppp->ifp))
{
*(ip_addr*)(&ml_endp[0]) = mppp->ifp->n_ipaddr;
}
MEMCPY(ucp, ml_endp, ml_endplen);
ucp += ml_endplen;
}
}
#endif /* PPP_MULTILINK */
#ifdef LQR_SUPPORT
if(go->neg_lqr)
{
*ucp++ = CI_QUALITY;
*ucp++ = CILEN_LQR;
ucp = ppp_putshort(ucp, PPP_LQR);
ucp = ppp_putlong(ucp + 2, go->lqr_period);
}
#endif /* LQR_SUPPORT */
if(go->neg_magicnumber)
{
*ucp++ = CI_MAGICNUMBER;
*ucp++ = CILEN_LONG;
ucp = ppp_putlong(ucp, go->magicnumber);
}
if(go->neg_pcompression)
{
*ucp++ = CI_PCOMPRESSION;
*ucp++ = CILEN_VOID;
}
if(go->neg_accompression)
{
*ucp++ = CI_ACCOMPRESSION;
*ucp++ = CILEN_VOID;
}
len = ucp - &mppp->lastci[0];
#ifdef NPDEBUG
if(len > MAX_CILEN)
{
//ConPrintf("ci too big for buffer\n");
dtrap("lcp 1\n"); /* programming error */
return 0;
}
#endif /* NPDEBUG */
//PrintString('x',&mppp->lastci[0],len);
return (len);
}
/* FUNCTION: lcp_ackci()
*
* lcp_ackci - received Ack of our CIs.
* This should not modify any state if the Ack is bad.
*
*
* PARAM1: mppp - our PPP connection
* PARAM2: u_char * p - received CI data
* PARAM3: int len - length of ucp
*
* RETURNS: 0 if Ack was good or nonzero if Ack was bad.
*/
int
lcp_ackci(M_PPP mppp, u_char * p, int len)
{
int ci_ok;
#if LCP_DEBUG
Printu("lcp_ackci\r\n");
#endif
ci_ok = MEMCMP(p, mppp->lastci, len);
// ConPrintf("LCP rcvd ACK: %s\n", ci_ok?"BAD":"OK");
return ci_ok;
}
/* FUNCTION: lcp_nakci()
*
* lcp_nakci - Peer has sent a NAK for some of our CIs.
* This should not modify any state if the Nak is bad
* or if LCP is in the OPENED state.
*
*
* PARAM1: M_PPP mppp
* PARAM2: u_char * p
* PARAM3: int len
*
* RETURNS: 0 - Nak was good or 1 if Nak was bad
*/
int
lcp_nakci(M_PPP mppp, u_char * p, int len)
{
u_char cilen;
u_short cishort;
u_long cilong;
lcp_options no; /* options we've seen Naks for */
lcp_options tryfor; /* options to request next time */
lcp_options * go = &mppp->lcp_gotoptions;
lcp_options * wo = &mppp->lcp_wantoptions;
int looped_back = 0;
#if LCP_DEBUG
Printu("lcp_nakci\r\n");
#endif
/* initialize local option lists */
MEMSET(&no, 0, sizeof(no)); /* null NAK list */
MEMCPY(&tryfor, go, sizeof(*go)); /* copy latest "got" list */
//ConPrintf("rcvd NAK; ");
/* loop through NAKed options */
while(len > 0)
{
if((*p) > CI_LCP_MAX)
{
//ConPrintf("Bad LCP option 0x%x\n", *p);
return 1;
}
//ConPrintf("opt:%s ", lcp_opts[*p]);
cilen = *(p + 1); /* length of this option field */
switch (*p) /* switch based on option */
{
case CI_MRU:
/* if he NAKed an option we didn't send, punt pkt */
if(go->neg_mru == 0)
goto rcvd_bad_nak;
/*
* We don't care if they want to send us smaller packets than we
* want. Therefore, accept any MRU less than what we asked for
* but then ignore the new value when setting the MRU. If they
* send us a bigger MRU than what we asked, accept it, up to
* the limit of the default MRU we'd get if we didn't negotiate.
*/
no.neg_mru = 1;
cishort = ppp_getshort(p + 2);
if (cishort <= wo->mru || cishort < ppp_mru)
tryfor.mru = cishort;
break;
case CI_ASYNCMAP:
/* Add any characters they want to our (receive-side) asyncmap. */
if(go->neg_asyncmap == 0)
goto rcvd_bad_nak;
no.neg_asyncmap = 1;
cilong = ppp_getlong(p + 2);
tryfor.asyncmap = go->asyncmap | cilong;
break;
case CI_AUTHTYPE:
/* If they can't cope with our CHAP hash algorithm, we'll have
* to stop asking for CHAP. We haven't got any other algorithm.
*/
if(go->neg_chap)
{
tryfor.neg_chap = 0;
tryfor.neg_upap = 1; /* ask for PAP instead */
}
else /* They NAKed UPAP? */
{
if(go->neg_upap == 0) /* bad pkt */
goto rcvd_bad_nak;
/* Peer shouldn't send Nak for UPAP, protocol compression or
* address/control compression requests; they should send
* a Reject instead. If they sent a Nak, treat it as a Reject.
*/
tryfor.neg_upap = 0;
}
break;
#ifdef LQR_SUPPORT
case CI_QUALITY:
/*
* If they can't cope with our link quality protocol, we'll have
* to stop asking for LQR. We haven't got any other protocol.
* Some folks can't hold their LIQR.
* If they Nak the reporting period, take their value.
*/
if(go->neg_lqr == 0)
goto rcvd_bad_nak;
no.neg_lqr = 1;
cishort = ppp_getshort(p + 2);
cilong = ppp_getlong(p + 4);
if (cishort != PPP_LQR)
tryfor.neg_lqr = 0;
else
tryfor.lqr_period = cilong;
break;
#endif /* LQR_SUPPORT */
case CI_PCOMPRESSION:
if(go->neg_pcompression == 0)
goto rcvd_bad_nak;
no.neg_pcompression = 1;
tryfor.neg_pcompression = 0;
break;
case CI_ACCOMPRESSION:
if(go->neg_accompression == 0)
goto rcvd_bad_nak;
no.neg_accompression = 1;
tryfor.neg_accompression = 0;
break;
case CI_MAGICNUMBER:
/* Check for a looped-back line. */
if(go->neg_magicnumber == 0)
goto rcvd_bad_nak;
no.magicnumber = 1;
tryfor.magicnumber = ppp_magic(mppp);
++tryfor.numloops;
looped_back = 1;
break;
#ifdef PPP_MULTILINK
case CI_ML_MRU:
if(go->neg_ml_mru == 0)
goto rcvd_bad_nak;
if((mppp->pppflags & ALLOW_ML) == 0)
{
no.neg_ml_mru = 0;
break;
}
no.neg_ml_mru = 1;
/* If he suggested short MRU try for it */
if(go->ml_mru < ppp_mru)
tryfor.ml_mru = go->ml_mru;
else
tryfor.ml_mru = ppp_mru; /* else repeat our best offer */
break;
case CI_ML_SSN:
if(go->neg_ml_ssn == 0)
goto rcvd_bad_nak;
if((mppp->pppflags & ALLOW_ML) == 0)
{
no.neg_ml_ssn = 0;
break;
}
no.neg_ml_ssn = 1;
/* We don;t really care about this, try without it */
tryfor.neg_ml_ssn = 0;
break;
case CI_ML_ENDP:
goto rcvd_bad_nak; /* he's not supposed to NAK this */
break;
#endif /* PPP_MULTILINK */
default:
// ConPrintf("lcp: Bad NAK option 0x%x\n", *p);
goto rcvd_bad_nak;
}
p += cilen;
len -= cilen;
}
/* Nak is good - update "gotoptions" so we can confreq again. */
if (mppp->states[LCP_STATE] != ST_OPENED)
{
MEMCPY(go, &tryfor, sizeof(tryfor));
if (looped_back && ((tryfor.numloops % lcp_warnloops) == 0))
{
// ConPrintf("The line appears to be looped back; closing:");
ppp_close(mppp, LCP_STATE);
}
}
else
{
//ConPrintf("Got LCP NAK in OPENED state.");
}
//ConPrintf("\n");
return 0; /* good return */
rcvd_bad_nak:
//ConPrintf("lcp: rcvd bad NAK (option:0x%x)\n", *p);
return 1;
}
/* FUNCTION: lcp_rejci()
*
* lcp_rejci - Peer has Rejected some of our CIs.
* This should not modify any state if the Reject is bad
* or if LCP is in the OPENED state.
*
*
* 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
lcp_rejci(M_PPP mppp, u_char * p, int len)
{
lcp_options * go = &mppp->lcp_gotoptions;
u_char cilen;
u_short cishort;
u_long cilong;
lcp_options tryfor; /* options to request next time */
#if LCP_DEBUG
Printu("lcp_rejci\r\n");
#endif
MEMCPY(&tryfor, go, sizeof(tryfor));
while(len > 0)
{
cilen = *(p + 1); /* length of this option field */
//ConPrintf("lcp reject of 0x%x\n", *p);
switch(*p)
{
case CI_MRU:
if(go->neg_mru == 0)
goto rcvd_bad_rej;
cishort = ppp_getshort(p + 2);
if(cishort != go->mru) /* did he rej wrong value? */
goto rcvd_bad_rej;
tryfor.neg_mru = 0;
break;
case CI_ASYNCMAP:
if(go->neg_asyncmap == 0)
goto rcvd_bad_rej;
cilong = ppp_getlong(p + 2);
if(cilong != go->asyncmap) /* did he rej wrong value? */
goto rcvd_bad_rej;
tryfor.neg_asyncmap = 0;
break;
case CI_AUTHTYPE:
if(go->neg_chap)
{
tryfor.neg_chap = 0;
tryfor.neg_upap = 1; /* ask for PAP instead */
}
else /* They rejected UPAP? */
{
if(go->neg_upap == 0) /* bad pkt */
goto rcvd_bad_rej;
tryfor.neg_upap = 0;
}
break;
#ifdef LQR_SUPPORT
case CI_QUALITY:
if(go->neg_lqr == 0)
goto rcvd_bad_rej;
cishort = ppp_getshort(p + 2);
if(cishort != PPP_LQR) /* did he rej wrong value? */
goto rcvd_bad_rej;
tryfor.neg_lqr = 0;
break;
#endif /* LQR_SUPPORT */
case CI_MAGICNUMBER:
if(go->magicnumber == 0)
goto rcvd_bad_rej;
cilong = ppp_getlong(p + 2);
if(cilong != go->magicnumber) /* check rejected value */
goto rcvd_bad_rej;
tryfor.neg_magicnumber = 0;
break;
case CI_PCOMPRESSION:
if(go->neg_pcompression == 0)
goto rcvd_bad_rej;
tryfor.neg_pcompression = 0;
break;
case CI_ACCOMPRESSION:
if(go->neg_accompression == 0)
goto rcvd_bad_rej;
tryfor.neg_accompression = 0;
break;
#ifdef PPP_MULTILINK
case CI_ML_MRU:
if(go->neg_ml_mru == 0)
goto rcvd_bad_rej;
tryfor.neg_ml_mru = 0; /* forget about multilink */
break;
case CI_ML_SSN:
if(go->neg_ml_ssn == 0)
goto rcvd_bad_rej;
tryfor.neg_ml_ssn = 0;
break;
case CI_ML_ENDP:
if(go->neg_ml_endp == 0)
goto rcvd_bad_rej;
tryfor.neg_ml_endp = 0;
break;
#endif
default:
//ConPrintf("lcp: REG for bad option 0x%x\n", *p);
goto rcvd_bad_rej;
}
p += cilen;
len -= cilen;
}
/* Now we can update state. */
if (mppp->states[LCP_STATE] != ST_OPENED)
MEMCPY(go, &tryfor, sizeof(tryfor));
return EV_RXJP;
rcvd_bad_rej:
//ConPrintf("lcp_rejci: bad; len %d opt: 0x%x", len, *p);
return EV_NOEVENT;
}
/* FUNCTION: lcp_reqci()
*
* lcp_reqci - Check the peer's requested CIs and send
* appropriate response.
*
* Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
* appropriately. If reject_if_disagree is non-zero, doesn't return
* CONFNAK; returns CONFREJ if it can't return CONFACK.
*
* This leaves the reply option list for NAK, ACK or REJ in inp with
* the reply length set in lenp.
*
*
* PARAM1: M_PPP mppp
* PARAM2: u_char * inp
* PARAM3: int * lenp
* PARAM4: int reject_if_disagree
*
* RETURNS: CONFACK, CONFNAK or CONFREJ
*/
int
lcp_reqci(M_PPP mppp,
u_char * inp, /* Requested CIs */
int * lenp, /* Length of requested CIs */
int reject_if_disagree)
{
u_char * cip; /* Pointer to current and next CIs */
u_char cilen; /* length of current CI */
u_char citype; /* type of CI */
#ifdef CHAP_SUPPORT /* char only used for MD5 digest type */
u_char cichar; /* Parsed char value */
#endif
u_short cishort; /* Parsed short value */
u_long cilong; /* Parse long value */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?