net/tcp: Support initial sequence number described in RFC 6528
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
5096a2c9fd
commit
d1c73b6ed6
@ -158,6 +158,17 @@ config NET_TCP_CC_NEWRENO
|
||||
The TCP Congestion Control defines four congestion control algorithms,
|
||||
slow start, congestion avoidance, fast retransmit, and fast recovery.
|
||||
|
||||
config NET_TCP_ISN_RFC6528
|
||||
bool "Use Initial Sequence Number Algorithm from RFC 6528"
|
||||
default n
|
||||
depends on CRYPTO
|
||||
---help---
|
||||
Initial Sequence Number Generation Algorithm from RFC 6528:
|
||||
ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
|
||||
|
||||
M is the 4 microsecond timer, and F() is a pseudorandom
|
||||
function (PRF) which is MD5 (suggested by RFC 6528).
|
||||
|
||||
config NET_TCP_WINDOW_SCALE
|
||||
bool "Enable TCP/IP Window Scale Option"
|
||||
default n
|
||||
|
@ -896,7 +896,7 @@ uint32_t tcp_addsequence(FAR uint8_t *seqno, uint16_t len);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tcp_initsequence(FAR uint8_t *seqno);
|
||||
void tcp_initsequence(FAR struct tcp_conn_s *conn);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_nextsequence
|
||||
|
@ -1200,7 +1200,7 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
||||
conn->rport = tcp->srcport;
|
||||
conn->tcpstateflags = TCP_SYN_RCVD;
|
||||
|
||||
tcp_initsequence(conn->sndseq);
|
||||
tcp_initsequence(conn);
|
||||
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
||||
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
|
||||
#endif
|
||||
@ -1506,13 +1506,6 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
*/
|
||||
|
||||
conn->tcpstateflags = TCP_SYN_SENT;
|
||||
tcp_initsequence(conn->sndseq);
|
||||
|
||||
/* Save initial sndseq to rexmit_seq, otherwise it will be zero */
|
||||
|
||||
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
||||
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
|
||||
#endif
|
||||
|
||||
conn->tx_unacked = 1; /* TCP length of the SYN is one. */
|
||||
conn->nrtx = 0;
|
||||
@ -1528,6 +1521,16 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
conn->sndseq_max = 0;
|
||||
#endif
|
||||
|
||||
/* Set initial sndseq when we have both local/remote addr and port */
|
||||
|
||||
tcp_initsequence(conn);
|
||||
|
||||
/* Save initial sndseq to rexmit_seq, otherwise it will be zero */
|
||||
|
||||
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
||||
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_TCP_CC_NEWRENO
|
||||
/* Initialize the variables of congestion control. */
|
||||
|
||||
|
@ -43,23 +43,84 @@
|
||||
#include <nuttx/config.h>
|
||||
#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <crypto/md5.h>
|
||||
#include <debug.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/net/netconfig.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
|
||||
#include "devif/devif.h"
|
||||
#include "tcp/tcp.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* g_tcpsequence is used to generate initial TCP sequence numbers */
|
||||
/* These fields are used to generate initial TCP sequence numbers */
|
||||
|
||||
#ifdef CONFIG_NET_TCP_ISN_RFC6528
|
||||
/* RFC 6528, Section 3: Key lengths of 128 bits should be adequate. */
|
||||
|
||||
static uint32_t g_tcp_isnkey[4];
|
||||
#else
|
||||
static uint32_t g_tcpsequence;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_isn_rfc6528
|
||||
*
|
||||
* Description:
|
||||
* Calculate the initial sequence number described in RFC 6528.
|
||||
* ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP_ISN_RFC6528
|
||||
static uint32_t tcp_isn_rfc6528(FAR struct tcp_conn_s *conn)
|
||||
{
|
||||
const size_t addrlen = net_ip_domain_select(conn->domain,
|
||||
sizeof(in_addr_t), sizeof(net_ipv6addr_t));
|
||||
MD5_CTX ctx;
|
||||
uint32_t digest[MD5_DIGEST_LENGTH / 4];
|
||||
uint32_t m;
|
||||
|
||||
/* Make sure we have a secret key */
|
||||
|
||||
if (g_tcp_isnkey[0] == 0)
|
||||
{
|
||||
net_getrandom(g_tcp_isnkey, sizeof(g_tcp_isnkey));
|
||||
}
|
||||
|
||||
/* M is the 4 microsecond timer */
|
||||
|
||||
m = TICK2USEC(clock_systime_ticks()) / 4;
|
||||
|
||||
/* F() is suggested to be MD5 */
|
||||
|
||||
md5init(&ctx);
|
||||
|
||||
/* Calculate F(localip, localport, remoteip, remoteport, secretkey) */
|
||||
|
||||
md5update(&ctx, net_ip_binding_laddr(&conn->u, conn->domain), addrlen);
|
||||
md5update(&ctx, &conn->lport, sizeof(conn->lport));
|
||||
md5update(&ctx, net_ip_binding_raddr(&conn->u, conn->domain), addrlen);
|
||||
md5update(&ctx, &conn->rport, sizeof(conn->rport));
|
||||
md5update(&ctx, g_tcp_isnkey, sizeof(g_tcp_isnkey));
|
||||
|
||||
md5final((FAR uint8_t *)digest, &ctx);
|
||||
|
||||
/* ISN = M + F(localip, localport, remoteip, remoteport, secretkey) */
|
||||
|
||||
return m + digest[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -142,8 +203,11 @@ uint32_t tcp_addsequence(FAR uint8_t *seqno, uint16_t len)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tcp_initsequence(FAR uint8_t *seqno)
|
||||
void tcp_initsequence(FAR struct tcp_conn_s *conn)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP_ISN_RFC6528
|
||||
tcp_setsequence(conn->sndseq, tcp_isn_rfc6528(conn));
|
||||
#else
|
||||
/* If g_tcpsequence is already initialized, just copy it */
|
||||
|
||||
if (g_tcpsequence == 0)
|
||||
@ -164,7 +228,8 @@ void tcp_initsequence(FAR uint8_t *seqno)
|
||||
}
|
||||
}
|
||||
|
||||
tcp_setsequence(seqno, g_tcpsequence);
|
||||
tcp_setsequence(conn->sndseq, g_tcpsequence);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -180,7 +245,9 @@ void tcp_initsequence(FAR uint8_t *seqno)
|
||||
|
||||
void tcp_nextsequence(void)
|
||||
{
|
||||
#ifndef CONFIG_NET_TCP_ISN_RFC6528
|
||||
g_tcpsequence++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_TCP */
|
||||
|
Loading…
x
Reference in New Issue
Block a user