+ // If not a RST, send a RST
+ if( !(hdr->Flags & TCP_FLAG_RST) )
+ {
+ TCP_int_SendRSTTo(Interface, Address, Length, hdr);
+ }
+}
+
+void TCP_IPError(tInterface *Interface, tIPErrorMode Mode, const void *Address, int Length, const void *Buffer)
+{
+ if( Length < sizeof(tTCPHeader) ) return ;
+
+ const tTCPHeader *hdr = Buffer;
+
+ // TODO: Handle errors for server connections
+
+ for( tTCPConnection *conn = gTCP_OutbountCons; conn; conn = conn->Next )
+ {
+ if(conn->Interface != Interface)
+ continue;
+ if(conn->RemotePort != ntohs(hdr->SourcePort))
+ continue;
+ if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
+ continue ;
+
+ // Mark an error on the interface
+ VFS_MarkError(&conn->Node, 1);
+ return ;
+ }
+}
+
+/*
+ * Handle packets in LISTEN state
+ */
+int TCP_INT_HandleServerPacket(tInterface *Interface, tTCPListener *Server, const void *Address, tTCPHeader *Header, size_t Length)
+{
+ if( Header->Flags & TCP_FLAG_RST ) {
+ LOG("RST, ignore");
+ return 0;
+ }
+ else if( Header->Flags & TCP_FLAG_ACK ) {
+ LOG("ACK, send RST");
+ TCP_int_SendRSTTo(Interface, Address, Length, Header);
+ return 0;
+ }
+ else if( !(Header->Flags & TCP_FLAG_SYN) ) {
+ LOG("Other, ignore");
+ return 0;
+ }
+
+ Log_Log("TCP", "TCP_GetPacket: Opening Connection");
+
+ // TODO: Check security (a TCP Option)
+ // TODO: Check SEG.PRC
+ // TODO: Check for halfopen max
+
+ tTCPConnection *conn = TCP_int_CreateConnection(Interface, TCP_ST_SYN_RCVD);
+ conn->LocalPort = Server->Port;
+ conn->RemotePort = ntohs(Header->SourcePort);
+
+ switch(Interface->Type)
+ {
+ case 4: conn->RemoteIP.v4 = *(tIPv4*)Address; break;
+ case 6: conn->RemoteIP.v6 = *(tIPv6*)Address; break;
+ default: ASSERTC(Interface->Type,==,4); return 0;
+ }
+
+ conn->NextSequenceRcv = ntohl( Header->SequenceNumber ) + 1;
+ conn->HighestSequenceRcvd = conn->NextSequenceRcv;
+ conn->NextSequenceSend = rand();
+ conn->LastACKSequence = ntohl( Header->SequenceNumber );
+
+ conn->Node.ImplInt = Server->NextID ++;
+ conn->Node.Size = -1;
+
+ // Hmm... Theoretically, this lock will never have to wait,
+ // as the interface is locked to the watching thread, and this
+ // runs in the watching thread. But, it's a good idea to have
+ // it, just in case
+ // Oh, wait, there is a case where a wildcard can be used
+ // (Server->Interface == NULL) so having the lock is a good idea
+ SHORTLOCK(&Server->lConnections);
+ conn->Server = Server;
+ conn->Prev = Server->ConnectionsTail;
+ if(Server->Connections) {
+ ASSERT(Server->ConnectionsTail);
+ Server->ConnectionsTail->Next = conn;
+ }
+ else {
+ ASSERT(!Server->ConnectionsTail);
+ Server->Connections = conn;
+ }
+ Server->ConnectionsTail = conn;
+ if(!Server->NewConnections)
+ Server->NewConnections = conn;
+ VFS_MarkAvaliable( &Server->Node, 1 );
+ SHORTREL(&Server->lConnections);
+ Semaphore_Signal(&Server->WaitingConnections, 1);
+
+ // Send the SYN ACK
+ Header->Flags = TCP_FLAG_ACK|TCP_FLAG_SYN;
+ Header->AcknowlegementNumber = htonl(conn->NextSequenceRcv);
+ Header->SequenceNumber = htonl(conn->NextSequenceSend);
+ Header->DestPort = Header->SourcePort;
+ Header->SourcePort = htons(Server->Port);
+ Header->DataOffset = (sizeof(tTCPHeader)/4) << 4;
+ TCP_SendPacket( conn, Header, 0, NULL );
+ conn->NextSequenceSend ++;
+ return 0;