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

📄 if_ppp.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (sc->sc_pass_filt.bf_insns != 0) {	FREE(sc->sc_pass_filt.bf_insns, M_DEVBUF);	sc->sc_pass_filt.bf_insns = 0;	sc->sc_pass_filt.bf_len = 0;    }    if (sc->sc_active_filt.bf_insns != 0) {	FREE(sc->sc_active_filt.bf_insns, M_DEVBUF);	sc->sc_active_filt.bf_insns = 0;	sc->sc_active_filt.bf_len = 0;    }#endif /* PPP_FILTER */#ifdef VJC    if (sc->sc_comp != 0) {	FREE(sc->sc_comp, M_DEVBUF);	sc->sc_comp = 0;    }#endif}/* * Ioctl routine for generic ppp devices. */intpppioctl(sc, cmd, data, flag, p)    struct ppp_softc *sc;    int cmd;    caddr_t data;    int flag;    struct proc *p;{    int s, flags, mru, npx, taskid;    struct npioctl *npi;    time_t t;#ifdef PPP_FILTER    int error;    struct bpf_program *bp, *nbp;    struct bpf_insn *newcode, *oldcode;    int newcodelen;#endif /* PPP_FILTER */#ifdef	PPP_COMPRESS    int nb;    struct ppp_option_data *odp;    struct compressor **cp;    u_char ccp_option[CCP_MAX_OPTION_LENGTH];#endif    switch (cmd) {    case FIONREAD:	*(int *)data = sc->sc_inq.ifq_len;	break;    case PPPIOCSTASK:	taskid = *(int *)data;	sc->sc_pppdtask = taskid;	break;    case PPPIOCGUNIT:	*(int *)data = sc->sc_if.if_unit;	break;    case PPPIOCGFLAGS:	*(u_int *)data = sc->sc_flags;	break;    case PPPIOCSFLAGS:	flags = *(int *)data & SC_MASK;	s = splsoftnet();#ifdef PPP_COMPRESS	if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))	    ppp_ccp_closed(sc);#endif	s = splimp();	sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;	splx(s);	break;    case PPPIOCSMRU:	mru = *(int *)data;        if ( mru >= MCLBYTES ) {          /* error - currently only handle 1 culster sized MRU */          /* if we want to handle up to PPP_MAXMRU then we */          /*   need to reallocate all mbufs on the freeq */          /*   this can only be done with iterrupts disabled */          return ( -1 );        }        else if ( mru >= PPP_MRU ) {          /* update the size */          sc->sc_mru = mru;        }	break;    case PPPIOCGMRU:	*(int *)data = sc->sc_mru;	break;#ifdef VJC    case PPPIOCSMAXCID:	if (sc->sc_comp) {	    s = splsoftnet();	    vj_compress_init(sc->sc_comp, *(int *)data);	    splx(s);	}	break;#endif    case PPPIOCXFERUNIT:	sc->sc_xfer = 0; /* Always root p->p_pid;*/	break;#ifdef PPP_COMPRESS    case PPPIOCSCOMPRESS:	odp = (struct ppp_option_data *) data;	nb = odp->length;	if (nb > sizeof(ccp_option))	    nb = sizeof(ccp_option);	if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)	    return (error);	if (ccp_option[1] < 2)	/* preliminary check on the length byte */	    return (EINVAL);	for (cp = ppp_compressors; *cp != NULL; ++cp)	    if ((*cp)->compress_proto == ccp_option[0]) {		/*		 * Found a handler for the protocol - try to allocate		 * a compressor or decompressor.		 */		error = 0;		if (odp->transmit) {		    s = splsoftnet();		    if (sc->sc_xc_state != NULL)			(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);		    sc->sc_xcomp = *cp;		    sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);		    if (sc->sc_xc_state == NULL) {			if (sc->sc_flags & SC_DEBUG)			    printf("ppp%d: comp_alloc failed\n",			       sc->sc_if.if_unit);			error = ENOBUFS;		    }		    splimp();		    sc->sc_flags &= ~SC_COMP_RUN;		    splx(s);		} else {		    s = splsoftnet();		    if (sc->sc_rc_state != NULL)			(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);		    sc->sc_rcomp = *cp;		    sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);		    if (sc->sc_rc_state == NULL) {			if (sc->sc_flags & SC_DEBUG)			    printf("ppp%d: decomp_alloc failed\n",			       sc->sc_if.if_unit);			error = ENOBUFS;		    }		    splimp();		    sc->sc_flags &= ~SC_DECOMP_RUN;		    splx(s);		}		return (error);	    }	if (sc->sc_flags & SC_DEBUG)	    printf("ppp%d: no compressor for [%x %x %x], %x\n",		   sc->sc_if.if_unit, ccp_option[0], ccp_option[1],		   ccp_option[2], nb);	return (EINVAL);	/* no handler found */#endif /* PPP_COMPRESS */    case PPPIOCGNPMODE:    case PPPIOCSNPMODE:	npi = (struct npioctl *) data;	switch (npi->protocol) {	case PPP_IP:	    npx = NP_IP;	    break;	default:	    return EINVAL;	}	if (cmd == PPPIOCGNPMODE) {	    npi->mode = sc->sc_npmode[npx];	} else {	    if (npi->mode != sc->sc_npmode[npx]) {		s = splsoftnet();		sc->sc_npmode[npx] = npi->mode;		if (npi->mode != NPMODE_QUEUE) {		    ppp_requeue(sc);		    (*sc->sc_start)(sc);		}		splx(s);	    }	}	break;    case PPPIOCGIDLE:	s = splsoftnet();        microtime(&ppp_time);	t = ppp_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;#ifdef PPP_FILTER    case PPPIOCSPASS:    case PPPIOCSACTIVE:	nbp = (struct bpf_program *) data;	if ((unsigned) nbp->bf_len > BPF_MAXINSNS)	    return EINVAL;	newcodelen = nbp->bf_len * sizeof(struct bpf_insn);	if (newcodelen != 0) {	    MALLOC(newcode, struct bpf_insn *, newcodelen, M_DEVBUF, M_WAITOK);	    if (newcode == 0) {		return EINVAL;		/* or sumpin */	    }	    if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode,			       newcodelen)) != 0) {		FREE(newcode, M_DEVBUF);		return error;	    }	    if (!bpf_validate(newcode, nbp->bf_len)) {		FREE(newcode, M_DEVBUF);		return EINVAL;	    }	} else	    newcode = 0;	bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt;	oldcode = bp->bf_insns;	s = splimp();	bp->bf_len = nbp->bf_len;	bp->bf_insns = newcode;	splx(s);	if (oldcode != 0)	    FREE(oldcode, M_DEVBUF);	break;#endif    default:	return (-1);    }    return (0);}/* * Process an ioctl request to the ppp network interface. */static intpppsioctl(ifp, cmd, data)    register struct ifnet *ifp;    int cmd;    caddr_t data;{    /*struct proc *p = curproc;*/	/* XXX */    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;    case SIOCSIFMTU:	sc->sc_if.if_mtu = ifr->ifr_mtu;	break;    case SIOCGIFMTU:	ifr->ifr_mtu = sc->sc_if.if_mtu;	break;    case SIOCADDMULTI:    case SIOCDELMULTI:	if (ifr == 0) {	    error = EAFNOSUPPORT;	    break;	}	switch(ifr->ifr_addr.sa_family) {#ifdef INET	case AF_INET:	    break;#endif	default:	    error = EAFNOSUPPORT;	    break;	}	break;    case SIO_RTEMS_SHOW_STATS:        printf("              MRU:%-8u",   sc->sc_mru);        printf("   Bytes received:%-8u",   sc->sc_stats.ppp_ibytes);        printf(" Packets received:%-8u",   sc->sc_stats.ppp_ipackets);        printf("   Receive errors:%-8u\n", sc->sc_stats.ppp_ierrors);        printf("       Bytes sent:%-8u",   sc->sc_stats.ppp_obytes);        printf("     Packets sent:%-8u",   sc->sc_stats.ppp_opackets);        printf("  Transmit errors:%-8u\n", sc->sc_stats.ppp_oerrors);	break;    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, rtp)    struct ifnet *ifp;    struct mbuf *m0;    struct sockaddr *dst;    struct rtentry *rtp;{    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.     */    m0->m_flags &= ~M_HIGHPRI;    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 packet has the "low delay" bit set in the IP header,	 * put it on the fastq instead.	 */	ip = mtod(m0, struct ip *);	if (ip->ip_tos & IPTOS_LOWDELAY)	    m0->m_flags |= M_HIGHPRI;	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.     * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)     */    if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {	m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);	if (m0 == 0) {	    error = ENOBUFS;	    goto bad;	}	m0->m_len = 0;    } else	m0->m_data -= 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) {#ifdef PPP_FILTER	/*	 * Apply the pass and active filters to the packet,	 * but only if it is a data packet.	 */	*mtod(m0, u_char *) = 1;	/* indicates outbound */	if (sc->sc_pass_filt.bf_insns != 0	    && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0,			  len, 0) == 0) {	    error = 0;		/* drop this packet */	    goto bad;	}	/*	 * Update the time we sent the most recent packet.	 */	if (sc->sc_active_filt.bf_insns == 0	    || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m0, len, 0))	    sc->sc_last_sent = time.tv_sec;	*mtod(m0, u_char *) = address;#else	/*	 * Update the time we sent the most recent data packet.	 */	microtime(&ppp_time);	sc->sc_last_sent = ppp_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, m0);#endif    /*     * Put the packet on the appropriate queue.     */    s = splsoftnet();    if (mode == NPMODE_QUEUE) {	/* XXX we should limit the number of packets on this queue */	*sc->sc_npqtail = m0;	m0->m_nextpkt = NULL;	sc->sc_npqtail = &m0->m_nextpkt;    } else {	ifq = (m0->m_flags & M_HIGHPRI)? &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_lastchange = ppp_time;    ifp->if_opackets++;    ifp->if_obytes += len;    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 splsoftnet. */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_nextpkt;	    m->m_nextpkt = NULL;	    ifq = (m->m_flags & M_HIGHPRI)? &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_nextpkt;	    m_freem(m);	    break;	case NPMODE_QUEUE:	    mpp = &m->m_nextpkt;	    break;	}    }    sc->sc_npqtail = mpp;}/* * Get a packet to send.  This procedure is intended to be called at * splsoftnet, 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;#ifdef VJC    struct mbuf *mp;#endif    u_char *cp;    int address, control, protocol;

⌨️ 快捷键说明

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