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

📄 if_ppp.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 3 页
字号:
 */voidpppintr(){    struct ppp_softc *sc;    int i, s, s2;    struct mbuf *m;    sc = ppp_softc;    s = splnet();    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)) {	    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 (%x+%x > %x+%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_if.if_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_if.if_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();    m->m_context = lost;    IF_ENQUEUE(&sc->sc_rawq, m);    schednetisr(NETISR_PPP);    splx(s);}/* * Process a received PPP packet, doing decompression as necessary. * Should be called at splnet. */#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, *lock;    int s, ilen, xlen, proto, rv;    u_char *cp, adrs, ctrl;    struct mbuf *mp, *dmp = NULL, *pc;    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("ppp%d: got %d bytes\n", ifp->if_unit, ilen);	pppdumpm(m);    }    cp = mtod(m, u_char *);    adrs = PPP_ADDRESS(cp);    ctrl = PPP_CONTROL(cp);    proto = PPP_PROTOCOL(cp);    if (m->m_context) {	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("ppp%d: decompress failed %d\n", ifp->if_unit, 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("ppp%d: VJ uncompress failed on type comp\n",			ifp->if_unit);	    goto bad;	}	/* Copy the PPP and IP headers into a new mbuf. */	MGET(mp, M_DONTWAIT, MT_DATA);	if (mp == NULL)	    goto bad;	mp->m_len = 0;	mp->m_next = NULL;	if (hlen + PPP_HDRLEN > MLEN) {	    MCLGET(mp, pc);	    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_off += 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("ppp%d: VJ uncompress failed on type uncomp\n",			ifp->if_unit);	    goto bad;	}	proto = PPP_IP;	cp[3] = PPP_IP;    }#endif /* VJC */    /*     * If the packet will fit in an ordinary mbuf, don't waste a     * whole cluster on it.     */    if (ilen <= MLEN && M_IS_CLUSTER(m)) {	MGET(mp, M_DONTWAIT, MT_DATA);	if (mp != NULL) {	    m_copydata(m, mtod(mp, caddr_t), ilen);	    m_freem(m);	    m = mp;	    m->m_len = ilen;	}    }    /*     * Record the time that we received this packet.     */    if ((proto & 0x8000) == 0) {	sc->sc_last_recv = time.tv_sec;    }#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_off += PPP_HDRLEN;	m->m_len -= PPP_HDRLEN;	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();    lock = inq;    smp_lock(&lock->lk_ifqueue, LK_RETRY);    if (IF_QFULL(inq)) {	IF_DROP(inq);	smp_unlock(&lock->lk_ifqueue);	splx(s);	if (sc->sc_flags & SC_DEBUG)	    printf("ppp%d: input queue full\n", ifp->if_unit);	goto bad;    }    IF_ENQUEUEIF(inq, m, &sc->sc_if);    smp_unlock(&lock->lk_ifqueue);    splx(s);    ifp->if_ipackets++;    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 = mtod(m, 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];	}	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 + -