2006-04-24 17:42:49 +02:00
|
|
|
#ifndef _GPXE_TCP_H
|
|
|
|
#define _GPXE_TCP_H
|
2006-03-23 22:32:03 +01:00
|
|
|
|
|
|
|
/** @file
|
|
|
|
*
|
|
|
|
* TCP protocol
|
|
|
|
*
|
|
|
|
* This file defines the gPXE TCP API.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2006-12-28 00:09:46 +01:00
|
|
|
#include "latch.h"
|
2006-08-02 02:02:21 +02:00
|
|
|
#include <gpxe/tcpip.h>
|
2006-03-23 22:32:03 +01:00
|
|
|
|
2006-12-28 00:09:46 +01:00
|
|
|
/**
|
|
|
|
* A TCP header
|
|
|
|
*/
|
|
|
|
struct tcp_header {
|
|
|
|
uint16_t src; /* Source port */
|
|
|
|
uint16_t dest; /* Destination port */
|
|
|
|
uint32_t seq; /* Sequence number */
|
|
|
|
uint32_t ack; /* Acknowledgement number */
|
|
|
|
uint8_t hlen; /* Header length (4), Reserved (4) */
|
|
|
|
uint8_t flags; /* Reserved (2), Flags (6) */
|
|
|
|
uint16_t win; /* Advertised window */
|
|
|
|
uint16_t csum; /* Checksum */
|
|
|
|
uint16_t urg; /* Urgent pointer */
|
|
|
|
};
|
|
|
|
|
2007-01-13 18:36:17 +01:00
|
|
|
/**
|
|
|
|
* TCP MSS option
|
|
|
|
*/
|
|
|
|
struct tcp_mss_option {
|
|
|
|
uint8_t kind;
|
|
|
|
uint8_t length;
|
|
|
|
uint16_t mss;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Code for the TCP MSS option */
|
|
|
|
#define TCP_OPTION_MSS 2
|
|
|
|
|
2006-12-28 00:09:46 +01:00
|
|
|
/*
|
|
|
|
* TCP flags
|
|
|
|
*/
|
|
|
|
#define TCP_CWR 0x80
|
|
|
|
#define TCP_ECE 0x40
|
|
|
|
#define TCP_URG 0x20
|
|
|
|
#define TCP_ACK 0x10
|
|
|
|
#define TCP_PSH 0x08
|
|
|
|
#define TCP_RST 0x04
|
|
|
|
#define TCP_SYN 0x02
|
|
|
|
#define TCP_FIN 0x01
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup tcpstates TCP states
|
|
|
|
*
|
2006-12-29 01:44:31 +01:00
|
|
|
* The TCP state is defined by a combination of the flags that have
|
|
|
|
* been sent to the peer, the flags that have been acknowledged by the
|
|
|
|
* peer, and the flags that have been received from the peer.
|
2006-12-28 00:09:46 +01:00
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2006-12-29 01:44:31 +01:00
|
|
|
/** TCP flags that have been sent in outgoing packets */
|
|
|
|
#define TCP_STATE_SENT(flags) ( (flags) << 0 )
|
|
|
|
#define TCP_FLAGS_SENT(state) ( ( (state) >> 0 ) & 0xff )
|
2006-12-28 00:09:46 +01:00
|
|
|
|
|
|
|
/** TCP flags that have been acknowledged by the peer
|
|
|
|
*
|
|
|
|
* Note that this applies only to SYN and FIN.
|
|
|
|
*/
|
|
|
|
#define TCP_STATE_ACKED(flags) ( (flags) << 8 )
|
2006-12-30 02:32:22 +01:00
|
|
|
#define TCP_FLAGS_ACKED(state) ( ( (state) >> 8 ) & 0xff )
|
2006-12-28 00:09:46 +01:00
|
|
|
|
|
|
|
/** TCP flags that have been received from the peer
|
|
|
|
*
|
|
|
|
* Note that this applies only to SYN and FIN, and that once SYN has
|
|
|
|
* been received, we should always be sending ACK.
|
|
|
|
*/
|
2006-12-30 02:32:22 +01:00
|
|
|
#define TCP_STATE_RCVD(flags) ( (flags) << 16 )
|
|
|
|
#define TCP_FLAGS_RCVD(state) ( ( (state) >> 16 ) & 0xff )
|
2006-12-28 00:09:46 +01:00
|
|
|
|
2006-12-29 01:44:31 +01:00
|
|
|
/** TCP flags that are currently being sent in outgoing packets */
|
|
|
|
#define TCP_FLAGS_SENDING(state) \
|
|
|
|
( TCP_FLAGS_SENT ( state ) & ~TCP_FLAGS_ACKED ( state ) )
|
|
|
|
|
2006-12-28 00:09:46 +01:00
|
|
|
/** CLOSED
|
|
|
|
*
|
|
|
|
* The connection has not yet been used for anything.
|
|
|
|
*/
|
|
|
|
#define TCP_CLOSED TCP_RST
|
|
|
|
|
|
|
|
/** LISTEN
|
|
|
|
*
|
|
|
|
* Not currently used as a state; we have no support for listening
|
|
|
|
* connections. Given a unique value to avoid compiler warnings.
|
|
|
|
*/
|
|
|
|
#define TCP_LISTEN 0
|
|
|
|
|
|
|
|
/** SYN_SENT
|
|
|
|
*
|
|
|
|
* SYN has been sent, nothing has yet been received or acknowledged.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_SYN_SENT ( TCP_STATE_SENT ( TCP_SYN ) )
|
2006-12-28 00:09:46 +01:00
|
|
|
|
|
|
|
/** SYN_RCVD
|
|
|
|
*
|
|
|
|
* SYN has been sent but not acknowledged, SYN has been received.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_SYN_RCVD ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
|
2006-12-28 00:09:46 +01:00
|
|
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
|
|
|
|
|
|
|
/** ESTABLISHED
|
|
|
|
*
|
|
|
|
* SYN has been sent and acknowledged, SYN has been received.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_ESTABLISHED ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
|
|
|
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
2006-12-28 00:09:46 +01:00
|
|
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
|
|
|
|
|
|
|
/** FIN_WAIT_1
|
|
|
|
*
|
|
|
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
|
|
|
* been sent but not acknowledged, FIN has not been received.
|
|
|
|
*
|
|
|
|
* RFC 793 shows that we can enter FIN_WAIT_1 without have had SYN
|
|
|
|
* acknowledged, i.e. if the application closes the connection after
|
|
|
|
* sending and receiving SYN, but before having had SYN acknowledged.
|
|
|
|
* However, we have to *pretend* that SYN has been acknowledged
|
|
|
|
* anyway, otherwise we end up sending SYN and FIN in the same
|
|
|
|
* sequence number slot. Therefore, when we transition from SYN_RCVD
|
|
|
|
* to FIN_WAIT_1, we have to remember to set TCP_STATE_ACKED(TCP_SYN)
|
|
|
|
* and increment our sequence number.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_FIN_WAIT_1 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
|
|
|
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
2006-12-28 00:09:46 +01:00
|
|
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
|
|
|
|
|
|
|
/** FIN_WAIT_2
|
|
|
|
*
|
|
|
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
|
|
|
* been sent and acknowledged, FIN ha not been received.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_FIN_WAIT_2 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
|
|
|
|
TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
|
2006-12-28 00:09:46 +01:00
|
|
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
|
|
|
|
|
|
|
/** CLOSING / LAST_ACK
|
|
|
|
*
|
|
|
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
|
|
|
* been sent but not acknowledged, FIN has been received.
|
|
|
|
*
|
|
|
|
* This state actually encompasses both CLOSING and LAST_ACK; they are
|
|
|
|
* identical with the definition of state that we use. I don't
|
|
|
|
* *believe* that they need to be distinguished.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_CLOSING_OR_LAST_ACK \
|
|
|
|
( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
|
|
|
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
2006-12-28 00:09:46 +01:00
|
|
|
TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
|
|
|
|
|
|
|
|
/** TIME_WAIT
|
|
|
|
*
|
|
|
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
|
|
|
* been sent and acknowledged, FIN has been received.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_TIME_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
|
|
|
|
TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
|
2006-12-28 00:09:46 +01:00
|
|
|
TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
|
|
|
|
|
|
|
|
/** CLOSE_WAIT
|
|
|
|
*
|
|
|
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
|
|
|
* been received.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_CLOSE_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
|
|
|
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
2006-12-28 00:09:46 +01:00
|
|
|
TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
|
|
|
|
|
|
|
|
/** Can send data in current state
|
|
|
|
*
|
|
|
|
* We can send data if and only if we have had our SYN acked and we
|
|
|
|
* have not yet sent our FIN.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_CAN_SEND_DATA(state) \
|
|
|
|
( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \
|
|
|
|
TCP_STATE_SENT ( TCP_FIN ) ) ) \
|
2006-12-28 00:09:46 +01:00
|
|
|
== TCP_STATE_ACKED ( TCP_SYN ) )
|
|
|
|
|
|
|
|
/** Have closed gracefully
|
|
|
|
*
|
|
|
|
* We have closed gracefully if we have both received a FIN and had
|
|
|
|
* our own FIN acked.
|
|
|
|
*/
|
2006-12-29 01:44:31 +01:00
|
|
|
#define TCP_CLOSED_GRACEFULLY(state) \
|
|
|
|
( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) | \
|
|
|
|
TCP_STATE_RCVD ( TCP_FIN ) ) ) \
|
2006-12-28 00:09:46 +01:00
|
|
|
== ( TCP_STATE_ACKED ( TCP_FIN ) | TCP_STATE_RCVD ( TCP_FIN ) ) )
|
|
|
|
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
/** Mask for TCP header length field */
|
|
|
|
#define TCP_MASK_HLEN 0xf0
|
|
|
|
|
|
|
|
/** Smallest port number on which a TCP connection can listen */
|
|
|
|
#define TCP_MIN_PORT 1
|
|
|
|
|
|
|
|
/* Some PKB constants */
|
|
|
|
#define MAX_HDR_LEN 100
|
|
|
|
#define MAX_PKB_LEN 1500
|
|
|
|
#define MIN_PKB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Advertised TCP window size
|
|
|
|
*
|
|
|
|
* Our TCP window is actually limited by the amount of space available
|
|
|
|
* for RX packets in the NIC's RX ring; we tend to populate the rings
|
|
|
|
* with far fewer descriptors than a typical driver. Since we have no
|
|
|
|
* way of knowing how much of this RX ring space will be available for
|
|
|
|
* received TCP packets (consider, for example, that they may all be
|
|
|
|
* consumed by a series of unrelated ARP requests between other
|
|
|
|
* machines on the network), it is actually not even theoretically
|
|
|
|
* possible for us to specify an accurate window size. We therefore
|
|
|
|
* guess an arbitrary number that is empirically as large as possible
|
|
|
|
* while avoiding retransmissions due to dropped packets.
|
|
|
|
*/
|
2007-01-13 18:36:17 +01:00
|
|
|
#define TCP_WINDOW_SIZE 4096
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Advertised TCP MSS
|
|
|
|
*
|
|
|
|
* We currently hardcode this to a reasonable value and hope that the
|
|
|
|
* sender uses path MTU discovery. The alternative is breaking the
|
|
|
|
* abstraction layer so that we can find out the MTU from the IP layer
|
|
|
|
* (which would have to find out from the net device layer).
|
|
|
|
*/
|
|
|
|
#define TCP_MSS 1460
|
2006-12-28 00:09:46 +01:00
|
|
|
|
|
|
|
/** TCP maximum segment lifetime
|
|
|
|
*
|
|
|
|
* Currently set to 2 minutes, as per RFC 793.
|
|
|
|
*/
|
|
|
|
#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC )
|
|
|
|
|
|
|
|
struct tcp_application;
|
2006-03-23 22:32:03 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* TCP operations
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
struct tcp_operations {
|
2006-04-30 18:59:45 +02:00
|
|
|
/*
|
|
|
|
* Connection closed
|
2006-03-23 22:32:03 +01:00
|
|
|
*
|
2006-12-28 00:09:46 +01:00
|
|
|
* @v app TCP application
|
2006-04-30 18:59:45 +02:00
|
|
|
* @v status Error code, if any
|
2006-03-23 22:32:03 +01:00
|
|
|
*
|
2006-04-30 18:59:45 +02:00
|
|
|
* This is called when the connection is closed for any
|
|
|
|
* reason, including timeouts or aborts. The status code
|
|
|
|
* contains the negative error number, if the closure is due
|
|
|
|
* to an error.
|
2006-03-23 22:32:03 +01:00
|
|
|
*
|
2006-12-28 00:09:46 +01:00
|
|
|
* When closed() is called, the application no longer has a
|
|
|
|
* valid TCP connection. Note that connected() may not have
|
|
|
|
* been called before closed(), if the close is due to an
|
|
|
|
* error during connection setup.
|
2006-03-23 22:32:03 +01:00
|
|
|
*/
|
2006-12-28 00:09:46 +01:00
|
|
|
void ( * closed ) ( struct tcp_application *app, int status );
|
2006-03-23 22:32:03 +01:00
|
|
|
/**
|
2006-12-28 00:09:46 +01:00
|
|
|
* Connection established
|
2006-03-23 22:32:03 +01:00
|
|
|
*
|
2006-12-28 00:09:46 +01:00
|
|
|
* @v app TCP application
|
2006-03-23 22:32:03 +01:00
|
|
|
*/
|
2006-12-28 00:09:46 +01:00
|
|
|
void ( * connected ) ( struct tcp_application *app );
|
2006-03-23 22:32:03 +01:00
|
|
|
/**
|
|
|
|
* Data acknowledged
|
|
|
|
*
|
2006-12-28 00:09:46 +01:00
|
|
|
* @v app TCP application
|
2006-03-23 22:32:03 +01:00
|
|
|
* @v len Length of acknowledged data
|
|
|
|
*
|
|
|
|
* @c len is guaranteed to not exceed the outstanding amount
|
|
|
|
* of unacknowledged data.
|
|
|
|
*/
|
2006-12-28 00:09:46 +01:00
|
|
|
void ( * acked ) ( struct tcp_application *app, size_t len );
|
2006-03-23 22:32:03 +01:00
|
|
|
/**
|
|
|
|
* New data received
|
|
|
|
*
|
2006-12-28 00:09:46 +01:00
|
|
|
* @v app TCP application
|
2006-03-23 22:32:03 +01:00
|
|
|
* @v data Data
|
|
|
|
* @v len Length of data
|
|
|
|
*/
|
2006-12-28 00:09:46 +01:00
|
|
|
void ( * newdata ) ( struct tcp_application *app,
|
2006-03-23 22:32:03 +01:00
|
|
|
void *data, size_t len );
|
|
|
|
/**
|
|
|
|
* Transmit data
|
|
|
|
*
|
2006-12-28 00:09:46 +01:00
|
|
|
* @v app TCP application
|
2006-06-18 01:20:54 +02:00
|
|
|
* @v buf Temporary data buffer
|
|
|
|
* @v len Length of temporary data buffer
|
2006-03-23 22:32:03 +01:00
|
|
|
*
|
|
|
|
* The application should transmit whatever it currently wants
|
|
|
|
* to send using tcp_send(). If retransmissions are required,
|
|
|
|
* senddata() will be called again and the application must
|
|
|
|
* regenerate the data. The easiest way to implement this is
|
|
|
|
* to ensure that senddata() never changes the application's
|
|
|
|
* state.
|
2006-06-18 01:20:54 +02:00
|
|
|
*
|
|
|
|
* The application may use the temporary data buffer to
|
|
|
|
* construct the data to be sent. Note that merely filling
|
|
|
|
* the buffer will do nothing; the application must call
|
|
|
|
* tcp_send() in order to actually transmit the data. Use of
|
|
|
|
* the buffer is not compulsory; the application may call
|
|
|
|
* tcp_send() on any block of data.
|
2006-03-23 22:32:03 +01:00
|
|
|
*/
|
2006-12-28 00:09:46 +01:00
|
|
|
void ( * senddata ) ( struct tcp_application *app, void *buf,
|
2006-06-18 01:20:54 +02:00
|
|
|
size_t len );
|
2006-03-23 22:32:03 +01:00
|
|
|
};
|
|
|
|
|
2006-12-28 00:09:46 +01:00
|
|
|
struct tcp_connection;
|
2006-08-01 22:46:50 +02:00
|
|
|
|
2006-03-23 22:32:03 +01:00
|
|
|
/**
|
2006-12-28 00:09:46 +01:00
|
|
|
* A TCP application
|
2006-03-23 22:32:03 +01:00
|
|
|
*
|
2006-12-28 00:09:46 +01:00
|
|
|
* This data structure represents an application with a TCP connection.
|
2006-03-23 22:32:03 +01:00
|
|
|
*/
|
2006-12-28 00:09:46 +01:00
|
|
|
struct tcp_application {
|
|
|
|
/** TCP connection data
|
|
|
|
*
|
|
|
|
* This is filled in by TCP calls that initiate a connection,
|
|
|
|
* and reset to NULL when the connection is closed.
|
|
|
|
*/
|
|
|
|
struct tcp_connection *conn;
|
|
|
|
/** TCP connection operations table */
|
2006-03-23 22:32:03 +01:00
|
|
|
struct tcp_operations *tcp_op;
|
|
|
|
};
|
|
|
|
|
2006-12-28 00:09:46 +01:00
|
|
|
extern int tcp_connect ( struct tcp_application *app,
|
|
|
|
struct sockaddr_tcpip *peer,
|
|
|
|
uint16_t local_port );
|
|
|
|
extern void tcp_close ( struct tcp_application *app );
|
|
|
|
extern int tcp_senddata ( struct tcp_application *app );
|
|
|
|
extern int tcp_send ( struct tcp_application *app, const void *data,
|
2006-08-01 22:46:50 +02:00
|
|
|
size_t len );
|
|
|
|
|
2006-12-28 00:09:46 +01:00
|
|
|
extern struct tcpip_protocol tcp_protocol;
|
2006-08-01 22:46:50 +02:00
|
|
|
|
2006-04-24 17:42:49 +02:00
|
|
|
#endif /* _GPXE_TCP_H */
|