From owner-p4-projects@FreeBSD.ORG Wed Jun 27 15:06:28 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 07B5616A46B; Wed, 27 Jun 2007 15:06:28 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id B0EB116A468 for ; Wed, 27 Jun 2007 15:06:27 +0000 (UTC) (envelope-from taleks@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id A1C3B13C44B for ; Wed, 27 Jun 2007 15:06:27 +0000 (UTC) (envelope-from taleks@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l5RF6Rkn052190 for ; Wed, 27 Jun 2007 15:06:27 GMT (envelope-from taleks@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l5RF6R0I052187 for perforce@freebsd.org; Wed, 27 Jun 2007 15:06:27 GMT (envelope-from taleks@FreeBSD.org) Date: Wed, 27 Jun 2007 15:06:27 GMT Message-Id: <200706271506.l5RF6R0I052187@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to taleks@FreeBSD.org using -f From: Alexey Tarasov To: Perforce Change Reviews Cc: Subject: PERFORCE change 122406 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Jun 2007 15:06:28 -0000 http://perforce.freebsd.org/chv.cgi?CH=122406 Change 122406 by taleks@taleks_th on 2007/06/27 15:06:11 Main changes are done to TCP related module. Due to rather big number of lines and functions it is divided in three modules: connection, tcp and segment module. tcp module contains rewritten to be more compliant to RFC 793 callback function and state handlers. This module task now is to dispatch packets to coorect connection and send confirmation/system packets using segments module. connection module is responsible for establishing and breaking communcation. It's task to work with pxe_tcp_connection objects. segment module - organizes creating of segment, checking of acked segments, resending of segments including some memory managment for this purposes. Other updates: added sending mss option, some macro are moved to other headers, cosmetic changes to comments. Affected files ... .. //depot/projects/soc2007/taleks-pxe_http/Makefile#7 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_buffer.h#3 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#1 add .. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.h#1 add .. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#16 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#13 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_ip.h#6 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.c#1 add .. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.h#1 add .. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#8 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#3 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.h#5 edit Differences ... ==== //depot/projects/soc2007/taleks-pxe_http/Makefile#7 (text+ko) ==== @@ -3,8 +3,9 @@ LIB= pxe_http INTERNALLIB= -SRCS= pxe_conv.c pxe_isr.S pxe_mem.c pxe_buffer.c pxe_sock.c pxe_await.c pxe_arp.c pxe_ip.c pxe_mutex.c \ - pxe_core.c pxe_icmp.c pxe_udp.c pxe_filter.c pxe_dns.c pxe_dhcp.c +SRCS= pxe_conv.c pxe_isr.S pxe_mem.c pxe_buffer.c pxe_await.c pxe_arp.c pxe_ip.c pxe_mutex.c \ + pxe_core.c pxe_icmp.c pxe_udp.c pxe_filter.c pxe_dns.c pxe_dhcp.c pxe_segment.c pxe_tcp.c pxe_sock.c \ + pxe_connection.c CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../btx/lib \ -I${.CURDIR}/../../../contrib/dev/acpica \ @@ -13,7 +14,7 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/ #debug flag -#CFLAGS+= -DPXE_DEBUG +CFLAGS+= -DPXE_DEBUG #CFLAGS+= -DPXE_DEBUG_HELL .include ==== //depot/projects/soc2007/taleks-pxe_http/pxe_buffer.h#3 (text+ko) ==== @@ -3,6 +3,10 @@ #include +/* buffer size choosed by default for sending/recieving*/ +#define PXE_DEFAULT_RECV_BUFSIZE 8192 +#define PXE_DEFAULT_SEND_BUFSIZE 4096 + /* pxe_buffer - buffer related information */ typedef struct pxe_buffer { ==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#16 (text+ko) ==== @@ -1009,3 +1009,19 @@ core_ips[id].ip = new_ip; } } + +/* pxe_get_secs() - returns time in seconds + * in: + * none + * out: + * elapsed time in seconds + */ +time_t +pxe_get_secs() +{ + time_t secs; + + time(&secs); + + return (secs); +} ==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#13 (text+ko) ==== @@ -1,6 +1,7 @@ #ifndef PXE_CORE_H_INCLUDED #define PXE_CORE_H_INCLUDED +#include #include #include @@ -119,4 +120,7 @@ uint32_t pxe_get_ip32(uint8_t id); void pxe_set_ip32(uint8_t id, uint32_t ip); +/* returns time in seconds */ +time_t pxe_get_secs(); + #endif // PXE_CORE_H_INCLUDED ==== //depot/projects/soc2007/taleks-pxe_http/pxe_ip.h#6 (text+ko) ==== @@ -26,6 +26,16 @@ uint32_t dst_ip; /* destination ip address */ } __packed PXE_IP_HDR; +/* pseudo header, used in checksum calculation for UDP and TCP */ +typedef struct pxe_ip4_pseudo_hdr { + + uint32_t src_ip; /* source ip */ + uint32_t dst_ip; /* destination ip */ + uint8_t zero; /* filled by zero */ + uint8_t proto; /* protocol */ + uint16_t length; /* length (protocol header + data) */ +} __packed PXE_IP4_PSEUDO_HDR; + /* IPv4 address */ typedef struct pxe_ipaddr { union { ==== //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#8 (text+ko) ==== @@ -7,12 +7,7 @@ #include "pxe_buffer.h" #include "pxe_filter.h" #include "pxe_ip.h" -/* buffer size choosed by default for sending/recieving*/ -#define PXE_DEFAULT_RECV_BUFSIZE 8192 -#define PXE_DEFAULT_SEND_BUFSIZE 2048 -/* minimal and max packet sizes to optimize tcp usage*/ -#define PXE_MIN_SEND_PACKET_SIZE 512 -#define PXE_MTU 1500 + /* default count of sockets used at the same time */ #define PXE_DEFAULT_SOCKETS 8 /* default count of waiting queue */ ==== //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#3 (text+ko) ==== @@ -1,27 +1,23 @@ #include #include "pxe_await.h" +#include "pxe_connection.h" #include "pxe_conv.h" #include "pxe_core.h" #include "pxe_filter.h" #include "pxe_ip.h" -#include "pxe_sock.h" #include "pxe_tcp.h" /* state handle functions */ -static int tcp_syn_sent(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); -static int tcp_established(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); -static int tcp_fin_wait1(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); -static int tcp_closing(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); -static int tcp_fin_wait2(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); -static int tcp_time_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); -static int tcp_close_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); -static int tcp_last_ack(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection); +static int tcp_syn_sent(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); +static int tcp_established(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); +static int tcp_fin_wait1(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); +static int tcp_closing(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); +static int tcp_fin_wait2(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); +static int tcp_time_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); +static int tcp_close_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); +static int tcp_last_ack(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen); -/* connection structs storage */ -static PXE_TCP_CONNECTION tcp_connections[PXE_MAX_TCP_CONNECTIONS]; -/* currently allocated connections */ -static int all_connections = 0; /* pointers to appropriate state handlers */ static pxe_tcp_state_func state_functions[PXE_TCP_ALL_STATES] = { NULL, /* PXE_TCP_CLOSED */ @@ -36,135 +32,300 @@ tcp_time_wait, /* PXE_TCP_TIME_WAIT */ }; -/* filter_to_connection() - returns connections, associated with provided filter +/* check_time_to_die() - moves to CLOSED state connections from state + * TIME_WAIT if last received packet (ACK for FIN in most cases) + * was more than 2*MSL time ago. * in: - * filter - pointer to filter entry structure, for which connection is searched + * connection - connection to check * out: - * NULL - failed to find - * not NULL- searched connections + * none */ -static PXE_TCP_CONNECTION * -filter_to_connection(PXE_FILTER_ENTRY *filter) +static void +check_time_to_die(PXE_TCP_CONNECTION *connection) { - int con_index = 0; - - for ( ; con_index < PXE_MAX_TCP_CONNECTIONS; ++con_index) { + /* if connection in other states - do nothing */ + if (connection->state != PXE_TCP_TIME_WAIT) + return; + + time_t cur_time = pxe_get_secs(); - if (tcp_connections[con_index].filter == filter) { - return (&tcp_connections[con_index]); - } + if (cur_time - connection->last_recv > 2 * PXE_TCP_MSL) { + /* release filter */ + PXE_FILTER_ENTRY *filter = connection->filter; + + if (filter != NULL) /* it must always be non NULL */ + pxe_filter_remove(filter); + + /* release connection */ + free_connection(connection); } +} - return (NULL); +/* tcp_send_rst_for() - sends RST in reply to provided packet + * in: + * tcp_packet - packet which caused RST sending + * out: + * 0 - failed + * 1 - success + */ +static int +tcp_send_rst_for(PXE_TCP_PACKET *tcp_packet, uint32_t ack, uint32_t seq, uint8_t flags, uint16_t seglen) +{ + PXE_TCP_CONNECTION connection; + pxe_memset(&connection, 0, sizeof(PXE_TCP_CONNECTION)); + + connection.dst_port = tcp_packet->tcphdr.src_port; + connection.src_port = tcp_packet->tcphdr.dst_port; + connection.dst_ip = tcp_packet->iphdr.src_ip; + + connection.next_recv = seq + seglen; /* acking */ + connection.next_send = ack; /* next send */ + + return pxe_tcp_send(&connection, 0, flags); } -/* alloc_connection() - returns pointer to free connection structure +/* tcp_is_acceptable() - first check for SYN_RECEIVED, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, + * CLOSE_WAIT, CLOSING, LAST_ACK, TIME_WAIT states * in: - * none + * connection - connection for which packet received + * tcp_packet - received packet + * seglen - segment length * out: - * NULL - failed to alloc - * non NULL- pointer to allocated structure + * 0 - not acceptable + * 1 - acceptable */ -PXE_TCP_CONNECTION * -alloc_connection() +int +tcp_is_acceptable(PXE_TCP_CONNECTION *connection, PXE_TCP_PACKET *tcp_packet, uint16_t seglen) { - if (all_connections == PXE_MAX_TCP_CONNECTIONS) - return (NULL); - - uint16_t index = 0; + uint16_t window = connection->recv->bufleft; + uint32_t seq = tcp_packet->tcphdr.sequence; - for ( ; index < PXE_MAX_TCP_CONNECTIONS; ++index) { + if (seglen == 0) { - if (tcp_connections[index].state == PXE_TCP_CLOSED) { - /* if state is closed, it's free structure*/ - all_connections += 1; - return &tcp_connections[index]; + if (window == 0) { + if (seq == connection->next_recv) + return (1); } + + if (connection->next_recv > seq) + return (0); + + if (seq < connection->next_recv + window) + return (1); + + } else { /* segment size > 0 */ + + if (window == 0) + return (0); + + if ((connection->next_recv <= seq) && + (seq < connection->next_recv + window) ) + return (1); + + /* or? */ + if ((connection->next_recv <= seq + seglen - 1) && + (seq +seglen -1 < connection->next_recv + window) ) + return (1); } - /* NOTE: we must not ever get here */ - return (NULL); + return (0); +} + +/* tcp checks has same numbers as in RFC 793, page 65+ */ + +/* tcp_check_1() - check if packet is acceptable, sends ACK if not + * in: + * connection - connection for which packet received + * tcp_packet - received packet + * seglen - segment length + * out: + * 0 - not acceptable + * 1 - acceptable + */ +static int +tcp_check_1(PXE_TCP_CONNECTION *connection, PXE_TCP_PACKET *tcp_packet, uint16_t seglen) +{ + if (tcp_is_acceptable(connection, tcp_packet, seglen)) { + return (1); + } + + pxe_tcp_send(connection, 0, PXE_TCP_ACK); + +#ifdef PXE_DEBUG_HELL + printf("tcp_check_1(): failed\n"); +#endif + return (0); } -/* free_connection() - releases connections +/* tcp_check_2() - check if packet has RST flag * in: - * connection - pointer to connection to release (assuming it's valid connection) + * tcp_packet - received packet * out: - * none + * 0 - not have + * 1 - have */ -void -free_connection(PXE_TCP_CONNECTION *connection) +static int +tcp_check_2(PXE_TCP_PACKET *tcp_packet) { + if (tcp_packet->tcphdr.flags & PXE_TCP_RST) + return (1); - connection->state = PXE_TCP_CLOSED; - all_connections -= 1; +#ifdef PXE_DEBUG_HELL + printf("tcp_check_2(): failed\n"); +#endif + return (0); +} + +/* tcp_check_3() - check precedence + * in: + * connection - connection for which packet received + * tcp_packet - received packet + * out: + * 0 - failed + * 1 - precedence ok + */ +static int +tcp_check_3(PXE_TCP_CONNECTION *connection, PXE_TCP_PACKET *tcp_packet) +{ + /* TODO?: implement */ + return (1); } -/* get_secs() - returns time in seconds +/* tcp_check_4() - check if packet has SYN flag and sends RST * in: - * none + * connection - connection for which packet received + * tcp_packet - received packet + * seglen - segment length * out: - * elapsed time in seconds + * 0 - not have + * 1 - have */ -static time_t -get_secs() +static int +tcp_check_4(PXE_TCP_CONNECTION *connection, PXE_TCP_PACKET *tcp_packet, uint16_t seglen) { - time_t secs; - time(&secs); + if ( (tcp_packet->tcphdr.flags & PXE_TCP_SYN) == 0) { +#ifdef PXE_DEBUG_HELL + printf("tcp_check_4(): failed\n"); +#endif + return (0); + } + + tcp_send_rst_for(tcp_packet, 0, connection->next_send, PXE_TCP_RST, seglen); - return (secs); + return (1); } -/* check_time_to_die() - moves to CLOSED state connections from state - * TIME_WAIT if last received packet (ACK for FIN in most cases) - * was more than 2*MSL time ago. +/* tcp_check_5() - check if packet has ACK flag * in: - * connection - connection to check + * connection - connection for which packet received + * tcp_packet - received packet * out: - * none + * 0 - not have + * 1 - have */ -static void -check_time_to_die(PXE_TCP_CONNECTION *connection) +static int +tcp_check_5(PXE_TCP_CONNECTION *connection, PXE_TCP_PACKET *tcp_packet) { - /* if connection in other states - do nothing */ - if (connection->state != PXE_TCP_TIME_WAIT) - return; + if ((tcp_packet->tcphdr.flags & PXE_TCP_ACK) == 0) { +#ifdef PXE_DEBUG_HELL + printf("tcp_check_5(): failed\n"); +#endif + return (0); + } - time_t cur_time = get_secs(); + uint32_t ack = tcp_packet->tcphdr.ack_next; + + if (ack > connection->next_send) { /* acked something, that was not sent */ +#ifdef PXE_DEBUG_HELL + printf("tcp_check_5(): acked %d, but nxt_snd = %d. Check failed\n", ack, connection->next_send); +#endif + pxe_tcp_send(connection, 0, PXE_TCP_ACK); + return (0); + } + +/* printf("tcp_check_5(): una = %d, ack = %d\n", connection->una, ack); + if ( connection->una < ack) { */ + connection->una = ack; + pxe_resend_update(connection); +/* } else { /* ignore dublicate packet */ +/* #ifdef PXE_DEBUG + printf("tcp_check_5(): failed\n"); +#endif + return (0); + } +*/ + + connection->remote_window = tcp_packet->tcphdr.window_size; + + return (1); +} + +/* tcp_check_6() - check if packet has URG flag + * in: + * tcp_packet - received packet + * out: + * 0 - not have + * 1 - have + */ +static int +tcp_check_6(PXE_TCP_PACKET *tcp_packet) +{ + if (tcp_packet->tcphdr.flags & PXE_TCP_URG) + return (1); + +#ifdef PXE_DEBUG + printf("tcp_check_6(): failed\n"); +#endif + return (0); +} - if (cur_time - connection->last_recv > 2 * PXE_TCP_MSL) { - /* release filter */ - PXE_FILTER_ENTRY *filter = connection->filter; - - if (filter != NULL) /* it must always be non NULL */ - pxe_filter_remove(filter); - - /* release connection */ - free_connection(connection); +/* tcp_process_7() - processes data and sends ACK + * in: + * connection - connection for which packet received + * tcp_packet - received packet + * seglen - segment length + * out: + * 0 - not have + * 1 - have + */ +static void +tcp_process_7(PXE_TCP_CONNECTION *connection, PXE_TCP_PACKET *tcp_packet, uint16_t seglen) +{ + connection->next_recv += seglen; + + if (seglen == 0 ) + connection->next_recv += 1; + +#ifdef PXE_DEBUG + printf("tcp_process_7(): ack = %d, seq = %d, seglen = %d\n", connection->next_recv, connection->next_send, seglen); +#endif + if (seglen > 0) { + /* write data to buffer */ + void *data = ((void *)tcp_packet) + sizeof(PXE_IP_HDR) + 4 * (tcp_packet->tcphdr.data_off >> 4); + pxe_buffer_write(connection->recv, data, seglen); } + + pxe_tcp_send(connection, 0, PXE_TCP_ACK); + connection->last_recv = pxe_get_secs(); } -/* tcp_send_rst_for() - sends RST in reply to provided packet +/* tcp_check_8() - check if packet has FIN flag * in: - * tcp_packet - packet which caused RST sending + * tcp_packet - received packet * out: - * 0 - failed - * 1 - success + * 0 - not have + * 1 - have */ static int -tcp_send_rst_for(PXE_TCP_PACKET *tcp_packet) +tcp_check_8(PXE_TCP_PACKET *tcp_packet) { - PXE_TCP_CONNECTION connection; - pxe_memset(&connection, 0, sizeof(PXE_TCP_CONNECTION)); - - connection.dst_port = le2be16(tcp_packet->tcphdr.src_port); - connection.src_port = le2be16(tcp_packet->tcphdr.dst_port); - connection.dst_ip = tcp_packet->iphdr.src_ip; - connection.next_recv = le2be32(tcp_packet->tcphdr.sequence) + 1; - connection.next_send = le2be32(tcp_packet->tcphdr.ack_next); - - return pxe_tcp_send(&connection, 0, PXE_TCP_RST | PXE_TCP_ACK); + if (tcp_packet->tcphdr.flags & PXE_TCP_FIN) + return (1); +#ifdef PXE_DEBUG + printf("tcp_check_8(): failed\n"); +#endif + return (0); } /* tcp_syn_sent() - SYN_SENT state handler @@ -177,34 +338,81 @@ * 2 - try next state handler */ static int -tcp_syn_sent(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection) +tcp_syn_sent(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen) { - uint8_t flags = tcp_packet->tcphdr.flags; + uint8_t flags = tcp_packet->tcphdr.flags; + uint32_t ack = tcp_packet->tcphdr.ack_next; + uint32_t seq = tcp_packet->tcphdr.sequence; + int acceptable = 1; - /* accepting only SYN+ACK */ - if ( (flags & (PXE_TCP_SYN | PXE_TCP_ACK)) - != (PXE_TCP_SYN | PXE_TCP_ACK)) - { - return (0); /* drop, may be better RST */ - } + /* first check */ + if ( flags & PXE_TCP_ACK) { + + if ( (ack <= connection->iss) || (ack > connection->next_send) ) { + - connection->next_recv = le2be32(tcp_packet->tcphdr.sequence) + 1; - connection->next_send = le2be32(tcp_packet->tcphdr.ack_next); - -#ifdef PXE_DEBUG_HELL - printf("tcp_syn_sent(): ack = %d, seq = %d\n", connection->next_recv, connection->next_send); -#endif - if (pxe_tcp_send(connection, 0, PXE_TCP_ACK)) { - connection->state = PXE_TCP_ESTABLISHED; -#ifdef PXE_DEBUG_HELL - printf("tcp_syn_sent(): new state - ESTABLISHED\n"); + if ( (flags & PXE_TCP_RST) == 0) { /* sending RST, if it was not sent to us */ +#ifdef PXE_DEBUG + printf("tcp_syn_sent(): resetting, ack = %d, iss = %d, nxt = %d\n", + ack, connection->iss, connection->next_send); #endif - /* updating last recv time. Used in resending and TIME_WAIT state */ - connection->last_recv = get_secs(); - } else { - printf("tcp_syn_sent(): failed to ack syn reply packet.\n"); + tcp_send_rst_for(tcp_packet, ack, 0, PXE_TCP_RST, 0); + } + + /* drop segment and return */ + return (0); + } + + /* check if ACK acceptable */ + if ( (connection->una > ack) || (ack > connection->next_send) ) { + acceptable = 0; + } + } + + /* second check, check RST */ + if (flags & PXE_TCP_RST) { + + if (acceptable == 0) { /* just drop */ + return (0); + } + + /* destroy connection */ +#ifdef PXE_DEBUG + printf("tcp_syn_sent(): new state - CLOSED\n"); +#endif + connection->state = PXE_TCP_CLOSED; + return (0); } + + /* third check */ + /* TODO?: check security/compartment and precedence */ + + /* fourth check, check SYN */ + if (flags & PXE_TCP_SYN) { + if (acceptable == 1) { + connection->next_recv = seq + 1; + connection->irs = seq; + connection->una = ack; + pxe_resend_update(connection); + } + + if ((connection->una > connection->iss) || (acceptable == 1) ) { + /* acking */ + if (pxe_tcp_send(connection, 0, PXE_TCP_ACK)) { +#ifdef PXE_DEBUG + printf("tcp_syn_sent(): new state - ESTABLISHED\n"); +#endif + connection->state = PXE_TCP_ESTABLISHED; + connection->last_recv = pxe_get_secs(); + } else { + printf("tcp_syn_sent(): failed to ack syn reply packet.\n"); + } + } else { + /* enter SYN_RECEIVED, form SYN+ACK */ + } + } + return (0); } @@ -218,35 +426,46 @@ * 2 - try next state handler */ static int -tcp_established(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection) +tcp_established(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen) { - uint8_t flags = tcp_packet->tcphdr.flags; + /* first check, if acceptable at all */ + if (!tcp_check_1(connection, tcp_packet, seglen)) + return (0); + + /* check, if have RST flag, sequentially incorrect or have SYN */ + if (( tcp_check_2(tcp_packet)) || + (!tcp_check_3(connection, tcp_packet)) || + ( tcp_check_4(connection, tcp_packet, seglen))) + { + connection->state = PXE_TCP_CLOSED; +#ifdef PXE_DEBUG + printf("tcp_established(): new state - CLOSED\n"); +#endif + pxe_resend_free(connection); + return (0); + } + + /* fifth check, if ACK received */ + if (!tcp_check_5(connection, tcp_packet)) { + return (0); + } - if (flags & PXE_TCP_FIN) { /* remote host requested connection break */ + /* sixth check, if urgent */ + if (tcp_check_6(tcp_packet)) { /* ignore for now */ + return (0); + } - connection->next_recv = le2be32(tcp_packet->tcphdr.sequence) + 1; - connection->next_send = le2be32(tcp_packet->tcphdr.ack_next); - -#ifdef PXE_DEBUG_HELL - printf("tcp_established(): ack = %d, seq = %d\n", connection->next_recv, connection->next_send); -#endif - if (!pxe_tcp_send(connection, 0, PXE_TCP_ACK)) { - printf("tcp_established(): failed to ack FIN request.\n"); - return (0); - } + /* seventh, process segment */ + tcp_process_7(connection, tcp_packet, seglen); - connection->last_recv = get_secs(); + /* eighth, check FIN */ + if (tcp_check_8(tcp_packet)) { /* remote host requested connection break */ connection->state = PXE_TCP_CLOSE_WAIT; -#ifdef PXE_DEBUG_HELL +#ifdef PXE_DEBUG printf("tcp_established(): new state - CLOSE_WAIT\n"); #endif - return (0); } - /* TODO: process data receiving */ - - - connection->last_recv = get_secs(); return (0); } @@ -260,45 +479,64 @@ * 2 - try next state handler */ static int -tcp_fin_wait1(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection) +tcp_fin_wait1(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen) { - uint8_t flags = tcp_packet->tcphdr.flags; + /* first check, if acceptable at all */ + if (!tcp_check_1(connection, tcp_packet, seglen)) + return (0); + + /* check, if have RST or SYN flag */ + if ((tcp_check_2(tcp_packet)) || + (tcp_check_4(connection, tcp_packet, seglen)) ) + { + connection->state = PXE_TCP_CLOSED; +#ifdef PXE_DEBUG + printf("tcp_fin_wait1(): new state - CLOSED\n"); +#endif + pxe_resend_free(connection); + return (0); + } - if ( (flags & (PXE_TCP_ACK | PXE_TCP_FIN)) == ((PXE_TCP_ACK | PXE_TCP_FIN)) ) { - /* remote host acked our FIN and sent FIN */ - - connection->next_recv = le2be32(tcp_packet->tcphdr.sequence) + 1; - connection->next_send = le2be32(tcp_packet->tcphdr.ack_next); - -#ifdef PXE_DEBUG_HELL - printf("tcp_fin_wait1(): ack = %d, seq = %d\n", connection->next_recv, connection->next_send); -#endif - - if (!pxe_tcp_send(connection, 0, PXE_TCP_ACK)) { - printf("tcp_fin_wait2(): failed to ack FIN request.\n"); - return (0); - } - - connection->state = PXE_TCP_CLOSING; -#ifdef PXE_DEBUG_HELL - printf("tcp_fin_wait1(): new state - CLOSING\n"); -#endif - connection->last_recv = get_secs(); + /* check if ACK */ + if (!tcp_check_5(connection, tcp_packet)) { return (0); + } else { + /* TODO: move updating of next_send to pxe_tcp_send() */ + connection->next_send = tcp_packet->tcphdr.ack_next; } - if (flags & PXE_TCP_ACK) { /* remote host just acked our FIN */ - -/* connection->next_recv = le2be32(tcp_packet->tcphdr.sequence) + 1; */ - connection->next_send = le2be32(tcp_packet->tcphdr.ack_next); + /* if acked FIN */ +/* if (tcp_check_8(tcp_packet)) { */ + if (connection->state_out == PXE_TCP_FIN) { connection->state = PXE_TCP_FIN_WAIT2; -#ifdef PXE_DEBUG_HELL - printf("tcp_fin_wait1(): ack = %d, seq = %d\n", connection->next_recv, connection->next_send); +#ifdef PXE_DEBUG printf("tcp_fin_wait1(): new state - FIN_WAIT_2\n"); -#endif - connection->last_recv = get_secs(); +#endif + return (0); + } + + if (tcp_check_6(tcp_packet)) { /* ignore for now */ + return (0); } + tcp_process_7(connection, tcp_packet, seglen); + + /* check acked FIN */ + if (tcp_check_8(tcp_packet)) { + if (connection->state_out == PXE_TCP_FIN) { + connection->state = PXE_TCP_TIME_WAIT; +#ifdef PXE_DEBUG + printf("tcp_fin_wait1(): new state - TIME_WAIT\n"); +#endif + /* TODO: start TIME_WAIT timer */ + } else { + connection->state = PXE_TCP_CLOSING; +#ifdef PXE_DEBUG + printf("tcp_fin_wait1(): new state - CLOSING\n"); +#endif + } + } + return (0); } @@ -312,16 +550,34 @@ * 2 - try next state handler */ static int -tcp_closing(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection) +tcp_closing(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen) { - uint8_t flags = tcp_packet->tcphdr.flags; + /* first check, if acceptable at all */ + if (!tcp_check_1(connection, tcp_packet, seglen)) + return (0); + + /* check, if have RST OR SYN flag */ + if ( (tcp_check_2(tcp_packet)) || + (tcp_check_4(connection, tcp_packet, seglen)) ) + { + connection->state = PXE_TCP_CLOSED; +#ifdef PXE_DEBUG + printf("tcp_closing(): new state - CLOSED\n"); +#endif + pxe_resend_free(connection); + return (0); + } - if (flags & PXE_TCP_ACK) { /* remote host acked FIN */ + /* check ACK */ + if (!tcp_check_5(connection, tcp_packet)) { + return (0); + } + + if (connection->state_out = PXE_TCP_FIN) { connection->state = PXE_TCP_TIME_WAIT; -#ifdef PXE_DEBUG_HELL +#ifdef PXE_DEBUG printf("tcp_closing(): new state - TIME_WAIT\n"); #endif - connection->last_recv = get_secs(); } return (0); @@ -337,27 +593,50 @@ * 2 - try next state handler */ static int -tcp_fin_wait2(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection) +tcp_fin_wait2(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen) { - uint8_t flags = tcp_packet->tcphdr.flags; + /* first check, if acceptable at all */ + if (!tcp_check_1(connection, tcp_packet, seglen)) + return (0); + + /* check, if have RST or SYN flag */ + if ((tcp_check_2(tcp_packet)) || + (tcp_check_4(connection, tcp_packet, seglen)) ) + { + connection->state = PXE_TCP_CLOSED; +#ifdef PXE_DEBUG + printf("tcp_fin_wait2(): new state - CLOSED\n"); +#endif + pxe_resend_free(connection); + return (0); + } + + if (!tcp_check_5(connection, tcp_packet)) { + return (0); + } + +/* + if (tcp_queue_size(connection) == 0) { + connection->state = PXE_TCP_CLOSE; + } +*/ + /* check URG flag */ + if (tcp_check_6(tcp_packet)) { /* ignore for now */ + return (0); + } + + connection->next_send = tcp_packet->tcphdr.ack_next; - if (flags & PXE_TCP_FIN) { /* remote sent FIN */ + /* process data */ + tcp_process_7(connection, tcp_packet, seglen); - connection->next_recv = le2be32(tcp_packet->tcphdr.sequence) + 1; - connection->next_send = le2be32(tcp_packet->tcphdr.ack_next); -#ifdef PXE_DEBUG_HELL - printf("tcp_fin_wait2(): ack = %d, seq = %d\n", connection->next_recv, connection->next_send); -#endif - if (!pxe_tcp_send(connection, 0, PXE_TCP_ACK)) { - printf("tcp_fin_wait2(): failed to ack FIN request.\n"); - return (0); - } - + /* check acked FIN */ + if (tcp_check_8(tcp_packet)) { connection->state = PXE_TCP_TIME_WAIT; -#ifdef PXE_DEBUG_HELL +#ifdef PXE_DEBUG printf("tcp_fin_wait2(): new state - TIME_WAIT\n"); -#endif - connection->last_recv = get_secs(); +#endif + /* TODO: start TIME_WAIT timer */ } return (0); @@ -373,12 +652,36 @@ * 2 - try next state handler */ static int -tcp_time_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection) +tcp_time_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen) { - /* this state grabs lost packets */ + /* first check, if acceptable at all */ + if (!tcp_check_1(connection, tcp_packet, seglen)) + return (0); + + /* check, if have RST or SYN flag */ + if ((tcp_check_2(tcp_packet)) || + (tcp_check_4(connection, tcp_packet, seglen)) ) + { + connection->state = PXE_TCP_CLOSED; +#ifdef PXE_DEBUG + printf("tcp_time_wait(): new state - CLOSED\n"); +#endif + pxe_resend_free(connection); + return (0); + } - check_time_to_die(connection); + if (!tcp_check_5(connection, tcp_packet)) { + /* testart 2MSL timeout */ + return (0); + } + /* ignore URG flag in this state */ +/* if (tcp_check_6(tcp_packet)) { + return (0); + } +*/ + /* ignore data processing */ + return (0); } @@ -392,11 +695,35 @@ * 2 - try next state handler */ static int -tcp_close_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection) +tcp_close_wait(PXE_TCP_PACKET *tcp_packet, PXE_TCP_CONNECTION *connection, uint16_t seglen) { -#ifdef PXE_DEBUG_HELL - printf("tcp_close_wait(): started.\n"); + /* first check, if acceptable at all */ + if (!tcp_check_1(connection, tcp_packet, seglen)) + return (0); + + /* check, if have RST or SYN flag */ + if ((tcp_check_2(tcp_packet)) || + (tcp_check_4(connection, tcp_packet, seglen)) ) + { + connection->state = PXE_TCP_CLOSED; +#ifdef PXE_DEBUG + printf("tcp_close_wait(): new state - CLOSED\n"); #endif + pxe_resend_free(connection); + return (0); + } + >>> TRUNCATED FOR MAIL (1000 lines) <<<