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

📄 if_ppp.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 3 页
字号:
	    if (!suser())		return EPERM;	    if (npi->mode != sc->sc_npmode[npx]) {		s = splnet();		sc->sc_npmode[npx] = npi->mode;		if (npi->mode != NPMODE_QUEUE) {		    ppp_requeue(sc);		    (*sc->sc_start)(sc);		}		splx(s);	    }	}	break;    case PPPIOCGIDLE:	s = splnet();	t = time.tv_sec;	((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;	((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;	splx(s);	break;    default:	return (-1);    }    return (0);}/* * Process an ioctl request to the ppp network interface. */intpppsioctl(ifp, cmd, data)    register struct ifnet *ifp;    int cmd;    caddr_t data;{    struct proc *p = u.u_procp;    register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];    register struct ifaddr *ifa = (struct ifaddr *)data;    register struct ifreq *ifr = (struct ifreq *)data;    struct ppp_stats *psp;#ifdef	PPP_COMPRESS    struct ppp_comp_stats *pcp;#endif    int s = splimp(), error = 0;    switch (cmd) {    case SIOCSIFFLAGS:	if ((ifp->if_flags & IFF_RUNNING) == 0)	    ifp->if_flags &= ~IFF_UP;	break;    case SIOCSIFADDR:	if (ifa->ifa_addr.sa_family != AF_INET)	    error = EAFNOSUPPORT;	break;    case SIOCSIFDSTADDR:	if (ifa->ifa_addr.sa_family != AF_INET)	    error = EAFNOSUPPORT;	break;/* * Ioctls other than the above don't get through until the * interface has its IP addresses set :-( */#if 0    case SIOCSIFMTU:	if (!suser())	    return EPERM;	sc->sc_if.if_mtu = ifr->ifr_mtu;	break;    case SIOCGIFMTU:	ifr->ifr_mtu = sc->sc_if.if_mtu;	break;#endif    case SIOCGPPPSTATS:	psp = &((struct ifpppstatsreq *) data)->stats;	bzero(psp, sizeof(*psp));	psp->p = sc->sc_stats;#if defined(VJC) && !defined(SL_NO_STATS)	if (sc->sc_comp) {	    psp->vj.vjs_packets = sc->sc_comp->sls_packets;	    psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;	    psp->vj.vjs_searches = sc->sc_comp->sls_searches;	    psp->vj.vjs_misses = sc->sc_comp->sls_misses;	    psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;	    psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;	    psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;	    psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;	}#endif /* VJC */	break;#ifdef PPP_COMPRESS    case SIOCGPPPCSTATS:	pcp = &((struct ifpppcstatsreq *) data)->stats;	bzero(pcp, sizeof(*pcp));	if (sc->sc_xc_state != NULL)	    (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);	if (sc->sc_rc_state != NULL)	    (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);	break;#endif /* PPP_COMPRESS */    default:	error = EINVAL;    }    splx(s);    return (error);}/* * Queue a packet.  Start transmission if not active. * Packet is placed in Information field of PPP frame. */intpppoutput(ifp, m0, dst)    struct ifnet *ifp;    struct mbuf *m0;    struct sockaddr *dst;{    register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];    int protocol, address, control;    u_char *cp;    int s, error;    struct ip *ip;    struct ifqueue *ifq;    enum NPmode mode;    int len;    struct mbuf *m;    if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0	|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {	error = ENETDOWN;	/* sort of */	goto bad;    }    /*     * Compute PPP header.     * We use the m_context field of the mbuf to indicate whether     * the packet should go on the fast queue.     */    m0->m_context = 0;    switch (dst->sa_family) {#ifdef INET    case AF_INET:	address = PPP_ALLSTATIONS;	control = PPP_UI;	protocol = PPP_IP;	mode = sc->sc_npmode[NP_IP];	/*	 * If this is a TCP packet to or from an "interactive" port,	 * put the packet on the fastq instead.	 */	if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {	    register int p = ntohl(((int *)ip)[ip->ip_hl]);	    if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))		m0->m_context = 1;	}	break;#endif    case AF_UNSPEC:	address = PPP_ADDRESS(dst->sa_data);	control = PPP_CONTROL(dst->sa_data);	protocol = PPP_PROTOCOL(dst->sa_data);	mode = NPMODE_PASS;	break;    default:	printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);	error = EAFNOSUPPORT;	goto bad;    }    /*     * Drop this packet, or return an error, if necessary.     */    if (mode == NPMODE_ERROR) {	error = ENETDOWN;	goto bad;    }    if (mode == NPMODE_DROP) {	error = 0;	goto bad;    }    /*     * Add PPP header.  If no space in first mbuf, allocate another.     */    if (M_IS_CLUSTER(m0) || m0->m_off < MMINOFF + PPP_HDRLEN) {	struct mbuf *m;	MGET(m, M_DONTWAIT, MT_DATA);	if (m == NULL) {	    m_freem(m0);	    return (ENOBUFS);	}	m->m_len = 0;	m->m_next = m0;	m0 = m;    } else	m0->m_off -= PPP_HDRLEN;    cp = mtod(m0, u_char *);    *cp++ = address;    *cp++ = control;    *cp++ = protocol >> 8;    *cp++ = protocol & 0xff;    m0->m_len += PPP_HDRLEN;    len = 0;    for (m = m0; m != 0; m = m->m_next)	len += m->m_len;    if (sc->sc_flags & SC_LOG_OUTPKT) {	printf("ppp%d output: ", ifp->if_unit);	pppdumpm(m0);    }    if ((protocol & 0x8000) == 0) {	/*	 * Update the time we sent the most recent data packet.	 */	sc->sc_last_sent = time.tv_sec;    }#if NBPFILTER > 0    /*     * See if bpf wants to look at the packet.     */    if (sc->sc_bpf)	bpf_mtap(sc->sc_bpf, m0);#endif    /*     * Put the packet on the appropriate queue.     */    s = splnet();    if (mode == NPMODE_QUEUE) {	/* XXX we should limit the number of packets on this queue */	*sc->sc_npqtail = m0;	m0->m_act = NULL;	sc->sc_npqtail = &m0->m_act;    } else {	ifq = m0->m_context? &sc->sc_fastq: &ifp->if_snd;	if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {	    IF_DROP(ifq);	    splx(s);	    sc->sc_if.if_oerrors++;	    sc->sc_stats.ppp_oerrors++;	    error = ENOBUFS;	    goto bad;	}	IF_ENQUEUE(ifq, m0);	(*sc->sc_start)(sc);    }    ifp->if_opackets++;    splx(s);    return (0);bad:    m_freem(m0);    return (error);}/* * After a change in the NPmode for some NP, move packets from the * npqueue to the send queue or the fast queue as appropriate. * Should be called at splnet. */static voidppp_requeue(sc)    struct ppp_softc *sc;{    struct mbuf *m, **mpp;    struct ifqueue *ifq;    enum NPmode mode;    for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {	switch (PPP_PROTOCOL(mtod(m, u_char *))) {	case PPP_IP:	    mode = sc->sc_npmode[NP_IP];	    break;	default:	    mode = NPMODE_PASS;	}	switch (mode) {	case NPMODE_PASS:	    /*	     * This packet can now go on one of the queues to be sent.	     */	    *mpp = m->m_act;	    m->m_act = NULL;	    ifq = m->m_context? &sc->sc_fastq: &sc->sc_if.if_snd;	    if (IF_QFULL(ifq)) {		IF_DROP(ifq);		sc->sc_if.if_oerrors++;		sc->sc_stats.ppp_oerrors++;	    } else		IF_ENQUEUE(ifq, m);	    break;	case NPMODE_DROP:	case NPMODE_ERROR:	    *mpp = m->m_act;	    m_freem(m);	    break;	case NPMODE_QUEUE:	    mpp = &m->m_act;	    break;	}    }    sc->sc_npqtail = mpp;}/* * Transmitter has finished outputting some stuff; * remember to call sc->sc_start later at splnet. */voidppp_restart(sc)    struct ppp_softc *sc;{    int s = splimp();    sc->sc_flags &= ~SC_TBUSY;    schednetisr(NETISR_PPP);    splx(s);}/* * Get a packet to send.  This procedure is intended to be called at * splnet, since it may involve time-consuming operations such as * applying VJ compression, packet compression, address/control and/or * protocol field compression to the packet. */struct mbuf *ppp_dequeue(sc)    struct ppp_softc *sc;{    struct mbuf *m, *mp;    u_char *cp;    int address, control, protocol;    int s;    /*     * Grab a packet to send: first try the fast queue, then the     * normal queue.     */    IF_DEQUEUE(&sc->sc_fastq, m);    if (m == NULL)	IF_DEQUEUE(&sc->sc_if.if_snd, m);    if (m == NULL)	return NULL;    ++sc->sc_stats.ppp_opackets;    /*     * Extract the ppp header of the new packet.     * The ppp header will be in one mbuf.     */    cp = mtod(m, u_char *);    address = PPP_ADDRESS(cp);    control = PPP_CONTROL(cp);    protocol = PPP_PROTOCOL(cp);    switch (protocol) {    case PPP_IP:#ifdef VJC	/*	 * If the packet is a TCP/IP packet, see if we can compress it.	 */	if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {	    struct ip *ip;	    int type;	    mp = m;	    ip = (struct ip *) (cp + PPP_HDRLEN);	    if (mp->m_len <= PPP_HDRLEN) {		mp = mp->m_next;		if (mp == NULL)		    break;		ip = mtod(mp, struct ip *);	    }	    /* this code assumes the IP/TCP header is in one non-shared mbuf */	    if (ip->ip_p == IPPROTO_TCP) {		type = sl_compress_tcp(mp, ip, sc->sc_comp,				       !(sc->sc_flags & SC_NO_TCP_CCID));		switch (type) {		case TYPE_UNCOMPRESSED_TCP:		    protocol = PPP_VJC_UNCOMP;		    break;		case TYPE_COMPRESSED_TCP:		    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)) {	struct mbuf *mcomp = NULL;	int slen, clen;	slen = 0;	for (mp = m; mp != NULL; mp = mp->m_next)	    slen += mp->m_len;	clen = (*sc->sc_xcomp->compress)	    (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN);	if (mcomp != NULL) {	    if (sc->sc_flags & SC_CCP_UP) {		/* Send the compressed packet instead of the original. */		m_freem(m);		m = mcomp;		cp = mtod(m, u_char *);		protocol = cp[3];	    } else {		/* Can't transmit compressed packets until CCP is up. */		m_freem(mcomp);	    }	}    }#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 */	m->m_off += 2;	m->m_len -= 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];	}	++m->m_off;	--m->m_len;    }    return m;}/* * Software interrupt routine, called at splnet.

⌨️ 快捷键说明

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