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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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();
}