📄 bpfproto.c
字号:
/* bpfProto.c - Berkeley Packet Filter (BPF) protocol interface *//* Copyright 1999 - 2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.c 7.5 (Berkeley) 7/15/91 * * static char rcsid[] = * "$Header: bpf.c,v 1.67 96/09/26 22:00:52 leres Exp $"; *//*modification history--------------------01e,13nov01,wap added support for NPT Drivers and allow for qtag support.01d,26jan01,ijm corrected leak in bpfBsdProtoInput01c,17nov00,spm added support for BSD Ethernet devices01b,26oct00,spm fixed merge from tor3_x branch and updated mod history01a,23oct00,niq created from version 01c of tor3_x branch*/#define INCLUDE_IP /* hack to have ipProto filter out promisc pkts *//* includes */#include "vxWorks.h"#include "stdio.h"#include "stdlib.h"#include "lstLib.h"#include "logLib.h"#include "netLib.h"#include "muxLib.h"#include "muxTkLib.h"#include "netBufLib.h"#include "end.h"#include "etherLib.h"#include "private/muxLibP.h" /* PCOOKIE_TO_ENDOBJ conversion macro */#include "private/bpfLibP.h"#include "net/bpf.h"#ifdef INCLUDE_IP#include "ifLib.h"#endif/* defines */#define BPF_PROTO_NAME "Berkeley Packet Filter"#define DEBUG#ifdef DEBUG#undef LOCAL#define LOCAL#endif /* DEBUG *//* locals */LOCAL BOOL bpfProtoInitDone = FALSE; /* TRUE if BPF MUX proto */ /* has been initialized */LOCAL LIST lstProtoInUse; /* attached network interfaces */LOCAL int bpfDltTbl [] = /* Translation tbl from m2 ifType to DLT */ { DLT_NULL, DLT_NULL, /* M2_ifType_other */ DLT_NULL, /* M2_ifType_regular1822 */ DLT_NULL, /* M2_ifType_hdh1822 */ DLT_AX25, /* M2_ifType_ddn_x25 */ DLT_AX25, /* M2_ifType_rfc877_x25 */ DLT_EN10MB, /* M2_ifType_ethernet_csmacd */ DLT_IEEE802, /* M2_ifType_iso88023_csmacd */ DLT_IEEE802, /* M2_ifType_iso88024_tokenBus */ DLT_IEEE802, /* M2_ifType_iso88025_tokenRing */ DLT_IEEE802, /* M2_ifType_iso88026_man */ DLT_NULL, /* M2_ifType_starLan */ DLT_PRONET, /* M2_ifType_proteon_10Mbit */ DLT_PRONET, /* M2_ifType_proteon_80Mbit */ DLT_NULL, /* M2_ifType_hyperchannel */ DLT_FDDI, /* M2_ifType_fddi */ DLT_NULL, /* M2_ifType_lapb */ DLT_NULL, /* M2_ifType_sdlc */ DLT_NULL, /* M2_ifType_ds1 */ DLT_NULL, /* M2_ifType_e1 */ DLT_NULL, /* M2_ifType_basicISDN */ DLT_NULL, /* M2_ifType_primaryISDN */ DLT_NULL, /* M2_ifType_propPointToPointSerial */ DLT_PPP, /* M2_ifType_ppp */ DLT_NULL, /* M2_ifType_softwareLoopback */ DLT_NULL, /* M2_ifType_eon */ DLT_EN3MB, /* M2_ifType_ethernet_3Mbit */ DLT_NULL, /* M2_ifType_nsip */ DLT_SLIP, /* M2_ifType_slip */ DLT_NULL, /* M2_ifType_ultra */ DLT_NULL, /* M2_ifType_ds3 */ DLT_NULL, /* M2_ifType_sip */ DLT_NULL, /* M2_ifType_frame_relay */ };LOCAL int bpfDltTblSize = NELEMENTS (bpfDltTbl); /* size of BPF DLT */ /* translation table */LOCAL int bpfBsdDevCount = 0; /* BPF devices attached to BSD devices. *//* forward declarations */LOCAL BOOL bpfProtoInput (void * pCookie, long type, M_BLK_ID pMBlk, LL_HDR_INFO * pLlHdrInfo, void * pProtoCtrl);LOCAL BOOL bpfBsdProtoInput (struct ifnet * pIf, char * pBuffer, int length);LOCAL STATUS bpfProtoShutdown (void * pCookie, void * pProtoCtrl);LOCAL STATUS bpfTkProtoShutdown (void * pProtoCtrl);LOCAL BOOL bpfTkProtoInput (void * pProtoCtrl, long type, M_BLK_ID pMBlk, void * pSpare); /* * Called with global BPF lock to prevent conflicts with attach routine * and promiscuous setting. This routine removes the last attachment * of a BPF device from a network interface and also detaches the * corresponding BPF MUX protocols. */STATUS _bpfProtoDetach ( BPF_DEV_CTRL * pBpfDev /* BPF device control structure */ ) { BPF_PROTO_CTRL * pNew; /* BPF units from other devices, if any. */ BOOL bsdFlag; /* Attached to BSD or END device? */ bsdFlag = pBpfDev->pNetDev->bsdFlag; /* * Find a BPF device using the same * network interface as this unit. */ for (pNew = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse); pNew != NULL; pNew = (BPF_PROTO_CTRL *)lstNext ((NODE *)pNew)) { if (bsdFlag) { if (pNew->pCookie == pBpfDev->pNetDev->pCookie) break; } else if (PCOOKIE_TO_ENDOBJ(pNew->pCookie) == PCOOKIE_TO_ENDOBJ(pBpfDev->pNetDev->pCookie)) break; } if (pNew == NULL) /* No such device attached? (Can't really occur). */ return (ERROR); if (pNew != pBpfDev->pNetDev) { /* * The given BPF unit is part of a BPF device which shares the * same network interface as an earlier BPF device. Just remove * it from the private list. */ lstDelete (& (pNew->bpfDevList), (NODE *) (pBpfDev->pNetDev)); } else { /* * The given BPF unit is part of the first BPF device which * used the network interface. Update the global list if other * BPF devices are using the same network interface. */ if (lstCount (& (pNew->bpfDevList)) != 0) { /* Move the first shared device element to the global list. */ pNew = (BPF_PROTO_CTRL *)lstGet (& (pBpfDev->pNetDev->bpfDevList)); if (pNew != NULL) { lstInsert (&lstProtoInUse, (NODE *) (pBpfDev->pNetDev), (NODE *)pNew); /* Move other attached devices to the (new) private list. */ lstConcat (& (pNew->bpfDevList), & (pBpfDev->pNetDev->bpfDevList)); } } /* Remove the (old) root of the private list from the global list. */ lstDelete (&lstProtoInUse, (NODE *) (pBpfDev->pNetDev)); } /* * No BPF units from the old BPF device are using the * network interface. Remove any attached MUX protocols. * Alternatively, remove the Ethernet input hook if no * other BPF devices are using any BSD network interface. */ if (pBpfDev->pNetDev->bsdFlag == TRUE) { bpfBsdDevCount--; if (bpfBsdDevCount == 0) etherInputHookDelete (bpfBsdProtoInput, NULL, 0); } else if (pBpfDev->pNetDev->pCookie != NULL) { int deviceType = muxTkDrvCheck (pBpfDev->pNetDev->devName); if (deviceType != ERROR) { if ( deviceType == 0 ) muxUnbind (pBpfDev->pNetDev->pCookie, MUX_PROTO_SNARF, (FUNCPTR) bpfProtoInput); else muxUnbind (pBpfDev->pNetDev->pCookie, MUX_PROTO_SNARF, (FUNCPTR) bpfTkProtoInput); } } return (OK); }LOCAL STATUS bpfProtoShutdown ( void * pCookie, void * pProtoCtrl ) { BPF_PROTO_CTRL * pBpfProto; BPF_DEV_CTRL * pBpfDev; pBpfProto = (BPF_PROTO_CTRL *) pProtoCtrl; for (pBpfDev = (BPF_DEV_CTRL *) lstFirst (& (pBpfProto->bpfUnitList)); pBpfDev != NULL; pBpfDev = (BPF_DEV_CTRL *) lstNext ((NODE *) pBpfDev)) { _bpfDevDetach (pBpfDev); } return (OK); } /* * Check incoming frame against every BPF unit attached to a network * device using the MUX/END interface. The BPF device containing the * attachment data must still exist or the MUX would not call this * routine. Always return FALSE to allow normal stack processing after * applying any filters. */LOCAL BOOL bpfProtoInput ( void * pCookie, long type, M_BLK_ID pMBlk, LL_HDR_INFO * pLlHdrInfo, void * pProtoCtrl ) { BPF_PROTO_CTRL * pNetDev; /* Access a BPF unit's attachment to the network interface. */ pNetDev = (BPF_PROTO_CTRL *)pProtoCtrl; if (pNetDev->pCookie != pCookie) { /* Mismatched binding? Should never occur. */ return (FALSE); } /* Apply the current filters and save matching frames. */ _bpfPacketTap (& (pNetDev->bpfUnitList), type, pMBlk, pLlHdrInfo->dataOffset); return (FALSE); } /* * Check incoming frame against any BPF unit attached to the * network device using the BSD interface. Always return FALSE * to allow normal stack processing after applying any filters. */LOCAL BOOL bpfBsdProtoInput ( struct ifnet * pIf, /* interface which received frame */ char * pBuffer, /* pointer to received frame */ int length /* length of received frame */ ) { BPF_PROTO_CTRL * pFirst; BPF_PROTO_CTRL * pNext; M_BLK_ID pMbuf; /* Find any BPF units attached to the network interface. */ for (pFirst = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse); pFirst != NULL; pFirst = (BPF_PROTO_CTRL *)lstNext ((NODE *)pFirst)) { /* Ignore attachments to END network interfaces. */ if (pFirst->bsdFlag == FALSE) continue; /* Ignore attachments to different BSD network interfaces. */ if (pFirst->pCookie == pIf) break; } /* * Exit if no BPF device is using this BSD network interface. * (This situation can occur frequently since all devices call * this routine with incoming data as long as any input hook is * installed). */ if (pFirst == NULL) return (FALSE); /* * Build an mBlk chain containing the data. * (This step is wasteful since the driver does the same thing, * but the Ethernet hook interface doesn't allow access to that * mBlk and the BPF implementation requires one). */ pMbuf = bcopy_to_mbufs (pBuffer, length, 0, pIf, NONE); if (pMbuf == NULL) return (FALSE); /* Apply the current filters and save matching frames. */ _bpfPacketTap (& (pFirst->bpfUnitList), ETHERTYPE_IP, pMbuf, SIZEOF_ETHERHEADER); for (pNext = (BPF_PROTO_CTRL *)lstFirst (& (pFirst->bpfDevList)); pNext != NULL; pNext = (BPF_PROTO_CTRL *)lstNext ((NODE *)pNext)) { _bpfPacketTap (& (pNext->bpfUnitList), ETHERTYPE_IP, pMbuf, SIZEOF_ETHERHEADER); } /* Free the buffer */ netMblkClChainFree(pMbuf); return (FALSE); }/* * Make pBpfDev listen on named interface. * Must be called by a routine holding the global BPF lock. */STATUS _bpfProtoAttach ( BPF_DEV_CTRL * pBpfDev, char * pDevName, /* Name of network interface device. */ int devUnit, /* Unit number of network interface. */ struct ifnet * pIf /* Interface handle for BSD device. */ ) { M2_INTERFACETBL m2Tbl; BPF_DEV_CTRL * pBpfUnit; BPF_PROTO_CTRL * pNetIfCtrl; BPF_PROTO_CTRL * pFirst; BPF_PROTO_CTRL * pLast = NULL; NODE tmpNode; /* Check if a BPF device is already attached to the network interface. */ for (pNetIfCtrl = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse); pNetIfCtrl != NULL; pNetIfCtrl = (BPF_PROTO_CTRL *) lstNext ((NODE *) pNetIfCtrl)) { if (devUnit == pNetIfCtrl->devUnit && strncmp (pDevName, pNetIfCtrl->devName, END_NAME_MAX) == 0) break; } if (pNetIfCtrl == NULL) { /* Add this BPF unit's attachment data to the global list. */ pFirst = pBpfDev->pNetIfCtrl; if (pFirst == NULL) return (ENOBUFS); lstAdd (&lstProtoInUse, (NODE *)pFirst); pLast = pFirst; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -