📄 if_ppp.c
字号:
struct ppp_softc *sc;{ int s; NETBUF_T m; u_char *cp; int address, control, protocol;#if NS_TARGET >= 40 struct timeval tv_time;#endif /* * Grab a packet to send: first try the fast queue, then the * normal queue. */ m = nbq_dequeue(&sc->sc_fastq); if (m == NULL) m = nbq_dequeue(&sc->sc_slowq); if (m == NULL) return; /* * Extract the ppp header of the new packet. * The ppp header will be in one netbuf. */ cp = mtod(m, u_char *); address = PPP_ADDRESS(cp); control = PPP_CONTROL(cp); protocol = PPP_PROTOCOL(cp);#if NS_TARGET >= 40 ns_time_to_timeval(clock_value(System), &tv_time);#endif /* NS_TARGET */ switch (protocol) { case PPP_IP: /* * Update the time we sent the most recent packet. */#if NS_TARGET >= 40 sc->sc_last_sent = tv_time.tv_sec;#else sc->sc_last_sent = time.tv_sec;#endif /* NS_TARGET */#ifdef VJC /* * If the packet is a TCP/IP packet, see if we can compress it. */ if (sc->sc_flags & SC_COMP_TCP) { struct ip *ip; int type; u_char *vjhdr; ip = (struct ip *) (cp + PPP_HDRLEN); /* this code assumes the IP/TCP header is in one netbuf */ if (ip->ip_p == IPPROTO_TCP) { type = vj_compress_tcp(ip, NB_SIZE(m) - PPP_HDRLEN, &sc->sc_comp, !(sc->sc_flags & SC_NO_TCP_CCID), &vjhdr); switch (type) { case TYPE_UNCOMPRESSED_TCP: protocol = PPP_VJC_UNCOMP; break; case TYPE_COMPRESSED_TCP: NB_SHRINK_TOP(m, vjhdr - (u_char *) ip); protocol = PPP_VJC_COMP; cp = mtod(m, u_char *); cp[0] = address; /* header has moved */ cp[1] = control; cp[2] = 0; break; } cp[3] = protocol; /* update protocol in PPP header */ } }#endif /* VJC */ break;#ifdef PPP_COMPRESS case PPP_CCP: ppp_ccp(sc, m, 0); break;#endif /* PPP_COMPRESS */ }#ifdef PPP_COMPRESS if (protocol != PPP_LCP && protocol != PPP_CCP && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { NETBUF_T mcomp; int slen, clen; slen = NB_SIZE(m); clen = (*sc->sc_xcomp->compress) (sc->sc_xc_state, &mcomp, m, slen, sc->sc_flags & SC_CCP_UP? if_mtu(sc->sc_if): 0); if (mcomp && (NB_SIZE(mcomp) >= slen)) IOLog("BSD Warning... packet growth: Orig=%d New=%d.\n", slen, NB_SIZE(mcomp)); if (mcomp != NULL) { NB_FREE(m); m = mcomp; cp = mtod(m, u_char *); protocol = cp[3]; } }#endif /* PPP_COMPRESS */ /* * Compress the address/control and protocol, if possible. */ if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && control == PPP_UI && protocol != PPP_ALLSTATIONS && protocol != PPP_LCP) { /* can compress address/control */ NB_SHRINK_TOP(m, 2); } if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { /* can compress protocol */ if (mtod(m, u_char *) == cp) { cp[2] = cp[1]; /* move address/control up */ cp[1] = cp[0]; } NB_SHRINK_TOP(m, 1); } s = splimp(); nbq_enqueue(&sc->sc_compq, m); (*sc->sc_start)(sc); splx(s);}#ifdef PPP_COMPRESS/* * Handle a CCP packet. `rcvd' is 1 if the packet was received, * 0 if it is about to be transmitted. */static voidppp_ccp(sc, m, rcvd) struct ppp_softc *sc; NETBUF_T m; int rcvd;{ u_char *dp, *ep; int slen, s; /* * Get a pointer to the data after the PPP header. */ dp = mtod(m, u_char *) + PPP_HDRLEN; ep = mtod(m, u_char *) + NB_SIZE(m); if (dp + CCP_HDRLEN > ep) return; slen = CCP_LENGTH(dp); if (dp + slen > ep) { IOLogDbg("ppp%d: ccp: not enough data in netbuf (%x+%x > %x+%x)\n", if_unit(sc->sc_if), dp, slen, mtod(m, u_char *), NB_SIZE(m)); return; } switch (CCP_CODE(dp)) { case CCP_CONFREQ: case CCP_TERMREQ: case CCP_TERMACK: /* CCP must be going down - disable compression */ if (sc->sc_flags & SC_CCP_UP) { s = splimp(); sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); splx(s); } break; case CCP_CONFACK: if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) && slen >= CCP_HDRLEN + CCP_OPT_MINLEN && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { if (!rcvd) { /* we're agreeing to send compressed packets. */ if (sc->sc_xc_state != NULL && (*sc->sc_xcomp->comp_init) (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, if_unit(sc->sc_if), 0, sc->sc_flags & SC_DEBUG)) { s = splimp(); sc->sc_flags |= SC_COMP_RUN; splx(s); } } else { /* peer is agreeing to send compressed packets. */ if (sc->sc_rc_state != NULL && (*sc->sc_rcomp->decomp_init) (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, if_unit(sc->sc_if),#ifdef VJC VJ_HDRLEN +#endif 0, sc->sc_mru, sc->sc_flags & SC_DEBUG)) { s = splimp(); sc->sc_flags |= SC_DECOMP_RUN; sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); splx(s); } } } break; case CCP_RESETACK: if (sc->sc_flags & SC_CCP_UP) { if (!rcvd) { if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); nbq_flush(&sc->sc_compq); /* Flush pre-compressed packets */ } } else { if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); s = splimp(); sc->sc_flags &= ~SC_DC_ERROR; splx(s); } } } break; }}/* * CCP is down; free (de)compressor state if necessary. */static voidppp_ccp_closed(sc) struct ppp_softc *sc;{ if (sc->sc_xc_state) { (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); sc->sc_xc_state = NULL; } if (sc->sc_rc_state) { (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); sc->sc_rc_state = NULL; }}#endif /* PPP_COMPRESS *//* * PPP packet input routine. * The caller has checked and removed the FCS and has inserted * the address/control bytes and the protocol high byte if they * were omitted. */voidppppktin(sc, m, lost) struct ppp_softc *sc; NETBUF_T m; int lost;{ int error, s = splimp(); NB_SET_MARK(m,(lost ? M_ERRMARK : 0)); /* XXX - we should check for the raw queue overflowing... */ nbq_enqueue(&sc->sc_rawq, m); if (!sc->sc_decompsched) { if ((error = pppsched(pppintr_decomp, sc)) == KERN_SUCCESS) sc->sc_decompsched = 1; else IOLogDbg("ppp%d: decompression callout failed returning %d\n", if_unit(sc->sc_if), error); } splx(s);}/* * Process a received PPP packet, doing decompression as necessary. */#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ TYPE_UNCOMPRESSED_TCP)static voidppp_inproc(sc, m) struct ppp_softc *sc; NETBUF_T m;{ struct nb_queue *inq; int s, ilen, xlen, proto, rv; mark_t flags; u_char *cp, adrs, ctrl; NETBUF_T dmp; u_char *iphdr; u_int hlen;#if NS_TARGET >= 40 struct timeval tv_time;#endif /* NS_TARGET */ incr_cnt(sc->sc_if, if_ipackets); NB_GET_MARK(m,&flags); if (sc->sc_flags & SC_LOG_INPKT) { IOLog("ppp%d: got %d bytes\n", if_unit(sc->sc_if), NB_SIZE(m)); pppdumpm(m); } cp = mtod(m, u_char *); adrs = PPP_ADDRESS(cp); ctrl = PPP_CONTROL(cp); proto = PPP_PROTOCOL(cp); if (flags & M_ERRMARK) { s = splimp(); sc->sc_flags |= SC_VJ_RESET; splx(s); }#ifdef PPP_COMPRESS /* * Decompress this packet if necessary, update the receiver's * dictionary, or take appropriate action on a CCP packet. */ if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { /* decompress this packet */ rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); if (rv == DECOMP_OK){ NB_FREE(m); if (dmp == NULL){ /* No error, but no decompressed packet returned */ return; } m = dmp; cp = mtod(m, u_char *); proto = PPP_PROTOCOL(cp); } else { /* * An error has occurred in decompression. * Pass the compressed packet up to pppd, which may take * CCP down or issue a Reset-Req. */ IOLogDbg("ppp%d: decompress failed %d\n", if_unit(sc->sc_if), rv); s = splimp(); sc->sc_flags |= SC_VJ_RESET; if (rv == DECOMP_ERROR) sc->sc_flags |= SC_DC_ERROR; else sc->sc_flags |= SC_DC_FERROR; splx(s); } } else { if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); } if (proto == PPP_CCP) { ppp_ccp(sc, m, 1); } }#endif ilen = NB_SIZE(m);#ifdef VJC if (sc->sc_flags & SC_VJ_RESET) { /* * If we've missed a packet, we must toss subsequent compressed * packets which don't have an explicit connection ID. *//* IOLog("SC_VJ_RESET was set!\n"); */ vj_uncompress_err(&sc->sc_comp); s = splimp(); sc->sc_flags &= ~SC_VJ_RESET; splx(s); } /* * See if we have a VJ-compressed packet to uncompress. */ if (proto == PPP_VJC_COMP) { if (sc->sc_flags & SC_REJ_COMP_TCP) goto bad; xlen = vj_uncompress_tcp(cp + PPP_HDRLEN, ilen - PPP_HDRLEN, ilen - PPP_HDRLEN, &sc->sc_comp, &iphdr, &hlen); if (xlen <= 0) {/* IOLogDbg("ppp%d: VJ uncompress failed on type comp\n", if_unit(sc->sc_if));*/ goto bad; } /* * Write the IP/TCP header back into the datagram. * The pointers point to the stored copy in the VJ * compression table. */ NB_GROW_TOP(m, hlen - xlen); NB_WRITE(m, PPP_HDRLEN, hlen, iphdr); cp = mtod(m, u_char *);#ifdef TCP_CHECKSUM {#define getip_hl(base) ((base).ip_hl) u_short mytcpcksum (struct ip *pip); struct tcphdr *ptcp; struct ip *iphdr; u_short thecksum; u_long hlen; iphdr = (struct ip*) (cp + PPP_HDRLEN); hlen = getip_hl(*iphdr) << 2; /* Length is in words */ ptcp = (struct tcphdr *)&((u_char *)iphdr)[hlen]; thecksum = (u_short)mytcpcksum(iphdr); if(ptcp->th_sum != thecksum) {#ifdef NEWVJ_RESYNC set_newvj_error_mode();#endif IOLog("NEWVJ: Warning... TCP checksum failed Received=%u, Calculated=%u)\n", (ptcp->th_sum)&0xffff, thecksum&0xffff); } } #endif cp[0] = adrs; cp[1] = ctrl; cp[2] = 0; cp[3] = PPP_IP; proto = PPP_IP; ilen += hlen - xlen; } else if (proto == PPP_VJC_UNCOMP) { if (sc->sc_flags & SC_REJ_COMP_TCP) goto bad; vj_uncompress_uncomp(cp + PPP_HDRLEN, ilen-PPP_HDRLEN, &sc->sc_comp); proto = PPP_IP; cp[3] = PPP_IP; }#endif /* VJC */ rv = 0; switch (proto) {#ifdef INET case PPP_IP: /* * IP packet - take off the ppp header and pass it up to IP. */ if ((if_flags(sc->sc_if) & IFF_UP) == 0 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { /* interface is down - drop the packet. */ NB_FREE(m); IOLogDbg("ppp%d: IP packed dropped (NPmode)\n", if_unit(sc->sc_if)); return; } NB_SHRINK_TOP(m, PPP_HDRLEN); inet_queue(sc->sc_if, NB_TO_nb(m));#if NS_TARGET >= 40 /* I am assuming the time is different here than above. */ ns_time_to_timeval(clock_value(System), &tv_time); sc->sc_last_recv = tv_time.tv_sec; /* update time of last pkt rcvd */#else sc->sc_last_recv = time.tv_sec; /* update time of last pkt rcvd */#endif return;#endif default: /* * Some other protocol - place on input queue for read(). */ inq = &sc->sc_inq; rv = 1; break; } /* * Put the packet on the appropriate input queue. */ s = splimp(); if (nbq_full(inq)) { nbq_drop(inq); splx(s); IOLog("ppp%d: input queue full\n", if_unit(sc->sc_if)); goto bad; } nbq_enqueue(inq, m); splx(s); if (rv) (*sc->sc_ctlp)(sc); return; bad: NB_FREE(m); incr_cnt(sc->sc_if, if_ierrors);}#define MAX_DUMP_BYTES 128static voidpppdumpm(m0) NETBUF_T m0;{ char buf[3*MAX_DUMP_BYTES+4]; char *bp = buf; static char digits[] = "0123456789abcdef"; int l = NB_SIZE(m0); u_char *rptr = mtod(m0, u_char *); while (l--) { if (bp > buf + sizeof(buf) - 4) goto done; *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ *bp++ = digits[*rptr++ & 0xf]; } *bp++ = ' ';done: if (l) *bp++ = '>'; *bp = 0; IOLog("%s\n", buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -