📄 lcp.c
字号:
#endif
orc = CONFREJ;
break;
default:
#if TRACELCP
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype);
traceNdx = strlen(traceBuf);
#endif
orc = CONFREJ;
break;
}
endswitch:
#if TRACELCP
if (traceNdx >= 80 - 32) {
LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd%s\n", traceBuf));
traceNdx = 0;
}
#endif
if (orc == CONFACK && /* Good CI */
rc != CONFACK) { /* but 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? */
&& citype != CI_MAGICNUMBER) {
orc = CONFREJ; /* Get tough if so */
} else {
if (rc == CONFREJ) { /* Rejecting prior CI? */
continue; /* Don't send this one */
}
rc = CONFNAK;
}
}
if (orc == CONFREJ) { /* Reject this CI */
rc = CONFREJ;
if (cip != rejp) { /* Need to move rejected CI? */
BCOPY(cip, rejp, cilen); /* Move it */
}
INCPTR(cilen, rejp); /* Update output pointer */
}
}
/*
* If we wanted to send additional NAKs (for unsent CIs), the
* code would go here. The extra NAKs would go at *nakp.
* At present there are no cases where we want to ask the
* peer to negotiate an option.
*/
switch (rc) {
case CONFACK:
*lenp = (int)(next - inp);
break;
case CONFNAK:
/*
* Copy the Nak'd options from the nak_buffer to the caller's buffer.
*/
*lenp = (int)(nakp - nak_buffer);
BCOPY(nak_buffer, inp, *lenp);
break;
case CONFREJ:
*lenp = (int)(rejp - inp);
break;
}
#if TRACELCP > 0
if (traceNdx > 0) {
LCPDEBUG((LOG_INFO, "lcp_reqci: %s\n", traceBuf));
}
#endif
LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.\n", CODENAME(rc)));
return (rc); /* Return final code */
}
/*
* lcp_up - LCP has come UP.
*/
static void
lcp_up(fsm *f)
{
lcp_options *wo = &lcp_wantoptions[f->unit];
lcp_options *ho = &lcp_hisoptions[f->unit];
lcp_options *go = &lcp_gotoptions[f->unit];
lcp_options *ao = &lcp_allowoptions[f->unit];
if (!go->neg_magicnumber) {
go->magicnumber = 0;
}
if (!ho->neg_magicnumber) {
ho->magicnumber = 0;
}
/*
* Set our MTU to the smaller of the MTU we wanted and
* the MRU our peer wanted. If we negotiated an MRU,
* set our MRU to the larger of value we wanted and
* the value we got in the negotiation.
*/
ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
(ho->neg_asyncmap? ho->asyncmap: 0xffffffffl),
ho->neg_pcompression, ho->neg_accompression);
/*
* If the asyncmap hasn't been negotiated, we really should
* set the receive asyncmap to ffffffff, but we set it to 0
* for backwards contemptibility.
*/
ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU),
(go->neg_asyncmap? go->asyncmap: 0x00000000),
go->neg_pcompression, go->neg_accompression);
if (ho->neg_mru) {
peer_mru[f->unit] = ho->mru;
}
lcp_echo_lowerup(f->unit); /* Enable echo messages */
link_established(f->unit);
}
/*
* lcp_down - LCP has gone DOWN.
*
* Alert other protocols.
*/
static void
lcp_down(fsm *f)
{
lcp_options *go = &lcp_gotoptions[f->unit];
lcp_echo_lowerdown(f->unit);
link_down(f->unit);
ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0);
ppp_recv_config(f->unit, PPP_MRU,
(go->neg_asyncmap? go->asyncmap: 0x00000000),
go->neg_pcompression, go->neg_accompression);
peer_mru[f->unit] = PPP_MRU;
}
/*
* lcp_starting - LCP needs the lower layer up.
*/
static void
lcp_starting(fsm *f)
{
link_required(f->unit);
}
/*
* lcp_finished - LCP has finished with the lower layer.
*/
static void
lcp_finished(fsm *f)
{
link_terminated(f->unit);
}
#if 0
/*
* print_string - print a readable representation of a string using
* printer.
*/
static void
print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg)
{
int c;
printer(arg, "\"");
for (; len > 0; --len) {
c = *p++;
if (' ' <= c && c <= '~') {
if (c == '\\' || c == '"') {
printer(arg, "\\");
}
printer(arg, "%c", c);
} else {
switch (c) {
case '\n':
printer(arg, "\\n");
break;
case '\r':
printer(arg, "\\r");
break;
case '\t':
printer(arg, "\\t");
break;
default:
printer(arg, "\\%.3o", c);
}
}
}
printer(arg, "\"");
}
/*
* lcp_printpkt - print the contents of an LCP packet.
*/
static char *lcp_codenames[] = {
"ConfReq", "ConfAck", "ConfNak", "ConfRej",
"TermReq", "TermAck", "CodeRej", "ProtRej",
"EchoReq", "EchoRep", "DiscReq"
};
static int
lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
{
int code, id, len, olen;
u_char *pstart, *optend;
u_short cishort;
u32_t cilong;
if (plen < HEADERLEN) {
return 0;
}
pstart = p;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < HEADERLEN || len > plen) {
return 0;
}
if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) {
printer(arg, " %s", lcp_codenames[code-1]);
} else {
printer(arg, " code=0x%x", code);
}
printer(arg, " id=0x%x", id);
len -= HEADERLEN;
switch (code) {
case CONFREQ:
case CONFACK:
case CONFNAK:
case CONFREJ:
/* print option list */
while (len >= 2) {
GETCHAR(code, p);
GETCHAR(olen, p);
p -= 2;
if (olen < 2 || olen > len) {
break;
}
printer(arg, " <");
len -= olen;
optend = p + olen;
switch (code) {
case CI_MRU:
if (olen == CILEN_SHORT) {
p += 2;
GETSHORT(cishort, p);
printer(arg, "mru %d", cishort);
}
break;
case CI_ASYNCMAP:
if (olen == CILEN_LONG) {
p += 2;
GETLONG(cilong, p);
printer(arg, "asyncmap 0x%lx", cilong);
}
break;
case CI_AUTHTYPE:
if (olen >= CILEN_SHORT) {
p += 2;
printer(arg, "auth ");
GETSHORT(cishort, p);
switch (cishort) {
case PPP_PAP:
printer(arg, "pap");
break;
case PPP_CHAP:
printer(arg, "chap");
break;
default:
printer(arg, "0x%x", cishort);
}
}
break;
case CI_QUALITY:
if (olen >= CILEN_SHORT) {
p += 2;
printer(arg, "quality ");
GETSHORT(cishort, p);
switch (cishort) {
case PPP_LQR:
printer(arg, "lqr");
break;
default:
printer(arg, "0x%x", cishort);
}
}
break;
case CI_CALLBACK:
if (olen >= CILEN_CHAR) {
p += 2;
printer(arg, "callback ");
GETSHORT(cishort, p);
switch (cishort) {
case CBCP_OPT:
printer(arg, "CBCP");
break;
default:
printer(arg, "0x%x", cishort);
}
}
break;
case CI_MAGICNUMBER:
if (olen == CILEN_LONG) {
p += 2;
GETLONG(cilong, p);
printer(arg, "magic 0x%x", cilong);
}
break;
case CI_PCOMPRESSION:
if (olen == CILEN_VOID) {
p += 2;
printer(arg, "pcomp");
}
break;
case CI_ACCOMPRESSION:
if (olen == CILEN_VOID) {
p += 2;
printer(arg, "accomp");
}
break;
}
while (p < optend) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
printer(arg, ">");
}
break;
case TERMACK:
case TERMREQ:
if (len > 0 && *p >= ' ' && *p < 0x7f) {
printer(arg, " ");
print_string((char*)p, len, printer, arg);
p += len;
len = 0;
}
break;
case ECHOREQ:
case ECHOREP:
case DISCREQ:
if (len >= 4) {
GETLONG(cilong, p);
printer(arg, " magic=0x%x", cilong);
p += 4;
len -= 4;
}
break;
}
/* print the rest of the bytes in the packet */
for (; len > 0; --len) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
return (int)(p - pstart);
}
#endif
/*
* Time to shut down the link because there is nothing out there.
*/
static void
LcpLinkFailure (fsm *f)
{
if (f->state == LS_OPENED) {
LCPDEBUG((LOG_INFO, "No response to %d echo-requests\n", lcp_echos_pending));
LCPDEBUG((LOG_NOTICE, "Serial link appears to be disconnected.\n"));
lcp_close(f->unit, "Peer not responding");
}
}
/*
* Timer expired for the LCP echo requests from this process.
*/
static void
LcpEchoCheck (fsm *f)
{
LcpSendEchoRequest (f);
/*
* Start the timer for the next interval.
*/
LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0);
TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
lcp_echo_timer_running = 1;
}
/*
* LcpEchoTimeout - Timer expired on the LCP echo
*/
static void
LcpEchoTimeout (void *arg)
{
if (lcp_echo_timer_running != 0) {
lcp_echo_timer_running = 0;
LcpEchoCheck ((fsm *) arg);
}
}
/*
* LcpEchoReply - LCP has received a reply to the echo
*/
static void
lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len)
{
u32_t magic;
LWIP_UNUSED_ARG(id);
/* Check the magic number - don't count replies from ourselves. */
if (len < 4) {
LCPDEBUG((LOG_WARNING, "lcp: received short Echo-Reply, length %d\n", len));
return;
}
GETLONG(magic, inp);
if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) {
LCPDEBUG((LOG_WARNING, "appear to have received our own echo-reply!\n"));
return;
}
/* Reset the number of outstanding echo frames */
lcp_echos_pending = 0;
}
/*
* LcpSendEchoRequest - Send an echo request frame to the peer
*/
static void
LcpSendEchoRequest (fsm *f)
{
u32_t lcp_magic;
u_char pkt[4], *pktp;
/*
* Detect the failure of the peer at this point.
*/
if (lcp_echo_fails != 0) {
if (lcp_echos_pending++ >= lcp_echo_fails) {
LcpLinkFailure(f);
lcp_echos_pending = 0;
}
}
/*
* Make and send the echo request frame.
*/
if (f->state == LS_OPENED) {
lcp_magic = lcp_gotoptions[f->unit].magicnumber;
pktp = pkt;
PUTLONG(lcp_magic, pktp);
fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt));
}
}
/*
* lcp_echo_lowerup - Start the timer for the LCP frame
*/
static void
lcp_echo_lowerup (int unit)
{
fsm *f = &lcp_fsm[unit];
/* Clear the parameters for generating echo frames */
lcp_echos_pending = 0;
lcp_echo_number = 0;
lcp_echo_timer_running = 0;
/* If a timeout interval is specified then start the timer */
if (lcp_echo_interval != 0) {
LcpEchoCheck (f);
}
}
/*
* lcp_echo_lowerdown - Stop the timer for the LCP frame
*/
static void
lcp_echo_lowerdown (int unit)
{
fsm *f = &lcp_fsm[unit];
if (lcp_echo_timer_running != 0) {
UNTIMEOUT (LcpEchoTimeout, f);
lcp_echo_timer_running = 0;
}
}
#endif /* PPP_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -