TCP bug fix, TCP refactoring

This commit is contained in:
Oliver 2011-11-08 02:14:58 +01:00
parent 7d1f607f0f
commit 6b84ae0807
3 changed files with 141 additions and 41 deletions

View File

@ -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), &current_tcp_socket->foreign_address.sin6_addr, 16);
memcpy(&(temp_ipv6_header->srcaddr), &current_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(&current_queued_socket->foreign_tcp_status, tcp_header->ack_nr, STATIC_MSS, tcp_header->seq_nr, ESTABLISHED, tcp_header->window);

View File

@ -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_ */

View File

@ -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: