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

VxWorks

开发平台:

C/C++

  1. /* bpfProto.c - Berkeley Packet Filter (BPF) protocol interface */
  2. /* Copyright 1999 - 2001 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. 01e,13nov01,wap  added support for NPT Drivers and allow for qtag support.
  50. 01d,26jan01,ijm  corrected leak in bpfBsdProtoInput
  51. 01c,17nov00,spm  added support for BSD Ethernet devices
  52. 01b,26oct00,spm  fixed merge from tor3_x branch and updated mod history
  53. 01a,23oct00,niq  created from version 01c of tor3_x branch
  54. */
  55. #define INCLUDE_IP     /* hack to have ipProto filter out promisc pkts */
  56. /* includes */
  57. #include "vxWorks.h"
  58. #include "stdio.h"
  59. #include "stdlib.h"
  60. #include "lstLib.h"
  61. #include "logLib.h"
  62. #include "netLib.h"
  63. #include "muxLib.h"
  64. #include "muxTkLib.h"
  65. #include "netBufLib.h"
  66. #include "end.h"
  67. #include "etherLib.h"
  68. #include "private/muxLibP.h"    /* PCOOKIE_TO_ENDOBJ conversion macro */
  69. #include "private/bpfLibP.h"
  70. #include "net/bpf.h"
  71. #ifdef INCLUDE_IP
  72. #include "ifLib.h"
  73. #endif
  74. /* defines */
  75. #define BPF_PROTO_NAME "Berkeley Packet Filter"
  76. #define DEBUG
  77. #ifdef DEBUG
  78. #undef LOCAL
  79. #define LOCAL
  80. #endif  /* DEBUG */
  81. /* locals */
  82. LOCAL BOOL bpfProtoInitDone = FALSE;   /* TRUE if BPF MUX proto */
  83.                                        /* has been initialized */
  84. LOCAL LIST lstProtoInUse;    /* attached network interfaces */
  85. LOCAL int bpfDltTbl [] =         /* Translation tbl from m2 ifType to DLT */
  86.     {
  87. DLT_NULL,
  88. DLT_NULL,      /* M2_ifType_other */
  89. DLT_NULL,      /* M2_ifType_regular1822 */
  90. DLT_NULL,      /* M2_ifType_hdh1822 */
  91. DLT_AX25,      /* M2_ifType_ddn_x25 */
  92. DLT_AX25,      /* M2_ifType_rfc877_x25 */
  93. DLT_EN10MB,    /* M2_ifType_ethernet_csmacd */
  94. DLT_IEEE802,   /* M2_ifType_iso88023_csmacd */
  95. DLT_IEEE802,   /* M2_ifType_iso88024_tokenBus */
  96. DLT_IEEE802,   /* M2_ifType_iso88025_tokenRing */
  97. DLT_IEEE802,   /* M2_ifType_iso88026_man */
  98. DLT_NULL,      /* M2_ifType_starLan */
  99. DLT_PRONET,    /* M2_ifType_proteon_10Mbit */
  100. DLT_PRONET,    /* M2_ifType_proteon_80Mbit */
  101. DLT_NULL,      /* M2_ifType_hyperchannel */
  102. DLT_FDDI,      /* M2_ifType_fddi */
  103. DLT_NULL,      /* M2_ifType_lapb */
  104. DLT_NULL,      /* M2_ifType_sdlc */
  105. DLT_NULL,      /* M2_ifType_ds1 */
  106. DLT_NULL,      /* M2_ifType_e1 */
  107. DLT_NULL,      /* M2_ifType_basicISDN */
  108. DLT_NULL,      /* M2_ifType_primaryISDN */
  109. DLT_NULL,      /* M2_ifType_propPointToPointSerial */
  110. DLT_PPP,       /* M2_ifType_ppp */
  111. DLT_NULL,      /* M2_ifType_softwareLoopback */
  112. DLT_NULL,      /* M2_ifType_eon */
  113. DLT_EN3MB,     /* M2_ifType_ethernet_3Mbit */
  114. DLT_NULL,      /* M2_ifType_nsip */
  115. DLT_SLIP,      /* M2_ifType_slip */
  116. DLT_NULL,      /* M2_ifType_ultra */
  117. DLT_NULL,      /* M2_ifType_ds3 */
  118. DLT_NULL,      /* M2_ifType_sip */
  119. DLT_NULL,      /* M2_ifType_frame_relay */
  120.     };
  121. LOCAL int bpfDltTblSize = NELEMENTS (bpfDltTbl);  /* size of BPF DLT   */
  122.                                                   /* translation table */
  123. LOCAL int bpfBsdDevCount = 0;  /* BPF devices attached to BSD devices. */
  124. /* forward declarations */
  125. LOCAL BOOL bpfProtoInput (void * pCookie, long type, M_BLK_ID pMBlk,
  126.   LL_HDR_INFO * pLlHdrInfo, 
  127.   void * pProtoCtrl);
  128. LOCAL BOOL bpfBsdProtoInput (struct ifnet * pIf, char * pBuffer, int length);
  129. LOCAL STATUS bpfProtoShutdown (void * pCookie, void * pProtoCtrl);
  130. LOCAL STATUS bpfTkProtoShutdown (void * pProtoCtrl);
  131. LOCAL BOOL bpfTkProtoInput (void * pProtoCtrl, long type, M_BLK_ID pMBlk,
  132.                             void * pSpare);
  133.     /*
  134.      * Called with global BPF lock to prevent conflicts with attach routine
  135.      * and promiscuous setting. This routine removes the last attachment
  136.      * of a BPF device from a network interface and also detaches the
  137.      * corresponding BPF MUX protocols.
  138.      */
  139. STATUS _bpfProtoDetach
  140.     (
  141.     BPF_DEV_CTRL * pBpfDev  /* BPF device control structure */
  142.     )
  143.     {
  144.     BPF_PROTO_CTRL * pNew;      /* BPF units from other devices, if any. */
  145.     BOOL bsdFlag;  /* Attached to BSD or END device? */
  146.     bsdFlag = pBpfDev->pNetDev->bsdFlag;
  147.     /*
  148.      * Find a BPF device using the same
  149.      * network interface as this unit.
  150.      */
  151.     for (pNew = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse);
  152.          pNew != NULL;
  153.          pNew = (BPF_PROTO_CTRL *)lstNext ((NODE *)pNew))
  154.         {
  155.         if (bsdFlag)
  156.             {
  157.             if (pNew->pCookie == pBpfDev->pNetDev->pCookie)
  158.                 break;
  159.             }
  160.         else if (PCOOKIE_TO_ENDOBJ(pNew->pCookie) ==
  161.                     PCOOKIE_TO_ENDOBJ(pBpfDev->pNetDev->pCookie))
  162.             break;
  163.         }
  164.     if (pNew == NULL)    /* No such device attached? (Can't really occur). */
  165.         return (ERROR);
  166.     if (pNew != pBpfDev->pNetDev)
  167.         {
  168.         /*
  169.          * The given BPF unit is part of a BPF device which shares the
  170.          * same network interface as an earlier BPF device. Just remove
  171.          * it from the private list.
  172.          */
  173.         lstDelete (& (pNew->bpfDevList), (NODE *) (pBpfDev->pNetDev));
  174.         }
  175.     else
  176.         {
  177.         /*
  178.          * The given BPF unit is part of the first BPF device which
  179.          * used the network interface. Update the global list if other
  180.          * BPF devices are using the same network interface.
  181.          */
  182.         if (lstCount (& (pNew->bpfDevList)) != 0)
  183.             {
  184.             /* Move the first shared device element to the global list. */
  185.             pNew = (BPF_PROTO_CTRL *)lstGet (& (pBpfDev->pNetDev->bpfDevList));
  186.             if (pNew != NULL)
  187.                 {
  188.                 lstInsert (&lstProtoInUse, (NODE *) (pBpfDev->pNetDev),
  189.                            (NODE *)pNew);
  190.                 /* Move other attached devices to the (new) private list. */
  191.                 lstConcat (& (pNew->bpfDevList),
  192.                            & (pBpfDev->pNetDev->bpfDevList));
  193.                 }
  194.             }
  195.         /* Remove the (old) root of the private list from the global list. */
  196.         lstDelete (&lstProtoInUse, (NODE *) (pBpfDev->pNetDev));
  197.         }
  198.     /*
  199.      * No BPF units from the old BPF device are using the
  200.      * network interface. Remove any attached MUX protocols.
  201.      * Alternatively, remove the Ethernet input hook if no
  202.      * other BPF devices are using any BSD network interface.
  203.      */
  204.     if (pBpfDev->pNetDev->bsdFlag == TRUE)
  205.         {
  206.         bpfBsdDevCount--;
  207.         if (bpfBsdDevCount == 0)
  208.             etherInputHookDelete (bpfBsdProtoInput, NULL, 0);
  209.         }
  210.     else if (pBpfDev->pNetDev->pCookie != NULL)
  211.         {
  212.         int deviceType = muxTkDrvCheck (pBpfDev->pNetDev->devName);
  213.         if (deviceType != ERROR)
  214.             {
  215.             if ( deviceType == 0 )
  216.                 muxUnbind (pBpfDev->pNetDev->pCookie, MUX_PROTO_SNARF,
  217.                        (FUNCPTR) bpfProtoInput);
  218.             else
  219.                 muxUnbind (pBpfDev->pNetDev->pCookie, MUX_PROTO_SNARF,
  220.                        (FUNCPTR) bpfTkProtoInput);
  221.             }
  222.         }
  223.     return (OK);
  224.     }
  225. LOCAL STATUS bpfProtoShutdown 
  226.     (
  227.     void * pCookie,
  228.     void * pProtoCtrl
  229.     )
  230.     {
  231.     BPF_PROTO_CTRL * pBpfProto;
  232.     BPF_DEV_CTRL * pBpfDev;
  233.     pBpfProto = (BPF_PROTO_CTRL *) pProtoCtrl;
  234.     for (pBpfDev = (BPF_DEV_CTRL *) lstFirst (& (pBpfProto->bpfUnitList));
  235.          pBpfDev != NULL;
  236.          pBpfDev = (BPF_DEV_CTRL *) lstNext ((NODE *) pBpfDev))
  237.         {
  238.         _bpfDevDetach (pBpfDev);
  239.         }
  240.     
  241.     return (OK);
  242.     }
  243.     /*
  244.      * Check incoming frame against every BPF unit attached to a network
  245.      * device using the MUX/END interface. The BPF device containing the
  246.      * attachment data must still exist or the MUX would not call this
  247.      * routine. Always return FALSE to allow normal stack processing after
  248.      * applying any filters.
  249.      */
  250. LOCAL BOOL bpfProtoInput 
  251.     (
  252.     void * pCookie, 
  253.     long type,
  254.     M_BLK_ID pMBlk,
  255.     LL_HDR_INFO * pLlHdrInfo, 
  256.     void * pProtoCtrl
  257.     )
  258.     {
  259.     BPF_PROTO_CTRL * pNetDev;
  260.     /* Access a BPF unit's attachment to the network interface. */
  261.     pNetDev = (BPF_PROTO_CTRL *)pProtoCtrl;
  262.     if (pNetDev->pCookie != pCookie)
  263.         {
  264.         /* Mismatched binding? Should never occur. */
  265.         return (FALSE);
  266.         }
  267.     /* Apply the current filters and save matching frames. */
  268.     _bpfPacketTap (& (pNetDev->bpfUnitList), type, pMBlk,
  269.                     pLlHdrInfo->dataOffset);
  270.     return (FALSE);
  271.     }
  272.     /*
  273.      * Check incoming frame against any BPF unit attached to the
  274.      * network device using the BSD interface. Always return FALSE
  275.      * to allow normal stack processing after applying any filters.
  276.      */
  277. LOCAL BOOL bpfBsdProtoInput 
  278.     (
  279.     struct ifnet * pIf,  /* interface which received frame */
  280.     char * pBuffer,  /* pointer to received frame */
  281.     int length  /* length of received frame */
  282.     )
  283.     {
  284.     BPF_PROTO_CTRL * pFirst;
  285.     BPF_PROTO_CTRL * pNext;
  286.     M_BLK_ID pMbuf;
  287.     /* Find any BPF units attached to the network interface. */
  288.     for (pFirst = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse);
  289.          pFirst != NULL;
  290.          pFirst = (BPF_PROTO_CTRL *)lstNext ((NODE *)pFirst))
  291.         {
  292.         /* Ignore attachments to END network interfaces. */
  293.         if (pFirst->bsdFlag == FALSE)
  294.             continue;
  295.         /* Ignore attachments to different BSD network interfaces. */
  296.         if (pFirst->pCookie == pIf)
  297.             break;
  298.         }
  299.      /*
  300.       * Exit if no BPF device is using this BSD network interface.
  301.       * (This situation can occur frequently since all devices call
  302.       * this routine with incoming data as long as any input hook is
  303.       * installed).
  304.       */
  305.     if (pFirst == NULL)
  306.         return (FALSE);
  307.     /*
  308.      * Build an mBlk chain containing the data.
  309.      * (This step is wasteful since the driver does the same thing,
  310.      * but the Ethernet hook interface doesn't allow access to that
  311.      * mBlk and the BPF implementation requires one).
  312.      */
  313.     pMbuf = bcopy_to_mbufs (pBuffer, length, 0, pIf, NONE);
  314.     if (pMbuf == NULL)
  315.         return (FALSE);
  316.     /* Apply the current filters and save matching frames. */
  317.     _bpfPacketTap (& (pFirst->bpfUnitList), ETHERTYPE_IP, pMbuf,
  318.                     SIZEOF_ETHERHEADER);
  319.     for (pNext = (BPF_PROTO_CTRL *)lstFirst (& (pFirst->bpfDevList));
  320.          pNext != NULL;
  321.          pNext = (BPF_PROTO_CTRL *)lstNext ((NODE *)pNext))
  322.         {
  323.         _bpfPacketTap (& (pNext->bpfUnitList), ETHERTYPE_IP, pMbuf,
  324.                         SIZEOF_ETHERHEADER);
  325.         }
  326.     /* Free the buffer */
  327.     netMblkClChainFree(pMbuf);
  328.     return (FALSE);
  329.     }
  330. /*
  331.  * Make pBpfDev listen on named interface. 
  332.  * Must be called by a routine holding the global BPF lock.
  333.  */
  334. STATUS _bpfProtoAttach
  335.     (
  336.     BPF_DEV_CTRL * pBpfDev,
  337.     char *  pDevName,  /* Name of network interface device. */
  338.     int  devUnit,  /* Unit number of network interface. */
  339.     struct ifnet * pIf  /* Interface handle for BSD device. */
  340.     )
  341.     {
  342.     M2_INTERFACETBL m2Tbl;
  343.    
  344.     BPF_DEV_CTRL *   pBpfUnit;
  345.     BPF_PROTO_CTRL * pNetIfCtrl;
  346.     BPF_PROTO_CTRL * pFirst;
  347.     BPF_PROTO_CTRL * pLast = NULL;
  348.     NODE tmpNode;
  349.     /* Check if a BPF device is already attached to the network interface. */
  350.     for (pNetIfCtrl = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse);
  351.          pNetIfCtrl != NULL;
  352.          pNetIfCtrl = (BPF_PROTO_CTRL *) lstNext ((NODE *) pNetIfCtrl))
  353.         {
  354.         if (devUnit == pNetIfCtrl->devUnit &&
  355.             strncmp (pDevName, pNetIfCtrl->devName, END_NAME_MAX) == 0)
  356.             break;
  357.         }
  358.     if (pNetIfCtrl == NULL)
  359.         {
  360.         /* Add this BPF unit's attachment data to the global list. */
  361.         pFirst = pBpfDev->pNetIfCtrl;
  362.         if (pFirst == NULL)
  363.             return (ENOBUFS);
  364.         lstAdd (&lstProtoInUse, (NODE *)pFirst);
  365.         pLast = pFirst;
  366.         }
  367.     else
  368.         {
  369.         /*
  370.          * At least one BPF device is already attached to the interface.
  371.          * Find the attached parent device for this BPF unit, if any.
  372.          */
  373.         pFirst = pNetIfCtrl;
  374.         pBpfUnit = (BPF_DEV_CTRL *)lstFirst ( &(pNetIfCtrl->bpfUnitList));
  375.         if (pBpfUnit == NULL)
  376.             return (ENOBUFS);
  377.         if (pBpfDev->bpfDevId != pBpfUnit->bpfDevId)
  378.             {
  379.             /*
  380.              * This BPF unit is not from the first attached device.
  381.              * Search for a matching shared device.
  382.              */
  383.             pNetIfCtrl = (BPF_PROTO_CTRL *)lstFirst (& (pFirst->bpfDevList));
  384.             while (pNetIfCtrl != NULL)
  385.                 {
  386.             pBpfUnit = (BPF_DEV_CTRL *)lstFirst ( &(pNetIfCtrl->bpfUnitList));
  387.             if (pBpfUnit == NULL)
  388.                 return (ENOBUFS);
  389.                 if (pBpfDev->bpfDevId == pBpfUnit->bpfDevId)
  390.                     break;
  391.                 pLast = pNetIfCtrl;
  392.                 pNetIfCtrl = (BPF_PROTO_CTRL *)lstNext ((NODE *) pNetIfCtrl);
  393.                 }
  394.             }
  395.         if (pNetIfCtrl != NULL)
  396.             {
  397.             /*
  398.              * Parent device found. Save the network interface attachment in
  399.              * the BPF unit entry, which will be appended to the existing list.
  400.              */
  401.             pBpfDev->pNetDev = pNetIfCtrl;
  402.             return (OK);
  403.             }
  404.         /*
  405.          * No other BPF unit from this device is attached to the
  406.          * given network interface. Add the unit's entry to the
  407.          * (private) list of BPF devices which share a network interface.
  408.          */
  409.         if (pBpfDev->pNetIfCtrl == NULL)
  410.             return (ENOBUFS);
  411.         /* Append the new attachment data to the private list. */
  412.         lstInsert (& (pFirst->bpfDevList), (NODE *)pLast,
  413.                    (NODE *)pBpfDev->pNetIfCtrl);
  414.         pLast = pBpfDev->pNetIfCtrl;
  415.         }
  416.     /*
  417.      * Attach the BPF MUX protocols and initialize the attachment data
  418.      * for a network interface attached to the global or a private list.
  419.      * Alternatively, use the existing Ethernet input hook attachment
  420.      * or add the input hook if no other BPF devices are using any BSD
  421.      * network interface.
  422.      */
  423.     /* Delete the data in this node, but don't clobber list pointers. */
  424.     tmpNode.next = pLast->bpfProtoLstNode.next;
  425.     tmpNode.previous = pLast->bpfProtoLstNode.previous;
  426.     bzero ( (char *)pLast, sizeof (BPF_PROTO_CTRL));
  427.     pLast->bpfProtoLstNode.next = tmpNode.next;
  428.     pLast->bpfProtoLstNode.previous = tmpNode.previous;
  429.     if (pIf)
  430.         {
  431.         /* Attaching a BPF device to a BSD network interface. */
  432.         bpfBsdDevCount++;
  433.         pLast->bsdFlag = TRUE;
  434.         pLast->pCookie = pIf;
  435.         }
  436.     else
  437.         {
  438.         /* Attach to MUX to receive incoming packets */
  439.         int deviceType = muxTkDrvCheck (pDevName);
  440.         if (deviceType == ERROR)
  441.             goto bpfProtoAttachErr;
  442. /*logMsg("BPF PROTO ATTACH: %dn", deviceType, 0, 0, 0, 0, 0);*/
  443.         pLast->bsdFlag = FALSE;
  444.         if (deviceType == 0)
  445.             pLast->pCookie = muxBind (pDevName, devUnit, bpfProtoInput, 
  446.                                       bpfProtoShutdown, NULL, NULL, 
  447.                                       MUX_PROTO_SNARF, BPF_PROTO_NAME, 
  448.                                       pLast);
  449.         else
  450.             pLast->pCookie = muxTkBind (pDevName, devUnit, bpfTkProtoInput, 
  451.                                         bpfTkProtoShutdown, NULL, NULL, 
  452.                                         MUX_PROTO_SNARF, BPF_PROTO_NAME, pLast,
  453.                                         NULL, NULL);
  454.         if (pLast->pCookie == NULL)
  455.             {
  456.             goto bpfProtoAttachErr;
  457.             }
  458.         }
  459.     /* Initialize list of attached BPF units and store interface name. */
  460.     lstInit (& (pLast->bpfUnitList));
  461.     strncpy (pLast->devName, pDevName, END_NAME_MAX);
  462.     pLast->devUnit = devUnit;
  463.     /* Reset the private attachment list for possible later use. */
  464.     lstInit (& (pLast->bpfDevList));
  465.     /* Copy remaining interface settings if possible. */
  466.     if (pFirst != pLast)
  467.         {
  468.         /*
  469.          * More than one BPF device is sharing the same network interface.
  470.          * Copy the common values from the first attachment.
  471.          */
  472.         pLast->mtuSize = pFirst->mtuSize;
  473.         pLast->dataLinkType = pFirst->dataLinkType;
  474.         }
  475.     else
  476.         {
  477.         /*
  478.          * The BPF unit is the first attachment to the network interface.
  479.          * Retrieve and save the interface information.
  480.          * Add the Ethernet input hook if no other BSD device is in use.
  481.          */
  482.         if (pLast->bsdFlag)
  483.             {
  484.             if (bpfBsdDevCount == 1)
  485.                 {
  486.                 if (etherInputHookAdd (bpfBsdProtoInput, NULL, 0) == ERROR)
  487.                     goto bpfProtoAttachErr;
  488.                 }
  489.             pLast->mtuSize = ETHERMTU;
  490.             pLast->dataLinkType = DLT_EN10MB;
  491.             }
  492.         else
  493.             {
  494.             if (muxIoctl (pLast->pCookie, EIOCGMIB2, (char *)&m2Tbl) != OK)
  495.                 {
  496.                 goto bpfProtoAttachErr;
  497.                 }
  498.             pLast->mtuSize = m2Tbl.ifMtu;
  499.             if (m2Tbl.ifType < 0 || m2Tbl.ifType >= bpfDltTblSize)
  500.                 {
  501.                 pLast->dataLinkType = DLT_NULL;
  502.                 }
  503.             else
  504.                 {
  505.                 pLast->dataLinkType = bpfDltTbl [m2Tbl.ifType];
  506.                 }
  507.             }
  508.         }
  509.     /* Save the new network interface attachment in the BPF unit entry. */
  510.     pBpfDev->pNetDev = pLast;
  511.     return (OK);
  512.     /*
  513.      * Remove any linked BPF MUX protocols if an error occurred
  514.      * while attaching to the network interface.
  515.      */
  516. bpfProtoAttachErr:
  517.     if ( (pLast->bsdFlag == FALSE) && pLast->pCookie != NULL)
  518.         {
  519.         int deviceType = muxTkDrvCheck (pLast->devName);
  520.         if (deviceType != ERROR)
  521.             {
  522.             if (deviceType == 0)
  523.                 muxUnbind (pLast->pCookie, MUX_PROTO_SNARF,
  524.                        (FUNCPTR) bpfProtoInput);
  525.             else
  526.                 muxUnbind (pLast->pCookie, MUX_PROTO_SNARF,
  527.                        (FUNCPTR) bpfTkProtoInput);
  528.             }
  529.         }
  530.     return (EINVAL);
  531.     }
  532. /* INTERNAL: Each device contains a table for binding BPF file
  533.  * descriptors to network interfaces. Each BPF unit adds an element
  534.  * to that table so that the associated file descriptor can use any
  535.  * network interface. That element is unused if the file descriptor
  536.  * uses the same network interface as another BPF unit of the same
  537.  * device, but this approach allows users to create BPF devices without
  538.  * limiting the number of unique network interfaces allowed.
  539.  * This routine allows every BPF device access to a list of the network
  540.  * interfaces which are currently in use so that the MUX bindings are
  541.  * appropriately established and maintained.
  542.  */
  543. void _bpfProtoInit (void)
  544.     {
  545.     if (!bpfProtoInitDone)
  546.         {
  547.         lstInit (&lstProtoInUse);
  548.         bpfProtoInitDone = TRUE;
  549.         }
  550.     return;
  551.     }
  552. STATUS _bpfProtoPromisc
  553.     (
  554.     BPF_PROTO_CTRL * pBpfProto,
  555.     BOOL           on
  556.     )
  557.     {
  558.     ULONG endFlags;
  559.     int error = OK;
  560.     BPF_PROTO_CTRL * pFirst;    /* First attachment to network interface. */
  561. #ifdef INCLUDE_IP
  562.     char devName [IFNAMSIZ];
  563. #endif  /* INCLUDE_IP */
  564.     if (pBpfProto->bsdFlag)
  565.         return (EINVAL);
  566.     if (on)
  567.         {
  568.         error = muxIoctl (pBpfProto->pCookie, EIOCGFLAGS, (char *) &endFlags);
  569.         if (error != OK)
  570.             {
  571.             return (EINVAL);
  572.             }
  573.         /* Enable promiscuous mode if not already enabled */ 
  574.         if ( (endFlags & IFF_PROMISC) == 0)
  575.             {
  576.             endFlags = IFF_PROMISC;
  577.             error = muxIoctl (pBpfProto->pCookie, EIOCSFLAGS, 
  578.                               (char *) endFlags);
  579.             if (error != OK)
  580.                 {
  581.                 return (EINVAL);
  582.                 }
  583. #ifdef INCLUDE_IP
  584.             sprintf (devName, "%s%d", pBpfProto->devName, 
  585.                      pBpfProto->devUnit); 
  586.             ifFlagChange (devName, IFF_PROMISC, TRUE);
  587. #endif  /* INCLUDE_IP */
  588.             }
  589.  
  590.         pBpfProto->bpfPromiscEnabled = TRUE;
  591.         pBpfProto->numPromisc ++;
  592.         return (OK);
  593.         }
  594.     pBpfProto->numPromisc --;
  595.     /*
  596.      * Disable the network interface's promiscuous mode if no other BPF
  597.      * units from any BPF devices are using it.
  598.      */
  599.     if (pBpfProto->numPromisc == 0)
  600.         {
  601.         /* This BPF device no longer uses promiscuous mode. */
  602.         pBpfProto->bpfPromiscEnabled = FALSE;
  603.         /* Find the start of the attachment list for this network interface. */
  604.         for (pFirst = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse);
  605.              pFirst != NULL;
  606.              pFirst = (BPF_PROTO_CTRL *)lstNext ((NODE *)pFirst))
  607.             {
  608.             if (pFirst->bsdFlag == TRUE)    /* Ignore BSD network devices. */
  609.                 continue;
  610.             if (PCOOKIE_TO_ENDOBJ(pFirst->pCookie) ==
  611.                 PCOOKIE_TO_ENDOBJ(pBpfProto->pCookie))
  612.                 break; 
  613.             }
  614.         if (pFirst == NULL)    /* No device attached? (Can't really occur). */
  615.             return (OK);
  616.         if (pFirst->numPromisc)
  617.             {
  618.             /*
  619.              * The first BPF device attached to the network
  620.              * interface is using the promiscuous mode setting.
  621.              */
  622.             return (OK);
  623.             }
  624.         else
  625.             {
  626.             /*
  627.              * Check the promiscuous mode setting for any
  628.              * BPF devices sharing a network interface.
  629.              */
  630.             pFirst = (BPF_PROTO_CTRL *)lstFirst (& (pFirst->bpfDevList));
  631.             while (pFirst != NULL)
  632.                 {
  633.                 if (pFirst->numPromisc)
  634.                     break;
  635.                 pFirst = (BPF_PROTO_CTRL *)lstNext ( (NODE *)pFirst);
  636.                 }
  637.             /* Leave interface setting unchanged if promiscuous mode found. */
  638.             if (pFirst != NULL)
  639.                 return (OK);
  640.             }
  641.         endFlags = IFF_PROMISC;
  642.         /* Set mask which causes muxIoctl() routine to disable flags. */
  643.         endFlags = - endFlags - 1;
  644.         error = muxIoctl (pBpfProto->pCookie, EIOCSFLAGS, 
  645.                           (char *) endFlags);
  646.         if (error != OK)
  647.             error = EINVAL;
  648. #ifdef INCLUDE_IP
  649.         sprintf (devName, "%s%d", pBpfProto->devName,
  650.                  pBpfProto->devUnit); 
  651.         ifFlagChange (devName, IFF_PROMISC, FALSE);
  652. #endif  /* INCLUDE_IP */
  653.         }
  654.     return (error);
  655.     }
  656. STATUS _bpfProtoSend
  657.     (
  658.     BPF_PROTO_CTRL * pBpfProto,
  659.     char * pBuf,
  660.     int nBytes,
  661.     BOOL nonBlocking
  662.     )
  663.     {
  664.     M_BLK_ID pMBlk;
  665.     END_OBJ * pEnd;
  666.     if (pBpfProto->bsdFlag)
  667.         return (ERROR);
  668.     pEnd = PCOOKIE_TO_ENDOBJ(pBpfProto->pCookie);
  669.     
  670.     pMBlk = netTupleGet (pEnd->pNetPool, nBytes,
  671.                          (nonBlocking ? M_DONTWAIT : M_WAIT), MT_DATA, TRUE);
  672.     if (pMBlk == NULL)
  673. {
  674. netErrnoSet (ENOBUFS);
  675. return (ERROR);
  676. }
  677.     return (muxSend (pBpfProto->pCookie, pMBlk));
  678.     }
  679. /*****************************************************************************
  680. * bpfTkProtoInput - Check incoming frame against every BPF unit
  681. *
  682. * This routine checks incoming frame against every BPF unit attached to a
  683. * NPT device using the muxTk/END interface. The BPF device containing the
  684. * attachment data must still exist or the MUX would not call this
  685. * routine. Always return FALSE to allow normal stack processing after
  686. * applying any filters.
  687. *
  688. * RETURNS: FALSE
  689. */
  690. LOCAL BOOL bpfTkProtoInput 
  691.     (
  692.     void *      pProtoCtrl,
  693.     long        type,
  694.     M_BLK_ID    pMBlk,
  695.     void *      pSpare
  696.     )
  697.     {
  698.     BPF_PROTO_CTRL * pBpfProto;
  699.     ulong_t          dataOffset;
  700.     if (pProtoCtrl == NULL)
  701.         return (FALSE);
  702.     /* Access a BPF unit's attachment to the network interface. */
  703.     pBpfProto = (BPF_PROTO_CTRL *) pProtoCtrl;
  704.     dataOffset = 0;
  705.     if (muxIoctl (pBpfProto->pCookie, EIOCGHDRLEN,
  706.                   (caddr_t)&dataOffset) != OK)
  707.         return (FALSE);
  708.     /* Apply the current filters and save matching frames. */
  709.     _bpfPacketTap (&(pBpfProto->bpfUnitList), type, pMBlk, dataOffset);
  710.     return (FALSE);
  711.     }
  712. /*****************************************************************************
  713. * bpfTkProtoShutdown - shutdown routine
  714. *
  715. * This is the shut down routine passed to muxTkBind call
  716. *
  717. * RETURNS: OK or ERROR
  718. */
  719. LOCAL STATUS bpfTkProtoShutdown 
  720.     (
  721.     void * pProtoCtrl
  722.     )
  723.     {
  724.     if (pProtoCtrl != NULL)
  725.         {
  726.         return (bpfProtoShutdown (NULL, pProtoCtrl));
  727.         }
  728.     return (OK);
  729.     }