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; }
__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; }
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; }
void rx_upcall(socket_t so, void *arg, __unused int waitflag) { mbuf_t m; int error = 0; int i, flags = 0; struct msghdr msg; struct sockaddr_storage ss; struct sockaddr *sa = NULL; struct sockaddr_in from; struct rx_packet *p; afs_int32 rlen; afs_int32 tlen; afs_int32 savelen; /* was using rlen but had aliasing problems */ size_t nbytes, resid, noffset; p = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE); rx_computelen(p, tlen); rx_SetDataSize(p, tlen); /* this is the size of the user data area */ tlen += RX_HEADER_SIZE; /* now this is the size of the entire packet */ rlen = rx_maxJumboRecvSize; /* this is what I am advertising. Only check * it once in order to avoid races. */ tlen = rlen - tlen; if (tlen > 0) { tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF); if (tlen > 0) { tlen = rlen - tlen; } else tlen = rlen; } else tlen = rlen; /* add some padding to the last iovec, it's just to make sure that the * read doesn't return more data than we expect, and is done to get around * our problems caused by the lack of a length field in the rx header. */ savelen = p->wirevec[p->niovecs - 1].iov_len; p->wirevec[p->niovecs - 1].iov_len = savelen + RX_EXTRABUFFERSIZE; resid = nbytes = tlen + sizeof(afs_int32); memset(&msg, 0, sizeof(struct msghdr)); msg.msg_name = &ss; msg.msg_namelen = sizeof(struct sockaddr_storage); sa =(struct sockaddr *) &ss; do { m = NULL; error = sock_receivembuf(so, &msg, &m, MSG_DONTWAIT, &nbytes); if (!error) { size_t sz, offset = 0; noffset = 0; resid = nbytes; for (i=0;i<p->niovecs && resid;i++) { sz=MIN(resid, p->wirevec[i].iov_len); error = mbuf_copydata(m, offset, sz, p->wirevec[i].iov_base); if (error) break; resid-=sz; offset+=sz; noffset += sz; } } } while (0); mbuf_freem(m); /* restore the vec to its correct state */ p->wirevec[p->niovecs - 1].iov_len = savelen; if (error == EWOULDBLOCK && noffset > 0) error = 0; if (!error) { int host, port; nbytes -= resid; if (sa->sa_family == AF_INET) from = *(struct sockaddr_in *)sa; p->length = nbytes - RX_HEADER_SIZE;; if ((nbytes > tlen) || (p->length & 0x8000)) { /* Bogus packet */ if (nbytes <= 0) { if (rx_stats_active) { MUTEX_ENTER(&rx_stats_mutex); rx_atomic_inc(&rx_stats.bogusPacketOnRead); rx_stats.bogusHost = from.sin_addr.s_addr; MUTEX_EXIT(&rx_stats_mutex); } dpf(("B: bogus packet from [%x,%d] nb=%d", from.sin_addr.s_addr, from.sin_port, nbytes)); } return; } else { /* Extract packet header. */ rxi_DecodePacketHeader(p); host = from.sin_addr.s_addr; port = from.sin_port; if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) { if (rx_stats_active) { rx_atomic_inc(&rx_stats.packetsRead[p->header.type - 1]); } } #ifdef RX_TRIMDATABUFS /* Free any empty packet buffers at the end of this packet */ rxi_TrimDataBufs(p, 1); #endif /* receive pcket */ p = rxi_ReceivePacket(p, so, host, port, 0, 0); } } /* free packet? */ if (p) rxi_FreePacket(p); return; }
int osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec, int nvecs, int *alength) { #ifdef AFS_DARWIN80_ENV socket_t asocket = (socket_t)so; struct msghdr msg; struct sockaddr_storage ss; int rlen; mbuf_t m; #else struct socket *asocket = (struct socket *)so; struct uio u; #endif int i; struct iovec iov[RX_MAXIOVECS]; struct sockaddr *sa = NULL; int code; size_t resid; int haveGlock = ISAFS_GLOCK(); /*AFS_STATCNT(osi_NetReceive); */ if (nvecs > RX_MAXIOVECS) osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs); for (i = 0; i < nvecs; i++) iov[i] = dvec[i]; if ((afs_termState == AFSOP_STOP_RXK_LISTENER) || (afs_termState == AFSOP_STOP_COMPLETE)) return -1; if (haveGlock) AFS_GUNLOCK(); #if defined(KERNEL_FUNNEL) thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); #endif #ifdef AFS_DARWIN80_ENV resid = *alength; memset(&msg, 0, sizeof(struct msghdr)); msg.msg_name = &ss; msg.msg_namelen = sizeof(struct sockaddr_storage); sa =(struct sockaddr *) &ss; code = sock_receivembuf(asocket, &msg, &m, 0, alength); if (!code) { size_t offset=0,sz; resid = *alength; for (i=0;i<nvecs && resid;i++) { sz=MIN(resid, iov[i].iov_len); code = mbuf_copydata(m, offset, sz, iov[i].iov_base); if (code) break; resid-=sz; offset+=sz; } } mbuf_freem(m); #else u.uio_iov = &iov[0]; u.uio_iovcnt = nvecs; u.uio_offset = 0; u.uio_resid = *alength; u.uio_segflg = UIO_SYSSPACE; u.uio_rw = UIO_READ; u.uio_procp = NULL; code = soreceive(asocket, &sa, &u, NULL, NULL, NULL); resid = u.uio_resid; #endif #if defined(KERNEL_FUNNEL) thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); #endif if (haveGlock) AFS_GLOCK(); if (code) return code; *alength -= resid; if (sa) { if (sa->sa_family == AF_INET) { if (addr) *addr = *(struct sockaddr_in *)sa; } else printf("Unknown socket family %d in NetReceive\n", sa->sa_family); #ifndef AFS_DARWIN80_ENV FREE(sa, M_SONAME); #endif } return code; }
void REACConnection::filterCommandGateMsg(OSObject *target, void *data_mbuf, void *eth_header_ptr, void*, void*) { REACConnection *proto = OSDynamicCast(REACConnection, target); if (NULL == proto) { // This should never happen IOLog("REACConnection::filterCommandGateMsg(): Internal error.\n"); return; } const EthernetHeader *ethernetHeader = (const EthernetHeader *)eth_header_ptr; const int samplesSize = REAC_SAMPLES_PER_PACKET*REAC_RESOLUTION*proto->deviceInfo->in_channels; mbuf_t *data = (mbuf_t *)data_mbuf; UInt32 len = MbufUtils::mbufTotalLength(*data); REACPacketHeader packetHeader; // Check that the packet length is long enough if (len < sizeof(REACPacketHeader)+sizeof(REACConstants::ENDING)) { IOLog("REACConnection[%p]::filterCommandGateMsg(): Got packet of too short length\n", proto); return; } // Check packet ending UInt8 packetEnding[sizeof(REACConstants::ENDING)]; if (0 != mbuf_copydata(*data, len-sizeof(REACConstants::ENDING), sizeof(REACConstants::ENDING), &packetEnding)) { IOLog("REACConnection[%p]::filterCommandGateMsg(): Failed to fetch REAC packet ending\n", proto); return; } if (0 != memcmp(packetEnding, REACConstants::ENDING, sizeof(packetEnding))) { // Incorrect ending. Not a REAC packet? IOLog("REACConnection[%p]::filterCommandGateMsg(): Incorrect packet ending.\n", proto); return; } // Fetch packet header if (0 != mbuf_copydata(*data, 0, sizeof(REACPacketHeader), &packetHeader)) { IOLog("REACConnection[%p]::filterCommandGateMsg(): Failed to fetch REAC packet header\n", proto); return; } // Check packet counter // TODO This doesn't work when more than one unit (for instance two splits) is connected if (proto->isConnected() && /* This prunes a lost packet message when connecting */ proto->lastCounter+1 != packetHeader.getCounter()) { if (!(65535 == proto->lastCounter && 0 == packetHeader.getCounter())) { IOLog("REACConnection[%p]::filterCommandGateMsg(): Lost packet [%d %d]\n", proto, proto->lastCounter, packetHeader.getCounter()); } } // Process packet header proto->dataStream->gotPacket(&packetHeader, ethernetHeader); // Check packet length if (sizeof(REACPacketHeader)+samplesSize+sizeof(UInt16) == len) { // Hack: Announce connect if (!proto->isConnected()) { proto->connected = true; if (NULL != proto->connectionCallback) { proto->connectionCallback(proto, &proto->cookieA, &proto->cookieB, proto->deviceInfo); } } // Save the time we got the packet, for use by REACConnection::timerFired proto->lastSeenConnectionCounter = proto->connectionCounter; if (proto->isConnected()) { if (NULL != proto->samplesCallback) { UInt8* inBuffer = NULL; UInt32 inBufferSize = 0; proto->samplesCallback(proto, &proto->cookieA, &proto->cookieB, &inBuffer, &inBufferSize); if (NULL != inBuffer) { const UInt32 bytesPerSample = REAC_RESOLUTION * proto->deviceInfo->in_channels; const UInt32 bytesPerPacket = bytesPerSample * REAC_SAMPLES_PER_PACKET; if (inBufferSize != bytesPerPacket) { IOLog("REACConnection::filterCommandGateMsg(): Got incorrectly sized buffer (not the same as a packet).\n"); } else { MbufUtils::copyAudioFromMbufToBuffer(*data, sizeof(REACPacketHeader), inBufferSize, inBuffer); } } } } } if (REAC_SLAVE == proto->mode) { proto->getAndSendSamples(); } proto->lastCounter = packetHeader.getCounter(); }