From 6b84ae08075d0e31c3a7440a478c5121199e17df Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 8 Nov 2011 02:14:58 +0100 Subject: [PATCH] TCP bug fix, TCP refactoring --- sys/net/destiny/socket.c | 72 ++++++++++++++++++++++++-- sys/net/destiny/socket.h | 4 ++ sys/net/destiny/tcp.c | 106 ++++++++++++++++++++++++++------------- 3 files changed, 141 insertions(+), 41 deletions(-) diff --git a/sys/net/destiny/socket.c b/sys/net/destiny/socket.c index a68a79057d..7e23fe6f7b 100644 --- a/sys/net/destiny/socket.c +++ b/sys/net/destiny/socket.c @@ -13,6 +13,38 @@ #include "socket.h" #include "sys/net/net_help/net_help.h" +void print_tcp_flags (tcp_hdr_t *tcp_header) + { + printf("FLAGS: "); + if ((tcp_header->reserved_flags & TCP_ACK) > 0) + { + printf("ACK "); + } + if ((tcp_header->reserved_flags & TCP_RST) > 0) + { + printf("RST "); + } + if ((tcp_header->reserved_flags & TCP_SYN) > 0) + { + printf("SYN "); + } + if ((tcp_header->reserved_flags & TCP_FIN) > 0) + { + printf("FIN "); + } + printf("\n\n"); + } + +void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) + { + printf("--- %s TCP packet: ---\n", (in_or_out == INC_PACKET ? "Incoming" : "Outgoing")); + ipv6_print_addr(&ipv6_header->srcaddr); + ipv6_print_addr(&ipv6_header->destaddr); + printf("Source Port: %i, Dest. Port: %i\n", tcp_header->src_port, tcp_header->dst_port); + printf("ACK: %li, SEQ: %li, Window: %i\n", tcp_header->ack_nr, tcp_header->seq_nr, tcp_header->window); + print_tcp_flags(tcp_header); + } + void print_socket(uint8_t socket) { socket_internal_t *current_socket_internal = &sockets[socket - 1]; @@ -271,6 +303,26 @@ void set_tcp_packet(tcp_hdr_t *tcp_hdr, uint16_t src_port, uint16_t dst_port, ui tcp_hdr->window = window; } +// Check for consistent ACK and SEQ number +// TODO: Use error codes for different kinds of inconsistency when needed! +int check_tcp_consistency(socket_t *current_tcp_socket, tcp_hdr_t *tcp_header) + { + if (IS_TCP_ACK(tcp_header->reserved_flags)) + { + if(tcp_header->ack_nr != (current_tcp_socket->local_tcp_status.seq_nr+1)) + { + // TODO: possible loss of a packet (MAYBE!) + return -1; + } + } + if (tcp_header->seq_nr <= current_tcp_socket->foreign_tcp_status.seq_nr) + { + // TODO: possible repetition of a packet or wrong order of arriving + return -1; + } + return 1; + } + int connect(int socket, sockaddr6_t *addr, uint32_t addrlen, uint8_t tcp_client_thread) { // Variables @@ -310,8 +362,6 @@ int connect(int socket, sockaddr6_t *addr, uint32_t addrlen, uint8_t tcp_client_ // Fill TCP SYN packet set_tcp_packet(current_tcp_packet, current_tcp_socket->local_address.sin6_port, current_tcp_socket->foreign_address.sin6_port, current_tcp_socket->local_tcp_status.seq_nr, 0, 0, TCP_SYN, current_tcp_socket->local_tcp_status.window, 0, 0); - printf("PORT orig: %i, PORT socket: %i\n", addr->sin6_port, current_tcp_socket->foreign_address.sin6_port); - printTCPHeader(current_tcp_packet); // Fill IPv6 Header memcpy(&(temp_ipv6_header->destaddr), ¤t_tcp_socket->foreign_address.sin6_addr, 16); memcpy(&(temp_ipv6_header->srcaddr), ¤t_tcp_socket->local_address.sin6_addr, 16); @@ -326,7 +376,13 @@ int connect(int socket, sockaddr6_t *addr, uint32_t addrlen, uint8_t tcp_client_ msg_receive(&msg_from_server); // Read packet content - tcp_hdr_t *tcp_header = ((tcp_hdr_t*)(msg_from_server.content.ptr+IPV6_HDR_LEN)); + tcp_hdr_t *tcp_header = ((tcp_hdr_t*)(buffer_tcp+IPV6_HDR_LEN)); + + // Check for consistency + if (check_tcp_consistency(current_tcp_socket, tcp_header) == -1) + { + printf("TCP packets not consistent!\n"); + } // Got SYN ACK from Server // Refresh foreign TCP socket information @@ -584,8 +640,14 @@ int handle_new_tcp_connection(socket_t *current_queued_socket, socket_internal_t ipv6_hdr_t *ipv6_header; tcp_hdr_t *tcp_header; - ipv6_header = ((ipv6_hdr_t*)(msg_recv_client_ack.content.ptr)); - tcp_header = ((tcp_hdr_t*)(msg_recv_client_ack.content.ptr)); + ipv6_header = ((ipv6_hdr_t*)(buffer_tcp)); + tcp_header = ((tcp_hdr_t*)(buffer_tcp+IPV6_HDR_LEN)); + + // Check for consistency + if (check_tcp_consistency(current_queued_socket, tcp_header) == -1) + { + printf("TCP packets not consistent!\n"); + } // Got ack, connection established, refresh local and foreign tcp socket status set_tcp_status(¤t_queued_socket->foreign_tcp_status, tcp_header->ack_nr, STATIC_MSS, tcp_header->seq_nr, ESTABLISHED, tcp_header->window); diff --git a/sys/net/destiny/socket.h b/sys/net/destiny/socket.h index 96b8c0a207..f2ad696254 100644 --- a/sys/net/destiny/socket.h +++ b/sys/net/destiny/socket.h @@ -113,6 +113,9 @@ #define STATIC_MSS 32 #define STATIC_WINDOW 32 +#define INC_PACKET 0 +#define OUT_PACKET 1 + typedef struct __attribute__ ((packed)) socka6 { uint8_t sin6_family; /* AF_INET6 */ @@ -161,5 +164,6 @@ void print_sockets(void); void print_socket(uint8_t socket); bool exists_socket(uint8_t socket); socket_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *socket); +void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header); #endif /* SOCKET_H_ */ diff --git a/sys/net/destiny/tcp.c b/sys/net/destiny/tcp.c index 4ba419cf37..7acfe7ae7f 100644 --- a/sys/net/destiny/tcp.c +++ b/sys/net/destiny/tcp.c @@ -51,9 +51,69 @@ uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) return (sum == 0) ? 0xffff : HTONS(sum); } +void handle_tcp_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket) + { + msg_t m_recv_tcp, m_send_tcp; + if (getWaitingConnectionSocket(tcp_socket->socket_id)->local_tcp_status.state == SYN_RCVD) + { + msg_send_receive(&m_send_tcp, &m_recv_tcp, tcp_socket->pid); + } + } + +void handle_tcp_rst_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket) + { + + } + +void handle_tcp_syn_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket) + { + msg_t m_send_tcp; + if (tcp_socket->in_socket.local_tcp_status.state == LISTEN) + { + socket_t *new_socket = new_tcp_queued_socket(ipv6_header, tcp_header, tcp_socket); + if (new_socket != NULL) + { + // notify socket function accept(..) that a new connection request has arrived + // No need to wait for an answer because the server accept() function isnt reading from anything other than the queued sockets + msg_send(&m_send_tcp, tcp_socket->pid, 0); + } + else + { + printf("Dropped TCP SYN Message because an error occured while requesting a new queued socket!\n"); + } + } + else + { + printf("Droppec TCP SYN Message because socket was not in state LISTEN!"); + } + } + +void handle_tcp_syn_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket) + { + msg_t m_recv_tcp, m_send_tcp; + if (tcp_socket->in_socket.local_tcp_status.state == SYN_SENT) + { + msg_send_receive(&m_send_tcp, &m_recv_tcp, tcp_socket->pid); + } + else + { + printf("Socket not in state SYN_SENT, dropping SYN-ACK-packet!"); + } + } + +void handle_tcp_fin_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket) + { + + } + +void handle_tcp_fin_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket) + { + + } + void tcp_packet_handler (void) { - msg_t m_recv_ip, m_send_ip, m_recv_tcp, m_send_tcp; + msg_t m_recv_ip, m_send_ip; ipv6_hdr_t *ipv6_header; tcp_hdr_t *tcp_header; uint8_t *payload; @@ -66,12 +126,14 @@ void tcp_packet_handler (void) ipv6_header = ((ipv6_hdr_t*)&buffer_tcp); tcp_header = ((tcp_hdr_t*)(&buffer_tcp[IPV6_HDR_LEN])); payload = &buffer_tcp[IPV6_HDR_LEN+TCP_HDR_LEN]; - printTCPHeader(tcp_header); + //printTCPHeader(tcp_header); chksum = tcp_csum(ipv6_header, tcp_header); printf("Checksum is %x!\n", chksum); tcp_socket = get_tcp_socket(ipv6_header, tcp_header); + print_tcp_status(INC_PACKET, ipv6_header, tcp_header); + if ((chksum == 0xffff) && (tcp_socket != NULL)) { // Remove reserved bits from tcp flags field @@ -83,69 +145,41 @@ void tcp_packet_handler (void) case TCP_ACK: { // only ACK Bit set - if (getWaitingConnectionSocket(tcp_socket->socket_id)->local_tcp_status.state == SYN_RCVD) - { - m_send_tcp.content.ptr = (char*)buffer; - m_send_tcp.content.value = IPV6_HDR_LEN + ipv6_header->length; - msg_send_receive(&m_recv_tcp, &m_send_tcp, tcp_socket->pid); - } + handle_tcp_ack_packet(ipv6_header, tcp_header, tcp_socket); break; } case TCP_RST: { printf("RST Bit set!\n"); // only RST Bit set + handle_tcp_rst_packet(ipv6_header, tcp_header, tcp_socket); break; } case TCP_SYN: { // only SYN Bit set, look for matching, listening socket and request new queued socket printf("SYN Bit set!\n"); - if (tcp_socket->in_socket.local_tcp_status.state == LISTEN) - { - socket_t *new_socket = new_tcp_queued_socket(ipv6_header, tcp_header, tcp_socket); - if (new_socket != NULL) - { - // notify socket function accept(..) that a new connection request has arrived - // No need to wait for an answer because the server accept() function isnt reading from anything other than the queued sockets - msg_send(&m_send_tcp, tcp_socket->pid, 0); - } - else - { - printf("Dropped TCP SYN Message because an error occured while requesting a new queued socket!\n"); - } - } - else - { - printf("Droppec TCP SYN Message because socket was not in state LISTEN!"); - } + handle_tcp_syn_packet(ipv6_header, tcp_header, tcp_socket); break; } case TCP_SYN_ACK: { // only SYN and ACK Bit set, complete three way handshake when socket in state SYN_SENT - if (tcp_socket->in_socket.local_tcp_status.state == SYN_SENT) - { - m_send_tcp.content.ptr = (char*)buffer; - m_send_tcp.content.value = IPV6_HDR_LEN + ipv6_header->length; - msg_send_receive(&m_recv_tcp, &m_send_tcp, tcp_socket->pid); - } - else - { - printf("Socket not in state SYN_SENT, dropping SYN-ACK-packet!"); - } + handle_tcp_syn_ack_packet(ipv6_header, tcp_header, tcp_socket); break; } case TCP_FIN: { printf("FIN Bit set!\n"); // only FIN Bit set + handle_tcp_fin_packet(ipv6_header, tcp_header, tcp_socket); break; } case TCP_FIN_ACK: { printf("FIN ACK Bit set!\n"); // only FIN and ACK Bit set + handle_tcp_fin_ack_packet(ipv6_header, tcp_header, tcp_socket); break; } default: