📄 lcp.c
字号:
break; } GETSHORT(cishort, p); /* possibly should insist on a minimum/maximum MRRU here */ ho->neg_mrru = 1; ho->mrru = cishort; break; case CI_SSNHF: if (!ao->neg_ssnhf || !multilink || cilen != CILEN_VOID) { orc = CONFREJ; break; } ho->neg_ssnhf = 1; break; case CI_EPDISC: if (!ao->neg_endpoint || cilen < CILEN_CHAR || cilen > CILEN_CHAR + MAX_ENDP_LEN) { orc = CONFREJ; break; } GETCHAR(cichar, p); cilen -= CILEN_CHAR; ho->neg_endpoint = 1; ho->endpoint.class = cichar; ho->endpoint.length = cilen; BCOPY(p, ho->endpoint.value, cilen); INCPTR(cilen, p); break; default: LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype)); orc = CONFREJ; break; }endswitch: 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 = next - inp; break; case CONFNAK: /* * Copy the Nak'd options from the nak_buffer to the caller's buffer. */ *lenp = nakp - nak_buffer; BCOPY(nak_buffer, inp, *lenp); break; case CONFREJ: *lenp = rejp - inp; break; } LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); return (rc); /* Return final code */}/* * lcp_up - LCP has come UP. */static voidlcp_up(f) 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]; int mtu; 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. * Note on the MTU: the link MTU can be the MRU the peer wanted, * the interface MTU is set to the lower of that and the * MTU we want to use. */ mtu = ho->neg_mru? ho->mru: PPP_MRU;#ifdef HAVE_MULTILINK if (!(multilink && go->neg_mrru && ho->neg_mrru))#endif /* HAVE_MULTILINK */ netif_set_mtu(f->unit, MIN(mtu, ao->mru)); ppp_send_config(f->unit, mtu, (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), ho->neg_pcompression, ho->neg_accompression); ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU), (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), 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 voidlcp_down(f) 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, 0xffffffff, 0, 0); ppp_recv_config(f->unit, PPP_MRU, (go->neg_asyncmap? go->asyncmap: 0xffffffff), go->neg_pcompression, go->neg_accompression); peer_mru[f->unit] = PPP_MRU;}/* * lcp_starting - LCP needs the lower layer up. */static voidlcp_starting(f) fsm *f;{ link_required(f->unit);}/* * lcp_finished - LCP has finished with the lower layer. */static voidlcp_finished(f) fsm *f;{ link_terminated(f->unit);}/* * 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 intlcp_printpkt(p, plen, printer, arg) u_char *p; int plen; void (*printer) __P((void *, char *, ...)); void *arg;{ int code, id, len, olen, i; u_char *pstart, *optend; u_short cishort; u_int32_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%x", 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"); if (p < optend) { switch (*p) { case CHAP_DIGEST_MD5: printer(arg, " MD5"); ++p; break;#ifdef CHAPMS case CHAP_MICROSOFT: printer(arg, " m$oft"); ++p; break;#endif } } 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 "); GETCHAR(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; case CI_MRRU: if (olen == CILEN_SHORT) { p += 2; GETSHORT(cishort, p); printer(arg, "mrru %d", cishort); } break; case CI_SSNHF: if (olen == CILEN_VOID) { p += 2; printer(arg, "ssnhf"); } break; case CI_EPDISC:#ifdef HAVE_MULTILINK if (olen >= CILEN_CHAR) { struct epdisc epd; p += 2; GETCHAR(epd.class, p); epd.length = olen - CILEN_CHAR; if (epd.length > MAX_ENDP_LEN) epd.length = MAX_ENDP_LEN; if (epd.length > 0) { BCOPY(p, epd.value, epd.length); p += epd.length; } printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); }#else printer(arg, "endpoint");#endif 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 (i = 0; i < len && i < 32; ++i) { GETCHAR(code, p); printer(arg, " %.2x", code); } if (i < len) { printer(arg, " ..."); p += len - i; } return p - pstart;}/* * Time to shut down the link because there is nothing out there. */staticvoid LcpLinkFailure (f) fsm *f;{ if (f->state == OPENED) { info("No response to %d echo-requests", lcp_echos_pending); notice("Serial link appears to be disconnected."); lcp_close(f->unit, "Peer not responding"); status = EXIT_PEER_DEAD; }}/* * Timer expired for the LCP echo requests from this process. */static voidLcpEchoCheck (f) fsm *f;{ LcpSendEchoRequest (f); if (f->state != OPENED) return; /* * Start the timer for the next interval. */ if (lcp_echo_timer_running) warn("assertion lcp_echo_timer_running==0 failed"); TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); lcp_echo_timer_running = 1;}/* * LcpEchoTimeout - Timer expired on the LCP echo */static voidLcpEchoTimeout (arg) 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 voidlcp_received_echo_reply (f, id, inp, len) fsm *f; int id; u_char *inp; int len;{ u_int32_t magic; /* Check the magic number - don't count replies from ourselves. */ if (len < 4) { dbglog("lcp: received short Echo-Reply, length %d", len); return; } GETLONG(magic, inp); if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) { warn("appear to have received our own echo-reply!"); return; } /* Reset the number of outstanding echo frames */ lcp_echos_pending = 0;}/* * LcpSendEchoRequest - Send an echo request frame to the peer */static voidLcpSendEchoRequest (f) fsm *f;{ u_int32_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 == OPENED) { lcp_magic = lcp_gotoptions[f->unit].magicnumber; pktp = pkt; PUTLONG(lcp_magic, pktp); fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt); ++lcp_echos_pending; }}/* * lcp_echo_lowerup - Start the timer for the LCP frame */static voidlcp_echo_lowerup (unit) 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 voidlcp_echo_lowerdown (unit) int unit;{ fsm *f = &lcp_fsm[unit]; if (lcp_echo_timer_running != 0) { UNTIMEOUT (LcpEchoTimeout, f); lcp_echo_timer_running = 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -