/// <summary> /// FIN wait1 handler /// </summary> /// <param name="con"></param> /// <param name="buffer"></param> private unsafe static void finWaitOneHandler(TCPConnection con, byte *buffer) { TCPHeader *header = (TCPHeader *)buffer; /** * ACK received? */ if ((header->Flags & (FLAG_ACK)) > 0) { con.State = TCPConnectionState.FIN_WAIT2; con.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); } else if ((header->Flags & (FLAG_FIN)) > 0) { con.SequenceNumber = Byte.ReverseBytes(Byte.ReverseBytes(con.SequenceNumber) + 1); con.State = TCPConnectionState.CLOSING; con.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); SendPacket(con.IP, con.SequenceNumber, con.AcknowledgeNumber, con.InPort, con.DestPort, FLAG_FIN, null, 0); } else { // Failed? } }
/// <summary> /// Finish header and create checksum /// </summary> /// <param name="packet"></param> /// <param name="header"></param> /// <param name="sourceIp"></param> /// <param name="packetLength"></param> /// <param name="dataLength"></param> /// <returns></returns> private static unsafe bool FinishHeader(NetPacketDesc *packet, TCPHeader *header, byte[] sourceIp, int packetLength, int dataLength) { // Welp! if (packetLength % 4 != 0) { return(false); } header->Length = (byte)((packetLength / 4) << 4); ushort size = (ushort)packetLength; size += (ushort)sizeof(TCPChecksum); // Let's introduce some junk (i love that :)) TCPChecksum *checksumHeader = (TCPChecksum *)(packet->buffer + packet->start - sizeof(TCPChecksum)); Memory.Memcpy(checksumHeader->SrcIP, Network.Settings->IP, 4); Memory.Memcpy(checksumHeader->DstIP, Util.ObjectToVoidPtr(sourceIp), 4); checksumHeader->Protocol = PROTOCOL_TCP; checksumHeader->Reserved = 0; checksumHeader->Length = Byte.ReverseBytes((ushort)((ushort)packetLength + dataLength)); byte *ptr = packet->buffer + packet->start - sizeof(TCPChecksum); header->Checksum = NetworkTools.Checksum(ptr, size + dataLength); return(true); }
/// <summary> /// Reset connection /// </summary> /// <param name="con"></param> private unsafe static void Reset(TCPConnection con, byte *buffer) { TCPHeader *header = (TCPHeader *)buffer; con.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); SendPacket(con.IP, con.SequenceNumber, con.AcknowledgeNumber, con.InPort, con.DestPort, FLAG_RST | FLAG_ACK, null, 0); con.State = TCPConnectionState.CLOSED; }
/// <summary> /// TCP packet handler /// </summary> /// <param name="xid">Identification ID</param> /// <param name="buffer">Buffer pointer</param> /// <param name="size">Packet size</param> private static unsafe void handler(byte[] sourceIp, byte *buffer, uint size) { TCPHeader *header = (TCPHeader *)buffer; ushort dest = Byte.ReverseBytes(header->DestPort); if (m_connections[dest] != null) { handleConnection(m_connections[dest], sourceIp, buffer, size); } }
/// <summary> /// Add header to packet /// </summary> /// <param name="packet"></param> /// <param name="srcPort"></param> /// <param name="dstPort"></param> /// <param name="flags"></param> /// <param name="seqNum"></param> /// <param name="ackNum"></param> /// <param name="winSize"></param> /// <returns></returns> private static unsafe TCPHeader *addHeader(NetPacketDesc *packet, ushort srcPort, ushort dstPort, byte flags, uint seqNum, uint ackNum, ushort winSize) { packet->start -= (short)sizeof(TCPHeader); // Generate stub header TCPHeader *header = (TCPHeader *)(packet->buffer + packet->start); header->SourcePort = Byte.ReverseBytes(srcPort); header->DestPort = Byte.ReverseBytes(dstPort); header->Flags = flags; header->Urgent = 0; header->WindowSize = Byte.ReverseBytes(winSize); header->Acknowledge = ackNum; header->Sequence = seqNum; header->Checksum = 0; return(header); }
/// <summary> /// Established handler /// </summary> /// <param name="connection"></param> /// <param name="sourceIP"></param> /// <param name="buffer"></param> /// <param name="size"></param> private static unsafe void LastAckHandler(TCPConnection connection, byte[] sourceIP, byte *buffer, uint size) { TCPHeader *header = (TCPHeader *)buffer; /** * * Possible flags: * - PUSH * - FIN */ if ((header->Flags & FLAG_ACK) > 0) { connection.State = TCPConnectionState.TIME_WAIT; } else { } }
/// <summary> /// CLOSING handler /// </summary> /// <param name="con"></param> /// <param name="buffer"></param> private unsafe static void closingHandler(TCPConnection con, byte *buffer) { TCPHeader *header = (TCPHeader *)buffer; if ((header->Flags & (FLAG_ACK)) > 0) { con.SequenceNumber = Byte.ReverseBytes(Byte.ReverseBytes(con.SequenceNumber) + 1); con.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); // AND We're DONE! setConnectionForWait(con); } else { // Error handling? } }
/// <summary> /// FIN wait2 handler /// </summary> /// <param name="con"></param> /// <param name="buffer"></param> private unsafe static void finWaitTwoHandler(TCPConnection con, byte *buffer) { TCPHeader *header = (TCPHeader *)buffer; if ((header->Flags & (FLAG_FIN)) > 0) { con.SequenceNumber = Byte.ReverseBytes(Byte.ReverseBytes(con.SequenceNumber) + 1); con.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); SendPacket(con.IP, con.SequenceNumber, con.AcknowledgeNumber, con.InPort, con.DestPort, FLAG_ACK, null, 0); setConnectionForWait(con); } else { } }
/// <summary> /// Syn sent handler /// </summary> /// <param name="con"></param> /// <param name="buffer"></param> private unsafe static void SynSentHandler(TCPConnection con, byte *buffer) { TCPHeader *header = (TCPHeader *)buffer; if ((header->Flags & (FLAG_SYN | FLAG_ACK)) == (FLAG_SYN | FLAG_ACK)) { con.SequenceNumber = Byte.ReverseBytes(Byte.ReverseBytes(con.SequenceNumber) + 1); con.State = TCPConnectionState.ESTABLISHED; con.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); SendPacket(con.IP, con.SequenceNumber, Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1), con.InPort, con.DestPort, FLAG_ACK, null, 0); } else { // Failed? } }
/// <summary> /// Syn received /// </summary> /// <param name="con"></param> /// <param name="buffer"></param> private unsafe static void SynReceivedHandler(TCPConnection con, byte *buffer) { TCPHeader *header = (TCPHeader *)buffer; /** * ACK received? */ if ((header->Flags & (FLAG_ACK)) > 0) { con.SequenceNumber = Byte.ReverseBytes(Byte.ReverseBytes(con.SequenceNumber) + 1); con.State = TCPConnectionState.ESTABLISHED; /** * Do we need to notify we have a new connection? */ if (con.Type == TCPConnectionType.CHILD_CONNECTION) { /** * Put ACCEPT in queue */ TCPPacketDescriptor *buf = (TCPPacketDescriptor *)Heap.Alloc(sizeof(TCPPacketDescriptor)); buf->Size = 4; buf->Type = TCPPacketDescriptorTypes.ACCEPT; buf->Data = (byte *)Heap.Alloc(4); buf->xid = con.XID; for (int i = 0; i < 4; i++) { buf->Data[i] = con.IP[i]; } con.BaseConnection.ReceiveQueue.Push(buf); } } else { // Failed? } }
/// <summary> /// Send packet to TCP /// </summary> /// <param name="destIP"></param> /// <param name="seqNum"></param> /// <param name="acknumb"></param> /// <param name="srcPort"></param> /// <param name="destPort"></param> /// <param name="flags"></param> /// <param name="data"></param> /// <param name="count"></param> /// <returns></returns> private static unsafe bool SendPacket(byte[] destIP, uint seqNum, uint acknumb, ushort srcPort, ushort destPort, byte flags, byte *data, int count) { NetPacketDesc *packet = NetPacket.Alloc(); if (count > 0) { Memory.Memcpy(packet->buffer + packet->start, data, count); packet->end += (short)count; } TCPHeader *outHeader = addHeader(packet, srcPort, destPort, flags, seqNum, acknumb, 8192); FinishHeader(packet, outHeader, destIP, sizeof(TCPHeader), count); IPV4.Send(packet, destIP, PROTOCOL_TCP); NetPacket.Free(packet); return(true); }
/// <summary> /// Established handler /// </summary> /// <param name="connection"></param> /// <param name="sourceIP"></param> /// <param name="buffer"></param> /// <param name="size"></param> private static unsafe void EstablishedHandler(TCPConnection connection, byte[] sourceIP, byte *buffer, uint size) { TCPHeader *header = (TCPHeader *)buffer; /** * * Possible flags: * - PUSH * - FIN */ if ((header->Flags & (FLAG_FIN | FLAG_ACK)) == (FLAG_FIN | FLAG_ACK)) { connection.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); SendPacket(connection.IP, connection.SequenceNumber, Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1), connection.InPort, connection.DestPort, FLAG_ACK, null, 0); setConnectionForWait(connection); } else if ((header->Flags & FLAG_FIN) > 0) { /** * Todo: We need acknowledge our application here with status CLOSE_WAIT, for now we shift over to the LAST_ACK state */ connection.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); connection.State = TCPConnectionState.LAST_ACK; SendPacket(connection.IP, connection.SequenceNumber, Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1), connection.InPort, connection.DestPort, FLAG_ACK, null, 0); Sleep(300); SendPacket(connection.IP, connection.SequenceNumber, 0x00, connection.InPort, connection.DestPort, FLAG_FIN, null, 0); } if ((header->Flags & FLAG_PSH) > 0) { int sizePacket = (int)size - sizeof(TCPHeader); /** * Push packet in Queue */ TCPPacketDescriptor *buf = (TCPPacketDescriptor *)Heap.Alloc(sizeof(TCPPacketDescriptor)); buf->Size = sizePacket; buf->Type = TCPPacketDescriptorTypes.RECEIVE; buf->Data = (byte *)Heap.Alloc(sizePacket); buf->xid = connection.XID; Memory.Memcpy(buf->Data, buffer + sizeof(TCPHeader), sizePacket); Queue queue = connection.ReceiveQueue; /** * Is this a connection or a member? */ if (connection.Type != TCPConnectionType.CONNECTION) { queue = connection.BaseConnection.ReceiveQueue; } queue.Push(buf); connection.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + (uint)sizePacket); SendPacket(connection.IP, connection.SequenceNumber, connection.AcknowledgeNumber, connection.InPort, connection.DestPort, FLAG_ACK, null, 0); } else { } }
/// <summary> /// Listen state handler /// </summary> /// <param name="connection"></param> /// <param name="sourceIP"></param> /// <param name="buffer"></param> /// <param name="size"></param> private static unsafe void HandleListen(TCPConnection connection, byte[] sourceIP, byte *buffer, uint size) { TCPHeader *header = (TCPHeader *)buffer; ushort srcPort = header->SourcePort; long id = GenerateID(sourceIP, srcPort); TCPConnection clientConnection = (TCPConnection)connection.Clients.GetByKey(id); /** * Do we need to create a connection or just pass it though? */ if (clientConnection == null) { /** * We only handle SYN packets here! */ if ((header->Flags & FLAG_SYN) == 0) { //Close(connection); return; } /** * Add connection to clients list */ clientConnection = new TCPConnection(); clientConnection.XID = id; clientConnection.InPort = connection.InPort; clientConnection.DestPort = Byte.ReverseBytes(header->SourcePort); clientConnection.SequenceNumber = (uint)Random.Rand(); clientConnection.State = TCPConnectionState.SYN_RECEIVED; clientConnection.IP = new byte[4]; for (int i = 0; i < 4; i++) { clientConnection.IP[i] = sourceIP[i]; } clientConnection.AcknowledgeNumber = Byte.ReverseBytes(header->Acknowledge); clientConnection.Type = TCPConnectionType.CHILD_CONNECTION; clientConnection.Clients = connection.Clients; clientConnection.BaseConnection = connection; connection.Clients.Add(id, clientConnection); /** * Send SYN_ACK and transition to SYN_RECEIVED state */ clientConnection.SequenceNumber = Byte.ReverseBytes(Byte.ReverseBytes(connection.SequenceNumber) + 1); clientConnection.State = TCPConnectionState.SYN_RECEIVED; clientConnection.AcknowledgeNumber = Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1); SendPacket(clientConnection.IP, clientConnection.SequenceNumber, Byte.ReverseBytes(Byte.ReverseBytes(header->Sequence) + 1), clientConnection.InPort, clientConnection.DestPort, FLAG_SYN | FLAG_ACK, null, 0); } else { handleConnection(clientConnection, sourceIP, buffer, size); } }