bpfDrv.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:58k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* bpfDrv.c - Berkeley Packet Filter (BPF) I/O driver library */
  2. /* Copyright 1999 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*-
  5.  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * This code is derived from the Stanford/CMU enet packet filter,
  9.  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
  10.  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
  11.  * Berkeley Laboratory.
  12.  *
  13.  * Redistribution and use in source and binary forms, with or without
  14.  * modification, are permitted provided that the following conditions
  15.  * are met:
  16.  * 1. Redistributions of source code must retain the above copyright
  17.  *    notice, this list of conditions and the following disclaimer.
  18.  * 2. Redistributions in binary form must reproduce the above copyright
  19.  *    notice, this list of conditions and the following disclaimer in the
  20.  *    documentation and/or other materials provided with the distribution.
  21.  * 3. All advertising materials mentioning features or use of this software
  22.  *    must display the following acknowledgement:
  23.  * This product includes software developed by the University of
  24.  * California, Berkeley and its contributors.
  25.  * 4. Neither the name of the University nor the names of its contributors
  26.  *    may be used to endorse or promote products derived from this software
  27.  *    without specific prior written permission.
  28.  *
  29.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  30.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  33.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  35.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  38.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  39.  * SUCH DAMAGE.
  40.  *
  41.  * @(#)bpf.c 7.5 (Berkeley) 7/15/91
  42.  *
  43.  * static char rcsid[] =
  44.  * "$Header: bpf.c,v 1.67 96/09/26 22:00:52 leres Exp $";
  45.  */
  46. /*
  47. modification history
  48. --------------------
  49. 01f,07may02,wap  Correctly initialize filter length (SPR #74358)
  50. 01e,26mar02,wap  remember to call _bpfDevUnlock() when bpfIfSet() exits with
  51.                  error (SPR #74039)
  52. 01d,17nov00,spm  added support for BSD Ethernet devices
  53. 01c,24apr00,spm  updated to use NPT version of MUX cookie
  54. 01b,05apr00,spm  added interfaces to suspend filtering and remove I/O device
  55. 01a,24nov99,spm  created from BSD bpf.c,v 1.67 96/09/26 22:00:52
  56. */
  57. /*
  58. DESCRIPTION
  59. This library provides a driver which supports the customized retrieval of
  60. incoming network data that meets the criteria imposed by a user-specified
  61. filter.
  62. USER-CALLABLE ROUTINES
  63. The bpfDrv() routine initializes the driver and the bpfDevCreate() routine
  64. creates a packet filter device. Each BPF device allows direct access to the
  65. incoming data from one or more network interfaces.
  66. CREATING BPF DEVICES
  67. In order to retrieve incoming network data, a BPF device must be created by
  68. calling the bpfDevCreate() routine:
  69. .CS
  70.     STATUS bpfDevCreate
  71.         (
  72.         char *  pDevName,       /@ I/O system device name @/
  73.         int     numUnits,       /@ number of device units @/
  74.         int     bufSize         /@ block size for the BPF device @/
  75.         )
  76. .CE
  77. The <numUnits> parameter specifies the maximum number of BPF units for
  78. the device. Each unit is accessed through a separate file descriptor
  79. for use with a unique filter and/or a different network interface. For
  80. example, the following call creates the "/bpf0" and "/bpf1" units:
  81. .CS
  82.     bpfDevCreate ("/bpf", 2, 4096);
  83. .CE
  84. CONFIGURING BPF DEVICES
  85. After opening a device unit, the associated file descriptor must be bound to
  86. a specific network interface with the BIOCSETIF ioctl() option. The BIOCSETF
  87. ioctl() option adds any filter instructions. Each file descriptor receives
  88. a copy of any data which matches the filter. Different file descriptors may
  89. share the same interface. The underlying filters will receive an identical
  90. data stream.
  91. IOCTL FUNCTIONS
  92. The BPF driver supports the following ioctl() functions:
  93. NOTE
  94. When reading data from BPF units, the supplied buffer must be able to
  95. accept an entire block of data as defined by the <bufSize> parameter to
  96. the bpfDevCreate() routine. That value is also available with the BIOCGBLEN
  97. ioctl() option described above.
  98. INCLUDE FILES: bpfDrv.h
  99. SEE ALSO: ioLib
  100. */
  101. /* includes */
  102. #include "vxWorks.h"
  103. #include "stdlib.h"
  104. #include "stdio.h"
  105. #include "string.h"
  106. #include "ctype.h"  /* isdigit() declaration */
  107. #include "iosLib.h"
  108. #include "taskLib.h"
  109. #include "semLib.h"
  110. #include "tickLib.h"
  111. #include "errnoLib.h"
  112. #include "objLib.h"
  113. #include "sysLib.h"
  114. #include "net/if.h"
  115. #include "netLib.h"
  116. #include "net/bpf.h"
  117. #include "private/bpfLibP.h"
  118. #include "private/muxLibP.h"    /* PCOOKIE_TO_ENDOBJ conversion macro */
  119. /* defines */
  120. #define DEBUG
  121. #define ROTATE_BUFFERS(pBpfDev) 
  122.      (pBpfDev)->readHoldBuf = (pBpfDev)->recvStoreBuf; 
  123.      (pBpfDev)->readHoldLen = (pBpfDev)->recvStoreLen; 
  124.      (pBpfDev)->recvStoreBuf = (pBpfDev)->freeBuf;     
  125.      (pBpfDev)->recvStoreLen = 0;                      
  126.      (pBpfDev)->freeBuf = NULL;
  127. #define BPF_DEV_NAME "/dev/bpf"
  128. #ifdef DEBUG
  129. #undef LOCAL
  130. #define LOCAL
  131. #endif /* DEBUG */
  132. #define BPF_BUFSIZE 4096         /* default BPF buffer size */   
  133. /* globals */
  134. /* locals */
  135. LOCAL int  bpfDrvNum = 0;   /* BPF driver number */
  136. LOCAL int  bpfDrvCount = 0; /* Number of BPF driver users */
  137. LOCAL int bpfLockTaskId = 0;     /* ID of task holding global BPF lock */
  138. LOCAL SEM_ID bpfLockSemId;       /* Semaphore ID for global BPF lock */
  139. LOCAL int          numBpfDevs;   /* The number of allocated BPF devices */
  140. LOCAL BPF_DEV_CTRL * pBpfDevTbl; /* BPF device descriptor table */
  141. LOCAL UINT         bpfBufSize = BPF_BUFSIZE;   /* default BPF buffer size */
  142. /* forward declarations */
  143. LOCAL int bpfOpen (BPF_DEV_HDR * pBpfDevHdr, char * minorDevStr, int flags);
  144. LOCAL int bpfClose (BPF_DEV_CTRL * pBpfDev);
  145. LOCAL int bpfRead (BPF_DEV_CTRL * pBpfDev, char * pBuf, int nBytes);
  146. LOCAL int bpfWrite (BPF_DEV_CTRL * pBpfDev, char * pBuf, int nBytes);
  147. LOCAL STATUS bpfIoctl (BPF_DEV_CTRL * pBpfDev, int request, void * addr);
  148. LOCAL void bpfWakeup (BPF_DEV_CTRL * pBpfDev);
  149. LOCAL int bpfSleep (BPF_DEV_CTRL * pBpfDev, int numTicks);
  150. LOCAL void bpfTimeStamp (struct timeval * pTimeval);
  151. LOCAL STATUS bpfBufsAlloc (BPF_DEV_CTRL * pBpfDev);
  152. LOCAL void bpfDevReset (BPF_DEV_CTRL * pBpfDev);
  153. LOCAL STATUS bpfIfSet (BPF_DEV_CTRL * pBpfDev, struct ifreq * pIfReq, 
  154.                        BOOL restartFlag);
  155. LOCAL void bpfSelectAdd (BPF_DEV_CTRL *, SEL_WAKEUP_NODE *);
  156. LOCAL void bpfSelectDelete (BPF_DEV_CTRL *, SEL_WAKEUP_NODE *);
  157. LOCAL int bpfSetFilter (BPF_DEV_CTRL * pBpfDev, struct bpf_program * pBpfProg);
  158. LOCAL void bpfDevReset (BPF_DEV_CTRL * pBpfDev);
  159. LOCAL void bpfDevFree (FAST BPF_DEV_CTRL * pBpfDev);
  160. LOCAL void bpfPacketCatch (FAST BPF_DEV_CTRL * pBpfDev, FAST M_BLK_ID pMBlk, 
  161.                            FAST int snapLen, FAST int bpfHdrLen, 
  162.                            struct timeval * pTimeVal, FAST int linkHdrLen);
  163. /*******************************************************************************
  164. *
  165. * bpfDrv - initialize the BPF driver
  166. * This routine installs the Berkeley Packet Filter driver for access through
  167. * the I/O system. It is required before performing any I/O operations and is
  168. * executed automatically if INCLUDE_BPF is defined at the time the system
  169. * is built. Subsequent calls to the routine just count the number of users
  170. * with BPF access.
  171. *
  172. * RETURNS: OK, or ERROR if initialization fails.
  173. *
  174. * ERRNO: N/A
  175. */
  176. STATUS bpfDrv (void)
  177.     {
  178.     /*
  179.      * For additional calls to this installation routine,
  180.      * just increase the number of users.
  181.      */
  182.     if (bpfDrvNum)
  183.         {
  184.         bpfDrvCount++;
  185.         return (OK);
  186.         }
  187.     bpfLockSemId = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE 
  188.                                | SEM_INVERSION_SAFE);
  189.     if (bpfLockSemId == NULL)
  190.         {
  191.         return (ERROR);
  192.         }
  193.     
  194.     bpfDrvNum = iosDrvInstall (NULL, NULL, bpfOpen, bpfClose,
  195.                                bpfRead, bpfWrite, bpfIoctl);
  196.     if (bpfDrvNum == ERROR)
  197.         {
  198.         bpfDrvNum = 0;
  199.         return (ERROR);
  200.         }
  201.     bpfDrvCount++;
  202.     return (OK);
  203.     }
  204. /*******************************************************************************
  205. *
  206. * bpfDrvRemove - remove BPF driver support
  207. * This routine uninstalls the Berkeley Packet Filter driver, preventing
  208. * further access through the I/O system. It may only be called once to
  209. * reverse a particular installation with the bpfDrv initialization routine.
  210. * It has no effect if any other users retain BPF access through a separate
  211. * installation. The driver is also not removed if any BPF file descriptors
  212. * are currently open.
  213. *
  214. * RETURNS: OK, or ERROR if removal fails.
  215. *
  216. * ERRNO: S_ioLib_NO_DRIVER
  217. *
  218. * NOMANUAL
  219. */
  220. STATUS bpfDrvRemove (void)
  221.     {
  222.     STATUS result;
  223.     if (bpfDrvNum == 0)
  224.         {
  225.         errnoSet (S_ioLib_NO_DRIVER);
  226.         return (ERROR);
  227.         }
  228.     /* Decrease the number of users. Attempt removal if zero. */
  229.     bpfDrvCount--;
  230.     if (bpfDrvCount > 0)     /* Other users have access - do not remove. */
  231.         return (OK);
  232.     if (bpfDrvCount < 0)     /* Mismatched calls to remove routine. */
  233.         {
  234.         bpfDrvCount = 0;
  235.         return (ERROR);
  236.         }
  237.     /* Remove driver if no open files exist. */
  238.     result = iosDrvRemove (bpfDrvNum, FALSE);
  239.     if (result == ERROR)  /* Error: open files found.*/
  240.         {
  241.         bpfDrvCount = 1;     /* Allows removal attempt after closing files. */
  242.         return (ERROR);
  243.         }
  244.     /* Driver removed from I/O system. Remove global lock and reset number. */
  245.     semDelete (bpfLockSemId);
  246.     bpfDrvNum = 0;
  247.     return (OK);
  248.     }
  249. /*******************************************************************************
  250. *
  251. * bpfDevCreate - create Berkeley Packet Filter device
  252. *
  253. * This routine creates a Berkeley Packet Filter device. Each of the
  254. * <numUnits> units corresponds to a single available file descriptor for
  255. * monitoring a network device. The <pDevName> parameter provides the name
  256. * of the BPF device to the I/O system. The default name of "/bpf" (assigned
  257. * if <pDevName> is NULL) produces units named "/bpf0", "/bpf1", etc., up to
  258. * the <numUnits> limit.
  259. *
  260. * RETURNS: OK, or ERROR if device creation failed.
  261. *
  262. * ERRNO: S_ioLib_NO_DRIVER
  263. */
  264. STATUS bpfDevCreate
  265.     (
  266.     char *  pDevName,  /* I/O system device name */
  267.     int  numUnits,       /* number of device units */
  268.     int  bufSize  /* BPF device block size (0 for default) */
  269.     )
  270.     {
  271.     BPF_DEV_HDR * pBpfDevHdr;   /* I/O system device header for BPF units */
  272.     if (bpfDrvNum == 0)
  273.         {
  274.         errnoSet (S_ioLib_NO_DRIVER);
  275.         return (ERROR);
  276.         }
  277.     if (numUnits <= 0)
  278.         {
  279.         return (ERROR);
  280.         }
  281.     pBpfDevHdr = (BPF_DEV_HDR *)malloc (sizeof (BPF_DEV_HDR));
  282.     if (pBpfDevHdr == NULL)
  283.         {
  284.         return (ERROR);
  285.         }
  286.     pBpfDevHdr->lockSem = semBCreate (SEM_Q_FIFO, SEM_FULL);
  287.     if (pBpfDevHdr->lockSem == NULL)
  288.         {
  289.         free (pBpfDevHdr);
  290.         return (ERROR);
  291.         }
  292.     pBpfDevHdr->pBpfDevTbl = calloc (numUnits, sizeof (BPF_DEV_CTRL));
  293.     if (pBpfDevHdr->pBpfDevTbl == NULL)
  294.         {
  295.         free (pBpfDevHdr);
  296.         semDelete (pBpfDevHdr->lockSem);
  297.         return (ERROR);
  298.         }
  299.     pBpfDevHdr->pBpfNetIfTbl = calloc (numUnits, sizeof (BPF_PROTO_CTRL));
  300.     if (pBpfDevHdr->pBpfDevTbl == NULL)
  301.         {
  302.         free (pBpfDevHdr->pBpfDevTbl); 
  303.         free (pBpfDevHdr);
  304.         semDelete (pBpfDevHdr->lockSem);
  305.         return (ERROR);
  306.         }
  307.     if (pDevName == NULL)
  308.         pDevName = BPF_DEV_NAME;
  309.     if (iosDevAdd ( (DEV_HDR *) pBpfDevHdr, pDevName, bpfDrvNum) != OK)
  310.         {
  311.         free (pBpfDevHdr->pBpfNetIfTbl);
  312.         free (pBpfDevHdr->pBpfDevTbl);
  313.         free (pBpfDevHdr);
  314.         semDelete (pBpfDevHdr->lockSem);
  315.         return (ERROR);
  316.         }
  317.     pBpfDevHdr->numDevs = numUnits;
  318.     pBpfDevHdr->bufSize = (bufSize <= 0) ? bpfBufSize : bufSize;
  319.     /* Initialize attachment to network interfaces. */
  320.     _bpfProtoInit ();
  321.     return (OK);
  322.     }
  323. /*******************************************************************************
  324. *
  325. * bpfDevDelete - destroy Berkeley Packet Filter device
  326. *
  327. * This routine removes a Berkeley Packet Filter device and releases all
  328. * allocated memory. It will close any open files using the device.
  329. *
  330. * RETURNS: OK, or ERROR if device not found
  331. *
  332. * ERRNO: S_ioLib_NO_DRIVER
  333. *
  334. * INTERNAL
  335. * This routine reverses the bpfDevCreate() routine operations.
  336. */
  337. STATUS bpfDevDelete
  338.     (
  339.     char *  pDevName  /* name of BPF device to remove */
  340.     )
  341.     {
  342.     char *  pTail = NULL;  /* Pointer to tail of device name. */
  343.     BPF_DEV_HDR * pBpfDev;  /* I/O system device header for BPF units */
  344.     if (bpfDrvNum == 0)
  345.         {
  346.         errnoSet (S_ioLib_NO_DRIVER);
  347.         return (ERROR);
  348.         }
  349.     pBpfDev = (BPF_DEV_HDR *)iosDevFind (pDevName, &pTail);
  350.     if (pBpfDev == NULL || pTail == pDevName)  /* Device not found? */
  351.         return (ERROR);
  352.     /* Close any open files and remove the BPF device. */
  353.     iosDevDelete ( (DEV_HDR *)pBpfDev);
  354.     /*
  355.      * The I/O system device header is the first element in the overall
  356.      * BPF device header. Remove all other data structures for the device.
  357.      */
  358.     free (pBpfDev->pBpfNetIfTbl);
  359.     free (pBpfDev->pBpfDevTbl);
  360.     semDelete (pBpfDev->lockSem);
  361.     free (pBpfDev);
  362.     return (OK);
  363.     }
  364. /*******************************************************************************
  365. *
  366. * _bpfLock - provides mutual exclusion for the BPF driver
  367. *
  368. * This routine protects critical sections of the BPF code by obtaining
  369. * a global lock which prevents additional BPF operations by any BPF units
  370. * through their associated file descriptors.
  371. *
  372. * RETURNS:
  373. * BPF_LOCK_KEY  - if the BPF lock is newly acquired
  374. * BPF_DUMMY_KEY - if the calling task already owns the BPF_LOCK_KEY
  375. *
  376. * NOMANUAL
  377. */
  378. int _bpfLock (void)
  379.     {
  380.     int taskIdCurrent = taskIdSelf ();  /* ID of current task */
  381.     
  382.     /* If the task already owns the lock return a dummy key */
  383.     if (bpfLockTaskId == taskIdCurrent)
  384. {
  385. return (BPF_DUMMY_KEY);
  386. }
  387.     if (semTake (bpfLockSemId, WAIT_FOREVER) != OK)
  388. {
  389. panic ("bpfLock error");
  390. }
  391.     
  392.     bpfLockTaskId = taskIdCurrent;
  393.     return (BPF_LOCK_KEY);
  394.     }
  395. /*******************************************************************************
  396. *
  397. * _bpfUnlock - release the mutual exclusion for the BPF driver
  398. *
  399. * This routine permits parallel BPF operations by any BPF units through
  400. * their associated file descriptors. It releases the lock previously acquired
  401. * by _bpfLock.  The routine has no effect if <lockKey> equals BPF_DUMMY_KEY
  402. * because of redundant lock attempts. If <lockKey> equals BPF_LOCK_KEY then
  403. * the lock will be released if the calling task currently owns the BPF lock.
  404. *
  405. * RETURNS:
  406. * OK or ERROR if the calling task does not own the BPF lock
  407. *
  408. * NOMANUAL
  409. */
  410.  
  411. STATUS _bpfUnlock
  412.     (
  413.     int lockKey         /* BPF_LOCK_KEY or BPF_DUMMY_KEY */
  414.     )
  415.     {
  416.     int taskIdCurrent;  /* ID of current task */
  417.     if (lockKey == BPF_DUMMY_KEY)
  418. {
  419. return (OK);
  420. }
  421.     taskIdCurrent = taskIdSelf ();
  422.     /* Calling task must own the BPF lock in order to release it */
  423.     if (taskIdCurrent != bpfLockTaskId)
  424. {
  425. return (ERROR);
  426. }
  427.     bpfLockTaskId = 0;
  428.     semGive (bpfLockSemId);
  429.     return (OK);
  430.     }
  431. /*******************************************************************************
  432. *
  433. * _bpfDevLock - provides mutual exclusion for a BPF device
  434. *
  435. * This routine protects shared data structures in the BPF code by obtaining
  436. * a lock which prevents BPF operations by any BPF units associated
  437. * with the same I/O device. This lock primarily supports stable "snapshots"
  438. * of the list of BPF units from a device attached to a particular network
  439. * interface. It also guarantees that a particular BPF unit will only be
  440. * available through a single file descriptor at a time.
  441. *
  442. * RETURNS: N/A
  443. *
  444. * NOMANUAL
  445. */
  446. void _bpfDevLock
  447.     (
  448.     UINT32 devId  /* Unique identifier for BPF I/O device. */
  449.     )
  450.     {
  451.     BPF_DEV_HDR * pBpfDevHdr;     /* BPF device header */
  452.     pBpfDevHdr = (BPF_DEV_HDR *)devId;
  453.     if (semTake (pBpfDevHdr->lockSem, WAIT_FOREVER) != OK)
  454.         {
  455.         panic ("bpfDevLock error");
  456.         }
  457.     return;
  458.     }
  459. /*******************************************************************************
  460. *
  461. * _bpfDevUnlock - release the mutual exclusion for a BPF device
  462. *
  463. * This routine permits parallel BPF operations by any BPF units within
  464. * a particular BPF I/O device. It releases the lock previously acquired
  465. * by the _bpfDevLock routine.
  466. *
  467. * RETURNS: N/A
  468. *
  469. * NOMANUAL
  470. */
  471.  
  472. void _bpfDevUnlock
  473.     (
  474.     UINT32 devId  /* Unique identifier for BPF I/O device. */
  475.     )
  476.     {
  477.     BPF_DEV_HDR * pBpfDevHdr;     /* BPF device header */
  478.     pBpfDevHdr = (BPF_DEV_HDR *)devId;
  479.     semGive (pBpfDevHdr->lockSem);
  480.     return;
  481.     }
  482. /*******************************************************************************
  483. *
  484. * _bpfUnitLock - provides mutual exclusion for a BPF file descriptor
  485. *
  486. * This routine protects shared data structures in the BPF code by obtaining
  487. * a lock which prevents BPF operations by a specific BPF unit through its
  488. * associated file descriptor. This lock primarily prevents alterations to
  489. * settings (such as the buffer size) which are currently in use by a task.
  490. * It also guarantees that a particular BPF unit will only be available 
  491. * through a single file descriptor at a time.
  492. *
  493. * RETURNS: N/A
  494. *
  495. * NOMANUAL
  496. */
  497. void _bpfUnitLock
  498.     (
  499.     BPF_DEV_CTRL * pBpfDev  /* Control structure for open BPF unit */
  500.     )
  501.     {
  502.     if (semTake (pBpfDev->lockSem, WAIT_FOREVER) != OK)
  503.         {
  504.         panic ("bpfUnitLock error");
  505.         }
  506.     return;
  507.     }
  508. /*******************************************************************************
  509. *
  510. * _bpfUnitUnlock - release the mutual exclusion for a BPF file descriptor
  511. *
  512. * This routine permits parallel BPF operations for a BPF unit associated
  513. * with a single file descriptor. It releases the lock previously acquired
  514. * by the _bpfUnitLock routine.
  515. *
  516. * RETURNS: N/A
  517. *
  518. * NOMANUAL
  519. */
  520.  
  521. void _bpfUnitUnlock
  522.     (
  523.     BPF_DEV_CTRL * pBpfDev  /* Control structure for open BPF unit */
  524.     )
  525.     {
  526.     semGive (pBpfDev->lockSem);
  527.     return;
  528.     }
  529. /*******************************************************************************
  530. *
  531. * _bpfDevDetach - detach a BPF device from the network interface
  532. *
  533. * This routine detaches the device from the attached network interface.  If the
  534. * BPF device requested promiscous mode it will disable promiscuous mode for the
  535. * interface.  If no units of the BPF device remain attached to the network 
  536. * interface, then this routine will remove the BPF MUX protocol as well.
  537. *
  538. * RETURNS:
  539. * OK or ERROR
  540. *
  541. * CAVEATS:
  542. * Must be called by a task which holds the device-specific _bpfDevLock
  543. * and the unit-specific _bpfUnitLock.
  544. *
  545. * NOMANUAL
  546. */
  547. STATUS _bpfDevDetach
  548.     (
  549.     BPF_DEV_CTRL * pBpfDev   /* Device control structure for a BPF unit */
  550.     )
  551.     {
  552.     int lockKey;  /* BPF global lock */
  553.     LIST * pBpfUnitList;      /* list of BPF units attached to the interface */
  554.     pBpfUnitList = & (pBpfDev->pNetDev->bpfUnitList);
  555.     /* Disable promiscuous mode if established for this unit. */
  556.     if (pBpfDev->promiscMode)
  557.         {
  558.         pBpfDev->promiscMode = FALSE;
  559.         lockKey = _bpfLock ();
  560.         _bpfProtoPromisc (pBpfDev->pNetDev, FALSE);
  561.         _bpfUnlock (lockKey);
  562.         }
  563.     /* Remove the unit from the attachment list for the BPF device. */
  564.     lstDelete (pBpfUnitList, (NODE *) pBpfDev);
  565.     /* 
  566.      * Detach this instance of the BPF MUX protocol if no more
  567.      * units from this device are using the network interface.
  568.      * Remove the Ethernet input hook if no more units from any
  569.      * BPF device are using any BSD network interface.
  570.      */
  571.     if (lstCount (pBpfUnitList) == 0)
  572.         {
  573.         lockKey = _bpfLock ();
  574.         _bpfProtoDetach (pBpfDev);
  575.         _bpfUnlock (lockKey);
  576.         }
  577.     pBpfDev->pNetDev = NULL;
  578.     return (OK);
  579.     }
  580. /*******************************************************************************
  581. *
  582. * _bpfPacketTap - process packets
  583. *
  584. * This routine processes packets for BPF devices.  For each BPF device on the
  585. * list <pListBpfDev>, the device specific packet filter is applied.  If the
  586. * filter accepts the packet then it is copied to the device's buffer. That
  587. * list has at least one entry or the BPF MUX protocol would never execute 
  588. * this routine.
  589. *
  590. * RETURNS:
  591. * Not Applicable
  592. *
  593. * NOMANUAL
  594. */
  595. void _bpfPacketTap
  596.     (
  597.     LIST *  pListBpfDev,  /* BPF units attached to network interface */
  598.     long  type,  /* MUX encoding of frame type */
  599.     M_BLK_ID  pMBlk,  /* M_BLK chain containing the packet */
  600.     int  netDataOffset  /* offset to the start of frame data */
  601.     )
  602.     {
  603.     struct timeval   timeStamp;   /* Timestamp of packet arrival */
  604.     int snapLen;                  /* length of packet data to store */ 
  605.     int bpfHdrLen;                /* size of the BPF hdr + padding */
  606.     BPF_DEV_CTRL * pBpfDev = NULL;    /* BPF device */
  607.     BPF_DEV_CTRL * pStart = NULL;
  608.     bpfTimeStamp (&timeStamp);
  609.     
  610.     /* 
  611.      * Determine the size of the BPF header plus padding so that the
  612.      * network header is long word aligned 
  613.      */
  614.     bpfHdrLen = BPF_WORDALIGN (netDataOffset + sizeof (struct bpf_hdr))
  615.                     - netDataOffset;
  616.     pBpfDev = pStart = (BPF_DEV_CTRL *)lstFirst (pListBpfDev);
  617.     if (pBpfDev == NULL)
  618.         {
  619.         /*
  620.          * Last attached unit for this BPF device was just removed
  621.          * from the network interface.
  622.          */
  623.         return;
  624.         }
  625.     _bpfDevLock (pBpfDev->bpfDevId);    /*
  626.                                          * Protect list of attached BPF units
  627.                                          * while applying filters.
  628.                                          */
  629.     for ( ; pBpfDev != NULL;
  630.             pBpfDev = (BPF_DEV_CTRL *) lstNext ((NODE *) pBpfDev))
  631.         {
  632.         _bpfUnitLock (pBpfDev);  /* Prevent changing filter or buffer size. */
  633.         pBpfDev->pktRecvCount++;
  634.         snapLen = bpf_filter (pBpfDev->pBpfInsnFilter, (u_char *) pMBlk,
  635.                               pMBlk->mBlkPktHdr.len, 0, type, netDataOffset);
  636.         if (snapLen != 0)
  637.             {
  638.             /* Filter accepted the frame. Copy it to the BPF unit's buffer. */
  639.             bpfPacketCatch (pBpfDev, pMBlk, snapLen, bpfHdrLen, 
  640.                             &timeStamp, netDataOffset);
  641.             }
  642.         _bpfUnitUnlock (pBpfDev);
  643.         }
  644.     _bpfDevUnlock (pStart->bpfDevId);
  645.     return;
  646.     }
  647. /*******************************************************************************
  648. *
  649. * bpfOpen - BPF specific open routine 
  650. *
  651. * This routine opens a unit for a BPF device. It initializes a BPF_DEV_CTRL
  652. * structure. All subsequent I/O operations will supply a pointer to that
  653. * control structure through the file descriptor.
  654. *
  655. * RETURNS:
  656. * BPF_DEV_CTRL * - if open is successful
  657. * ERROR          - if open fails
  658. *
  659. * ERRNO:
  660. * S_errno_ENXIO  - if minor device number is invalid
  661. * S_errno_EBUSY  - if minor device is already in use
  662. * S_errno_ENOMEM - insufficient memory for device
  663. *
  664. * NOMANUAL
  665. */ 
  666. LOCAL int bpfOpen
  667.     (
  668.     BPF_DEV_HDR * pBpfDevHdr,    /* BPF device hdr (unused) */
  669.     char        * minorDevStr,   /* string containing device unit number */
  670.     int         flags            /* user open flags */
  671.     )
  672.     {
  673.     FAST BPF_DEV_CTRL * pBpfDev = NULL;  /* BPF device to open */
  674.     SEM_ID  readSem;  /* Trigger for incoming data. */
  675.     int  minorDevNum;    /* unit number for device */
  676.     /* Convert string to int and verify it contains a valid unit number */
  677.     if ( (minorDevStr == NULL) || 
  678.         ( (minorDevNum = atoi (minorDevStr)) < 0)
  679.          || (minorDevNum >= pBpfDevHdr->numDevs) )
  680.         {
  681.         netErrnoSet (ENXIO);
  682.         return (ERROR);
  683.         }
  684.     readSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
  685.     if (readSem == NULL)
  686.         {
  687.         netErrnoSet (ENOMEM);
  688.         return (ERROR);
  689.         }
  690.     pBpfDev = pBpfDevHdr->pBpfDevTbl + minorDevNum;
  691.     if (pBpfDev == NULL)     /* Device control header vanished!! */
  692.         {
  693.         semDelete (readSem);
  694.         netErrnoSet (ENOMEM);
  695.         return (ERROR);
  696.         }
  697.     /*
  698.      * Check if this BPF unit is already in use. A device lock is required
  699.      * for this test since the semaphore which provides unit locks will not
  700.      * exist if it is currently unused.
  701.      */
  702.     _bpfDevLock ( (UINT32)pBpfDevHdr);
  703.     if (pBpfDev->inUse)
  704.         {
  705.         _bpfDevUnlock ( (UINT32)pBpfDevHdr);
  706.         semDelete (readSem);
  707.         netErrnoSet (EBUSY);
  708.         return (ERROR);
  709.         }
  710.     /* Initialize device structure. */
  711.     bzero ( (char *)pBpfDev, sizeof (BPF_DEV_CTRL));
  712.     pBpfDev->lockSem = semBCreate (SEM_Q_FIFO, SEM_FULL);
  713.     if (pBpfDev->lockSem == NULL)
  714.         {
  715.         _bpfDevUnlock ( (UINT32)pBpfDevHdr);
  716.         semDelete (readSem);
  717.         netErrnoSet (ENOMEM);
  718.         return (ERROR);
  719.         }
  720.     pBpfDev->inUse = TRUE;
  721.     _bpfDevUnlock ( (UINT32)pBpfDevHdr);
  722.     pBpfDev->usrFlags = flags;
  723.     pBpfDev->bufSize = pBpfDevHdr->bufSize;
  724.     pBpfDev->readWkupSem = readSem;
  725.     pBpfDev->readTimeout = WAIT_FOREVER;
  726.     /* XXX - this uses semMInit() routine internally!  PD Violation??? */
  727.     selWakeupListInit (& (pBpfDev->selWkupList));
  728.     /*
  729.      * Set the element for attaching to a network interface. It is only
  730.      * used if this BPF unit is the first attachment to the network
  731.      * interface from the parent BPF device.
  732.      */
  733.     pBpfDev->pNetIfCtrl = pBpfDevHdr->pBpfNetIfTbl + minorDevNum;
  734.     /*
  735.      * Attaching a BPF unit to a network interface requires a value which
  736.      * uniquely identifies the parent device. This field also provides
  737.      * mutual exclusion on a device-specific basis when necessary.
  738.      */
  739.     pBpfDev->bpfDevId = (UINT32)pBpfDevHdr;
  740.     return ((int) pBpfDev);
  741.     }
  742. /*******************************************************************************
  743. *
  744. * bpfClose - BPF specific close routine 
  745. *
  746. * This routine closes a BPF device.  The steps are the following:
  747. * 1) Detach from the attached network interface if any. 
  748. * 2) Free any allocated memory for store buffers and the filter.
  749. * 3) Mark the device as being unused.
  750. *
  751. * RETURNS:
  752. * OK or ERROR
  753. *
  754. * ERRNO:
  755. *
  756. * NOMANUAL
  757. */ 
  758. LOCAL STATUS bpfClose
  759.     (
  760.     BPF_DEV_CTRL * pBpfDev   /* BPF device control structure */
  761.     )
  762.     {
  763.     _bpfUnitLock (pBpfDev);
  764.     if (pBpfDev->pNetDev != NULL)
  765.         {
  766.         /* Detach from the network interface */
  767.         _bpfDevLock (pBpfDev->bpfDevId);
  768.         (void) _bpfDevDetach (pBpfDev);
  769.         _bpfDevUnlock (pBpfDev->bpfDevId);
  770.         }
  771.     /* Release the buffers and mark the unit available. */
  772.     bpfDevFree (pBpfDev);
  773.     /* Remove the mutex semaphore for the BPF unit instead of unlocking. */
  774.     semDelete (pBpfDev->lockSem);
  775.     return (OK);
  776.     }
  777. /*******************************************************************************
  778. *
  779. * bpfRead - read next block of packets from device buffers 
  780. *
  781. * This routine reads the next block of packets from the BPF device store 
  782. * buffers.  The call will return immeadiately if using non-Blocking mode.  If
  783. * in immediate mode bpfRead will return when the timeout expires or when a
  784. * packet arrives.  In normal mode, the routine returns when the timeout
  785. * expires or when the storage buffer is filled.
  786. *
  787. * RETURNS: 
  788. * ERROR or the number of bytes read
  789. *
  790. * ERRNOS:
  791. * S_errno_EINVAL      - <nBytes> is not equal to the size of the BPF buffer
  792. * S_errno_EWOULDBLOCK - no packets are available and non-Blocking mode is on
  793. *
  794. * NOMANUAL
  795. */ 
  796. LOCAL int bpfRead
  797.     (
  798.     BPF_DEV_CTRL * pBpfDev,   /* BPF device control structure */
  799.     char         * pBuf,      /* user data buffer */
  800.     int          nBytes       /* number of bytes to read */
  801.     )
  802.     {
  803.     int error = OK;           /* return value errorno code */
  804.     _bpfUnitLock (pBpfDev);
  805.     /*
  806.      * Restrict application to use a buffer the same size as
  807.      * the internal BPF buffers.
  808.      */
  809.     if (nBytes != pBpfDev->bufSize)
  810.         {
  811.         _bpfUnitUnlock (pBpfDev);
  812.         netErrnoSet (EINVAL);
  813.         return (ERROR);
  814.         }
  815.     /*
  816.      * If the hold buffer is empty, then do a timed sleep, which
  817.      * ends when the timeout expires or when enough packets
  818.      * have arrived to fill the store buffer.
  819.      */
  820.     while (pBpfDev->readHoldBuf == NULL)
  821.         {
  822.         if (pBpfDev->nonBlockMode)
  823.             {
  824.             if (pBpfDev->recvStoreLen == 0)
  825.                 {
  826.                 _bpfUnitUnlock (pBpfDev);
  827.                 netErrnoSet (EWOULDBLOCK);
  828.                 return (ERROR);
  829.                 }
  830.             ROTATE_BUFFERS(pBpfDev);
  831.             break;
  832.             }
  833.         if (pBpfDev->immediateMode && pBpfDev->recvStoreLen != 0)
  834.             {
  835.             /*
  836.              * A packet(s) either arrived since the previous
  837.              * read or arrived while we were asleep.
  838.              * Rotate the buffers and return what's here.
  839.              */
  840.             ROTATE_BUFFERS(pBpfDev);
  841.             break;
  842.             }
  843.         _bpfUnitUnlock (pBpfDev);
  844.         error = bpfSleep (pBpfDev, pBpfDev->readTimeout);
  845.         _bpfUnitLock (pBpfDev);
  846.         if (error != OK) 
  847.             {
  848.             if (error == EWOULDBLOCK) 
  849.                 {
  850.                 /*
  851.                  * On a timeout, return what's in the buffer,
  852.                  * which may be empty. If new data is available,
  853.                  * swap the buffers to retrieve it.
  854.                  */
  855.                 if (pBpfDev->readHoldBuf != NULL)
  856.                     {
  857.                     /*
  858.                      * The read buffer is now available. The receive buffer
  859.                      * must have filled while sleeping and the buffers were
  860.                      * rotated then.
  861.                      */
  862.                     break;
  863.                     }
  864.                 if (pBpfDev->recvStoreLen == 0)
  865.                     {
  866.                     /* No data arrived while sleeping. */
  867.                     _bpfUnitUnlock (pBpfDev);
  868.                     return (0);
  869.                     }
  870.                 ROTATE_BUFFERS(pBpfDev);
  871.                 break;
  872.                 }
  873.             /* Fatal error occurred while sleeping. */
  874.             _bpfUnitUnlock (pBpfDev);
  875.             netErrnoSet (error);
  876.             return (ERROR);
  877.             }
  878.         }
  879.     
  880.     /*
  881.      * Move data from the read buffer into user space. The entire buffer
  882.      * is transferred since the target buffer is <pBpfDev>->bufSize bytes,
  883.      * so rotate the buffers appropriately.
  884.      */
  885.     nBytes = pBpfDev->readHoldLen;
  886.     bcopy (pBpfDev->readHoldBuf, pBuf, nBytes);
  887.     pBpfDev->freeBuf = pBpfDev->readHoldBuf;
  888.     pBpfDev->readHoldBuf = NULL;
  889.     pBpfDev->readHoldLen = 0;
  890.     _bpfUnitUnlock (pBpfDev);
  891.     
  892.     return (nBytes);
  893.     }
  894. /*******************************************************************************
  895. *
  896. * bpfWrite - outputs a packet directly to a network interface
  897. *
  898. * This routine takes a fully formed packet, including any data link layer
  899. * header required by the device, and outputs it on the attached network
  900. * interface.
  901. *
  902. * RETURNS:
  903. * ERROR or the number of bytes written to the interface 
  904. *
  905. * ERRNOS:
  906. * S_errno_ENXIO  - if the BPF device is not attached to a network interface
  907. *
  908. * NOMANUAL
  909. */
  910. LOCAL int bpfWrite
  911.     (
  912.     BPF_DEV_CTRL * pBpfDev,   /* BPF device control structure */
  913.     char         * pBuf,      /* user data buffer */
  914.     int          nBytes       /* number of bytes to read */
  915.     )
  916.     {
  917.     /* Must be attached to a network interface */
  918.     if (pBpfDev->pNetIfCtrl == NULL)
  919.         {
  920.         netErrnoSet (ENXIO);
  921.         return (ERROR);
  922.         }
  923.     if (_bpfProtoSend (pBpfDev->pNetIfCtrl, pBuf, nBytes,
  924.                        pBpfDev->nonBlockMode) != OK)
  925.         {
  926.         return (ERROR);
  927.         }
  928.     return (nBytes);
  929.     }
  930. /*******************************************************************************
  931. *
  932. * bpfIoctl - implements BPF specific I/O control commands 
  933. *
  934. * This routine implements the following I/O control commands for BPF devices:
  935. *
  936. *  FIONREAD Check for read packet available.
  937. *  BIOCGBLEN Get buffer len [for read()].
  938. *  BIOCSETF Set ethernet read filter.
  939. *  BIOCFLUSH Flush read packet buffer.
  940. *  BIOCPROMISC Put interface into promiscuous mode.
  941. *  BIOCGDLT Get link layer type.
  942. *  BIOCGETIF Get interface name.
  943. *  BIOCSETIF Set interface.
  944. *  BIOCSRTIMEOUT Set read timeout.
  945. *  BIOCGRTIMEOUT Get read timeout.
  946. *  BIOCGSTATS Get packet stats.
  947. *  BIOCIMMEDIATE Set immediate mode.
  948. *  BIOCVERSION Get filter language version.
  949. *
  950. * RETURNS:
  951. * OK or ERROR
  952. *
  953. * ERRNO:
  954. * S_errno_EINVAL - invalid command for BPF device
  955. * S_errno_ENOMEM - insufficient system memory
  956. * S_errno_ENOBUFS - expected buffer not found [from bpfProtoAttach() routine]
  957. * NOMANUAL
  958. */
  959. LOCAL STATUS bpfIoctl
  960.     (
  961.     BPF_DEV_CTRL * pBpfDev,   /* BPF device control structure */
  962.     int  request,     /* ioctl () command */
  963.     void         * addr       /* ioctl () command argument */
  964.     )
  965.     {
  966.     int                error = OK;    /* errno value to set */
  967.     int                lockKey;       /* BPF lock key */
  968.     FAST int           nBytes;        /* byte count */
  969.     struct timeval     * pTimeVal;    /* timeout value */
  970.     UINT               mSec;          /* timeout in milliseconds */
  971.     struct bpf_stat    * pBpfStat;    /* BPF device statistics */
  972.     struct bpf_version * pBpfVersion; /* BPF filter version info */
  973.     switch (request)
  974.         {
  975.         default:
  976.             error = EINVAL;
  977.             break;
  978.         case FIONBIO:
  979.             _bpfUnitLock (pBpfDev);
  980.             pBpfDev->nonBlockMode = * ((BOOL *) addr);
  981.             _bpfUnitUnlock (pBpfDev);
  982.             break;
  983.         case FIONREAD:
  984.             _bpfUnitLock (pBpfDev);
  985.             /* Retrieve amount of data in the read and immediate buffers. */
  986.             nBytes = pBpfDev->recvStoreLen;
  987.             if (pBpfDev->readHoldBuf != NULL)
  988.                 nBytes += pBpfDev->readHoldLen;
  989.             _bpfUnitUnlock (pBpfDev);
  990.             *(int *)addr = nBytes;
  991.             break;
  992.         case FIOSELECT:
  993.             /* Add BPF unit to wakeup list. */
  994.             _bpfUnitLock (pBpfDev);
  995.             bpfSelectAdd (pBpfDev, (SEL_WAKEUP_NODE *)addr);
  996.             _bpfUnitUnlock (pBpfDev);
  997.             break;
  998.         case FIOUNSELECT:
  999.             /* Remove BPF unit from wakeup list. */
  1000.             _bpfUnitLock (pBpfDev);
  1001.             bpfSelectDelete (pBpfDev, (SEL_WAKEUP_NODE *)addr);
  1002.             _bpfUnitUnlock (pBpfDev);
  1003.             break;
  1004.         case BIOCGBLEN:
  1005.             _bpfUnitLock (pBpfDev);
  1006.           *(u_int *)addr = pBpfDev->bufSize;
  1007.             _bpfUnitUnlock (pBpfDev);
  1008.             break;
  1009.         case BIOCSBLEN:
  1010.             _bpfUnitLock (pBpfDev);
  1011.             /* Cannot set buffer len after attaching to network interface. */
  1012.             if (pBpfDev->pNetDev != NULL)
  1013.                 {
  1014.                 _bpfUnitUnlock (pBpfDev);
  1015.                 error = EINVAL;
  1016.                 break;
  1017.                 }
  1018.             nBytes = *(u_int *)addr;
  1019.             /* New buffer size must be between maximum and minimum limits. */
  1020.             if (nBytes > BPF_MAXBUFSIZE)
  1021.                 nBytes = BPF_MAXBUFSIZE;
  1022.             if (nBytes < BPF_MINBUFSIZE)
  1023.                 {
  1024.                 nBytes = BPF_MINBUFSIZE;
  1025.                 }
  1026.             /* Determine if enough memory remains to allocate buffer. */
  1027.             if ( (nBytes = min (nBytes, memFindMax ())) < BPF_MINBUFSIZE)
  1028.                 {
  1029.                 _bpfUnitUnlock (pBpfDev);
  1030.                 error = ENOMEM;
  1031.                 break;
  1032.                 }
  1033.             *(u_int *)addr = nBytes;
  1034.             pBpfDev->bufSize = nBytes;
  1035.             (void) _bpfUnitUnlock (pBpfDev);
  1036.             break;
  1037.         case BIOCSETF:
  1038.             _bpfUnitLock (pBpfDev);
  1039.             error = bpfSetFilter (pBpfDev, (struct bpf_program *)addr);
  1040.             _bpfUnitUnlock (pBpfDev);
  1041.             break;
  1042.         case BIOCFLUSH:
  1043.             _bpfUnitLock (pBpfDev);
  1044.             bpfDevReset (pBpfDev);
  1045.             _bpfUnitUnlock (pBpfDev);
  1046.             break;
  1047.         case BIOCPROMISC:
  1048.             _bpfUnitLock (pBpfDev);
  1049.             if (pBpfDev->pNetDev == NULL)
  1050.                 {
  1051.                 /* No interface attached yet. */
  1052.                 error = EINVAL;
  1053.                 }
  1054.             else if (!pBpfDev->promiscMode)
  1055.                 {
  1056.                 lockKey = _bpfLock ();
  1057.                 error = _bpfProtoPromisc (pBpfDev->pNetDev, TRUE);
  1058.                 (void) _bpfUnlock (lockKey);
  1059.                 pBpfDev->promiscMode = (error == OK);
  1060.                 }
  1061.             _bpfUnitUnlock (pBpfDev);
  1062.             break;
  1063.         case BIOCGDLT:
  1064.             _bpfUnitLock (pBpfDev);
  1065.             if (pBpfDev->pNetDev == NULL)
  1066.                 error = EINVAL;
  1067.             else
  1068.                 {
  1069.                 *(u_int *)addr = pBpfDev->pNetDev->dataLinkType;
  1070.                 }
  1071.             _bpfUnitUnlock (pBpfDev);
  1072.             break;
  1073.         case BIOCGETIF:
  1074.             _bpfUnitLock (pBpfDev);
  1075.             if (pBpfDev->pNetDev == NULL)
  1076.                 error = EINVAL;
  1077.             else 
  1078.                 {
  1079.                 sprintf ( ( (struct ifreq *)addr)->ifr_name, "%s%d",
  1080.                          pBpfDev->pNetDev->devName,
  1081.                          pBpfDev->pNetDev->devUnit);
  1082.                 }
  1083.             _bpfUnitUnlock (pBpfDev);
  1084.             break;
  1085.         case BIOCSETIF:
  1086.             _bpfUnitLock (pBpfDev);
  1087.             error = bpfIfSet (pBpfDev, (struct ifreq *)addr, FALSE);
  1088.             _bpfUnitUnlock (pBpfDev);
  1089.             break;
  1090.         case BIOCSTOP:  /* Detach device from input stream. */
  1091.             _bpfUnitLock (pBpfDev);
  1092.             /* Do nothing if device is not attached. */
  1093.             if (pBpfDev->pNetDev == NULL)
  1094.                 {
  1095.                 _bpfUnitUnlock (pBpfDev);
  1096.                 break;
  1097.                 }
  1098.             _bpfDevLock (pBpfDev->bpfDevId);
  1099.             _bpfDevDetach (pBpfDev);
  1100.             _bpfDevUnlock (pBpfDev->bpfDevId);
  1101.             _bpfUnitUnlock (pBpfDev);
  1102.             break;
  1103.         case BIOCSTART: /* Reattach device to input stream. */
  1104.             _bpfUnitLock (pBpfDev);
  1105.             /* Do nothing if device is already attached. */
  1106.             if (pBpfDev->pNetDev != NULL)
  1107.                 {
  1108.                 _bpfUnitUnlock (pBpfDev);
  1109.                 break;
  1110.                 }
  1111.             error = bpfIfSet (pBpfDev, (struct ifreq *)addr, TRUE);
  1112.             _bpfUnitUnlock (pBpfDev);
  1113.             break;
  1114.         case BIOCSRTIMEOUT:
  1115.             pTimeVal = (struct timeval *)addr;
  1116.             mSec = pTimeVal->tv_sec * 1000; 
  1117.             mSec += pTimeVal->tv_usec / 1000;
  1118.             _bpfUnitLock (pBpfDev);
  1119.             /* scale milliseconds to ticks */
  1120.             pBpfDev->readTimeout = (mSec * sysClkRateGet ()) / 1000;
  1121.             if (pBpfDev->readTimeout == 0)
  1122.                 {
  1123.                 if (pTimeVal->tv_usec == 0)
  1124.                     {
  1125.                     pBpfDev->readTimeout = WAIT_FOREVER;
  1126.                     }
  1127.                 else
  1128.                     {
  1129.                     pBpfDev->readTimeout = 1;
  1130.                     }
  1131.                 }
  1132.             _bpfUnitUnlock (pBpfDev);
  1133.             break;
  1134.         case BIOCGRTIMEOUT:
  1135.             pTimeVal = (struct timeval *)addr;
  1136.             _bpfUnitLock (pBpfDev);
  1137.             if (pBpfDev->readTimeout == WAIT_FOREVER)
  1138.                 {
  1139.                 pTimeVal->tv_sec = 0;
  1140.                 pTimeVal->tv_usec = 0;
  1141.                 _bpfUnitUnlock (pBpfDev);
  1142.                 }
  1143.             else
  1144.                 {
  1145.                 mSec = (pBpfDev->readTimeout * sysClkRateGet ()) / 1000;
  1146.                 pTimeVal->tv_sec = mSec / 1000;
  1147.                 pTimeVal->tv_usec = mSec % 1000;
  1148.                 }
  1149.             _bpfUnitUnlock (pBpfDev);
  1150.             break;
  1151.         case BIOCGSTATS:
  1152.             pBpfStat = (struct bpf_stat *)addr;
  1153.             _bpfUnitLock (pBpfDev);
  1154.             pBpfStat->bs_recv = pBpfDev->pktRecvCount;
  1155.             pBpfStat->bs_drop = pBpfDev->pktDropCount;
  1156.             _bpfUnitUnlock (pBpfDev);
  1157.             break;
  1158.         case BIOCIMMEDIATE:
  1159.             _bpfUnitLock (pBpfDev);
  1160.             pBpfDev->immediateMode = *(u_int *)addr;
  1161.             _bpfUnitUnlock (pBpfDev);
  1162.             break;
  1163.         case BIOCVERSION:
  1164.             pBpfVersion = (struct bpf_version *)addr;
  1165.             pBpfVersion->bv_major = BPF_MAJOR_VERSION;
  1166.             pBpfVersion->bv_minor = BPF_MINOR_VERSION;
  1167.             break;
  1168.         }
  1169.     if (error != OK)
  1170.         {
  1171.         netErrnoSet (error);
  1172.         return (ERROR);
  1173.         }
  1174.     return (OK);
  1175.     }
  1176. /*******************************************************************************
  1177. *
  1178. * bpfDevReset - reset BPF device
  1179. *
  1180. * This routine resets a BPF device by flushing its packet buffer and clearing 
  1181. * the receive and drop counts.  
  1182. *
  1183. * RETURNS:
  1184. * Not Applicable
  1185. *
  1186. * CAVEATS:
  1187. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1188. *
  1189. * NOMANUAL
  1190. */
  1191. LOCAL void bpfDevReset 
  1192.     (
  1193.     BPF_DEV_CTRL * pBpfDev   /* BPF device control structure */
  1194.     )
  1195.     {
  1196.     if (pBpfDev->readHoldBuf != 0)
  1197.         {
  1198.         pBpfDev->freeBuf = pBpfDev->readHoldBuf;
  1199.         pBpfDev->readHoldBuf = 0;
  1200.         pBpfDev->readHoldLen = 0;
  1201.         }
  1202.     pBpfDev->recvStoreLen = 0;
  1203.     pBpfDev->pktRecvCount = 0;
  1204.     pBpfDev->pktDropCount = 0;
  1205.     }
  1206. /*******************************************************************************
  1207. *
  1208. * bpfSelectAdd - joins the wakeup list for select operation
  1209. *
  1210. * This routine implements the FIOSELECT operation. It adds a BPF device
  1211. * to the list of I/O devices waiting for activity through the select()
  1212. * routine. The add operation allows the bpfWakeup() routine to complete
  1213. * the selection process once sufficient data arrives.
  1214. *
  1215. * RETURNS: N/A
  1216. *
  1217. * CAVEATS:
  1218. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1219. *
  1220. * NOMANUAL
  1221. */
  1222. LOCAL void bpfSelectAdd
  1223.     (
  1224.     BPF_DEV_CTRL *  pBpfDev,  /* BPF device control structure */ 
  1225.     SEL_WAKEUP_NODE *  pWakeupNode  /* Control information from select */
  1226.     )
  1227.     {
  1228.     /* Only pend when selecting for read requests. */
  1229.     if (selWakeupType (pWakeupNode) == SELREAD)
  1230.         {
  1231.         if (selNodeAdd (& (pBpfDev->selWkupList), pWakeupNode) == ERROR)
  1232.             return;
  1233.         pBpfDev->selectFlag = TRUE;
  1234.         /* Wake the calling task immediately if data is already available. */
  1235.         if ( (pBpfDev->readHoldBuf != NULL) ||
  1236.             (pBpfDev->immediateMode && pBpfDev->recvStoreLen != 0))
  1237.             {
  1238.             selWakeup (pWakeupNode);
  1239.             }
  1240.         }
  1241.     return;
  1242.     }
  1243. /*******************************************************************************
  1244. *
  1245. * bpfSelectDelete - leaves the wakeup list for select operation
  1246. *
  1247. * This routine implements the FIOUNSELECT control operation. It removes a
  1248. * BPF device from the list of I/O devices waiting for activity through the
  1249. * select() routine. The remove operation completes the selection process
  1250. * started with the FIOSELECT operation.
  1251. *
  1252. * RETURNS: N/A
  1253. *
  1254. * CAVEATS:
  1255. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1256. *
  1257. * NOMANUAL
  1258. */
  1259. LOCAL void bpfSelectDelete
  1260.     (
  1261.     BPF_DEV_CTRL *  pBpfDev,  /* BPF device control structure */ 
  1262.     SEL_WAKEUP_NODE *  pWakeupNode  /* Control information from select */
  1263.     )
  1264.     {
  1265.     /* Only handle cancellations for read requests. */
  1266.     if (selWakeupType (pWakeupNode) == SELREAD)
  1267.         {
  1268.         selNodeDelete (& (pBpfDev->selWkupList), pWakeupNode);
  1269.         /*
  1270.          * A BPF unit is only accessible through a single file descriptor,
  1271.          * so the list length will usually be zero at this point. However,
  1272.          * a task may have shared that file descriptor with others. No
  1273.          * race condition occurs because this routine executes while the
  1274.          * BPF unit is locked.
  1275.          */
  1276.         if (selWakeupListLen (& (pBpfDev->selWkupList)) == 0)
  1277.             {
  1278.             pBpfDev->selectFlag = FALSE;
  1279.             }
  1280.         }
  1281.     return;
  1282.     }
  1283. /*******************************************************************************
  1284. *
  1285. * bpfSetFilter - sets the filter program used by a BPF device
  1286. *
  1287. * This routine sets the filter program to be used with a BPF device.  Before
  1288. * the filter progam is set it will be validated using the bpf_validate () 
  1289. * routine.
  1290. *
  1291. * RETURNS:
  1292. * OK
  1293. * EINVAL if the filter program is invalid
  1294. * ENOMEM if there is insufficient system memory to store the filter program
  1295. *
  1296. * CAVEATS:
  1297. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1298. *
  1299. * INTERNAL
  1300. * This routine returns errno values if a failure occurs so that the ioctl
  1301. * mechanism can set the error number appropriately.
  1302. *
  1303. * NOMANUAL
  1304. */
  1305. LOCAL int bpfSetFilter
  1306.     (
  1307.     BPF_DEV_CTRL       * pBpfDev,   /* BPF device control structure */ 
  1308.     struct bpf_program * pBpfProg   /* BPF filter program */
  1309.     )
  1310.     {
  1311.     struct bpf_insn * pBpfInsnNew;  /* New BPF filter instructions */
  1312.     struct bpf_insn * pBpfInsnOld;  /* Previous BPF filter instructions */ 
  1313.     UINT filterLen;                 /* size in instructions of new filter */
  1314.     UINT filterSize;                /* size in bytes of new filter */
  1315.     BOOL newFlag = FALSE;           /* allocate new storage for filter? */
  1316.     pBpfInsnOld = pBpfDev->pBpfInsnFilter;
  1317.     /* If filter program contains no instructions set filter to NULL */
  1318.     if (pBpfProg->bf_insns == NULL)
  1319.         {
  1320. /* If no filter instructions then filter instuction length must be 0 */
  1321.         if (pBpfProg->bf_len != 0)
  1322.             {
  1323.             return (EINVAL);
  1324.             }
  1325.         /* Set filter to NULL and reset device buffers */
  1326.         pBpfDev->pBpfInsnFilter = NULL;
  1327.         pBpfDev->filterLen = 0;
  1328.         bpfDevReset (pBpfDev);
  1329.         if (pBpfInsnOld != NULL)
  1330.             {
  1331.             free (pBpfInsnOld);
  1332.             return (OK);
  1333.             }
  1334.         }
  1335.     filterLen = pBpfProg->bf_len;
  1336.     if (filterLen > BPF_MAXINSNS)
  1337.         return (EINVAL);
  1338.     if (filterLen != pBpfDev->filterLen)
  1339.         newFlag = TRUE;
  1340.     pBpfDev->filterLen = filterLen;
  1341.     filterSize = filterLen * sizeof (*pBpfProg->bf_insns);
  1342.     if (newFlag)
  1343.         {
  1344.         pBpfInsnNew = (BPF_INSN *)malloc (filterSize);
  1345.         if (pBpfInsnNew == NULL)
  1346.             {
  1347.             return (ENOMEM);
  1348.             }
  1349.         }
  1350.     else
  1351.         pBpfInsnNew = pBpfInsnOld;
  1352.     /* Copy instructions from given program to internal storage */
  1353.     bcopy ((char *) pBpfProg->bf_insns, (char *) pBpfInsnNew, filterSize);
  1354.     /* 
  1355.      * Validate the filter.  Since the filter is executed as part of the
  1356.      * critical receive path, validation prevents crashing the network stack.
  1357.      */
  1358.     if (bpf_validate (pBpfInsnNew, filterLen))
  1359.         {
  1360.         pBpfDev->pBpfInsnFilter = pBpfInsnNew;
  1361.         bpfDevReset (pBpfDev);
  1362.         if (newFlag && pBpfInsnOld != NULL)
  1363.             {
  1364.             free (pBpfInsnOld);
  1365.             }
  1366.         return (OK);
  1367.         }
  1368.     /* New filter is invalid.  Free filter if necessary and return EINVAL */
  1369.     if (newFlag)
  1370.         free (pBpfInsnNew);
  1371.     return (EINVAL);
  1372.     }
  1373. /*******************************************************************************
  1374. *
  1375. * bpfIfSet - attaches BPF device to a network interface
  1376. *
  1377. * When <restartFlag> is TRUE, this routine reattaches a BPF device to a
  1378. * network interface (for the BIOCSTART ioctl). Otherwise, it handles
  1379. * the BIOCSETIF ioctl by detaching a BPF device from its current network
  1380. * interface, if any, and then attaching to a new network interface.
  1381. *
  1382. * RETURNS:
  1383. * OK, EINVAL, or ENOBUFS
  1384. *
  1385. * CAVEATS:
  1386. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1387. *
  1388. * INTERNAL
  1389. * This routine returns errno values if a failure occurs so that the ioctl
  1390. * mechanism can set the error number appropriately.
  1391. * NOMANUAL
  1392. */
  1393. LOCAL STATUS bpfIfSet
  1394.     (
  1395.     BPF_DEV_CTRL * pBpfDev,   /* BPF device control structure */
  1396.     struct ifreq * pIfReq,    /* Name of the network interface to attach to */
  1397.     BOOL  restartFlag  /* Create a new attachment or renew one? */
  1398.     )
  1399.     {
  1400.     char * pDevName;
  1401.     char devName [END_NAME_MAX + 1];
  1402.     int unit;
  1403.     int lockKey;     /* Blocks any other BPF operations. */
  1404.     STATUS result;
  1405.     BOOL attachFlag = FALSE;  /* New attachment to a network interface? */
  1406.     END_OBJ * pEnd = NULL;  /* Handle for END device. */
  1407.     struct ifnet * pIf = NULL;  /* Handle for BSD device. */
  1408.     /* Validate the name of the network interface. */
  1409.     if (pIfReq == NULL)
  1410.         return (EINVAL);
  1411.     pDevName = pIfReq->ifr_name;
  1412.     if (*pDevName == EOS)
  1413.         return (EINVAL);    /* No device name given. */
  1414.     while (*pDevName != EOS && !isdigit ( (int) (*pDevName)))
  1415.         pDevName++;
  1416.     if (*pDevName != EOS)
  1417.         unit = atoi (pDevName);
  1418.     else
  1419.         return (EINVAL);    /* No unit number included in device name. */
  1420.     if (unit < 0)
  1421.         return (EINVAL);    /* Invalid unit number. */
  1422.     bzero (devName, END_NAME_MAX + 1);
  1423.     strncpy (devName, pIfReq->ifr_name,
  1424.              min (END_NAME_MAX, pDevName - pIfReq->ifr_name));
  1425.     pEnd = endFindByName (devName, unit);
  1426.     if (pEnd == NULL)
  1427.         {
  1428.         /* Check for BSD device. */
  1429.         pIf = ifunit (pIfReq->ifr_name);
  1430.         if (pIf == NULL)
  1431.             return (EINVAL);    /* No such device. */
  1432.         }
  1433.     /* Allocate buffers for BPF unit if it hasn't been done yet. */
  1434.     if (!restartFlag && pBpfDev->recvStoreBuf == NULL)
  1435.         {
  1436.         if (bpfBufsAlloc (pBpfDev) != OK)
  1437.             {
  1438.             return (ENOMEM);
  1439.             }
  1440.         }
  1441.     /*
  1442.      * Bind BPF unit to network interface if not already attached to it.
  1443.      * Prevent any other BPF units in the device from changing the list
  1444.      * of network interface attachments.
  1445.      */
  1446.     _bpfDevLock (pBpfDev->bpfDevId);    /* Preserve attachments list. */
  1447.     if (pBpfDev->pNetDev == NULL)
  1448.         attachFlag = TRUE;    /* New attachment for BPF device. */
  1449.     else if (pEnd)
  1450.         {
  1451.         /* Check if changing attachments to new END device. */
  1452.         if ( (pBpfDev->pNetDev->bsdFlag == TRUE) ||
  1453.             (PCOOKIE_TO_ENDOBJ(pBpfDev->pNetDev->pCookie) != pEnd))
  1454.             attachFlag = TRUE;
  1455.         }
  1456.     else
  1457.         {
  1458.         /* Check if changing attachments to new BSD device. */
  1459.         if ( (pBpfDev->pNetDev->bsdFlag == FALSE) ||
  1460.             (pBpfDev->pNetDev->pCookie != pIf))
  1461.             attachFlag = TRUE;
  1462.         }
  1463.     if (attachFlag)
  1464.         {
  1465.         /* 
  1466.          * Detach BPF unit if attached to another network interface.
  1467.          * Only possible for BIOCSETIF (when restartFlag is FALSE). 
  1468.          */
  1469.         if (pBpfDev->pNetDev != NULL)
  1470.             {
  1471.             _bpfDevDetach (pBpfDev);
  1472.             }
  1473.         /* Attach to the new network interface. */
  1474.         lockKey = _bpfLock ();
  1475.         result = _bpfProtoAttach (pBpfDev, devName, unit, pIf);
  1476.         _bpfUnlock (lockKey);
  1477.         if (result != OK)
  1478.             {
  1479.             _bpfDevUnlock (pBpfDev->bpfDevId);
  1480.             return (result);
  1481.             }
  1482.         /* Add the BPF unit to the network device's list. */
  1483.         lstAdd ( & (pBpfDev->pNetDev->bpfUnitList), (NODE *) pBpfDev);
  1484.         }
  1485.     _bpfDevUnlock (pBpfDev->bpfDevId);
  1486.     /*
  1487.      * For BIOCSETIF operation, reset buffers even if re-attaching to
  1488.      * the same network interface.
  1489.      */
  1490.     if (!restartFlag)
  1491.         bpfDevReset (pBpfDev);
  1492.     return (OK);
  1493.     }
  1494. /*******************************************************************************
  1495. *
  1496. * bpfPacketCatch - copy a packet to the BPF device store buffer
  1497. *
  1498. * This routine copies a packet to the BPF device store buffer. If required, it
  1499. * will also wakeup any pended read tasks.
  1500. *
  1501. * RETURNS:
  1502. * Not Applicable
  1503. *
  1504. * CAVEATS:
  1505. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1506. *
  1507. * NOMANUAL
  1508. */
  1509. LOCAL void bpfPacketCatch
  1510.     (
  1511.     FAST BPF_DEV_CTRL * pBpfDev,    /* BPF device */
  1512.     FAST M_BLK_ID     pMBlk,        /* packet to copy to BPF device */
  1513.     FAST int          snapLen,      /* bytes of packet to copy */
  1514.     FAST int          bpfHdrLen,    /* len of bpf hdr + padding */
  1515.     struct timeval    * pTimeVal,   /* timestamp when packet was received */   
  1516.     FAST int          linkHdrLen    /* size of packet's link level header */
  1517.     )
  1518.     {
  1519.     FAST struct bpf_hdr * pBpfHdr;  /* BPF packet header */
  1520.     FAST int totLen;                /* total len of header + packet */
  1521.     FAST int curLen = 0;            /* current len of buffer */
  1522.     /* snapLen of -1 means copy entire packet */
  1523.     if (snapLen == -1) 
  1524. snapLen = pMBlk->mBlkPktHdr.len;
  1525.     /*
  1526.      * Figure out how many bytes to move.  If the packet is
  1527.      * greater or equal to the snapshot length, transfer that
  1528.      * much.  Otherwise, transfer the whole packet (unless
  1529.      * we hit the buffer size limit).
  1530.      */
  1531.     totLen = bpfHdrLen + min (snapLen, pMBlk->mBlkPktHdr.len);
  1532.     if (totLen > pBpfDev->bufSize)
  1533. {
  1534. totLen = pBpfDev->bufSize;
  1535. }
  1536.     /* Round up the end of the previous packet to the next longword. */
  1537.     
  1538.     curLen = BPF_WORDALIGN (pBpfDev->recvStoreLen);
  1539.     if (curLen + totLen > pBpfDev->bufSize)
  1540. {
  1541. /*
  1542.  * This packet will overflow the storage buffer.
  1543.  * Rotate the buffers if we can, then wakeup any
  1544.  * pending reads.
  1545.  */
  1546. if (pBpfDev->freeBuf == NULL)
  1547.     {
  1548.     /*
  1549.      * We haven't completed the previous read yet, 
  1550.      * so drop the packet. 
  1551.      */
  1552.     
  1553.     ++pBpfDev->pktDropCount;
  1554.     return;
  1555.     }
  1556. ROTATE_BUFFERS (pBpfDev);
  1557. bpfWakeup (pBpfDev);
  1558. curLen = 0;
  1559. }
  1560.     else if (pBpfDev->immediateMode)
  1561. {
  1562. /*
  1563.  * Immediate mode is set.  A packet arrived so any
  1564.  * pending reads should be triggered.
  1565.  */
  1566. bpfWakeup (pBpfDev);
  1567. }
  1568.     
  1569.     /* Fill bpf header */
  1570.     pBpfHdr = (struct bpf_hdr *) (pBpfDev->recvStoreBuf + curLen);
  1571.     pBpfHdr->bh_tstamp = * pTimeVal;
  1572.     pBpfHdr->bh_caplen = totLen - bpfHdrLen;
  1573.     pBpfHdr->bh_datalen = pMBlk->mBlkPktHdr.len;
  1574.     pBpfHdr->bh_hdrlen = bpfHdrLen;
  1575.     pBpfHdr->bh_linklen = linkHdrLen;
  1576.     /* Copy the packet data into the store buffer and update its length. */
  1577.     
  1578.     netMblkOffsetToBufCopy (pMBlk, 0, (char *) pBpfHdr + bpfHdrLen, 
  1579.     totLen - bpfHdrLen, NULL);
  1580.     pBpfDev->recvStoreLen = curLen + totLen;
  1581.     return;
  1582.     }
  1583. /*******************************************************************************
  1584. *
  1585. * bpfBufsAlloc - allocate space for BPF device buffers
  1586. *
  1587. * This routine allocates space for BPF device buffers.  Two buffers of size 
  1588. * <pBpfDev>->bufSize will be allocated from system memory. 
  1589. * RETURNS:
  1590. * OK or ERROR
  1591. *
  1592. * ERRNO:
  1593. * None
  1594. *
  1595. * CAVEATS:
  1596. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1597. *
  1598. * INTERNAL
  1599. * This routine only executes within the ioctl mechanism, which sets
  1600. * the error number to ENOMEM if it fails.
  1601. *
  1602. * NOMANUAL
  1603. */
  1604. LOCAL STATUS bpfBufsAlloc 
  1605.     (
  1606.     BPF_DEV_CTRL * pBpfDev   /* BPF device */
  1607.     )
  1608.     {
  1609.     pBpfDev->freeBuf = malloc (pBpfDev->bufSize);
  1610.     if (pBpfDev->freeBuf == NULL)
  1611.         return (ERROR);
  1612.     pBpfDev->recvStoreBuf = malloc (pBpfDev->bufSize);
  1613.     if (pBpfDev->recvStoreBuf == NULL)
  1614.         {
  1615.         free (pBpfDev->freeBuf);
  1616.         return (ERROR);
  1617.         }
  1618.     pBpfDev->recvStoreLen = 0;
  1619.     pBpfDev->readHoldLen = 0;
  1620.     return (OK);
  1621.     }
  1622. /*******************************************************************************
  1623. *
  1624. * bpfDevFree - free buffers in use by a BPF device
  1625. *
  1626. * This routine frees the buffers in use by a BPF device.  It then marks the
  1627. * BPF device as being no longer in use.
  1628. *
  1629. * RETURNS:
  1630. * Not Applicable
  1631. *
  1632. * CAVEATS:
  1633. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1634. *
  1635. * NOMANUAL
  1636. */
  1637. LOCAL void bpfDevFree
  1638.     (
  1639.     FAST BPF_DEV_CTRL * pBpfDev
  1640.     )
  1641.     {
  1642.     if (pBpfDev->recvStoreBuf != NULL)
  1643.         {
  1644.         free (pBpfDev->recvStoreBuf);
  1645.         }
  1646.     if (pBpfDev->readHoldBuf != NULL)
  1647.         {
  1648.         free (pBpfDev->readHoldBuf);
  1649.         }
  1650.     if (pBpfDev->freeBuf != NULL)
  1651.         {
  1652.         free (pBpfDev->freeBuf);
  1653.         }
  1654.     if (pBpfDev->pBpfInsnFilter != NULL)
  1655.         {
  1656.         free (pBpfDev->pBpfInsnFilter);
  1657.         }
  1658.     semDelete (pBpfDev->readWkupSem);
  1659.     /* Protect status change against conflicts with bpfOpen routine. */
  1660.     _bpfDevLock (pBpfDev->bpfDevId);
  1661.     pBpfDev->inUse = FALSE;
  1662.     _bpfDevUnlock (pBpfDev->bpfDevId);
  1663.     return;
  1664.     }
  1665. /*******************************************************************************
  1666. *
  1667. * bpfWakeup - wakes up all tasks pended on a BPF device
  1668. *
  1669. * This routine wakes up all tasks waiting for a BPF device to receive
  1670. * data. Tasks pended within an active read are triggered by the internal
  1671. * semaphore. Any tasks waiting with the select operation are started
  1672. * with the appropriate method.
  1673. *
  1674. * RETURNS:
  1675. * Not Applicable
  1676. *
  1677. * CAVEATS:
  1678. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1679. *
  1680. * NOMANUAL
  1681. */
  1682. LOCAL void bpfWakeup 
  1683.     (
  1684.     BPF_DEV_CTRL * pBpfDev   /* BPF device control structure */
  1685.     )
  1686.     {
  1687.     /* Wake all tasks pending in a read operation. */
  1688.     semFlush (pBpfDev->readWkupSem);
  1689.     /* Wake any tasks pending within a select operation. */
  1690.     if (pBpfDev->selectFlag)
  1691.         selWakeupAll (& (pBpfDev->selWkupList), SELREAD);
  1692.     return;
  1693.     }
  1694. /*******************************************************************************
  1695. *
  1696. * bpfSleep - block on a BPF device waiting for packets to arrive
  1697. *
  1698. * This routine will block on a BPF device to wait for packets to arrive.  When
  1699. * a packet arrives the pended task will be signalled.  If <numTicks> is 
  1700. * WAIT_FOREVER the task will block until packet arrival.  Otherwise the task
  1701. * will unblock when <numTicks> expires.
  1702. *
  1703. * RETURNS:
  1704. * OK
  1705. * EWOULDBLOCK - if <numTicks> expires before packets arrive
  1706. * EPIPE       - if the attached network interface is shut down or the
  1707. *               BPF unit is closed.
  1708. *
  1709. * CAVEATS:
  1710. * Must be called by a task which holds the unit-specific _bpfUnitLock.
  1711. *
  1712. * NOMANUAL
  1713. */
  1714. LOCAL int bpfSleep
  1715.     (
  1716.     BPF_DEV_CTRL * pBpfDev,
  1717.     int numTicks
  1718.     )
  1719.     {
  1720.     int error = OK;
  1721.     if (semTake (pBpfDev->readWkupSem, numTicks) != OK)
  1722.         {
  1723.         if (errnoOfTaskGet (taskIdSelf ()) == S_objLib_OBJ_TIMEOUT)
  1724.             error = EWOULDBLOCK;
  1725.         else
  1726.             error = EPIPE;
  1727.         }
  1728.     return (error);
  1729.     }
  1730. /*******************************************************************************
  1731. *
  1732. * bpfTimeStamp - returns a timestamp value
  1733. *
  1734. * This routine returns a timestamp value in <pTimeval>.
  1735. *
  1736. * RETURNS:
  1737. * Not Applicable
  1738. *
  1739. * NOMANUAL
  1740. */
  1741. LOCAL void bpfTimeStamp 
  1742.     (
  1743.     struct timeval * pTimeval   /* holds returned timestamp value */
  1744.     )
  1745.     {
  1746.     static int timeStamp = 0;
  1747.     pTimeval->tv_sec = ++timeStamp;
  1748.     pTimeval->tv_usec = 0;
  1749.     return;
  1750.     }