Ejemplo n.º 1
0
gssize udp_receiveUserData(UDP* udp, gpointer buffer, gsize nBytes, in_addr_t* ip, in_port_t* port) {
	MAGIC_ASSERT(udp);

	Packet* packet = socket_removeFromInputBuffer((Socket*)udp);
	if(!packet) {
		return -1;
	}

	/* copy lesser of requested and available amount to application buffer */
	guint packetLength = packet_getPayloadLength(packet);
	gsize copyLength = MIN(nBytes, packetLength);
	guint bytesCopied = packet_copyPayload(packet, 0, buffer, copyLength);

	utility_assert(bytesCopied == copyLength);
	packet_addDeliveryStatus(packet, PDS_RCV_SOCKET_DELIVERED);

	/* fill in address info */
	if(ip) {
		*ip = packet_getSourceIP(packet);
	}
	if(port) {
		*port = packet_getSourcePort(packet);
	}

	/* destroy packet, throwing away any bytes not claimed by the app */
	packet_unref(packet);

	/* update the tracker output buffer stats */
	Tracker* tracker = host_getTracker(worker_getCurrentHost());
	Socket* socket = (Socket* )udp;
	Descriptor* descriptor = (Descriptor *)socket;
	gsize outLength = socket_getOutputBufferLength(socket);
	gsize outSize = socket_getOutputBufferSize(socket);
	tracker_updateSocketOutputBuffer(tracker, descriptor->handle, outLength, outSize);

	debug("user read %u inbound UDP bytes", bytesCopied);

	return (gssize)bytesCopied;
}
Ejemplo n.º 2
0
void pcapwriter_writePacket(PCapWriter* pcap, Packet* packet) {
    if(!pcap || !pcap->pcapFile || !packet) {
        return;
    }

    guint32 ts_sec;         /* timestamp seconds */
    guint32 ts_usec;        /* timestamp microseconds */
    guint32 incl_len;       /* number of octets of packet saved in file */
    guint32 orig_len;       /* actual length of packet */

    /* get the current time that the packet is being sent/received */
    SimulationTime now = worker_getCurrentTime();
    ts_sec = now / SIMTIME_ONE_SECOND;
    ts_usec = (now % SIMTIME_ONE_SECOND) / SIMTIME_ONE_MICROSECOND;

    /* get the header and payload lengths */
    guint headerSize = packet_getHeaderSize(packet);
    guint payloadLength = packet_getPayloadLength(packet);
    incl_len = headerSize + payloadLength;
    orig_len = headerSize + payloadLength;

    /* get the TCP header and the payload */
    PacketTCPHeader tcpHeader;
    guchar *payload = g_new0(guchar, payloadLength);
    packet_getTCPHeader(packet, &tcpHeader);
    packet_copyPayload(packet, 0, payload, payloadLength);

    /* write the PCAP packet header to the pcap file */
    fwrite(&ts_sec, sizeof(ts_sec), 1, pcap->pcapFile);
    fwrite(&ts_usec, sizeof(ts_usec), 1, pcap->pcapFile);
    fwrite(&incl_len, sizeof(incl_len), 1, pcap->pcapFile);
    fwrite(&orig_len, sizeof(orig_len), 1, pcap->pcapFile);

    /* write the ethernet header */
    guint8 destinationMAC[6] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB};
    guint8 sourceMAC[6] = {0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6};
    guint16 type = htons(0x0800);

    fwrite(destinationMAC, 1, sizeof(destinationMAC), pcap->pcapFile);
    fwrite(sourceMAC, 1, sizeof(sourceMAC), pcap->pcapFile);
    fwrite(&type, 1, sizeof(type), pcap->pcapFile);

    /* write the IP header */
    guint8 versionAndHeaderLength = 0x45;
    guint8 fields = 0x00;
    guint16 totalLength = htons(orig_len - 14);
    guint16 identification = 0x0000;
    guint16 flagsAndFragment = 0x0040;
    guint8 timeToLive = 64;
    guint8 protocol = 6;  /* TCP */
    guint16 headerChecksum = 0x0000;
    guint32 sourceIP = tcpHeader.sourceIP;
    guint32 destinationIP = tcpHeader.destinationIP;

    fwrite(&versionAndHeaderLength, 1, sizeof(versionAndHeaderLength), pcap->pcapFile);
    fwrite(&fields, 1, sizeof(fields), pcap->pcapFile);
    fwrite(&totalLength, 1, sizeof(totalLength), pcap->pcapFile);
    fwrite(&identification, 1, sizeof(identification), pcap->pcapFile);
    fwrite(&flagsAndFragment, 1, sizeof(flagsAndFragment), pcap->pcapFile);
    fwrite(&timeToLive, 1, sizeof(timeToLive), pcap->pcapFile);
    fwrite(&protocol, 1, sizeof(protocol), pcap->pcapFile);
    fwrite(&headerChecksum, 1, sizeof(headerChecksum), pcap->pcapFile);
    fwrite(&sourceIP, 1, sizeof(sourceIP), pcap->pcapFile);
    fwrite(&destinationIP, 1, sizeof(destinationIP), pcap->pcapFile);


    /* write the TCP header */
    guint16 sourcePort = tcpHeader.sourcePort;
    guint16 destinationPort = tcpHeader.destinationPort;
    guint32 sequence = tcpHeader.sequence;
    guint32 acknowledgement = 0;
    if(tcpHeader.flags & PTCP_ACK) {
        acknowledgement = htonl(tcpHeader.acknowledgment);
    }
    guint8 headerLength = 0x80;
    guint8 tcpFlags = 0;
    if(tcpHeader.flags & PTCP_RST) tcpFlags |= 0x04;
    if(tcpHeader.flags & PTCP_SYN) tcpFlags |= 0x02;
    if(tcpHeader.flags & PTCP_ACK) tcpFlags |= 0x10;
    if(tcpHeader.flags & PTCP_FIN) tcpFlags |= 0x01;
    guint16 window = tcpHeader.window;
    guint16 tcpChecksum = 0x0000;
    guint8 options[14] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    fwrite(&sourcePort, 1, sizeof(sourcePort), pcap->pcapFile);
    fwrite(&destinationPort, 1, sizeof(destinationPort), pcap->pcapFile);
    fwrite(&sequence, 1, sizeof(sequence), pcap->pcapFile);
    fwrite(&acknowledgement, 1, sizeof(acknowledgement), pcap->pcapFile);
    fwrite(&headerLength, 1, sizeof(headerLength), pcap->pcapFile);
    fwrite(&tcpFlags, 1, sizeof(tcpFlags), pcap->pcapFile);
    fwrite(&window, 1, sizeof(window), pcap->pcapFile);
    fwrite(&tcpChecksum, 1, sizeof(tcpChecksum), pcap->pcapFile);
    fwrite(options, 1, sizeof(options), pcap->pcapFile);

    /* write payload data */
    if(payloadLength > 0) {
        fwrite(payload, 1, payloadLength, pcap->pcapFile);
    }

    g_free(payload);
}
Ejemplo n.º 3
0
gssize tcp_receiveUserData(TCP* tcp, gpointer buffer, gsize nBytes, in_addr_t* ip, in_port_t* port) {
	MAGIC_ASSERT(tcp);

	/*
	 * TODO
	 * We call descriptor_adjustStatus too many times here, to handle the readable
	 * state of the socket at times when we have a partially read packet. Consider
	 * adding a required hook for socket subclasses so the socket layer can
	 * query TCP for readability status.
	 */

	/* make sure we pull in all readable user data */
	_tcp_flush(tcp);

	gsize remaining = nBytes;
	gsize bytesCopied = 0;
	gsize totalCopied = 0;
	gsize offset = 0;
	gsize copyLength = 0;

	/* check if we have a partial packet waiting to get finished */
	if(remaining > 0 && tcp->partialUserDataPacket) {
		guint partialLength = packet_getPayloadLength(tcp->partialUserDataPacket);
		guint partialBytes = partialLength - tcp->partialOffset;
		g_assert(partialBytes > 0);

		copyLength = MIN(partialBytes, remaining);
		bytesCopied = packet_copyPayload(tcp->partialUserDataPacket, tcp->partialOffset, buffer, copyLength);
		totalCopied += bytesCopied;
		remaining -= bytesCopied;
		offset += bytesCopied;

		if(bytesCopied >= partialBytes) {
			/* we finished off the partial packet */
			packet_unref(tcp->partialUserDataPacket);
			tcp->partialUserDataPacket = NULL;
			tcp->partialOffset = 0;
		} else {
			/* still more partial bytes left */
			tcp->partialOffset += bytesCopied;
			g_assert(remaining == 0);
		}
	}

	while(remaining > 0) {
		/* if we get here, we should have read the partial packet above, or
		 * broken out below */
		g_assert(tcp->partialUserDataPacket == NULL);
		g_assert(tcp->partialOffset == 0);

		/* get the next buffered packet - we'll always need it.
		 * this could mark the socket as unreadable if this is its last packet.*/
		Packet* packet = socket_removeFromInputBuffer((Socket*)tcp);
		if(!packet) {
			/* no more packets or partial packets */
			break;
		}

		guint packetLength = packet_getPayloadLength(packet);
		copyLength = MIN(packetLength, remaining);
		bytesCopied = packet_copyPayload(packet, 0, buffer + offset, copyLength);
		totalCopied += bytesCopied;
		remaining -= bytesCopied;
		offset += bytesCopied;

		if(bytesCopied < packetLength) {
			/* we were only able to read part of this packet */
			tcp->partialUserDataPacket = packet;
			tcp->partialOffset = bytesCopied;
			break;
		}

		/* we read the entire packet, and are now finished with it */
		packet_unref(packet);
	}

	/* now we update readability of the socket */
	if((tcp->super.inputBufferLength > 0) || (tcp->partialUserDataPacket != NULL)) {
		/* we still have readable data */
		descriptor_adjustStatus(&(tcp->super.super.super), DS_READABLE, TRUE);
	} else {
		/* all of our ordered user data has been read */
		if((tcp->unorderedInputLength == 0) && (tcp->error & TCPE_RECEIVE_EOF)) {
			/* there is no more unordered data either, and we need to signal EOF */
			if(totalCopied > 0) {
				/* we just received bytes, so we can't EOF until the next call.
				 * make sure we stay readable so we DO actually EOF the socket */
				descriptor_adjustStatus(&(tcp->super.super.super), DS_READABLE, TRUE);
			} else {
				/* OK, no more data and nothing just received. */
				if(tcp->flags & TCPF_EOF_SIGNALED) {
					/* we already signaled close, now its an error */
					return -2;
				} else {
					/* we have not signaled close, do that now and close out the socket */
					_tcp_endOfFileSignalled(tcp);
					return 0;
				}
			}
		} else {
			/* our socket still has unordered data or is still open, but empty for now */
			descriptor_adjustStatus(&(tcp->super.super.super), DS_READABLE, FALSE);
		}
	}

	debug("%s <-> %s: receiving %lu user bytes", tcp->super.boundString, tcp->super.peerString, totalCopied);

	return (gssize) (totalCopied == 0 ? -1 : totalCopied);
}