⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_ppp.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Software interrupt routine, called at splsoftnet. */voidpppintr(){    struct ppp_softc *sc;    int i, s, s2;    struct mbuf *m;    sc = ppp_softc;    s = splsoftnet();    for (i = 0; i < NPPP; ++i, ++sc) {	if (!(sc->sc_flags & SC_TBUSY)	    && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head		|| sc->sc_outm)) {	    s2 = splimp();	    sc->sc_flags |= SC_TBUSY;	    splx(s2);	    (*sc->sc_start)(sc);	}	for (;;) {	    s2 = splimp();	    IF_DEQUEUE(&sc->sc_rawq, m);	    splx(s2);	    if (m == NULL)		break;	    ppp_inproc(sc, m);	}    }    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;    struct mbuf *m;    int rcvd;{    u_char *dp, *ep;    struct mbuf *mp;    int slen, s;    /*     * Get a pointer to the data after the PPP header.     */    if (m->m_len <= PPP_HDRLEN) {	mp = m->m_next;	if (mp == NULL)	    return;	dp = (mp != NULL)? mtod(mp, u_char *): NULL;    } else {	mp = m;	dp = mtod(mp, u_char *) + PPP_HDRLEN;    }    ep = mtod(mp, u_char *) + mp->m_len;    if (dp + CCP_HDRLEN > ep)	return;    slen = CCP_LENGTH(dp);    if (dp + slen > ep) {	if (sc->sc_flags & SC_DEBUG)	    printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",		dp, slen, mtod(mp, u_char *), mp->m_len);	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,			 sc->sc_unit, 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,			 sc->sc_unit, 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);	    } 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;    struct mbuf *m;    int lost;{    int s = splimp();    if (lost)	m->m_flags |= M_ERRMARK;    IF_ENQUEUE(&sc->sc_rawq, m);    schednetisr(NETISR_PPP);    splx(s);}/* * Process a received PPP packet, doing decompression as necessary. * Should be called at splsoftnet. */#define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \			 TYPE_UNCOMPRESSED_TCP)static voidppp_inproc(sc, m)    struct ppp_softc *sc;    struct mbuf *m;{    struct ifnet *ifp = &sc->sc_if;    struct ifqueue *inq;    int s, ilen, xlen, proto, rv;    u_char *cp, adrs, ctrl;    struct mbuf *mp, *dmp = NULL;    u_char *iphdr;    u_int hlen;    sc->sc_stats.ppp_ipackets++;    if (sc->sc_flags & SC_LOG_INPKT) {	ilen = 0;	for (mp = m; mp != NULL; mp = mp->m_next)	    ilen += mp->m_len;	printf("%s: got %d bytes\n", ifp->if_xname, ilen);	pppdumpm(m);    }    cp = mtod(m, u_char *);    adrs = PPP_ADDRESS(cp);    ctrl = PPP_CONTROL(cp);    proto = PPP_PROTOCOL(cp);    if (m->m_flags & M_ERRMARK) {	m->m_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) {	    m_freem(m);	    if (dmp == NULL) {		/* no error, but no decompressed packet produced */		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.	     */	    if (sc->sc_flags & SC_DEBUG)		printf("%s: decompress failed %d\n", ifp->if_xname, 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 = 0;    for (mp = m; mp != NULL; mp = mp->m_next)	ilen += mp->m_len;#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.	 */	if (sc->sc_comp)	    sl_uncompress_tcp(NULL, 0, TYPE_ERROR, 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) || sc->sc_comp == 0)	    goto bad;	xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,				      ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,				      sc->sc_comp, &iphdr, &hlen);	if (xlen <= 0) {	    if (sc->sc_flags & SC_DEBUG)		printf("%s: VJ uncompress failed on type comp\n",		    ifp->if_xname);	    goto bad;	}	/* Copy the PPP and IP headers into a new mbuf. */	MGETHDR(mp, M_DONTWAIT, MT_DATA);	if (mp == NULL)	    goto bad;	mp->m_len = 0;	mp->m_next = NULL;	if (hlen + PPP_HDRLEN > MHLEN) {	    MCLGET(mp, M_DONTWAIT);	    if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {		m_freem(mp);		goto bad;	/* lose if big headers and no clusters */	    }	}	cp = mtod(mp, u_char *);	cp[0] = adrs;	cp[1] = ctrl;	cp[2] = 0;	cp[3] = PPP_IP;	proto = PPP_IP;	bcopy(iphdr, cp + PPP_HDRLEN, hlen);	mp->m_len = hlen + PPP_HDRLEN;	/*	 * Trim the PPP and VJ headers off the old mbuf	 * and stick the new and old mbufs together.	 */	m->m_data += PPP_HDRLEN + xlen;	m->m_len -= PPP_HDRLEN + xlen;	if (m->m_len <= M_TRAILINGSPACE(mp)) {	    bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);	    mp->m_len += m->m_len;	    MFREE(m, mp->m_next);	} else	    mp->m_next = m;	m = mp;	ilen += hlen - xlen;    } else if (proto == PPP_VJC_UNCOMP) {	if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)	    goto bad;	xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,				      ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,				      sc->sc_comp, &iphdr, &hlen);	if (xlen < 0) {	    if (sc->sc_flags & SC_DEBUG)		printf("%s: VJ uncompress failed on type uncomp\n",		    ifp->if_xname);	    goto bad;	}	proto = PPP_IP;	cp[3] = PPP_IP;    }#endif /* VJC */    /*     * If the packet will fit in a header mbuf, don't waste a     * whole cluster on it.     */    if (ilen <= MHLEN && M_IS_CLUSTER(m)) {	MGETHDR(mp, M_DONTWAIT, MT_DATA);	if (mp != NULL) {	    m_copydata(m, 0, ilen, mtod(mp, caddr_t));	    m_freem(m);	    m = mp;	    m->m_len = ilen;	}    }    m->m_pkthdr.len = ilen;    m->m_pkthdr.rcvif = ifp;    if ((proto & 0x8000) == 0) {#ifdef PPP_FILTER	/*	 * See whether we want to pass this packet, and	 * if it counts as link activity.	 */	adrs = *mtod(m, u_char *);	/* save address field */	*mtod(m, u_char *) = 0;		/* indicate inbound */	if (sc->sc_pass_filt.bf_insns != 0	    && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m,			  ilen, 0) == 0) {	    /* drop this packet */	    m_freem(m);	    return;	}	if (sc->sc_active_filt.bf_insns == 0	    || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m, ilen, 0))	    sc->sc_last_recv = time.tv_sec;	*mtod(m, u_char *) = adrs;#else	/*	 * Record the time that we received this packet.	 */	sc->sc_last_recv = time.tv_sec;#endif /* PPP_FILTER */    }#if NBPFILTER > 0    /* See if bpf wants to look at the packet. */    if (sc->sc_bpf)	bpf_mtap(sc->sc_bpf, m);#endif    rv = 0;    switch (proto) {#ifdef INET    case PPP_IP:	/*	 * IP packet - take off the ppp header and pass it up to IP.	 */	if ((ifp->if_flags & IFF_UP) == 0	    || sc->sc_npmode[NP_IP] != NPMODE_PASS) {	    /* interface is down - drop the packet. */	    m_freem(m);	    return;	}	m->m_pkthdr.len -= PPP_HDRLEN;	m->m_data += PPP_HDRLEN;	m->m_len -= PPP_HDRLEN;#ifdef __NetBSD_Version__#ifdef GATEWAY	if (ipflow_fastforward(m))		return;#endif#endif	schednetisr(NETISR_IP);	inq = &ipintrq;	break;#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 (IF_QFULL(inq)) {	IF_DROP(inq);	splx(s);	if (sc->sc_flags & SC_DEBUG)	    printf("%s: input queue full\n", ifp->if_xname);	ifp->if_iqdrops++;	goto bad;    }    IF_ENQUEUE(inq, m);    splx(s);    ifp->if_ipackets++;    ifp->if_ibytes += ilen;    ifp->if_lastchange = time;    if (rv)	(*sc->sc_ctlp)(sc);    return; bad:    m_freem(m);    sc->sc_if.if_ierrors++;    sc->sc_stats.ppp_ierrors++;}#define MAX_DUMP_BYTES	128static voidpppdumpm(m0)    struct mbuf *m0;{    char buf[3*MAX_DUMP_BYTES+4];    char *bp = buf;    struct mbuf *m;    static char digits[] = "0123456789abcdef";    for (m = m0; m; m = m->m_next) {	int l = m->m_len;	u_char *rptr = (u_char *)m->m_data;	while (l--) {	    if (bp > buf + sizeof(buf) - 4)		goto done;	    *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */	    *bp++ = digits[*rptr++ & 0xf];	}	if (m->m_next) {	    if (bp > buf + sizeof(buf) - 3)		goto done;	    *bp++ = '|';	} else	    *bp++ = ' ';    }done:    if (m)	*bp++ = '>';    *bp = 0;    printf("%s\n", buf);}#endif	/* NPPP > 0 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -