lcp.c
来自「在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LE」· C语言 代码 · 共 1,350 行 · 第 1/3 页
C
1,350 行
int rc = CONFACK; /* Final packet return code */
int orc; /* Individual option return code */
u_char * p; /* Pointer to current char to parse */
u_char * next; /* scratch "next" pointer */
u_char * ucp = inp; /* Pointer to current output char */
int l = *lenp; /* Length left */
u_char nakcilen; /* Length of generated Configure-NAK CI (for auth) */
int i; /* index (for copying) */
lcp_options * go = &mppp->lcp_gotoptions;
lcp_options * ho = &mppp->lcp_hisoptions;
/* Process all his options. */
#if LCP_DEBUG
Printu("lcp_reqci\r\n");
#endif
p = next = inp;
while (l)
{
orc = CONFACK; /* Assume success */
cip = p = next; /* Remember begining of CI */
citype = *p++; /* Parse CI type */
cilen = *p++; /* Parse CI length */
if ((l < 2) || /* Not enough data for CI header or */
(cilen < 2) || /* CI length too small or */
(cilen > l)) /* CI length too big? */
{
//ConPrintf(( "lcp_reqci: bad CI length!"));
orc = CONFREJ; /* Reject bad CI */
cilen = (u_char)l; /* Reject till end of packet */
l = 0; /* Don't loop again */
goto endswitch;
}
l -= cilen; /* Adjust remaining length */
next += cilen; /* Step to next CI */
switch (citype)
{ /* Check CI type */
case CI_MRU:
//ConPrintf(("lcp_reqci: rcvd MRU"));
if (cilen != CILEN_SHORT) /* Check CI length */
{
orc = CONFREJ; /* Reject CI */
break;
}
cishort = ppp_getshort(p); /* Parse MRU */
//ConPrintf("(%d)", cishort);
/* He must be able to receive at least our minimum.
* and don't let him have more than our MTU.
*/
if(cishort < MINMRU)
{
orc = CONFNAK; /* Nak CI */
if ( !reject_if_disagree )
ppp_putshort(p, MINMRU); /* Give him a hint */
break;
}
ho->neg_mru = 1; /* Remember he sent MRU */
ho->mru = cishort; /* And remember value */
break;
case CI_ASYNCMAP:
//ConPrintf(("lcp_reqci: rcvd ASYNCMAP"));
if (cilen != CILEN_LONG)
{
orc = CODEREJ;
break;
}
cilong = ppp_getlong(p);
//ConPrintf("(%lx)", cilong);
if(cilong!=ppp_asyncmap_default)
{
ppp_putlong(p,ppp_asyncmap_default);
orc = CONFNAK;
break;
}
/* Asyncmap must have set at least the bits
* which are set in allow_asyncmap.
*/
if ((allow_asyncmap & ~cilong) != 0)
{
#if LCP_DEBUG
Printu("ASYNMAP:orc = CONFNAK;\r\n");
#endif
orc = CONFNAK;
if ( !reject_if_disagree )
{
ppp_putlong(p, (allow_asyncmap | cilong));
}
break;
}
ho->neg_asyncmap = 1;
ho->asyncmap = cilong;
break;
case CI_AUTHTYPE:
/*
* If we aren't willing to send authentication information to
* the peer, we should simply configure-reject any authentication
* protocol. Else, if the peer is requesting an authentication
* protocol that we support and are willing to use, we should
* configure-ack. Else, we must be willing to do something, so
* we should pick our preference and configure-nak suggesting
* that.
*
* Preference for authentication protocols: RFC 1334 section 2
* requires preference of "stronger" authentication protocols
* (e.g. CHAP) over PAP, but this applies to the peer too so
* if he requests PAP we should not try to push him toward
* CHAP. So we just pick a favorite/best
*/
// ConPrintf(("lcp_reqci: rcvd AUTHTYPE"));
#if LCP_DEBUG
Printu("cp_reqci: rcvd AUTHTYP\r\n");
#endif
if (cilen < CILEN_SHORT)
{
/* too-short authentication-protocol CI: configure-nak */
nak_auth_ci:
orc = CONFNAK;
/* if we're just going to reject, don't bother suggesting */
if (reject_if_disagree)
break;
/* figure out how long the CI will be in the configure-nak */
#ifdef CHAP_SUPPORT
nakcilen = CILEN_SHORT + 1;
#else /* neg_pap assumed true */
nakcilen = CILEN_SHORT;
#endif
/* if it's longer, move the rest of the CIs up to make room */
if (nakcilen > cilen)
{
for (i = l - 1; i >= 0; i--)
next[i + (nakcilen - cilen)] = next[i];
next += (nakcilen - cilen);
}
/* start rewriting CI at its length */
p = cip + 1;
*p++ = nakcilen;
#ifdef CHAP_SUPPORT
{
cishort = PPP_CHAP;
ppp_putshort(p, cishort);
p += 2;
#ifdef MSCHAP_SUPPORT
cichar = CHAP_DIGEST_MSCHAP;
#else
cichar = CHAP_DIGEST_MD5;
#endif /* MSCHAP_SUPPORT */
*p++ = cichar;
}
#else
#ifdef PAP_SUPPORT
{
cishort = PPP_UPAP;
ppp_putshort(p, cishort);
p += 2;
}
#else
/* break to reject, we have no auth-protocol support */
break;
#endif /* PAP_SUPPORT */
#endif /* CHAP_SUPPORT */
/* remember new length */
cilen = nakcilen;
break;
}
cishort = ppp_getshort(p);
p += 2;
//ConPrintf("(%x)", cishort);
switch (cishort)
{
#ifdef PAP_SUPPORT
case PPP_UPAP:
if (cilen != CILEN_SHORT)
{
/* short length for PAP: configure-nak */
goto nak_auth_ci;
}
ho->neg_upap = 1;
break;
#endif /* PAP_SUPPORT */
#ifdef CHAP_SUPPORT
case PPP_CHAP:
if (cilen < (CILEN_SHORT + 1))
{
/* short length for CHAP: configure-nak */
goto nak_auth_ci;
}
cichar = *p++; /* get digest(algorithm) type */
#ifdef MSCHAP_SUPPORT
if ((cichar != CHAP_DIGEST_MSCHAP)
&& (cichar != CHAP_DIGEST_MD5))
#else
if (cichar != CHAP_DIGEST_MD5)
#endif /* MSCHAP_SUPPORT */
{
//ConPrintf("Bad MD5 digest type %x, NAKing\n", (int)cichar);
/* unrecognized algorithm: configure-nak */
goto nak_auth_ci;
}
ho->chap_mdtype = cichar;
ho->neg_chap = 1;
break;
#endif /* CHAP_SUPPORT */
default:
/* unrecognized protocol: configure-nak */
goto nak_auth_ci;
}
/*
* If we got here, we're happy with the requested option.
* Keep it.
*/
break;
#ifdef LQR_SUPPORT
case CI_QUALITY:
//ConPrintf(("lcp_reqci: rcvd QUALITY"));
if (cilen != CILEN_LQR)
{
orc = CONFREJ;
break;
}
cishort = ppp_getshort(p);
p += 2;
cilong = ppp_getlong(p);
p += 4;
//ConPrintf("(%x %lx)", cishort, cilong);
if (cishort != PPP_LQR)
{
orc = CONFREJ;
break;
}
/*
* Check the reporting period.
* XXX When should we Nak this, and what with?
*/
break;
#endif /* LQR_SUPPORT - LQR */
case CI_MAGICNUMBER:
//ConPrintf("lcp_reqci: rcvd MAGICNUMBER");
if (!(go->neg_magicnumber) || (cilen != CILEN_LONG))
{
orc = CONFREJ;
break;
}
cilong = ppp_getlong(p); /* leave p at value for now */
//ConPrintf("(%lx)", cilong);
/*
* He must have a different magic number.
*/
if (go->neg_magicnumber &&
cilong == go->magicnumber)
{
orc = CONFNAK;
cilong = ppp_magic(mppp);
ppp_putlong(p, cilong); /* p still points two value */
break;
}
p += 4; /* bump past magic number value */
ho->neg_magicnumber = 1;
ho->magicnumber = cilong;
break;
case CI_PCOMPRESSION:
//ConPrintf(("lcp_reqci: rcvd PCOMPRESSION"));
if (cilen != CILEN_VOID)
{
orc = CONFREJ;
break;
}
ho->neg_pcompression = 1;
break;
case CI_ACCOMPRESSION:
//ConPrintf(("lcp_reqci: rcvd ACCOMPRESSION"));
if (cilen != CILEN_VOID)
{
orc = CONFREJ;
break;
}
ho->neg_accompression = 1;
break;
#ifdef PPP_MULTILINK
case CI_ML_MRU:
/* This option signals that he wants a Multilink capable
* connection. The actual value of the ML-MRU can be any
* RFC-legal value.
*/
//ConPrintf(("lcp_reqci: rcvd MULTILINK_MRU"));
if((mppp->pppflags & ALLOW_ML) == 0)
{
orc = CONFREJ;
break;
}
ho->ml_mru = ppp_getshort(p);
ho->neg_ml_mru = 1;
p += 2;
break;
case CI_ML_SSN: /* Short sequence number option OK */
//ConPrintf(("lcp_reqci: rcvd MULTILINK_SSN"));
if((mppp->pppflags & ALLOW_ML) == 0)
{
orc = CONFREJ;
break;
}
ho->neg_ml_ssn = 1;
break;
case CI_ML_ENDP:
//ConPrintf(("lcp_reqci: rcvd MULTILINK_ENDPT"));
if((mppp->pppflags & ALLOW_ML) == 0)
{
orc = CONFREJ;
break;
}
ho->neg_ml_endp = 1;
/* fill in MPPP fields from requested Endpoint descriptor. RFC1990
* disallows NAKing any particular values he wants to use, we can
* only reject (or accept) the entire option. We will use these
* values to start a new bundle or join an existing one when LCP
* comes up.
*/
mppp->ml_conf.endp_class = *p++;
mppp->ml_conf.endp_length = (u_char)(cilen - 3);
MEMCPY(mppp->ml_conf.endp_desc, p, cilen - 3);
break;
#endif
default:
//ConPrintf("lcp_reqci: rcvd unknown option %d", citype);
orc = CONFREJ;
break;
}
endswitch:
// ConPrintf("(%s)\n", CODENAME(orc));
if ((orc == CONFACK) && /* Good CI and */
(rc != CONFACK)) /* prior CI wasnt? */
{
continue; /* Don't send this one */
}
if (orc == CONFNAK) /* Nak this CI? */
{
if (reject_if_disagree) /* Getting fed up with sending NAKs? */
orc = CONFREJ; /* Get tough if so */
else
{
if (rc == CONFREJ) /* Rejecting prior CI? */
continue; /* Don't send this one */
if (rc == CONFACK) /* Ack'd all prior CIs? */
{
rc = CONFNAK; /* Not anymore... */
ucp = inp; /* Backup */
}
}
}
if((orc == CONFREJ) && /* Reject this CI */
(rc != CONFREJ)) /* but no prior ones? */
{
rc = CONFREJ;
ucp = inp; /* Backup */
}
if (ucp != cip) /* Need to move CI? */
MEMCPY(ucp, cip, cilen); /* Move it */
ucp += cilen; /* Update output pointer */
}
/*
* If we wanted to send additional NAKs (for unsent CIs), the
* code would go here. This must be done with care since it might
* require a longer packet than we received. At present there
* are no cases where we want to ask the peer to negotiate an option.
*/
*lenp = ucp - inp; /* Compute output length */
//ConPrintf("lcp_reqci: returning CONF%s.\n", CODENAME(rc));
/* RFC1661 actions (pg 10) don't distinguish between send-conf-nak and
* send-conf-reject; however we need to. Set the PPP flags bit to
* indicate to the logic which will form the NAK/REJ reply which code
* to use.
*/
if(rc == CONFREJ)
mppp->pppflags |= SEND_REJECT;
else
mppp->pppflags &= ~SEND_REJECT;
return (rc); /* Return final code */
}
/* FUNCTION: lcp_finished()
*
* lcp_finished - LCP has finished with the lower layer.
*
*
* PARAM1: M_PPP mppp
*
* RETURNS:
*/
void
lcp_finished(M_PPP mppp)
{
#if LCP_DEBUG
Printu("lcp_finished\r\n");
#endif
mppp->line.ln_disconnect(&mppp->line);
}
/* FUNCTION: lcp_starting()
*
* lcp_starting - LCP needs the lower layer up.
*
* PARAM1: M_PPP mppp
*
* RETURNS: void
*/
void
lcp_starting(M_PPP mppp)
{
#if LCP_DEBUG
Printu("lcp_starting\r\n");
#endif
mppp->line.ln_connect(&mppp->line);
}
#endif /* USE_PPP */
/* end of file lcp.c */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?