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

📄 pfilt.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	}}/* *  Pfilt_ioctl - ether net control * *  EIOCGETP	 - get ethernet parameters *  EIOCSETP	 - set ethernet read timeout *  EIOCSETF	 - set ethernet read filter *  EIOCENBS	 - enable signal when read packet available *  EIOCINHS     - inhibit signal when read packet available *  FIONREAD	 - check for read packet available *  EIOCSETW	 - set maximum read packet waiting queue length *  EIOCFLUSH	 - flush read packet waiting queue *  EIOCMBIS	 - set mode bits *  EIOCMBIC	 - clear mode bits *  EICODEVP	 - get device parameters *  EIOCMFREE	 - number of free minors *  EIOCIFNAME	 - get name of interface for this minor *  EIOCTRUNCATE - set maximum number of bytes of packet to be returned *  EIOCALLOWPROMISC - allows non-super-users to set IFF_PROMISC *  EIOCALLOWCOPYALL - allows non-super-users to set IFF_PFCOPYALL *  EIOCMAXBACKLOG - sets non-super-user's maximum backlog *  EIOCSRTIMEOUT - set read timeout *  EIOCGRTIMEOUT - get read timeout *  EIOCSETIF	  - set interface for this minor *//* ARGSUSED */Pfilt_ioctl(dev, cmd, addr, flag)caddr_t addr;dev_t flag;{    register struct enState *enStatep = enStatePs[ENUNIT(dev)];    register struct enOpenDescriptor * d = enAllDescriptors[ENINDEX(dev)];    struct enPacket *dummy;	/* a dummy pointer - used only for consistency				 * in the macro pfiltdequeue				 */    int ipl;#if	DEBUG    Pfiltprintf(ENDBG_TRACE)	    	("Pfilt_ioctl(%x, %x, %x, %x):\n", dev, cmd, addr, flag);#endif    switch (cmd)    {	case EIOCGETP:	{	    struct eniocb t;	    if (suser())	    	t.en_maxwaiting = ENMAXWAITING;	    else	    	t.en_maxwaiting = ENNOTSUWAITING;	    t.en_maxpriority = ENMAXPRI;	    t.en_rtout = d->enOD_Timeout;	    t.en_addr = -1;	    t.en_maxfilters = ENMAXFILTERS;	    bcopy((caddr_t)&t, addr, sizeof t);	}	endcase	case EIOCSETP:	{	    struct eniocb t;	    bcopy(addr, (caddr_t)&t, sizeof t);	    d->enOD_Timeout = t.en_rtout;	}	endcase	case EIOCSETF:	{	    struct enfilter f;	    unsigned short *fp;	    bcopy(addr, (caddr_t)&f, sizeof f);	    if (f.enf_FilterLen > ENMAXFILTERS)	    {		return(EINVAL);	    }	    /* insure that filter is installed indivisibly */	    ipl = splenet();	    smp_lock(&lk_pfilt, LK_RETRY);	    bcopy((caddr_t)&f, (caddr_t)&(d->enOD_OpenFilter), sizeof f);	    /* pre-compute length of filter */	    fp = &(d->enOD_OpenFilter.enf_Filter[0]);	    d->enOD_FiltEnd = &(fp[d->enOD_OpenFilter.enf_FilterLen]);	    d->enOD_RecvCount = 0;	/* reset counts when filter changes */	    d->enOD_Drops = 0;	    pfiltdequeue((struct Queue *)d->enOD_Link.B, dummy);	    enDesq.enQ_NumQueued--;	    PfiltInsertDescriptor(&(enDesq), d);	    smp_unlock(&lk_pfilt);	    splx(ipl);	}	endcase	/*	 *  Enable signal n on input packet	 */	case EIOCENBS:	{	    int snum;	    bcopy(addr, (caddr_t)&snum, sizeof snum);	    if (snum < NSIG) {		    d->enOD_SigProc = u.u_procp;		    d->enOD_SigPid  = u.u_procp->p_pid;		    d->enOD_SigNumb = snum;	/* This must be set last */	    } else {		    goto bad;	    }	}	endcase	/*	 *  Disable signal on input packet	 */	case EIOCINHS:	{		d->enOD_SigNumb = 0;	}	endcase	/*	 *  Check for packet waiting	 */	case FIONREAD:	{	    int n;	    register struct enWaitQueue *wq;	    ipl = splenet();	    smp_lock(&lk_pfilt, LK_RETRY);	    if ((wq = &(d->enOD_Waiting))->enWQ_NumQueued)		n = wq->enWQ_Packets[wq->enWQ_Head]->enP_ByteCount;	    else		n = 0;	    smp_unlock(&lk_pfilt);	    splx(ipl);	    bcopy((caddr_t)&n, addr, sizeof n);	}	endcase	/*	 *  Set maximum recv queue length for a device	 */	case EIOCSETW:	{	    unsigned un;	    bcopy(addr, (caddr_t)&un, sizeof un);	    /*	     *  unsigned un         MaxQueued             * ----------------    ------------             *  0               ->  DEFWAITING	     *  1..MAXWAITING   ->  un	     *  MAXWAITING..-1  ->  MAXWAITING	     *	     * Non-superusers use ENNOTSUWAITING instead of ENMAXWAITING             */	    if (!suser())		d->enOD_Waiting.enWQ_MaxWaiting = (un) ? min(un,ENNOTSUWAITING)                                        : ENDEFWAITING;	    else		d->enOD_Waiting.enWQ_MaxWaiting = (un) ? min(un, ENMAXWAITING)                                        : ENDEFWAITING;	}	endcase	/*	 *  Flush all packets queued for a device	 */	case EIOCFLUSH:	{	    ipl = splenet();	    smp_lock(&lk_pfilt, LK_RETRY);	    PfiltFlushWaitQueue(d);	    d->enOD_Drops = 0;	    smp_unlock(&lk_pfilt);	    splx(ipl);	}	endcase	/*	 *  Set mode bits	 */	case EIOCMBIS:	{	    u_short mode;	    short oldmode = d->enOD_Flag;	    bcopy(addr, (caddr_t)&mode, sizeof mode);	    if (mode&ENPRIVMODES)		return(EINVAL);	    else		d->enOD_Flag |= mode;	    /* if necessary, bump counter for promiscuous mode */	    if ((mode & ENPROMISC) && ((oldmode & ENPROMISC) == 0)) {		ipl = splenet();	/* lock PromiscCount */		smp_lock(&lk_pfilt, LK_RETRY);		incPromiscCount(enStatep, dev);		smp_unlock(&lk_pfilt);		splx(ipl);		/* unlock PromiscCount */	    }	    /* if necessary, bump counter for copy-all mode */	    if ((mode & ENCOPYALL) && ((oldmode & ENCOPYALL) == 0)) {		ipl = splenet();	/* lock CopyAllCount */		smp_lock(&lk_pfilt, LK_RETRY);		incCopyAllCount(enStatep, dev);		smp_unlock(&lk_pfilt);		splx(ipl);		/* unlock CopyAllCount */	    }	}	endcase	/*	 *  Clear mode bits	 */	case EIOCMBIC:	{	    u_short mode;	    short oldmode = d->enOD_Flag;	    bcopy(addr, (caddr_t)&mode, sizeof mode);	    if (mode&ENPRIVMODES)		return(EINVAL);	    else		d->enOD_Flag &= ~mode;	    /* if necessary, drop counter for promiscuous mode */	    if ((oldmode & ENPROMISC) && (mode & ENPROMISC)) {		ipl = splenet();	/* lock PromiscCount */		smp_lock(&lk_pfilt, LK_RETRY);		decPromiscCount(enStatep, dev);		smp_unlock(&lk_pfilt);		splx(ipl);		/* unlock PromiscCount */	    }	    /* if necessary, drop counter for copy-all mode */	    if ((oldmode & ENCOPYALL) && (mode & ENCOPYALL)) {		ipl = splenet();	/* lock CopyAllCount */		smp_lock(&lk_pfilt, LK_RETRY);		decCopyAllCount(enStatep, dev);		smp_unlock(&lk_pfilt);		splx(ipl);		/* unlock CopyAllCount */	    }	}	endcase	/*	 * Return hardware-specific device parameters.	 */	case EIOCDEVP:	{	    bcopy((caddr_t)&(enDevParams), addr, sizeof(struct endevp));	}	endcase;	/*	 * Return # of free minor devices.	 */	case EIOCMFREE:	{	    register int md;	    register int sum = 0;	    	    for (md = 0; md < enMaxMinors; md++)	    	if (enAllocMap[md] == FALSE)			sum++;	    *(int *)addr = sum;	}	endcase;		case EIOCIFNAME:	{		struct ifreq ifr;		register char *cp, *ep;		register struct ifnet *ifp = enet_info[ENUNIT(dev)].ifp;				ep = ifr.ifr_name + sizeof(ifr.ifr_name) - 2;		bcopy(ifp->if_name, ifr.ifr_name, (sizeof(ifr.ifr_name) - 2));		for (cp = ifr.ifr_name; (cp < ep) && *cp; cp++)			;		*cp++ = '0' + ifp->if_unit;	/* unit better be < 10 */		*cp = '\0';				bcopy((caddr_t)&ifr, addr, sizeof(ifr));	}	endcase;	/*	 *  Set maximum packet length to return	 */	case EIOCTRUNCATE:	{	    int truncation;	    bcopy(addr, (caddr_t)&truncation, sizeof truncation);	    if (truncation < 0)	    	d->enOD_Truncation = ENMAXINT;	    else	    	d->enOD_Truncation = truncation;	}	endcase	/*	 *  Allows non-super-users to set IFF_PROMISC.  This ioctl	 * (super-user-only) sets/clears a per-interface flag; if	 * the flag is set, then descriptors with ENPROMISC cause	 * the interface to go into promiscuous mode.  We keep a	 * reference count on this, and clear IFF_PROMISC when the	 * the count goes to zero.	 */	case EIOCALLOWPROMISC:	{	    int allowpromisc;	    register struct ifnet *ifp = enet_info[ENUNIT(dev)].ifp;	    int wantpromisc;	    bcopy(addr, (caddr_t)&allowpromisc, sizeof allowpromisc);	    if (allowpromisc < 0) {	/* attempt to read current setting */		allowpromisc = (enStatep->ens_AllowPromisc == true);		bcopy((caddr_t)&allowpromisc, addr, sizeof allowpromisc);		return(0);	    }	    if (!suser())		return(EPERM);	    ipl = splenet();	/* lock PromiscCount */	    smp_lock(&lk_pfilt, LK_RETRY);	    if ((enStatep->ens_AllowPromisc == true) && (allowpromisc == 0)) {		/* Must disable IFF_PROMISC if we set it */		if (enStatep->ens_PromiscCount > 0)		    enetSetIfflags(ifp, (ifp->if_flags & ~IFF_PROMISC));		enStatep->ens_PromiscCount = 0;		enStatep->ens_AllowPromisc = false;	    }	    if ((enStatep->ens_AllowPromisc == false) && (allowpromisc != 0)) {		/* Count the number of descriptors wanting promiscuous mode */		wantpromisc = 0;		forAllOpenDescriptors(d)		    if (d->enOD_Flag & ENPROMISC)			wantpromisc++;		enStatep->ens_PromiscCount = wantpromisc;		if (wantpromisc > 0)		    enetSetIfflags(ifp, (ifp->if_flags | IFF_PROMISC));		enStatep->ens_AllowPromisc = true;	    }	    smp_unlock(&lk_pfilt);	    splx(ipl);		/* unlock PromiscCount */	}	endcase	/*	 *  Allows non-super-users to set IFF_PFCOPYALL.  This ioctl	 * (super-user-only) sets/clears a per-interface flag; if	 * the flag is set, then descriptors with ENCOPYALL cause	 * ether_read() to go into copy-all mode.  We keep a	 * reference count on this, and clear IFF_PFCOPYALL when the	 * the count goes to zero.	 */	case EIOCALLOWCOPYALL:	{	    int allowcopyall;	    register struct ifnet *ifp = enet_info[ENUNIT(dev)].ifp;	    int wantcopyall;	    bcopy(addr, (caddr_t)&allowcopyall, sizeof allowcopyall);	    if (allowcopyall < 0) {	/* attempt to read current setting */		allowcopyall = (enStatep->ens_AllowCopyAll == true);		bcopy((caddr_t)&allowcopyall, addr, sizeof allowcopyall);		return(0);	    }	    if (!suser())		return(EPERM);	    ipl = splenet();	/* lock CopyAllCount */	    smp_lock(&lk_pfilt, LK_RETRY);	    if ((enStatep->ens_AllowCopyAll == true) && (allowcopyall == 0)) {		/* Must disable IFF_PFCOPYALL if we set it */		if (enStatep->ens_CopyAllCount > 0)		    enetSetIfflags(ifp, (ifp->if_flags & ~IFF_PFCOPYALL));		enStatep->ens_CopyAllCount = 0;		enStatep->ens_AllowCopyAll = false;	    }	    if ((enStatep->ens_AllowCopyAll == false) && (allowcopyall != 0)) {		/* Count the number of descriptors wanting copy-all mode */		wantcopyall = 0;		forAllOpenDescriptors(d)		    if (d->enOD_Flag & ENCOPYALL)			wantcopyall++;		enStatep->ens_CopyAllCount = wantcopyall;		if (wantcopyall > 0)		    enetSetIfflags(ifp, (ifp->if_flags | IFF_PFCOPYALL));		enStatep->ens_AllowCopyAll = true;	    }	    smp_unlock(&lk_pfilt);	    splx(ipl);		/* unlock CopyAllCount */	}	endcase	/*	 * Set the maximum backlog allowed for non-super-user descriptors.	 * Make sure it is within the legal range.	 */	case EIOCMAXBACKLOG:	{	    int maxbacklog;	    bcopy(addr, (caddr_t)&maxbacklog, sizeof maxbacklog);	    if (maxbacklog < 0) {	/* attempt to read current setting */		maxbacklog = enStatep->ens_UserMaxWaiting;		bcopy((caddr_t)&maxbacklog, addr, sizeof maxbacklog);		return(0);	    }	    if (!suser())		return(EPERM);	    if ((maxbacklog < 1) || (maxbacklog > ENMAXWAITING))		return(EINVAL);	    enStatep->ens_UserMaxWaiting = maxbacklog;	}	endcase	/*	 * Set the read timeout for this descriptor.  Converts	 * from struct timeval to ticks.	 */	case EIOCSRTIMEOUT:	{	    struct timeval rtv;	    long ticks;	    bcopy(addr, (caddr_t)&rtv, sizeof rtv);	    /* Check to make sure this is not too big */	    if (rtv.tv_sec >= ((1<<((NBBY*sizeof(long))-1))/hz) )	    if (rtv.tv_usec >= 1000000)	    	return(EINVAL);	    ticks = (rtv.tv_sec * hz) + (rtv.tv_usec / tick);	    d->enOD_Timeout = ticks;	}	endcase	/*	 * Get the read timeout for this descriptor.  Converts	 * from ticks to struct timeval.	 */	case EIOCGRTIMEOUT:	{	    struct timeval rtv;	    long ticks = d->enOD_Timeout;	    	    rtv.tv_sec = ticks / hz;

⌨️ 快捷键说明

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