📄 lcp.c
字号:
} /* * We don't recognize the protocol they're asking for. * Nak it with something we're willing to do. * (At this point we know ao->neg_upap || ao->neg_chap.) */ orc = CONFNAK; PUTCHAR(CI_AUTHTYPE, nakp); if (ao->neg_chap) { PUTCHAR(CILEN_CHAP, nakp); PUTSHORT(CHAP, nakp); PUTCHAR(ao->chap_mdtype, nakp); } else { PUTCHAR(CILEN_SHORT, nakp); PUTSHORT(UPAP, nakp); } break; case CI_QUALITY: LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY")); if (!ao->neg_lqr || cilen != CILEN_LQR) { orc = CONFREJ; break; } GETSHORT(cishort, p); GETLONG(cilong, p); LCPDEBUG((LOG_INFO, "(%x %lx)", cishort, cilong)); /* * Check the protocol and the reporting period. * XXX When should we Nak this, and what with? */ if (cishort != LQR) { orc = CONFNAK; PUTCHAR(CI_QUALITY, nakp); PUTCHAR(CILEN_LQR, nakp); PUTSHORT(LQR, nakp); PUTLONG(ao->lqr_period, nakp); break; } break; case CI_MAGICNUMBER: LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MAGICNUMBER")); if (!(ao->neg_magicnumber || go->neg_magicnumber) || cilen != CILEN_LONG) { orc = CONFREJ; break; } GETLONG(cilong, p); LCPDEBUG((LOG_INFO, "(%lx)", cilong)); /* * He must have a different magic number. */ if (go->neg_magicnumber && cilong == go->magicnumber) { orc = CONFNAK; cilong = magic(); /* Don't put magic() inside macro! */ orc = CONFNAK; PUTCHAR(CI_MAGICNUMBER, nakp); PUTCHAR(CILEN_LONG, nakp); PUTLONG(cilong, nakp); break; } ho->neg_magicnumber = 1; ho->magicnumber = cilong; break; case CI_PCOMPRESSION: LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION")); if (!ao->neg_pcompression || cilen != CILEN_VOID) { orc = CONFREJ; break; } ho->neg_pcompression = 1; break; case CI_ACCOMPRESSION: LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION")); if (!ao->neg_accompression || cilen != CILEN_VOID) { orc = CONFREJ; break; } ho->neg_accompression = 1; break; default: LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d", citype)); orc = CONFREJ; break; }endswitch: LCPDEBUG((LOG_INFO, " (%s)", CODENAME(orc))); 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((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc))); return (rc); /* Return final code */}/* * lcp_up - LCP has come UP. * * Start UPAP, IPCP, etc. */static voidlcp_up(f) fsm *f;{ lcp_options *wo = &ppp_if[f->unit]->lcp_wantoptions; lcp_options *ho = &ppp_if[f->unit]->lcp_hisoptions; lcp_options *go = &ppp_if[f->unit]->lcp_gotoptions; lcp_options *ao = &ppp_if[f->unit]->lcp_allowoptions; 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, MIN(ao->mru? ao->mru: MTU, (ho->neg_mru? ho->mru: MTU)), (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), 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? MAX(wo->mru, go->mru): MTU), (go->neg_asyncmap? go->asyncmap: 0x00000000), go->neg_pcompression, go->neg_accompression); if (ho->neg_mru) ppp_if[f->unit]->peer_mru = ho->mru; ChapLowerUp(f->unit); /* Enable CHAP */ upap_lowerup(f->unit); /* Enable UPAP */ ipcp_lowerup(f->unit); /* Enable IPCP */ 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_echo_lowerdown(f->unit); ipcp_lowerdown(f->unit); ChapLowerDown(f->unit); upap_lowerdown(f->unit); sifdown(f->unit); ppp_send_config(f->unit, MTU, 0xffffffff, 0, 0); ppp_recv_config(f->unit, MTU, 0x00000000, 0, 0); ppp_if[f->unit]->peer_mru = MTU; link_down(f->unit);}/* * 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;{ /* if passive or silent flags set and if lcp state is STOPPED or CLOSED * then reopen the link for the next connection */ if (((f->state == STOPPED) || (f->state == CLOSED)) && (f->flags & OPT_RESTART)) fsm_open (f); else link_terminated(f->unit);}/* * lcp_printpkt - print the contents of an LCP packet. */char *lcp_codenames[] = { "ConfReq", "ConfAck", "ConfNak", "ConfRej", "TermReq", "TermAck", "CodeRej", "ProtRej", "EchoReq", "EchoRep", "DiscReq"};intlcp_printpkt(p, plen, printer, arg) u_char *p; int plen; void (*printer) __ARGS((void *, char *, ...)); void *arg;{ int code, id, len, olen; u_char *pstart, *optend; u_short cishort; u_long 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 UPAP: printer(arg, "upap"); break; case 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 LQR: printer(arg, "lqr"); 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; } /* print the rest of the bytes in the packet */ for (; len > 0; --len) { GETCHAR(code, p); printer(arg, " %.2x", code); } return p - pstart;}/* * Time to shut down the link because there is nothing out there. */staticvoid LcpLinkFailure (f) fsm *f;{ if (f->state == OPENED) { syslog (LOG_NOTICE, "Excessive lack of response to LCP echo frames."); lcp_lowerdown(f->unit); /* Reset connection */ ppp_if[f->unit]->phase = PHASE_TERMINATE; }}/* * Timer expired for the LCP echo requests from this process. */static voidLcpEchoCheck (f) fsm *f;{ u_long delta;#ifdef __linux__ struct ppp_ddinfo ddinfo; u_long latest;/* * Read the time since the last packet was received. */ if (ioctl (fd, PPPIOCGTIME, &ddinfo) < 0) { syslog (LOG_ERR, "ioctl(PPPIOCGTIME): %m"); die (1); }/* * Choose the most recient frame received. It may be an IP or NON-IP frame. */ latest = ddinfo.nip_rjiffies < ddinfo.ip_rjiffies ? ddinfo.nip_rjiffies : ddinfo.ip_rjiffies;/* * Compute the time since the last packet was received. If the timer * has expired then send the echo request and reset the timer to maximum. */ delta = (lcp_echo_interval * HZ) - latest; if (delta < HZ || latest < 0L) { LcpSendEchoRequest (f); delta = lcp_echo_interval * HZ; } delta /= HZ;#else /* Other implementations do not have ability to find delta */ LcpSendEchoRequest (f); delta = ppp_if[f->unit]->lcp_echo_interval;#endif/* * Start the timer for the next interval. */ assert (ppp_if[f->unit]->lcp_echo_timer_running==0); PPP_TIMEOUT (LcpEchoTimeout, (caddr_t) f, delta); ppp_if[f->unit]->lcp_echo_timer_running = 1;}/* * LcpEchoTimeout - Timer expired on the LCP echo */static voidLcpEchoTimeout (arg) caddr_t arg;{ fsm *f = (fsm *)arg; if (ppp_if[f->unit]->lcp_echo_timer_running != 0) { ppp_if[f->unit]->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_long magic; /* Check the magic number - don't count replies from ourselves. */#ifdef notyet if (len < CILEN_LONG) return;#endif /* notyet */ GETLONG(magic, inp); if (ppp_if[f->unit]->lcp_gotoptions.neg_magicnumber && magic == ppp_if[f->unit]->lcp_gotoptions.magicnumber) return; /* Reset the number of outstanding echo frames */ ppp_if[f->unit]->lcp_echos_pending = 0;}/* * LcpSendEchoRequest - Send an echo request frame to the peer */static voidLcpSendEchoRequest (f) fsm *f;{ u_long lcp_magic; u_char pkt[4], *pktp;/* * Detect the failure of the peer at this point. */ if (ppp_if[f->unit]->lcp_echo_fails != 0) { if (ppp_if[f->unit]->lcp_echos_pending++ >= ppp_if[f->unit]->lcp_echo_fails) { LcpLinkFailure(f); ppp_if[f->unit]->lcp_echos_pending = 0; die(f->unit, 1); } }/* * Make and send the echo request frame. */ if (f->state == OPENED) { lcp_magic = ppp_if[f->unit]->lcp_gotoptions.neg_magicnumber ? ppp_if[f->unit]->lcp_gotoptions.magicnumber : 0L; pktp = pkt; PUTLONG(lcp_magic, pktp); fsm_sdata(f, ECHOREQ, ppp_if[f->unit]->lcp_echo_number++ & 0xFF, pkt, pktp - pkt); }}/* * lcp_echo_lowerup - Start the timer for the LCP frame */static voidlcp_echo_lowerup (unit) int unit;{ fsm *f = &ppp_if[unit]->lcp_fsm; /* Clear the parameters for generating echo frames */ ppp_if[unit]->lcp_echos_pending = 0; ppp_if[unit]->lcp_echo_number = 0; ppp_if[unit]->lcp_echo_timer_running = 0; /* If a timeout interval is specified then start the timer */ if (ppp_if[unit]->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 = &ppp_if[unit]->lcp_fsm; if (ppp_if[unit]->lcp_echo_timer_running != 0) { PPP_UNTIMEOUT (LcpEchoTimeout, (caddr_t) f); ppp_if[unit]->lcp_echo_timer_running = 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -