Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Jun 2007 15:06:27 GMT
From:      Alexey Tarasov <taleks@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 122406 for review
Message-ID:  <200706271506.l5RF6R0I052187@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <bsd.lib.mk>

==== //depot/projects/soc2007/taleks-pxe_http/pxe_buffer.h#3 (text+ko) ====

@@ -3,6 +3,10 @@
 
 #include <stdint.h>
 
+/* 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 <stand.h>
 #include <stdint.h>
 #include <stddef.h>
 
@@ -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 <stand.h>
 
 #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) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200706271506.l5RF6R0I052187>