📄 bpfproto.c
字号:
{ /* * At least one BPF device is already attached to the interface. * Find the attached parent device for this BPF unit, if any. */ pFirst = pNetIfCtrl; pBpfUnit = (BPF_DEV_CTRL *)lstFirst ( &(pNetIfCtrl->bpfUnitList)); if (pBpfUnit == NULL) return (ENOBUFS); if (pBpfDev->bpfDevId != pBpfUnit->bpfDevId) { /* * This BPF unit is not from the first attached device. * Search for a matching shared device. */ pNetIfCtrl = (BPF_PROTO_CTRL *)lstFirst (& (pFirst->bpfDevList)); while (pNetIfCtrl != NULL) { pBpfUnit = (BPF_DEV_CTRL *)lstFirst ( &(pNetIfCtrl->bpfUnitList)); if (pBpfUnit == NULL) return (ENOBUFS); if (pBpfDev->bpfDevId == pBpfUnit->bpfDevId) break; pLast = pNetIfCtrl; pNetIfCtrl = (BPF_PROTO_CTRL *)lstNext ((NODE *) pNetIfCtrl); } } if (pNetIfCtrl != NULL) { /* * Parent device found. Save the network interface attachment in * the BPF unit entry, which will be appended to the existing list. */ pBpfDev->pNetDev = pNetIfCtrl; return (OK); } /* * No other BPF unit from this device is attached to the * given network interface. Add the unit's entry to the * (private) list of BPF devices which share a network interface. */ if (pBpfDev->pNetIfCtrl == NULL) return (ENOBUFS); /* Append the new attachment data to the private list. */ lstInsert (& (pFirst->bpfDevList), (NODE *)pLast, (NODE *)pBpfDev->pNetIfCtrl); pLast = pBpfDev->pNetIfCtrl; } /* * Attach the BPF MUX protocols and initialize the attachment data * for a network interface attached to the global or a private list. * Alternatively, use the existing Ethernet input hook attachment * or add the input hook if no other BPF devices are using any BSD * network interface. */ /* Delete the data in this node, but don't clobber list pointers. */ tmpNode.next = pLast->bpfProtoLstNode.next; tmpNode.previous = pLast->bpfProtoLstNode.previous; bzero ( (char *)pLast, sizeof (BPF_PROTO_CTRL)); pLast->bpfProtoLstNode.next = tmpNode.next; pLast->bpfProtoLstNode.previous = tmpNode.previous; if (pIf) { /* Attaching a BPF device to a BSD network interface. */ bpfBsdDevCount++; pLast->bsdFlag = TRUE; pLast->pCookie = pIf; } else { /* Attach to MUX to receive incoming packets */ int deviceType = muxTkDrvCheck (pDevName); if (deviceType == ERROR) goto bpfProtoAttachErr;/*logMsg("BPF PROTO ATTACH: %d\n", deviceType, 0, 0, 0, 0, 0);*/ pLast->bsdFlag = FALSE; if (deviceType == 0) pLast->pCookie = muxBind (pDevName, devUnit, bpfProtoInput, bpfProtoShutdown, NULL, NULL, MUX_PROTO_SNARF, BPF_PROTO_NAME, pLast); else pLast->pCookie = muxTkBind (pDevName, devUnit, bpfTkProtoInput, bpfTkProtoShutdown, NULL, NULL, MUX_PROTO_SNARF, BPF_PROTO_NAME, pLast, NULL, NULL); if (pLast->pCookie == NULL) { goto bpfProtoAttachErr; } } /* Initialize list of attached BPF units and store interface name. */ lstInit (& (pLast->bpfUnitList)); strncpy (pLast->devName, pDevName, END_NAME_MAX); pLast->devUnit = devUnit; /* Reset the private attachment list for possible later use. */ lstInit (& (pLast->bpfDevList)); /* Copy remaining interface settings if possible. */ if (pFirst != pLast) { /* * More than one BPF device is sharing the same network interface. * Copy the common values from the first attachment. */ pLast->mtuSize = pFirst->mtuSize; pLast->dataLinkType = pFirst->dataLinkType; } else { /* * The BPF unit is the first attachment to the network interface. * Retrieve and save the interface information. * Add the Ethernet input hook if no other BSD device is in use. */ if (pLast->bsdFlag) { if (bpfBsdDevCount == 1) { if (etherInputHookAdd (bpfBsdProtoInput, NULL, 0) == ERROR) goto bpfProtoAttachErr; } pLast->mtuSize = ETHERMTU; pLast->dataLinkType = DLT_EN10MB; } else { if (muxIoctl (pLast->pCookie, EIOCGMIB2, (char *)&m2Tbl) != OK) { goto bpfProtoAttachErr; } pLast->mtuSize = m2Tbl.ifMtu; if (m2Tbl.ifType < 0 || m2Tbl.ifType >= bpfDltTblSize) { pLast->dataLinkType = DLT_NULL; } else { pLast->dataLinkType = bpfDltTbl [m2Tbl.ifType]; } } } /* Save the new network interface attachment in the BPF unit entry. */ pBpfDev->pNetDev = pLast; return (OK); /* * Remove any linked BPF MUX protocols if an error occurred * while attaching to the network interface. */bpfProtoAttachErr: if ( (pLast->bsdFlag == FALSE) && pLast->pCookie != NULL) { int deviceType = muxTkDrvCheck (pLast->devName); if (deviceType != ERROR) { if (deviceType == 0) muxUnbind (pLast->pCookie, MUX_PROTO_SNARF, (FUNCPTR) bpfProtoInput); else muxUnbind (pLast->pCookie, MUX_PROTO_SNARF, (FUNCPTR) bpfTkProtoInput); } } return (EINVAL); }/* INTERNAL: Each device contains a table for binding BPF file * descriptors to network interfaces. Each BPF unit adds an element * to that table so that the associated file descriptor can use any * network interface. That element is unused if the file descriptor * uses the same network interface as another BPF unit of the same * device, but this approach allows users to create BPF devices without * limiting the number of unique network interfaces allowed. * This routine allows every BPF device access to a list of the network * interfaces which are currently in use so that the MUX bindings are * appropriately established and maintained. */void _bpfProtoInit (void) { if (!bpfProtoInitDone) { lstInit (&lstProtoInUse); bpfProtoInitDone = TRUE; } return; }STATUS _bpfProtoPromisc ( BPF_PROTO_CTRL * pBpfProto, BOOL on ) { ULONG endFlags; int error = OK; BPF_PROTO_CTRL * pFirst; /* First attachment to network interface. */#ifdef INCLUDE_IP char devName [IFNAMSIZ];#endif /* INCLUDE_IP */ if (pBpfProto->bsdFlag) return (EINVAL); if (on) { error = muxIoctl (pBpfProto->pCookie, EIOCGFLAGS, (char *) &endFlags); if (error != OK) { return (EINVAL); } /* Enable promiscuous mode if not already enabled */ if ( (endFlags & IFF_PROMISC) == 0) { endFlags = IFF_PROMISC; error = muxIoctl (pBpfProto->pCookie, EIOCSFLAGS, (char *) endFlags); if (error != OK) { return (EINVAL); }#ifdef INCLUDE_IP sprintf (devName, "%s%d", pBpfProto->devName, pBpfProto->devUnit); ifFlagChange (devName, IFF_PROMISC, TRUE);#endif /* INCLUDE_IP */ } pBpfProto->bpfPromiscEnabled = TRUE; pBpfProto->numPromisc ++; return (OK); } pBpfProto->numPromisc --; /* * Disable the network interface's promiscuous mode if no other BPF * units from any BPF devices are using it. */ if (pBpfProto->numPromisc == 0) { /* This BPF device no longer uses promiscuous mode. */ pBpfProto->bpfPromiscEnabled = FALSE; /* Find the start of the attachment list for this network interface. */ for (pFirst = (BPF_PROTO_CTRL *)lstFirst (&lstProtoInUse); pFirst != NULL; pFirst = (BPF_PROTO_CTRL *)lstNext ((NODE *)pFirst)) { if (pFirst->bsdFlag == TRUE) /* Ignore BSD network devices. */ continue; if (PCOOKIE_TO_ENDOBJ(pFirst->pCookie) == PCOOKIE_TO_ENDOBJ(pBpfProto->pCookie)) break; } if (pFirst == NULL) /* No device attached? (Can't really occur). */ return (OK); if (pFirst->numPromisc) { /* * The first BPF device attached to the network * interface is using the promiscuous mode setting. */ return (OK); } else { /* * Check the promiscuous mode setting for any * BPF devices sharing a network interface. */ pFirst = (BPF_PROTO_CTRL *)lstFirst (& (pFirst->bpfDevList)); while (pFirst != NULL) { if (pFirst->numPromisc) break; pFirst = (BPF_PROTO_CTRL *)lstNext ( (NODE *)pFirst); } /* Leave interface setting unchanged if promiscuous mode found. */ if (pFirst != NULL) return (OK); } endFlags = IFF_PROMISC; /* Set mask which causes muxIoctl() routine to disable flags. */ endFlags = - endFlags - 1; error = muxIoctl (pBpfProto->pCookie, EIOCSFLAGS, (char *) endFlags); if (error != OK) error = EINVAL;#ifdef INCLUDE_IP sprintf (devName, "%s%d", pBpfProto->devName, pBpfProto->devUnit); ifFlagChange (devName, IFF_PROMISC, FALSE);#endif /* INCLUDE_IP */ } return (error); }STATUS _bpfProtoSend ( BPF_PROTO_CTRL * pBpfProto, char * pBuf, int nBytes, BOOL nonBlocking ) { M_BLK_ID pMBlk; END_OBJ * pEnd; if (pBpfProto->bsdFlag) return (ERROR); pEnd = PCOOKIE_TO_ENDOBJ(pBpfProto->pCookie); pMBlk = netTupleGet (pEnd->pNetPool, nBytes, (nonBlocking ? M_DONTWAIT : M_WAIT), MT_DATA, TRUE); if (pMBlk == NULL) { netErrnoSet (ENOBUFS); return (ERROR); } return (muxSend (pBpfProto->pCookie, pMBlk)); }/****************************************************************************** * bpfTkProtoInput - Check incoming frame against every BPF unit** This routine checks incoming frame against every BPF unit attached to a* NPT device using the muxTk/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.** RETURNS: FALSE*/LOCAL BOOL bpfTkProtoInput ( void * pProtoCtrl, long type, M_BLK_ID pMBlk, void * pSpare ) { BPF_PROTO_CTRL * pBpfProto; ulong_t dataOffset; if (pProtoCtrl == NULL) return (FALSE); /* Access a BPF unit's attachment to the network interface. */ pBpfProto = (BPF_PROTO_CTRL *) pProtoCtrl; dataOffset = 0; if (muxIoctl (pBpfProto->pCookie, EIOCGHDRLEN, (caddr_t)&dataOffset) != OK) return (FALSE); /* Apply the current filters and save matching frames. */ _bpfPacketTap (&(pBpfProto->bpfUnitList), type, pMBlk, dataOffset); return (FALSE); }/****************************************************************************** * bpfTkProtoShutdown - shutdown routine** This is the shut down routine passed to muxTkBind call** RETURNS: OK or ERROR*/LOCAL STATUS bpfTkProtoShutdown ( void * pProtoCtrl ) { if (pProtoCtrl != NULL) { return (bpfProtoShutdown (NULL, pProtoCtrl)); } return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -