TCP bug fix, TCP refactoring
This commit is contained in:
parent
7d1f607f0f
commit
6b84ae0807
@ -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);
|
||||
|
||||
@ -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_ */
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user