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

📄 pfilt.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	    ticks = ticks % hz;	    rtv.tv_usec = ticks * tick;	    bcopy((caddr_t)&rtv, addr, sizeof rtv);	}	endcase	/*	 * Change the interface associated with a minor device	 */	case EIOCSETIF:	{		struct ifreq ifr;		register struct ifnet *oldifp = enet_info[ENUNIT(dev)].ifp;		register struct ifnet *newifp;		register struct enState *newStatep = (struct enState *)0;		int unit;		struct ifnet *ifunit();		static struct ifnet *genericUnit();				bcopy(addr, (caddr_t)&ifr, sizeof(ifr));		if ((newifp = genericUnit(ifr.ifr_name)) == (struct ifnet *)0)		    if ((newifp = ifunit(ifr.ifr_name)) == (struct ifnet *)0)			return(EINVAL);		if (newifp == oldifp)	/* no change */		    return(0);		/* find enState pointer for new interface */		for (unit = 0; unit < enUnits; unit++) {		    if (enet_info[unit].ifp == newifp) {			newStatep = enStatePs[unit];			break;		    }		}		if (newStatep == (struct enState *)0)		    return(EINVAL);	/* interface not known */				ipl = splenet();		smp_lock(&lk_pfilt, LK_RETRY);		/* remove this from the old enState struct */		pfiltdequeue((struct Queue *)d->enOD_Link.B, dummy);		enCurOpens--;		if (d->enOD_Flag & ENPROMISC)		    decPromiscCount(enStatep, dev);		if (d->enOD_Flag & ENCOPYALL)		    decCopyAllCount(enStatep, dev);		enUnitMap[ENINDEX(dev)] = unit;	/* change unit map */		/* add this to the new enState struct */		PfiltInsertDescriptor(&(newStatep->ens_Desq), d);		PfiltFlushWaitQueue(d);		if (d->enOD_Flag & ENPROMISC)		    incPromiscCount(newStatep, dev);		if (d->enOD_Flag & ENCOPYALL)		    incCopyAllCount(newStatep, dev);		smp_unlock(&lk_pfilt);		splx(ipl);	}	endcase;	default:	{	bad:	    return(EINVAL);	}    }    return(0);}				/**************************************************************** *								* *		Support for select() system call		* *								* *	Other hooks in:						* *		PfiltInitDescriptor()				* *		PfiltInputDone()					* *		PfiltTimeout()					* ****************************************************************//* * inspired by the code in tty.c for the same purpose. *//* * Pfilt_select - returns true iff the specific operation *	will not block indefinitely.  Otherwise, return *	false but make a note that a selwakeup() must be done. */Pfilt_select(dev, rw)register dev_t dev;int rw;{	register struct enOpenDescriptor *d;	register struct enWaitQueue *wq;	register int ipl;	register int avail;		switch (rw) {		case FREAD:		/*		 * an imitation of the FIONREAD ioctl code		 */		d = (enAllDescriptors[ENINDEX(dev)]);				ipl = splenet();    		smp_lock(&lk_pfilt, LK_RETRY);		wq = &(d->enOD_Waiting);		if (wq->enWQ_NumQueued)			avail = 1;	/* at least one packet queued */		else {			avail = 0;	/* sorry, nothing queued now */			/*			 * If there's already a select() waiting on this			 * minor device then this is a collision.			 * [This shouldn't happen because enet minors			 * really should not be shared, but if a process			 * forks while one of these is open, it is possible			 * that both processes could select() us.]			 */			if (d->enOD_SelProc			     && d->enOD_SelProc->p_wchan == (caddr_t)&selwait)			     	d->enOD_SelColl = 1;			else				d->enOD_SelProc = u.u_procp;				}		smp_unlock(&lk_pfilt);		splx(ipl);			return(avail);	case FWRITE:		/*		 * since the queueing for output is shared not just with		 * the other enet devices but also with the IP system,		 * we can't predict what would happen on a subsequent		 * write.  However, since we presume that all writes		 * complete eventually, and probably fairly fast, we		 * pretend that select() is true.		 */		return(1);	default:		/* hmmm. */		return(1);		/* don't block in select() */	}}Pfilt_wakeup(d)register struct enOpenDescriptor *d;{	if (d->enOD_SelProc) {		selwakeup(d->enOD_SelProc, d->enOD_SelColl);		d->enOD_SelColl = 0;		d->enOD_SelProc = 0;	}}/* * pfilt_filter - incoming linkage from if_XXXXX.c */struct mbuf *PfiltInputDone();struct mbuf *pfilt_filter(edp, m, eptr, istrailer)struct ether_driver *edp;register struct mbuf *m;struct ether_header *eptr;int istrailer;{    register struct enPacket *p;    struct mbuf *m0;    int s;    int HowReceived = 0;    short d_addr[4];    register short *sb, *dap;    struct protosw *pr;    int mustcopy = 0;    int pfcopyall = (edp->ess_if.if_flags & IFF_PFCOPYALL);    register struct enpextent *exp;    register int offset;    register int extents_left;    struct enpextent map[MAX_EXTENTS];#ifdef	SELF_PROF    struct timeval starttv, endtv;    if (enSelfProf)	microtime(&starttv);#endif	SELF_PROF#if	DEBUG    Pfiltprintf(ENDBG_TRACE)("pfilt_filter(%d):\n", en);#endif    /* Copy the destination address into main memory */    sb = (short *)eptr->ether_dhost;    dap = d_addr;    dap[0] = sb[0];    dap[1] = sb[1];    dap[2] = sb[2];    /* Was it a MULTICAST (or BROADCAST) packet? */    if (eptr->ether_dhost[0] & 1) {	HowReceived = ENSF_MULTICAST;	/* set MULTICAST */	/*	 *  Was it a broadcast packet?	 */	if ((*((long *)dap) == 0xFFFFFFFF) &&	    (*((short *)&(dap[2])) == (short)0xFFFF)) {	    HowReceived = ENSF_BROADCAST; /* set BROADCAST */	    mustcopy = 1;	/* save a copy of the packet */	} else {	    /*	     * else we received a MULTICAST packet.	     * If other protocols might be interested	     * in the packet, save a copy of it.	     */	    pr = (struct protosw *) iftype_to_proto(eptr->ether_type);	    if (pr && pr->pr_ifinput) {		mustcopy = 1;	    }	}    } else {	/* else not MULTICAST or BROADCAST packet, check if it's ours */	if (edp->ess_if.if_flags & IFF_PROMISC) {	    /*	     * All promiscuously received packets go to the filter	     * This includes COPYALL packets that we sent since	     * they appear to belong to someone else.	     */	    sb = (short *)edp->ess_addr;	/* our address */	    if ((*((long *)dap) != *((long *)sb)) ||		    (dap[2] != sb[2])) {		HowReceived = ENSF_PROMISC;	    } else {		/*		 * We are in PROMISC mode and this packet was		 * addressed directly to us; need to make a copy		 * if IFF_COPYALL mode is set.		 */		if (pfcopyall > 1) {		    mustcopy = 1;		}	    }	} else {	    /* else not in PROMISC mode, check to see if our own	     * output packet was looped back (ie. COPYALL mode is set).	     * If so, insure we hand it to the packetfilter only.	     * If a packet reaches here, it must have been either:	     *	- directed at us, or	     *	- a packet we sent which was looped back	     */	    if (pfcopyall > 1) {		sb = (short *)edp->ess_addr;	/* our address */		if ((*((long *)dap) != *((long *)sb)) ||		    (dap[2] != sb[2])) {		    /* The destination address does not match our own,		     * so we let the packetfilter eat it.		     * This works because mustcopy==0 and because		     * we label the packet as PROMISC.		     */		    HowReceived = ENSF_PROMISC;		} else {		    /* else packet was directed at us (it came in normally)		     * must save a copy for the protocols		     */		    mustcopy = 1;		}	    }	}    }/* filter:	unused */#ifdef	DEBUG_ER    if (er_debug) {	int cprintf(), mprintf();	/* er_debug=1  print to console (cprintf)	 * er_debug=2  print to error log (mprintf)	 */	(er_debug == 2 ? mprintf : cprintf)("%02x-%02x-%02x-%02x-%02x-%02x -> %02x-%02x-%02x-%02x-%02x-%02x %04x %x\n",	eptr->ether_shost[0], eptr->ether_shost[1], eptr->ether_shost[2],	eptr->ether_shost[3], eptr->ether_shost[4], eptr->ether_shost[5],	eptr->ether_dhost[0], eptr->ether_dhost[1], eptr->ether_dhost[2],	eptr->ether_dhost[3], eptr->ether_dhost[4], eptr->ether_dhost[5],	eptr->ether_type, HowReceived);    }#endif	DEBUG_ER    /*     *  If we don't need to copy the packet (and we aren't     *  promiscuous), then we can return here and now and     *  not bother anymore with the packet filter.     */    if ((HowReceived != ENSF_PROMISC) && (mustcopy == 0))	return m;    /*     * If there are no active filters, just return.     * This can happen if we are in PROMISC mode     * or COPYALL mode, but not actually doing any filtering.     */    if (pfactive == 0) {	if (mustcopy) {	    return m;	} else {	    m_freem(m);	    return 0;	}    }    /*     * We need local net header after all.     */    MGET(m0, M_DONTWAIT, MT_DATA);    if (m0 == 0) {	/* out of mbufs? */	if (mustcopy) {	    return m;	} else {	    m_freem(m);	    return (struct mbuf *) 0;	}    }    /*     * If we must copy the mbuf, do it now.  If it     * fails, screw the packet filter and process it normally.     * If we don't have to copy, just append the mbuf.     */    if (mustcopy) {	m0->m_next = m_copy(m, 0, M_COPYALL);	/* m_copy returns NULL if it fails */	if (m0->m_next == NULL) {	    m_free(m0);	    return m;	}    } else {	m0->m_next = m;    }    /*     *  Copy the ether header and swap the protocol     *  type in "wire" format.     */    *(mtod(m0, struct ether_header *)) = *eptr;    eptr = mtod(m0, struct ether_header *);    eptr->ether_type = htons((u_short)eptr->ether_type);    m0->m_len = sizeof(struct ether_header);    s = splenet();    smp_lock(&lk_pfilt, LK_RETRY);    p = PfiltAllocatePacket();	/* panics if not possible */    p->enP_ByteCount = m_length(m0);    microtime(&(p->enP_Stamp.ens_tstamp));    p->enP_mbuf = m0;    p->enP_Stamp.ens_flags = HowReceived;    p->enP_Stamp.ens_ifoverflows = edp->ess_missed;        if (istrailer) { /* was trailer encapsulation */	p->enP_ByteCount -= 2 * sizeof(u_short);	/* we've dropped trailer type & length */	p->enP_Stamp.ens_flags |= ENSF_TRAILER;    }    /* Build a map from packet byte offsets to mbufs */    exp = map;    /* ASSUMPTION: m is non-null upon entry to this procedure */    exp->data = mtod(m0, char *);    exp->offset = 0;    offset = m0->m_len;    exp->afterEnd = offset;#if	INNERDEBUG    Pfiltprintf(ENDBG_TRACE)("[o%d: aE:%d]",exp->offset,exp->afterEnd);#endif    exp++;    extents_left = (MAX_EXTENTS - 2);	/* 1 just used, 1 left for sentinel */    while ((m0 = m0->m_next) && (--extents_left >= 0)) {	exp->data = mtod(m0, char *);	exp->offset = offset;	offset += m0->m_len;	exp->afterEnd = offset;#if	INNERDEBUG	Pfiltprintf(ENDBG_TRACE)("[o%d: aE:%d]",exp->offset,exp->afterEnd);#endif	exp++;    }#if	INNERDEBUG    Pfiltprintf(ENDBG_TRACE)("\n");#endif    /* The last extent always has data == 0; we reserved one for this */    exp->afterEnd = MAX_OFFSET;    exp->data = (char *)0;        m0 = PfiltInputDone(enStatePs[edp->ess_enetunit], p, map);    if (m0)	m_freem(m0);#ifdef	SELF_PROF    if (enSelfProf) {	microtime(&endtv);		enPerPktProf.tv_sec += (endtv.tv_sec - starttv.tv_sec);	enPerPktProf.tv_usec += (endtv.tv_usec - starttv.tv_usec);	enPktCount++;    }#endif	SELF_PROF    smp_unlock(&lk_pfilt);    splx(s);    if (mustcopy)	return m;    else	return 0;}/* * PfiltInputDone - process correctly received packet * SMP: assumes lock held coming in */struct mbuf *PfiltInputDone(enStatep, p, exp)register struct enState *enStatep;register struct enPacket *p;struct enpextent *exp;{    register struct enOpenDescriptor *d;    int queued = 0;    int drops = 0;    register unsigned long rcount;    register struct enOpenDescriptor *prevd;    int Exclusive;    struct mbuf *notwanted = 0;#ifdef	SELF_PROF    struct timeval starttv, endtv;    boolean accept;#endif	SELF_PROF    if (smp_debug) {	if (!(smp_owner(&lk_pfilt)))		panic("PfiltInputDone: not lock owner");    }#if	INNERDEBUG    Pfiltprintf(ENDBG_TRACE)("PfiltInputDone(%x): %x\n", enStatep, p);#endif    enRmissed = p->enP_Stamp.ens_ifoverflows;    forAllOpenDescriptors(d)    {	/* restrict access to promiscuously received packets */	if ( (p->enP_Stamp.ens_flags & ENSF_PROMISC) &&		((d->enOD_Flag & ENPROMISC) == 0) )	    continue;#ifdef	SELF_PROF	/* null filters always accept all packets */	if (d->enOD_OpenFilter.enf_FilterLen == 0)	    accept = true;	else if (!enSelfProf) {	    accept = PfiltDoFilter(p, d, exp);	} else {	    microtime(&starttv);	    accept = PfiltDoFilter(p, d

⌨️ 快捷键说明

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