Skip to content

Commit 46ba523

Browse files
shrek-wangkartben
authored andcommitted
net: tcp: Align TCP seqence validation with Spec
According to RFC 793, the seqnum test includes 4 cases when STATE > TCP_SYN_SENT: Seg-len Recv-win Test ------- -------- --------------------------------------- 0 0 SEG.SEQ = RCV.NXT 0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND >0 0 not acceptable >0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND or RCV.NXT =< SEG.SEQ+SEG.LEN-1 <RCV.NXT+RCV.WND After the seq validation, the 'send duplicated ACK' code in FIN_WAIT1/ 2/CLOSING/TIMEWAIT state processing is duplicated, so remove them. Added TEST_CLIENT_SEQ_VALIDATION ztest case in tests/net/tcp. Signed-off-by: Shrek Wang <inet_eman@outlook.com>
1 parent f8b70ee commit 46ba523

File tree

2 files changed

+294
-46
lines changed

2 files changed

+294
-46
lines changed

subsys/net/ip/tcp.c

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,10 +2428,38 @@ static struct tcp *tcp_conn_new(struct net_pkt *pkt)
24282428
return conn;
24292429
}
24302430

2431-
static bool tcp_validate_seq(struct tcp *conn, struct tcphdr *hdr)
2431+
/* According to RFC 793, the seqnum test includes 4 cases when STATE > TCP_SYN_SENT
2432+
*
2433+
* Seg-len Recv-win Test
2434+
* ------- -------- -----------------------------------------------
2435+
* 0 0 SEG.SEQ = RCV.NXT
2436+
* 0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
2437+
* >0 0 not acceptable
2438+
* >0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
2439+
* or RCV.NXT =< SEG.SEQ+SEG.LEN-1 <RCV.NXT+RCV.WND
2440+
*/
2441+
static bool tcp_validate_seq(struct tcp *conn, struct tcphdr *hdr, size_t len)
24322442
{
2433-
return (net_tcp_seq_cmp(th_seq(hdr), conn->ack) >= 0) &&
2434-
(net_tcp_seq_cmp(th_seq(hdr), conn->ack + conn->recv_win) < 0);
2443+
if ((conn->state == TCP_LISTEN) || (conn->state == TCP_SYN_SENT)) {
2444+
return true;
2445+
}
2446+
2447+
if (conn->recv_win > 0) {
2448+
if (len == 0) {
2449+
return ((net_tcp_seq_cmp(th_seq(hdr), conn->ack) >= 0) &&
2450+
(net_tcp_seq_cmp(th_seq(hdr), conn->ack + conn->recv_win) < 0));
2451+
}
2452+
return (((net_tcp_seq_cmp(th_seq(hdr), conn->ack) >= 0) &&
2453+
(net_tcp_seq_cmp(th_seq(hdr), conn->ack + conn->recv_win) < 0)) ||
2454+
((net_tcp_seq_cmp(th_seq(hdr) + len - 1, conn->ack) >= 0) &&
2455+
(net_tcp_seq_cmp(th_seq(hdr) + len - 1, conn->ack + conn->recv_win) < 0)));
2456+
}
2457+
2458+
if (len == 0) {
2459+
return (net_tcp_seq_cmp(th_seq(hdr), conn->ack) == 0);
2460+
}
2461+
2462+
return false;
24352463
}
24362464

24372465
static int32_t tcp_compute_new_length(struct tcp *conn, struct tcphdr *hdr, size_t len,
@@ -2769,14 +2797,21 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
27692797
goto out;
27702798
}
27712799

