@@ -2428,10 +2428,38 @@ static struct tcp *tcp_conn_new(struct net_pkt *pkt)
2428
2428
return conn ;
2429
2429
}
2430
2430
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 )
2432
2442
{
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;
2435
2463
}
2436
2464
2437
2465
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)
2769
2797
goto out ;
2770
2798
}
2771
2799
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 )) {
2775
2806
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 ) ;
2778
2809
}
2810
+ k_mutex_unlock (& conn -> lock );
2811
+ return NET_DROP ;
2812
+ }
2779
2813
2814
+ if (FL (& fl , & , RST )) {
2780
2815
/* Valid RST received. */
2781
2816
verdict = NET_OK ;
2782
2817
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)
2814
2849
goto out ;
2815
2850
}
2816
2851
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 )) {
2819
2853
/* According to RFC 793, ch 3.9 Event Processing, receiving SYN
2820
2854
* once the connection has been established is an error
2821
2855
* 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)
2851
2885
k_sem_give (& conn -> tx_sem );
2852
2886
}
2853
2887
2854
- len = tcp_data_len (pkt );
2855
-
2856
2888
switch (conn -> state ) {
2857
2889
case TCP_LISTEN :
2858
2890
if (FL (& fl , = = , SYN )) {
@@ -3296,11 +3328,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
3296
3328
}
3297
3329
tcp_out (conn , ACK );
3298
3330
verdict = NET_OK ;
3299
- } else {
3300
- if (len > 0 ) {
3301
- tcp_out (conn , ACK );
3302
- verdict = NET_OK ;
3303
- }
3304
3331
}
3305
3332
}
3306
3333
break ;
@@ -3337,12 +3364,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
3337
3364
3338
3365
verdict = NET_OK ;
3339
3366
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
- }
3346
3367
}
3347
3368
break ;
3348
3369
case TCP_CLOSING : {
@@ -3380,19 +3401,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
3380
3401
3381
3402
verdict = NET_OK ;
3382
3403
}
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
- }
3396
3404
}
3397
3405
break ;
3398
3406
case TCP_TIME_WAIT : {
@@ -3408,15 +3416,6 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
3408
3416
net_stats_update_tcp_seg_drop (conn -> iface );
3409
3417
3410
3418
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
- }
3420
3419
}
3421
3420
}
3422
3421
break ;
0 commit comments