/* * Call portmap to lookup a port number for a particular rpc program * Returns non-zero error on failure. */ int krpc_portmap( struct sockaddr_in *sin, /* server address */ u_int prog, u_int vers, u_int proto, /* host order */ u_int16_t *portp) /* network order */ { struct sdata { u_int32_t prog; /* call program */ u_int32_t vers; /* call version */ u_int32_t proto; /* call protocol */ u_int32_t port; /* call port (unused) */ } *sdata; struct rdata { u_int16_t pad; u_int16_t port; } *rdata; mbuf_t m; int error; /* The portmapper port is fixed. */ if (prog == PMAPPROG) { *portp = htons(PMAPPORT); return 0; } error = mbuf_gethdr(MBUF_WAITOK, MBUF_TYPE_DATA, &m); if (error) return error; mbuf_setlen(m, sizeof(*sdata)); mbuf_pkthdr_setlen(m, sizeof(*sdata)); sdata = mbuf_data(m); /* Do the RPC to get it. */ sdata->prog = htonl(prog); sdata->vers = htonl(vers); sdata->proto = htonl(proto); sdata->port = 0; sin->sin_port = htons(PMAPPORT); error = krpc_call(sin, SOCK_DGRAM, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, &m, NULL); if (error) return error; rdata = mbuf_data(m); if (mbuf_len(m) >= sizeof(*rdata)) { *portp = rdata->port; } if (mbuf_len(m) < sizeof(*rdata) || !rdata->port) error = EPROGUNAVAIL; mbuf_freem(m); return (error); }
/* * Copy a string into mbuf(s). * Return the number of bytes output, including XDR overheads. */ APPLESTATIC int nfsm_strtom(struct nfsrv_descript *nd, const char *cp, int siz) { mbuf_t m2; int xfer, left; mbuf_t m1; int rem, bytesize; u_int32_t *tl; char *cp2; NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); *tl = txdr_unsigned(siz); rem = NFSM_RNDUP(siz) - siz; bytesize = NFSX_UNSIGNED + siz + rem; m2 = nd->nd_mb; cp2 = nd->nd_bpos; left = M_TRAILINGSPACE(m2); /* * Loop around copying the string to mbuf(s). */ while (siz > 0) { if (left == 0) { if (siz > ncl_mbuf_mlen) NFSMCLGET(m1, M_WAITOK); else NFSMGET(m1); mbuf_setlen(m1, 0); mbuf_setnext(m2, m1); m2 = m1; cp2 = NFSMTOD(m2, caddr_t); left = M_TRAILINGSPACE(m2); } if (left >= siz) xfer = siz; else xfer = left; NFSBCOPY(cp, cp2, xfer); cp += xfer; mbuf_setlen(m2, mbuf_len(m2) + xfer); siz -= xfer; left -= xfer; if (siz == 0 && rem) { if (left < rem) panic("nfsm_strtom"); NFSBZERO(cp2 + xfer, rem); mbuf_setlen(m2, mbuf_len(m2) + rem); } } nd->nd_mb = m2; nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2); return (bytesize); }
IOReturn MbufUtils::copyFromBufferToMbuf(mbuf_t mbuf, UInt32 from, UInt32 bufferSize, void *data) { if (bufferSize > (UInt32) MbufUtils::mbufTotalLength(mbuf)-from) { IOLog("MbufUtils::copyFromBufferToMbuf(): Got insufficiently large buffer (mbuf too small).\n"); return kIOReturnNoMemory; } UInt8 *inBuffer = (UInt8 *)data; UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf); size_t mbufLength = mbuf_len(mbuf); UInt32 bytesLeft = bufferSize; skip_mbuf_macro(); while (bytesLeft) { ensure_mbuf_macro(); *mbufBuffer = *inBuffer; ++mbufBuffer; ++inBuffer; --mbufLength; --bytesLeft; } return kIOReturnSuccess; }
/* Network Interface functions */ static errno_t ipsec_demux(__unused ifnet_t interface, mbuf_t data, __unused char *frame_header, protocol_family_t *protocol) { struct ip *ip; u_int ip_version; while (data != NULL && mbuf_len(data) < 1) { data = mbuf_next(data); } if (data == NULL) return ENOENT; ip = mtod(data, struct ip *); ip_version = ip->ip_v; switch(ip_version) { case 4: *protocol = PF_INET; return 0; case 6: *protocol = PF_INET6; return 0; default: break; } return 0; }
size_t MbufUtils::mbufTotalLength(mbuf_t mbuf) { size_t len = 0; do { len += mbuf_len(mbuf); } while ((mbuf = mbuf_next(mbuf))); return len; }
/** * Calculates the number of segments required to represent the mbuf. * * @returns Number of segments. * @param pThis The instance. * @param pMBuf The mbuf. * @param pvFrame The frame pointer, optional. */ DECLINLINE(unsigned) vboxNetFltDarwinMBufCalcSGSegs(PVBOXNETFLTINS pThis, mbuf_t pMBuf, void *pvFrame) { NOREF(pThis); /* * Count the buffers in the chain. */ unsigned cSegs = 0; for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur)) if (mbuf_len(pCur)) cSegs++; else if ( !cSegs && pvFrame && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf)) cSegs++; #ifdef PADD_RUNT_FRAMES_FROM_HOST /* * Add one buffer if the total is less than the ethernet minimum 60 bytes. * This may allocate a segment too much if the ethernet header is separated, * but that shouldn't harm us much. */ if (mbuf_pkthdr_len(pMBuf) < 60) cSegs++; #endif #ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE /* maximize the number of segments. */ cSegs = RT_MAX(VBOXNETFLT_DARWIN_MAX_SEGS - 1, cSegs); #endif return cSegs ? cSegs : 1; }
errno_t IOWebFilterClass::tl_data_in_func(void *cookie, socket_t so, const struct sockaddr *from, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags) { SocketTracker *tracker = (SocketTracker*)cookie; // __asm__("int3"); LOG(LOG_DEBUG, "I am in, %s, magic=%ld", tracker->proc_name, tracker->magic); if(tracker==NULL || data==NULL || (tracker->magic&(kSocketTrackerInvalid|kSocketTrackerDetach))!=0) { LOG(LOG_DEBUG, "in return process"); return 0; } if(tracker->lock==NULL) { tracker->magic=kSocketTrackerInvalid; return 0; } IOLockLock(tracker->lock); mbuf_t head = *data; uint64_t len=0; if(head==NULL) { tracker->magic=kSocketTrackerInvalid; IOLockUnlock(tracker->lock); return 0; } while(head) { len += mbuf_len(head); head = mbuf_next(head); } if(len>sizeof(tracker->request_meg)-1) { tracker->magic=kSocketTrackerInvalid; IOLockUnlock(tracker->lock); return 0; } bzero(tracker->request_meg, sizeof(tracker->request_meg)); mbuf_copydata(*data, 0, len, tracker->request_meg); //todo: sync to shared memory, record a new request if(_queue) { LOG(LOG_DEBUG, "enter queue"); _queue->EnqueueTracker((DataArgs*)tracker); } IOLockUnlock(tracker->lock); return 0; }
int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst) { NOREF(pvIfData); int rc = VINF_SUCCESS; ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis); if (pIfNet) { /* * Create a mbuf for the gather list and push it onto the wire. * * Note! If the interface is in the promiscuous mode we need to send the * packet down the stack so it reaches the driver and Berkeley * Packet Filter (see @bugref{5817}). */ if ((fDst & INTNETTRUNKDIR_WIRE) || vboxNetFltDarwinIsPromiscuous(pThis)) { mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG); if (pMBuf) { errno_t err = ifnet_output_raw(pIfNet, PF_LINK, pMBuf); if (err) rc = RTErrConvertFromErrno(err); } else rc = VERR_NO_MEMORY; } /* * Create a mbuf for the gather list and push it onto the host stack. */ if (fDst & INTNETTRUNKDIR_HOST) { mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG); if (pMBuf) { /* This is what IONetworkInterface::inputPacket does. */ unsigned const cbEthHdr = 14; mbuf_pkthdr_setheader(pMBuf, mbuf_data(pMBuf)); mbuf_pkthdr_setlen(pMBuf, mbuf_pkthdr_len(pMBuf) - cbEthHdr); mbuf_setdata(pMBuf, (uint8_t *)mbuf_data(pMBuf) + cbEthHdr, mbuf_len(pMBuf) - cbEthHdr); mbuf_pkthdr_setrcvif(pMBuf, pIfNet); /* will crash without this. */ errno_t err = ifnet_input(pIfNet, pMBuf, NULL); if (err) rc = RTErrConvertFromErrno(err); } else rc = VERR_NO_MEMORY; } vboxNetFltDarwinReleaseIfNet(pThis, pIfNet); } return rc; }
size_t MbufUtils::attemptToSetLength(mbuf_t mbuf, size_t targetLength) { size_t mbufLength = mbuf_len(mbuf); size_t mbufMaxLength = mbuf_maxlen(mbuf); if (targetLength > mbufLength && mbufMaxLength != mbufLength) { size_t newBufLen = min_macro(targetLength, mbufMaxLength); mbuf_setlen(mbuf, newBufLen); mbufLength = newBufLen; } return mbufLength; }
static int smb_ioc_request( void * hContext, struct smb_header * header, const mbuf_t words, const mbuf_t bytes, mbuf_t response) { struct smbioc_rq krq; bzero(&krq, sizeof(krq)); krq.ioc_version = SMB_IOC_STRUCT_VERSION; krq.ioc_cmd = header->command; /* XXX For large I/O requests where the uint16_t byte count * (ioc_tbc) wraps to 0, this interface will get horribly * confused. I don't think we can fix this without revving the * ioctl version -- jpeach */ /* Set transmit words buffer ... */ krq.ioc_twc = mbuf_len(words) / sizeof(uint16_t); krq.ioc_twords = mbuf_data(words); /* Set transmit bytes buffer ... */ krq.ioc_tbc = mbuf_len(bytes); krq.ioc_tbytes = mbuf_data(bytes); /* Set receive buffer, reserving space for the word count and byte count ... */ krq.ioc_rpbufsz = (int32_t)mbuf_maxlen(response); krq.ioc_rpbuf = mbuf_data(response); if (smb_ioctl_call(((struct smb_ctx *)hContext)->ct_fd, SMBIOC_REQUEST, &krq) == -1) { return errno; } header->flags = krq.ioc_flags; header->flags2 = krq.ioc_flags2; header->status = krq.ioc_ntstatus; mbuf_setlen(response, krq.ioc_rpbufsz); return 0; }
/* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ void ppp_comp_logmbuf(char *msg, mbuf_t m) { int i, lcount, copycount, count; char lbuf[16], *data; if (m == NULL) return; IOLog("%s: \n", msg); for (count = mbuf_len(m), data = mbuf_data(m); m != NULL; ) { /* build a line of output */ for(lcount = 0; lcount < sizeof(lbuf); lcount += copycount) { if (!count) { m = mbuf_next(m); if (m == NULL) break; count = mbuf_len(m); data = mbuf_data(m); } copycount = (count > sizeof(lbuf) - lcount) ? sizeof(lbuf) - lcount : count; bcopy(data, &lbuf[lcount], copycount); data += copycount; count -= copycount; } /* output line (hex 1st, then ascii) */ IOLog("%s: 0x ", msg); for(i = 0; i < lcount; i++) { if (i == 8) IOLog(" "); IOLog("%02x ", (u_char)lbuf[i]); } for( ; i < sizeof(lbuf); i++) { if (i == 8) IOLog(" "); IOLog(" "); } IOLog(" '"); for(i = 0; i < lcount; i++) IOLog("%c",(lbuf[i]>=040 && lbuf[i]<=0176)?lbuf[i]:'.'); IOLog("'\n"); } }
//////////////////////////////////////////////////////////////////////////////// // // in_firewire_arp_input // // IN: register struct mbuf *m // // Invoked by : // firewire_arpintr calls it from the context of dlil_input_thread queue // // ARP for Internet protocols on 10 Mb/s Ethernet. // Algorithm is that given in RFC 826. // In addition, a sanity check is performed on the sender // protocol address, to catch impersonators. // We no longer handle negotiations for use of trailer protocol: // Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent // along with IP replies if we wanted trailers sent to us, // and also sent them in response to IP replies. // This allowed either end to announce the desire to receive trailer packets. // We no longer reply to requests for ETHERTYPE_TRAIL protocol either, // but formerly didn't normally send requests. // //////////////////////////////////////////////////////////////////////////////// static void inet_firewire_arp_input( mbuf_t m) { IP1394_ARP *fwa; struct sockaddr_dl sender_hw; struct sockaddr_in sender_ip; struct sockaddr_in target_ip; ifnet_t ifp = mbuf_pkthdr_rcvif((mbuf_t)m); IOFWInterface *fwIf = (IOFWInterface*)ifnet_softc(ifp); if(fwIf == NULL) return; IOFireWireIP *fwIpObj = (IOFireWireIP*)fwIf->getController(); if(fwIpObj == NULL) return; if (mbuf_len(m) < (int)sizeof(IP1394_ARP) && mbuf_pullup(&m, sizeof(IP1394_ARP)) != 0) return; fwa = (IP1394_ARP*)mbuf_data(m); // Verify this is an firewire/ip arp and address lengths are correct if (fwa->hardwareType != htons(ARP_HDW_TYPE) || fwa->protocolType != htons(FWTYPE_IP) || fwa->hwAddrLen != sizeof(IP1394_HDW_ADDR) || fwa->ipAddrLen != IPV4_ADDR_SIZE) { mbuf_free(m); return; } bzero(&sender_ip, sizeof(sender_ip)); sender_ip.sin_len = sizeof(sender_ip); sender_ip.sin_family = AF_INET; sender_ip.sin_addr.s_addr = fwa->senderIpAddress; target_ip = sender_ip; target_ip.sin_addr.s_addr = fwa->targetIpAddress; bzero(&sender_hw, sizeof(sender_hw)); sender_hw.sdl_len = sizeof(sender_hw); sender_hw.sdl_family = AF_LINK; sender_hw.sdl_type = IFT_IEEE1394; sender_hw.sdl_alen = FIREWIRE_ADDR_LEN; bcopy(&fwa->senderUniqueID, LLADDR(&sender_hw), FIREWIRE_ADDR_LEN); if(fwIpObj->arpCacheHandler(fwa)) inet_arp_handle_input(ifp, ntohs(fwa->opcode), &sender_hw, &sender_ip, &target_ip); mbuf_free((mbuf_t)m); }
static errno_t vboxNetAdpDarwinOutput(ifnet_t pIface, mbuf_t pMBuf) { PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface); Assert(pThis); if (pThis->u.s.nTapMode & BPF_MODE_OUTPUT) { Log2(("vboxnetadp: out len=%d\n%.*Rhxd\n", mbuf_len(pMBuf), 14, mbuf_data(pMBuf))); bpf_tap_out(pIface, DLT_EN10MB, pMBuf, NULL, 0); } mbuf_freem_list(pMBuf); return 0; }
/* ----------------------------------------------------------------------------- Called by socket layer to send a packet ----------------------------------------------------------------------------- */ int l2tp_send(struct socket *so, int flags, mbuf_t m, struct sockaddr *to, mbuf_t control, struct proc *p) { if (control) mbuf_freem(control); if (mbuf_len(m) == 0) { mbuf_freem(m); return 0; } return l2tp_rfc_output(so->so_pcb, m, to); }
/* * Advance the position in the mbuf chain. * If offs == 0, this is a no-op, but it is simpler to just return from * here than check for offs > 0 for all calls to nfsm_advance. * If left == -1, it should be calculated here. */ APPLESTATIC int nfsm_advance(struct nfsrv_descript *nd, int offs, int left) { int error = 0; if (offs == 0) goto out; /* * A negative offs should be considered a serious problem. */ if (offs < 0) panic("nfsrv_advance"); /* * If left == -1, calculate it here. */ if (left == -1) left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) - nd->nd_dpos; /* * Loop around, advancing over the mbuf data. */ while (offs > left) { offs -= left; nd->nd_md = mbuf_next(nd->nd_md); if (nd->nd_md == NULL) { error = EBADRPC; goto out; } left = mbuf_len(nd->nd_md); nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t); } nd->nd_dpos += offs; out: NFSEXITCODE(error); return (error); }
/* * Help break down an mbuf chain by setting the first siz bytes contiguous * pointed to by returned val. * This is used by the macro NFSM_DISSECT for tough * cases. */ APPLESTATIC void * nfsm_dissct(struct nfsrv_descript *nd, int siz, int how) { mbuf_t mp2; int siz2, xfer; caddr_t p; int left; caddr_t retp; retp = NULL; left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) - nd->nd_dpos; while (left == 0) { nd->nd_md = mbuf_next(nd->nd_md); if (nd->nd_md == NULL) return (retp); left = mbuf_len(nd->nd_md); nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t); } if (left >= siz) { retp = nd->nd_dpos; nd->nd_dpos += siz; } else if (mbuf_next(nd->nd_md) == NULL) { return (retp); } else if (siz > ncl_mbuf_mhlen) { panic("nfs S too big"); } else { MGET(mp2, MT_DATA, how); if (mp2 == NULL) return (NULL); mbuf_setnext(mp2, mbuf_next(nd->nd_md)); mbuf_setnext(nd->nd_md, mp2); mbuf_setlen(nd->nd_md, mbuf_len(nd->nd_md) - left); nd->nd_md = mp2; retp = p = NFSMTOD(mp2, caddr_t); NFSBCOPY(nd->nd_dpos, p, left); /* Copy what was left */ siz2 = siz - left; p += left; mp2 = mbuf_next(mp2); /* Loop around copying up the siz2 bytes */ while (siz2 > 0) { if (mp2 == NULL) return (NULL); xfer = (siz2 > mbuf_len(mp2)) ? mbuf_len(mp2) : siz2; if (xfer > 0) { NFSBCOPY(NFSMTOD(mp2, caddr_t), p, xfer); NFSM_DATAP(mp2, xfer); mbuf_setlen(mp2, mbuf_len(mp2) - xfer); p += xfer; siz2 -= xfer; } if (siz2 > 0) mp2 = mbuf_next(mp2); } mbuf_setlen(nd->nd_md, siz); nd->nd_md = mp2; nd->nd_dpos = NFSMTOD(mp2, caddr_t); } return (retp); }
static errno_t vboxNetAdpDarwinDemux(ifnet_t pIface, mbuf_t pMBuf, char *pFrameHeader, protocol_family_t *pProtocolFamily) { PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface); Assert(pThis); Log2(("vboxNetAdpDarwinDemux: mode=%d\n", pThis->u.s.nTapMode)); if (pThis->u.s.nTapMode & BPF_MODE_INPUT) { Log2(("vboxnetadp: in len=%d\n%.*Rhxd\n", mbuf_len(pMBuf), 14, pFrameHeader)); bpf_tap_in(pIface, DLT_EN10MB, pMBuf, pFrameHeader, ETHER_HDR_LEN); } return ether_demux(pIface, pMBuf, pFrameHeader, pProtocolFamily); }
/* Network Interface functions */ static errno_t utun_demux( __unused ifnet_t interface, mbuf_t data, __unused char *frame_header, protocol_family_t *protocol) { while (data != NULL && mbuf_len(data) < 1) { data = mbuf_next(data); } if (data == NULL) return ENOENT; *protocol = *(u_int32_t *)mbuf_data(data); return 0; }
void net_habitue_device_SC101::handleResolvePacket(sockaddr_in *addr, mbuf_t m, size_t len, outstanding *out, void *ctx) { clock_get_uptime(&_lastReply); if (mbuf_len(m) < out->len && mbuf_pullup(&m, out->len) != 0) { KINFO("pullup failed"); return; } KDEBUG("resolve succeeded!"); psan_resolve_response_t *res = (psan_resolve_response_t *)mbuf_data(m); sockaddr_in part; bzero(&part, sizeof(part)); part.sin_len = sizeof(part); part.sin_family = AF_INET; part.sin_port = htons(PSAN_PORT); part.sin_addr = res->ip4; OSData *partData = OSData::withBytes(&part, sizeof(part)); if (partData) { setProperty(gSC101DevicePartitionAddressKey, partData); partData->release(); } OSData *rootData = OSData::withBytes(addr, sizeof(*addr)); if (rootData) { setProperty(gSC101DeviceRootAddressKey, rootData); rootData->release(); } IODelete(out, outstanding, 1); mbuf_freem(m); if (!getProperty(gSC101DeviceSizeKey)) disk(); }
__private_extern__ errno_t ANControlListEntryAppend(OSMallocTag tag, ANControlListEntry * entry, mbuf_t packet) { uint32_t packSize = (uint32_t)mbuf_len(packet); if (packSize == 0) return 0; uint32_t newSize = packSize + entry->bufferLength; char * buffer = (char *)OSMalloc(newSize, tag); if (!buffer) return ENOMEM; if (entry->packetBuffer) { // copy old data to the buffer memcpy(buffer, entry->packetBuffer, entry->bufferLength); OSFree(entry->packetBuffer, entry->bufferLength, tag); } mbuf_copydata(packet, 0, packSize, &buffer[entry->bufferLength]); entry->packetBuffer = buffer; entry->bufferLength = newSize; return 0; }
IOReturn MbufUtils::copyAudioFromMbufToBuffer(mbuf_t mbuf, UInt32 from, UInt32 bufferSize, UInt8 *inBuffer) { if (bufferSize > (UInt32) MbufUtils::mbufTotalLength(mbuf)-from) { IOLog("MbufUtils::copyAudioFromMbufToBuffer(): Got insufficiently large buffer (mbuf too small).\n"); return kIOReturnNoMemory; } if (0 != bufferSize % (REAC_RESOLUTION*2)) { IOLog("MbufUtils::copyAudioFromMbufToBuffer(): Buffer size must be a multiple of %d.\n", REAC_RESOLUTION*2); return kIOReturnBadArgument; } UInt8 *inBufferEnd = inBuffer + bufferSize; UInt8 intermediaryBuffer[6]; UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf); size_t mbufLength = mbuf_len(mbuf); skip_mbuf_macro(); while (inBuffer < inBufferEnd) { for (UInt32 i=0; i<sizeof(intermediaryBuffer); i++) { ensure_mbuf_macro(); intermediaryBuffer[i] = *mbufBuffer; ++mbufBuffer; --mbufLength; } inBuffer[0] = intermediaryBuffer[1]; inBuffer[1] = intermediaryBuffer[0]; inBuffer[2] = intermediaryBuffer[3]; inBuffer[3] = intermediaryBuffer[2]; inBuffer[4] = intermediaryBuffer[5]; inBuffer[5] = intermediaryBuffer[4]; inBuffer += REAC_RESOLUTION*2; } return kIOReturnSuccess; }
UInt32 VoodooIntel3945::outputPacket( mbuf_t m, void* param ) { struct wpi_softc* sc = &fSelfData; struct ieee80211com* ic = &sc->sc_ic; struct ieee80211_node *ni; DPRINTF(("TX: mbuf len=%u\n", mbuf_len(m))); if (m == 0) return kIOReturnOutputDropped; // ??? ExtraMbufParams* p = (ExtraMbufParams*)param; if (p->is80211ManagementFrame) { ni = (struct ieee80211_node *)mbuf_pkthdr_rcvif(m); } else { if (sc->qfullmsk != 0) { freePacket(m); return kIOReturnOutputDropped; } if (ic->ic_state != IEEE80211_S_RUN) { freePacket(m); return kIOReturnOutputDropped; } /* Encapsulate and send data frames. */ if ((m = ieee80211_encap(ic, m, &ni)) == NULL) return kIOReturnOutputDropped; } if (wpi_tx(sc, m, ni) != 0) { ieee80211_release_node(ic, ni); if (m) freePacket(m); return kIOReturnOutputDropped; } else { DPRINTF(("(prev tx success)\n")); sc->sc_tx_timer = 5; return kIOReturnOutputSuccess; } }
IOReturn MbufUtils::zeroMbuf(mbuf_t mbuf, UInt32 from, UInt32 len) { if (from+len > (UInt32) MbufUtils::mbufTotalLength(mbuf)) { IOLog("MbufUtils::zeroMbuf(): Got insufficiently large buffer.\n"); return kIOReturnNoMemory; } UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf); size_t mbufLength = mbuf_len(mbuf); UInt32 bytesLeft = len; skip_mbuf_macro(); while (bytesLeft) { ensure_mbuf_macro(); *mbufBuffer = 0; ++mbufBuffer; --mbufLength; --bytesLeft; } return kIOReturnSuccess; }
IOReturn MbufUtils::copyAudioFromBufferToMbuf(mbuf_t mbuf, UInt32 from, UInt32 bufferSize, UInt8 *inBuffer) { if (bufferSize > (UInt32) MbufUtils::mbufTotalLength(mbuf)-from) { IOLog("MbufUtils::copyAudioFromBufferToMbuf(): Got insufficiently large buffer (mbuf too small).\n"); return kIOReturnNoMemory; } if (0 != bufferSize % (REAC_RESOLUTION*2)) { IOLog("MbufUtils::copyAudioFromBufferToMbuf(): Buffer size must be a multiple of %d.\n", REAC_RESOLUTION*2); return kIOReturnBadArgument; } UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf); size_t mbufLength = mbuf_len(mbuf); UInt32 bytesLeft = bufferSize; skip_mbuf_macro(); # define mbuf_move_buffer_forward_macro() \ ++mbufBuffer; \ --mbufLength; while (bytesLeft) { ensure_mbuf_macro(); *mbufBuffer = inBuffer[1]; mbuf_move_buffer_forward_macro(); ensure_mbuf_macro(); *mbufBuffer = inBuffer[0]; mbuf_move_buffer_forward_macro(); ensure_mbuf_macro(); *mbufBuffer = inBuffer[3]; mbuf_move_buffer_forward_macro(); ensure_mbuf_macro(); *mbufBuffer = inBuffer[2]; mbuf_move_buffer_forward_macro(); ensure_mbuf_macro(); *mbufBuffer = inBuffer[5]; mbuf_move_buffer_forward_macro(); ensure_mbuf_macro(); *mbufBuffer = inBuffer[4]; mbuf_move_buffer_forward_macro(); inBuffer += REAC_RESOLUTION*2; bytesLeft -= REAC_RESOLUTION*2; } return kIOReturnSuccess; }
UInt32 HoRNDIS::outputPacket(mbuf_t packet, void *param) { mbuf_t m; size_t pktlen = 0; IOReturn ior = kIOReturnSuccess; UInt32 poolIndx; int i; LOG(V_DEBUG, ""); /* Count the total size of this packet */ m = packet; while (m) { pktlen += mbuf_len(m); m = mbuf_next(m); } LOG(V_DEBUG, "%ld bytes", pktlen); if (pktlen > (mtu + 14)) { LOG(V_ERROR, "packet too large (%ld bytes, but I told you you could have %d!)", pktlen, mtu); fpNetStats->outputErrors++; return false; } /* Find an output buffer in the pool */ IOLockLock(outbuf_lock); for (i = 0; i < OUT_BUF_MAX_TRIES; i++) { AbsoluteTime ivl, deadl; for (poolIndx = 0; poolIndx < N_OUT_BUFS; poolIndx++) if (!outbufs[poolIndx].inuse) { outbufs[poolIndx].inuse = true; break; } if (poolIndx != N_OUT_BUFS) break; /* "while", not "if". See Symphony X's seminal work on this topic, /Paradise Lost/ (2007). */ nanoseconds_to_absolutetime(OUT_BUF_WAIT_TIME, &ivl); clock_absolutetime_interval_to_deadline(ivl, &deadl); LOG(V_NOTE, "waiting for buffer..."); IOLockSleepDeadline(outbuf_lock, outbufs, deadl, THREAD_INTERRUPTIBLE); } IOLockUnlock(outbuf_lock); if (poolIndx == N_OUT_BUFS) { LOG(V_ERROR, "timed out waiting for buffer"); return kIOReturnTimeout; } /* Start filling in the send buffer */ struct rndis_data_hdr *hdr; hdr = (struct rndis_data_hdr *)outbufs[poolIndx].buf; outbufs[poolIndx].inuse = true; outbufs[poolIndx].mdp->setLength(pktlen + sizeof *hdr); memset(hdr, 0, sizeof *hdr); hdr->msg_type = RNDIS_MSG_PACKET; hdr->msg_len = cpu_to_le32(pktlen + sizeof *hdr); hdr->data_offset = cpu_to_le32(sizeof(*hdr) - 8); hdr->data_len = cpu_to_le32(pktlen); mbuf_copydata(packet, 0, pktlen, hdr + 1); freePacket(packet); /* Now, fire it off! */ outbufs[poolIndx].comp.target = this; outbufs[poolIndx].comp.parameter = (void *)poolIndx; outbufs[poolIndx].comp.action = dataWriteComplete; ior = fOutPipe->Write(outbufs[poolIndx].mdp, &outbufs[poolIndx].comp); if (ior != kIOReturnSuccess) { LOG(V_ERROR, "write failed"); if (ior == kIOUSBPipeStalled) { fOutPipe->Reset(); ior = fOutPipe->Write(outbufs[poolIndx].mdp, &outbufs[poolIndx].comp); if (ior != kIOReturnSuccess) { LOG(V_ERROR, "write really failed"); fpNetStats->outputErrors++; return ior; } } } fpNetStats->outputPackets++; return kIOReturnOutputSuccess; }
UInt32 darwin_iwi3945::outputPacket(mbuf_t m, void * param) { //IOLog("outputPacket\n"); if((fNetif->getFlags() & IFF_RUNNING)!=0 || m==NULL) { if (m) if (!(mbuf_type(m) == MBUF_TYPE_FREE) ) freePacket(m); m=NULL; netStats->outputErrors++; return kIOReturnOutputDropped; } mbuf_t nm; int ret = kIOReturnOutputDropped; //checking supported packet IWI_DEBUG("outputPacket t: %d f:%04x\n",mbuf_type(m),mbuf_flags(m)); //drop mbuf is not PKTHDR if (!(mbuf_flags(m) & MBUF_PKTHDR) ){ IWI_ERR("BUG: dont support mbuf without pkthdr and dropped \n"); netStats->outputErrors++; goto finish; } if(mbuf_type(m) == MBUF_TYPE_FREE){ IWI_ERR("BUG: this is freed packet and dropped \n"); netStats->outputErrors++; goto finish; } nm = mergePacket(m); if (nm==NULL) { netStats->outputErrors++; goto finish; } if(mbuf_next(nm)){ IWI_ERR("BUG: dont support chains mbuf\n"); IWI_ERR("BUG: tx packet is not single mbuf mbuf_len(%d) mbuf_pkthdr_len(%d)\n",mbuf_len(nm) , mbuf_pkthdr_len(nm) ); IWI_ERR("BUG: next mbuf size %d\n",mbuf_len(mbuf_next(nm))); } IWI_DEBUG_FULL("call ieee80211_xmit - not done yet\n"); //ret = ieee80211_xmit(nm,priv->net_dev); //struct ieee80211_tx_control ctrl; //ret=ipw_tx_skb(priv, nm, &ctrl); finish: /* free finished packet */ //freePacket(m); //m=NULL; if (ret == kIOReturnOutputDropped) { //if (nm) //if (!(mbuf_type(nm) == MBUF_TYPE_FREE) ) freePacket(nm); //nm=NULL; } return ret; }
mbuf_t darwin_iwi3945::mergePacket(mbuf_t m) { mbuf_t nm,nm2; int offset; if(!mbuf_next(m)) { offset = (4 - ((int)(mbuf_data(m)) & 3)) % 4; //packet needs to be 4 byte aligned if (offset==0) return m; IWI_DEBUG_FULL("this packet dont have mbuf_next, merge is not required\n"); goto copy_packet; } /* allocate and Initialize New mbuf */ nm = allocatePacket(mbuf_pkthdr_len(m)); if (nm==0) return NULL; //if (mbuf_getpacket(MBUF_WAITOK, &nm)!=0) return NULL; mbuf_setlen(nm,0); mbuf_pkthdr_setlen(nm,0); if( mbuf_next(nm)) IWI_ERR("merged mbuf_next\n"); /* merging chains to single mbuf */ for (nm2 = m; nm2; nm2 = mbuf_next(nm2)) { memcpy (skb_put (nm, mbuf_len(nm2)), (UInt8*)mbuf_data(nm2), mbuf_len(nm2)); } /* checking if merged or not. */ if( mbuf_len(nm) == mbuf_pkthdr_len(m) ) { if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m); m=NULL; return nm; } /* merging is not completed. */ IWI_LOG("mergePacket is failed: data copy dont work collectly\n"); //IWI_LOG("orig_len %d orig_pktlen %d new_len %d new_pktlen %d\n", // mbuf_len(m),mbuf_pkthdr_len(m), // mbuf_len(nm),mbuf_pkthdr_len(nm) ); if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m); m=NULL; if (nm!=NULL) if (!(mbuf_type(nm) == MBUF_TYPE_FREE) ) freePacket(nm); nm=NULL; return NULL; copy_packet: if (mbuf_dup(m, MBUF_WAITOK , &nm)!=0) { if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m); m=NULL; return NULL; } if (m!=NULL) if (!(mbuf_type(m) == MBUF_TYPE_FREE) ) freePacket(m); m=NULL; return nm; //return copyPacket(m, 0); }
//callback for incoming data // only interested in DNS responses for IP:URL mappings // code inspired by: https://github.com/williamluke/peerguardian-linux/blob/master/pgosx/kern/ppfilter.c static errno_t data_in(void *cookie, socket_t so, const struct sockaddr *from, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags) { //dbg msg IOLog("LULU: in %s\n", __FUNCTION__); //port in_port_t port = 0; //peer name struct sockaddr_in6 peerName = {0}; //mem buffer mbuf_t memBuffer = NULL; //response size size_t responseSize = 0; //dns header dnsHeader* dnsHeader = NULL; //firewall event firewallEvent event = {0}; //destination socket ('from') might be null? // if so, grab it via 'getpeername' from the socket if(NULL == from) { //lookup remote socket info if(0 != sock_getpeername(so, (struct sockaddr*)&peerName, sizeof(peerName))) { //err msg IOLog("LULU ERROR: sock_getpeername() failed\n"); //bail goto bail; } //now, assign from = (const struct sockaddr*)&peerName; } //get port switch(from->sa_family) { //IPv4 case AF_INET: port = ntohs(((const struct sockaddr_in*)from)->sin_port); break; //IPv6 case AF_INET6: port = ntohs(((const struct sockaddr_in6*)from)->sin6_port); break; default: break; } //ignore non-DNS if(53 != port) { //bail goto bail; } //init memory buffer memBuffer = *data; if(NULL == memBuffer) { //bail goto bail; } //get memory buffer while(MBUF_TYPE_DATA != mbuf_type(memBuffer)) { //get next memBuffer = mbuf_next(memBuffer); if(NULL == memBuffer) { //bail goto bail; } } //sanity check length if(mbuf_len(memBuffer) <= sizeof(struct dnsHeader)) { //bail goto bail; } //get data // should be a DNS header dnsHeader = (struct dnsHeader*)mbuf_data(memBuffer); //ignore everything that isn't a DNS response // top bit flag will be 0x1, for "a name service response" if(0 == ((ntohs(dnsHeader->flags)) & (1<<(15)))) { //bail goto bail; } //ignore any errors // bottom (4) bits will be 0x0 for "successful response" if(0 != ((ntohs(dnsHeader->flags)) & (1<<(0)))) { //bail goto bail; } //ignore any packets that don't have answers if(0 == ntohs(dnsHeader->ancount)) { //bail goto bail; } //zero out event struct bzero(&event, sizeof(firewallEvent)); //set type event.dnsResponseEvent.type = EVENT_DNS_RESPONSE; //set size // max, 512 responseSize = MIN(sizeof(event.dnsResponseEvent.response), mbuf_len(memBuffer)); //copy response memcpy(event.dnsResponseEvent.response, mbuf_data(memBuffer), responseSize); //queue it up sharedDataQueue->enqueue_tail(&event, sizeof(firewallEvent)); bail: return kIOReturnSuccess; }
/* * Do a remote procedure call (RPC) and wait for its reply. * If from_p is non-null, then we are doing broadcast, and * the address from whence the response came is saved there. */ int krpc_call( struct sockaddr_in *sa, u_int sotype, u_int prog, u_int vers, u_int func, mbuf_t *data, /* input/output */ struct sockaddr_in *from_p) /* output */ { socket_t so; struct sockaddr_in *sin; mbuf_t m, nam, mhead; struct rpc_call *call; struct rpc_reply *reply; int error, timo, secs; size_t len; static u_int32_t xid = ~0xFF; u_int16_t tport; size_t maxpacket = 1<<16; /* * Validate address family. * Sorry, this is INET specific... */ if (sa->sin_family != AF_INET) return (EAFNOSUPPORT); /* Free at end if not null. */ nam = mhead = NULL; /* * Create socket and set its recieve timeout. */ if ((error = sock_socket(AF_INET, sotype, 0, 0, 0, &so))) goto out1; { struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; if ((error = sock_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))) goto out; } /* * Enable broadcast if necessary. */ if (from_p && (sotype == SOCK_DGRAM)) { int on = 1; if ((error = sock_setsockopt(so, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)))) goto out; } /* * Bind the local endpoint to a reserved port, * because some NFS servers refuse requests from * non-reserved (non-privileged) ports. */ if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m))) goto out; sin = mbuf_data(m); bzero(sin, sizeof(*sin)); mbuf_setlen(m, sizeof(*sin)); sin->sin_len = sizeof(*sin); sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; tport = IPPORT_RESERVED; do { tport--; sin->sin_port = htons(tport); error = sock_bind(so, (struct sockaddr*)sin); } while (error == EADDRINUSE && tport > IPPORT_RESERVED / 2); mbuf_freem(m); m = NULL; if (error) { printf("bind failed\n"); goto out; } /* * Setup socket address for the server. */ if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &nam))) goto out; sin = mbuf_data(nam); mbuf_setlen(nam, sa->sin_len); bcopy((caddr_t)sa, (caddr_t)sin, sa->sin_len); if (sotype == SOCK_STREAM) { struct timeval tv; tv.tv_sec = 60; tv.tv_usec = 0; error = sock_connect(so, mbuf_data(nam), MSG_DONTWAIT); if (error && (error != EINPROGRESS)) goto out; error = sock_connectwait(so, &tv); if (error) { if (error == EINPROGRESS) error = ETIMEDOUT; printf("krpc_call: error waiting for TCP socket connect: %d\n", error); goto out; } } /* * Prepend RPC message header. */ m = *data; *data = NULL; #if DIAGNOSTIC if ((mbuf_flags(m) & MBUF_PKTHDR) == 0) panic("krpc_call: send data w/o pkthdr"); if (mbuf_pkthdr_len(m) < mbuf_len(m)) panic("krpc_call: pkthdr.len not set"); #endif len = sizeof(*call); if (sotype == SOCK_STREAM) len += 4; /* account for RPC record marker */ mhead = m; if ((error = mbuf_prepend(&mhead, len, MBUF_WAITOK))) goto out; if ((error = mbuf_pkthdr_setrcvif(mhead, NULL))) goto out; /* * Fill in the RPC header */ if (sotype == SOCK_STREAM) { /* first, fill in RPC record marker */ u_int32_t *recmark = mbuf_data(mhead); *recmark = htonl(0x80000000 | (mbuf_pkthdr_len(mhead) - 4)); call = (struct rpc_call *)(recmark + 1); } else { call = mbuf_data(mhead); } bzero((caddr_t)call, sizeof(*call)); xid++; call->rp_xid = htonl(xid); /* call->rp_direction = 0; */ call->rp_rpcvers = htonl(2); call->rp_prog = htonl(prog); call->rp_vers = htonl(vers); call->rp_proc = htonl(func); /* call->rp_auth = 0; */ /* call->rp_verf = 0; */ /* * Send it, repeatedly, until a reply is received, * but delay each re-send by an increasing amount. * If the delay hits the maximum, start complaining. */ timo = 0; for (;;) { struct msghdr msg; /* Send RPC request (or re-send). */ if ((error = mbuf_copym(mhead, 0, MBUF_COPYALL, MBUF_WAITOK, &m))) goto out; bzero(&msg, sizeof(msg)); if (sotype == SOCK_STREAM) { msg.msg_name = NULL; msg.msg_namelen = 0; } else { msg.msg_name = mbuf_data(nam); msg.msg_namelen = mbuf_len(nam); } error = sock_sendmbuf(so, &msg, m, 0, 0); if (error) { printf("krpc_call: sosend: %d\n", error); goto out; } m = NULL; /* Determine new timeout. */ if (timo < MAX_RESEND_DELAY) timo++; else printf("RPC timeout for server " IP_FORMAT "\n", IP_LIST(&(sin->sin_addr.s_addr))); /* * Wait for up to timo seconds for a reply. * The socket receive timeout was set to 1 second. */ secs = timo; while (secs > 0) { size_t readlen; if (m) { mbuf_freem(m); m = NULL; } if (sotype == SOCK_STREAM) { int maxretries = 60; struct iovec aio; aio.iov_base = &len; aio.iov_len = sizeof(u_int32_t); bzero(&msg, sizeof(msg)); msg.msg_iov = &aio; msg.msg_iovlen = 1; do { error = sock_receive(so, &msg, MSG_WAITALL, &readlen); if ((error == EWOULDBLOCK) && (--maxretries <= 0)) error = ETIMEDOUT; } while (error == EWOULDBLOCK); if (!error && readlen < aio.iov_len) { /* only log a message if we got a partial word */ if (readlen != 0) printf("short receive (%ld/%ld) from server " IP_FORMAT "\n", readlen, sizeof(u_int32_t), IP_LIST(&(sin->sin_addr.s_addr))); error = EPIPE; } if (error) goto out; len = ntohl(len) & ~0x80000000; /* * This is SERIOUS! We are out of sync with the sender * and forcing a disconnect/reconnect is all I can do. */ if (len > maxpacket) { printf("impossible packet length (%ld) from server " IP_FORMAT "\n", len, IP_LIST(&(sin->sin_addr.s_addr))); error = EFBIG; goto out; } do { readlen = len; error = sock_receivembuf(so, NULL, &m, MSG_WAITALL, &readlen); } while (error == EWOULDBLOCK); if (!error && (len > readlen)) { printf("short receive (%ld/%ld) from server " IP_FORMAT "\n", readlen, len, IP_LIST(&(sin->sin_addr.s_addr))); error = EPIPE; } } else { len = maxpacket; readlen = len; bzero(&msg, sizeof(msg)); msg.msg_name = from_p; msg.msg_namelen = (from_p == NULL) ? 0 : sizeof(*from_p); error = sock_receivembuf(so, &msg, &m, 0, &readlen); } if (error == EWOULDBLOCK) { secs--; continue; } if (error) goto out; len = readlen; /* Does the reply contain at least a header? */ if (len < MIN_REPLY_HDR) continue; if (mbuf_len(m) < MIN_REPLY_HDR) continue; reply = mbuf_data(m); /* Is it the right reply? */ if (reply->rp_direction != htonl(RPC_REPLY)) continue; if (reply->rp_xid != htonl(xid)) continue; /* Was RPC accepted? (authorization OK) */ if (reply->rp_astatus != 0) { error = ntohl(reply->rp_u.rpu_errno); printf("rpc denied, error=%d\n", error); /* convert rpc error to errno */ switch (error) { case RPC_MISMATCH: error = ERPCMISMATCH; break; case RPC_AUTHERR: error = EAUTH; break; } goto out; } if (mbuf_len(m) < REPLY_SIZE) { error = RPC_SYSTEM_ERR; } else { error = ntohl(reply->rp_u.rpu_ok.rp_rstatus); } /* Did the call succeed? */ if (error != 0) { printf("rpc status=%d\n", error); /* convert rpc error to errno */ switch (error) { case RPC_PROGUNAVAIL: error = EPROGUNAVAIL; break; case RPC_PROGMISMATCH: error = EPROGMISMATCH; break; case RPC_PROCUNAVAIL: error = EPROCUNAVAIL; break; case RPC_GARBAGE: error = EINVAL; break; case RPC_SYSTEM_ERR: error = EIO; break; } goto out; } goto gotreply; /* break two levels */ } /* while secs */ } /* forever send/receive */ error = ETIMEDOUT; goto out; gotreply: /* * Pull as much as we can into first mbuf, to make * result buffer contiguous. Note that if the entire * result won't fit into one mbuf, you're out of luck. * XXX - Should not rely on making the entire reply * contiguous (fix callers instead). -gwr */ #if DIAGNOSTIC if ((mbuf_flags(m) & MBUF_PKTHDR) == 0) panic("krpc_call: received pkt w/o header?"); #endif len = mbuf_pkthdr_len(m); if (sotype == SOCK_STREAM) len -= 4; /* the RPC record marker was read separately */ if (mbuf_len(m) < len) { if ((error = mbuf_pullup(&m, len))) goto out; reply = mbuf_data(m); } /* * Strip RPC header */ len = sizeof(*reply); if (reply->rp_u.rpu_ok.rp_auth.rp_atype != 0) { len += ntohl(reply->rp_u.rpu_ok.rp_auth.rp_alen); len = (len + 3) & ~3; /* XXX? */ } mbuf_adj(m, len); /* result */ *data = m; out: sock_close(so); out1: if (nam) mbuf_freem(nam); if (mhead) mbuf_freem(mhead); return error; }
// data in is currently used for PASV FTP support static errno_t ppfilter_data_in (__unused void *cookie, socket_t so, const struct sockaddr *from, mbuf_t *data, __unused mbuf_t *control, __unused sflt_data_flag_t flags) { in_addr_t ip4; in_port_t port; if (!from) { struct sockaddr_in6 local; if (0 != sock_getpeername(so, (struct sockaddr*)&local, sizeof(local))) bzero(&local, sizeof(local)); from = (const struct sockaddr*)&local; } if (AF_INET == from->sa_family) { port = ntohs(((const struct sockaddr_in*)from)->sin_port); } else if (AF_INET6 == from->sa_family) { const struct sockaddr_in6* addr6 = (const struct sockaddr_in6*)from; if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) || !IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) return (0); // tables do not contain native ip6 addreses port = ntohs(addr6->sin6_port); } else return (0); // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Short-circuit optimization for ftp filter -- if any other filters are ever added, // this will have to be removed. if (21 != port) return (0); // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX mbuf_t mdata = *data; while (mdata && MBUF_TYPE_DATA != mbuf_type(mdata)) { mdata = mbuf_next(mdata); } if (!mdata) return (0); char *pkt = mbuf_data(mdata); if (!pkt) return (0); size_t len = mbuf_len(mdata); ip4 = INADDR_NONE; int block, i; pp_data_filter_t filt = pp_data_filters[0]; for (i = 1; filt; ++i) { block = filt(pkt, len, &ip4, &port); if (INADDR_NONE != ip4) { // add to dynamic list pp_dynentries_lock(); pp_dyn_entry_t e = pp_dyn_entry_get(); if (e) { e->addr = ip4; e->port = port; e->block = block; } pp_dynentries_unlock(); break; } filt = pp_data_filters[i]; } return (0); }