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; }
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); }
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); }