2772-
if (FL(&fl, &, RST)) {
2773-
/* We only accept RST packet that has valid seq field. */
2774-
if (!tcp_validate_seq(conn, th)) {
2800+
len = tcp_data_len(pkt);
2801+
2802+
/* first validate the seqnum */
2803+
if (!tcp_validate_seq(conn, th, len)) {
2804+
/* send ACK for non-RST packet */
2805+
if (FL(&fl, &, RST)) {
27752806
net_stats_update_tcp_seg_rsterr(net_pkt_iface(pkt));
2776-
k_mutex_unlock(&conn->lock);
2777-
return NET_DROP;
2807+
} else if ((len > 0) || FL(&fl, &, FIN)) {
2808+
tcp_out(conn, ACK);
27782809
}
2810+
k_mutex_unlock(&conn->lock);
2811+
return NET_DROP;
2812+
}
27792813

2814+
if (FL(&fl, &, RST)) {
27802815
/* Valid RST received. */
27812816
verdict = NET_OK;
27822817
net_stats_update_tcp_seg_rst(net_pkt_iface(pkt));
@@ -2814,8 +2849,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
28142849
goto out;
28152850
}
28162851

2817-
if ((conn->state != TCP_LISTEN) && (conn->state != TCP_SYN_SENT) &&
2818-
tcp_validate_seq(conn, th) && FL(&fl, &, SYN)) {
2852+
if ((conn->state != TCP_LISTEN) && (conn->state != TCP_SYN_SENT) && FL(&fl, &, SYN)) {
28192853
/* According to RFC 793, ch 3.9 Event Processing, receiving SYN
28202854
* once the connection has been established is an error
28212855
* condition, reset should be sent and connection closed.
@@ -2851,8 +2885,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
28512885
k_sem_give(&conn->tx_sem);
28522886
}
28532887

2854-
len = tcp_data_len(pkt);
2855-
28562888
switch (conn->state) {
28572889
case TCP_LISTEN:
28582890
if (FL(&fl, ==, SYN)) {
@@ -3296,11 +3328,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
32963328
}
32973329
tcp_out(conn, ACK);
32983330
verdict = NET_OK;
3299-
} else {
3300-
if (len > 0) {
3301-
tcp_out(conn, ACK);
3302-
verdict = NET_OK;
3303-
}
33043331
}
33053332
}
33063333
break;
@@ -3337,12 +3364,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
33373364

33383365
verdict = NET_OK;
33393366
tcp_out(conn, ACK);
3340-
} else {
3341-
if (len > 0) {
3342-
/* Send out a duplicate ACK */
3343-
tcp_out(conn, ACK);
3344-
verdict = NET_OK;
3345-
}
33463367
}
33473368
break;
33483369
case TCP_CLOSING: {
@@ -3380,19 +3401,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
33803401

33813402
verdict = NET_OK;
33823403
}
3383-
3384-
/*
3385-
* There can also be data in the message, so compute with the length
3386-
* of the packet to check with the ack
3387-
* Since the conn->ack was already incremented in TCP_FIN_WAIT_1
3388-
* add 1 in the comparison sequence
3389-
*/
3390-
if ((FL(&fl, &, FIN, net_tcp_seq_cmp(th_seq(th) + len + 1, conn->ack) == 0)) ||
3391-
(len > 0)) {
3392-
/* Send out a duplicate ACK */
3393-
tcp_out(conn, ACK);
3394-
verdict = NET_OK;
3395-
}
33963404
}
33973405
break;
33983406
case TCP_TIME_WAIT: {
@@ -3408,15 +3416,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
34083416
net_stats_update_tcp_seg_drop(conn->iface);
34093417

34103418
net_tcp_reply_rst(pkt);
3411-
} else {
3412-
/* Acknowledge any FIN attempts, in case retransmission took
3413-
* place.
3414-
*/
3415-
if ((FL(&fl, &, FIN, net_tcp_seq_cmp(th_seq(th) + 1, conn->ack) == 0)) ||
3416-
(len > 0)) {
3417-
tcp_out(conn, ACK);
3418-
verdict = NET_OK;
3419-
}
34203419
}
34213420
}
34223421
break;

0 commit comments

Comments
 (0)