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

📄 bpfdrv.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    nBytes = pBpfDev->readHoldLen;    bcopy (pBpfDev->readHoldBuf, pBuf, nBytes);    pBpfDev->freeBuf = pBpfDev->readHoldBuf;    pBpfDev->readHoldBuf = NULL;    pBpfDev->readHoldLen = 0;    _bpfUnitUnlock (pBpfDev);        return (nBytes);    }/********************************************************************************* bpfWrite - outputs a packet directly to a network interface** This routine takes a fully formed packet, including any data link layer* header required by the device, and outputs it on the attached network* interface.** RETURNS:* ERROR or the number of bytes written to the interface ** ERRNOS:* S_errno_ENXIO  - if the BPF device is not attached to a network interface** NOMANUAL*/LOCAL int bpfWrite    (    BPF_DEV_CTRL * pBpfDev,   /* BPF device control structure */    char         * pBuf,      /* user data buffer */    int          nBytes       /* number of bytes to read */    )    {    /* Must be attached to a network interface */    if (pBpfDev->pNetIfCtrl == NULL)        {        netErrnoSet (ENXIO);        return (ERROR);        }    if (_bpfProtoSend (pBpfDev->pNetIfCtrl, pBuf, nBytes,                       pBpfDev->nonBlockMode) != OK)        {        return (ERROR);        }    return (nBytes);    }/********************************************************************************* bpfIoctl - implements BPF specific I/O control commands ** This routine implements the following I/O control commands for BPF devices:**  FIONREAD		Check for read packet available.*  BIOCGBLEN		Get buffer len [for read()].*  BIOCSETF		Set ethernet read filter.*  BIOCFLUSH		Flush read packet buffer.*  BIOCPROMISC		Put interface into promiscuous mode.*  BIOCGDLT		Get link layer type.*  BIOCGETIF		Get interface name.*  BIOCSETIF		Set interface.*  BIOCSRTIMEOUT	Set read timeout.*  BIOCGRTIMEOUT	Get read timeout.*  BIOCGSTATS		Get packet stats.*  BIOCIMMEDIATE	Set immediate mode.*  BIOCVERSION		Get filter language version.** RETURNS:* OK or ERROR** ERRNO:* S_errno_EINVAL - invalid command for BPF device* S_errno_ENOMEM - insufficient system memory* S_errno_ENOBUFS - expected buffer not found [from bpfProtoAttach() routine]* * NOMANUAL*/LOCAL STATUS bpfIoctl    (    BPF_DEV_CTRL * pBpfDev,   /* BPF device control structure */    int		 request,     /* ioctl () command */    void         * addr       /* ioctl () command argument */    )    {    int                error = OK;    /* errno value to set */    int                lockKey;       /* BPF lock key */    FAST int           nBytes;        /* byte count */    struct timeval     * pTimeVal;    /* timeout value */    UINT               mSec;          /* timeout in milliseconds */    struct bpf_stat    * pBpfStat;    /* BPF device statistics */    struct bpf_version * pBpfVersion; /* BPF filter version info */    switch (request)        {        default:            error = EINVAL;            break;        case FIONBIO:            _bpfUnitLock (pBpfDev);            pBpfDev->nonBlockMode = * ((BOOL *) addr);            _bpfUnitUnlock (pBpfDev);            break;        case FIONREAD:            _bpfUnitLock (pBpfDev);            /* Retrieve amount of data in the read and immediate buffers. */            nBytes = pBpfDev->recvStoreLen;            if (pBpfDev->readHoldBuf != NULL)                nBytes += pBpfDev->readHoldLen;            _bpfUnitUnlock (pBpfDev);            *(int *)addr = nBytes;            break;        case FIOSELECT:            /* Add BPF unit to wakeup list. */            _bpfUnitLock (pBpfDev);            bpfSelectAdd (pBpfDev, (SEL_WAKEUP_NODE *)addr);            _bpfUnitUnlock (pBpfDev);            break;        case FIOUNSELECT:            /* Remove BPF unit from wakeup list. */            _bpfUnitLock (pBpfDev);            bpfSelectDelete (pBpfDev, (SEL_WAKEUP_NODE *)addr);            _bpfUnitUnlock (pBpfDev);            break;        case BIOCGBLEN:            _bpfUnitLock (pBpfDev);     	    *(u_int *)addr = pBpfDev->bufSize;            _bpfUnitUnlock (pBpfDev);            break;        case BIOCSBLEN:            _bpfUnitLock (pBpfDev);            /* Cannot set buffer len after attaching to network interface. */            if (pBpfDev->pNetDev != NULL)                {                _bpfUnitUnlock (pBpfDev);                error = EINVAL;                break;                }            nBytes = *(u_int *)addr;            /* New buffer size must be between maximum and minimum limits. */            if (nBytes > BPF_MAXBUFSIZE)                nBytes = BPF_MAXBUFSIZE;            if (nBytes < BPF_MINBUFSIZE)                {                nBytes = BPF_MINBUFSIZE;                }            /* Determine if enough memory remains to allocate buffer. */            if ( (nBytes = min (nBytes, memFindMax ())) < BPF_MINBUFSIZE)                {                _bpfUnitUnlock (pBpfDev);                error = ENOMEM;                break;                }            *(u_int *)addr = nBytes;            pBpfDev->bufSize = nBytes;            (void) _bpfUnitUnlock (pBpfDev);            break;        case BIOCSETF:            _bpfUnitLock (pBpfDev);            error = bpfSetFilter (pBpfDev, (struct bpf_program *)addr);            _bpfUnitUnlock (pBpfDev);            break;        case BIOCFLUSH:            _bpfUnitLock (pBpfDev);            bpfDevReset (pBpfDev);            _bpfUnitUnlock (pBpfDev);            break;        case BIOCPROMISC:            _bpfUnitLock (pBpfDev);            if (pBpfDev->pNetDev == NULL)                {                /* No interface attached yet. */                error = EINVAL;                }            else if (!pBpfDev->promiscMode)                {                lockKey = _bpfLock ();                error = _bpfProtoPromisc (pBpfDev->pNetDev, TRUE);                (void) _bpfUnlock (lockKey);                pBpfDev->promiscMode = (error == OK);                }            _bpfUnitUnlock (pBpfDev);            break;        case BIOCGDLT:            _bpfUnitLock (pBpfDev);            if (pBpfDev->pNetDev == NULL)                error = EINVAL;            else                {                *(u_int *)addr = pBpfDev->pNetDev->dataLinkType;                }            _bpfUnitUnlock (pBpfDev);            break;        case BIOCGETIF:            _bpfUnitLock (pBpfDev);            if (pBpfDev->pNetDev == NULL)                error = EINVAL;            else                 {                sprintf ( ( (struct ifreq *)addr)->ifr_name, "%s%d",                         pBpfDev->pNetDev->devName,                         pBpfDev->pNetDev->devUnit);                }            _bpfUnitUnlock (pBpfDev);            break;        case BIOCSETIF:            _bpfUnitLock (pBpfDev);            error = bpfIfSet (pBpfDev, (struct ifreq *)addr, FALSE);            _bpfUnitUnlock (pBpfDev);            break;        case BIOCSTOP: 		/* Detach device from input stream. */            _bpfUnitLock (pBpfDev);            /* Do nothing if device is not attached. */            if (pBpfDev->pNetDev == NULL)                {                _bpfUnitUnlock (pBpfDev);                break;                }            _bpfDevLock (pBpfDev->bpfDevId);            _bpfDevDetach (pBpfDev);            _bpfDevUnlock (pBpfDev->bpfDevId);            _bpfUnitUnlock (pBpfDev);            break;        case BIOCSTART:		/* Reattach device to input stream. */            _bpfUnitLock (pBpfDev);            /* Do nothing if device is already attached. */            if (pBpfDev->pNetDev != NULL)                {                _bpfUnitUnlock (pBpfDev);                break;                }            error = bpfIfSet (pBpfDev, (struct ifreq *)addr, TRUE);            _bpfUnitUnlock (pBpfDev);            break;        case BIOCSRTIMEOUT:            pTimeVal = (struct timeval *)addr;            mSec = pTimeVal->tv_sec * 1000;             mSec += pTimeVal->tv_usec / 1000;            _bpfUnitLock (pBpfDev);            /* scale milliseconds to ticks */            pBpfDev->readTimeout = (mSec * sysClkRateGet ()) / 1000;            if (pBpfDev->readTimeout == 0)                {                if (pTimeVal->tv_usec == 0)                    {                    pBpfDev->readTimeout = WAIT_FOREVER;                    }                else                    {                    pBpfDev->readTimeout = 1;                    }                }            _bpfUnitUnlock (pBpfDev);            break;        case BIOCGRTIMEOUT:            pTimeVal = (struct timeval *)addr;            _bpfUnitLock (pBpfDev);            if (pBpfDev->readTimeout == WAIT_FOREVER)                {                pTimeVal->tv_sec = 0;                pTimeVal->tv_usec = 0;                _bpfUnitUnlock (pBpfDev);                }            else                {                mSec = (pBpfDev->readTimeout * sysClkRateGet ()) / 1000;                pTimeVal->tv_sec = mSec / 1000;                pTimeVal->tv_usec = mSec % 1000;                }            _bpfUnitUnlock (pBpfDev);            break;        case BIOCGSTATS:            pBpfStat = (struct bpf_stat *)addr;            _bpfUnitLock (pBpfDev);            pBpfStat->bs_recv = pBpfDev->pktRecvCount;            pBpfStat->bs_drop = pBpfDev->pktDropCount;            _bpfUnitUnlock (pBpfDev);            break;        case BIOCIMMEDIATE:            _bpfUnitLock (pBpfDev);            pBpfDev->immediateMode = *(u_int *)addr;            _bpfUnitUnlock (pBpfDev);            break;        case BIOCVERSION:            pBpfVersion = (struct bpf_version *)addr;            pBpfVersion->bv_major = BPF_MAJOR_VERSION;            pBpfVersion->bv_minor = BPF_MINOR_VERSION;            break;        }    if (error != OK)        {        netErrnoSet (error);        return (ERROR);        }    return (OK);    }/********************************************************************************* bpfDevReset - reset BPF device** This routine resets a BPF device by flushing its packet buffer and clearing * the receive and drop counts.  ** RETURNS:* Not Applicable** CAVEATS:* Must be called by a task which holds the unit-specific _bpfUnitLock.** NOMANUAL*/LOCAL void bpfDevReset     (    BPF_DEV_CTRL * pBpfDev   /* BPF device control structure */    )    {    if (pBpfDev->readHoldBuf != 0)        {        pBpfDev->freeBuf = pBpfDev->readHoldBuf;        pBpfDev->readHoldBuf = 0;        pBpfDev->readHoldLen = 0;        }    pBpfDev->recvStoreLen = 0;    pBpfDev->pktRecvCount = 0;    pBpfDev->pktDropCount = 0;    }/********************************************************************************* bpfSelectAdd - joins the wakeup list for select operation** This routine implements the FIOSELECT operation. It adds a BPF device* to the list of I/O devices waiting for activity through the select()* routine. The add operation allows the bpfWakeup() routine to complete* the selection process once sufficient data arrives.** RETURNS: N/A** CAVEATS:* Must be called by a task which holds the unit-specific _bpfUnitLock.** NOMANUAL*/LOCAL void bpfSelectAdd    (    BPF_DEV_CTRL * 	pBpfDev, 	/* BPF device control structure */     SEL_WAKEUP_NODE * 	pWakeupNode 	/* Control information from select */    )    {    /* Only pend when selecting for read requests. */    if (selWakeupType (pWakeupNode) == SELREAD)        {        if (selNodeAdd (& (pBpfDev->selWkupList), pWakeupNode) == ERROR)            return;        pBpfDev->selectFlag = TRUE;        /* Wake the calling task immediately if data is already available. */        if ( (pBpfDev->readHoldBuf != NULL) ||            (pBpfDev->immediateMode && pBpfDev->recvStoreLen != 0))            {            selWakeup (pWakeupNode);            }        }    return;    }/********************************************************************************* bpfSelectDelete - leaves the wakeup list for select operation** This routine implements the FIOUNSELECT control operation. It removes a* BPF device from the list of I/O devices waiting for activity through the* select() routine. The remove operation completes the selection process* started with the FIOSELECT operation.** RETURNS: N/A** CAVEATS:* Must be called by a task which holds the unit-specific _bpfUnitLock.** NOMANUAL*/LOCAL void bpfSelectDelete    (    BPF_DEV_CTRL * 	pBpfDev, 	/* BPF device control structure */     SEL_WAKEUP_NODE * 	pWakeupNode 	/* Control information from select */    )    {    /* Only handle cancellations for read requests. */    if (selWakeupType (pWakeupNode) == SELREAD)        {        selNodeDelete (& (pBpfDev->selWkupList), pWakeupNode);        /*         * A BPF unit is only accessible through a single file descriptor,         * so the list length will usually be zero at this point. However,         * a task may have shared that file descriptor with others. No         * race condition occurs because this routine executes while the         * BPF unit is locked.         */        if (selWakeupListLen (& (pBpfDev->selWkupList)) == 0)            {            pBpfDev->selectFlag = FALSE;            }        }    return;    }/********************************************************************************* bpfSetFilter - sets the filter program used by a BPF device** This routine sets the filter program to be used with a BPF device.  Before* the filter progam is set it will be validated using the bpf_validate () * routine.** RETURNS:* OK* EINVAL if the filter program is invalid* ENOMEM if there is insufficient system memory to store the filter program** CAVEATS:* Must be called by a task which holds the unit-specific _bpfUnitLock.** INTERNAL* This routine returns errno values if a failure occurs so that the ioctl* mechanism can set the error number appropriately.** NOMANUAL*/LOCAL int bpfSetFilter    (    BPF_DEV_CTRL       * pBpfDev,   /* BPF device control structure */     struct bpf_program * pBpfProg   /* BPF filter program */    )    {    struct bpf_insn * pBpfInsnNew;  /* New BPF filter instructions */    struct bpf_insn * pBpfInsnOld;  /* Previous BPF filter instructions */     UINT filterLen;                 /* size in instructions of new filter */    UINT filterSize;                /* size in bytes of new filter */    BOOL newFlag = FALSE;           /* allocate new storage for filter? */    pBpfInsnOld = pBpfDev->pBpfInsnFilter;    /* If filter program contains no instructions set filter to NULL */

⌨️ 快捷键说明

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