diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 37c6bb61a..4305fd7b9 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -678,7 +678,17 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) npcb->local_port = pcb->local_port; npcb->remote_port = tcphdr->src; npcb->state = SYN_RCVD; + #if SYN_WITH_PAYLOAD_ENABLED + /* RFC Compliance: Account for both SYN flag and any payload in the SYN packet. + * Some implementations send data with SYN (SYN+data), and the ACK number must + * correctly reflect seqno + 1 (for SYN) + payload_length to comply with RFC. + * This ensures proper interoperability and passes robustness testing tools. */ + npcb->rcv_nxt = seqno + tcplen; + #else + /* Standard behavior: Only account for SYN flag, ignore any payload. + * This is the traditional lwIP behavior - SYN payload is discarded. */ npcb->rcv_nxt = seqno + 1; + #endif npcb->rcv_ann_right_edge = npcb->rcv_nxt; iss = tcp_next_iss(npcb); npcb->snd_wl2 = iss; @@ -838,6 +848,13 @@ tcp_process(struct tcp_pcb *pcb) } if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + #if SYN_WITH_PAYLOAD_ENABLED + /* RFC Compliance: Handle SYN with payload in unexpected states. + * Update rcv_nxt to account for SYN flag and any payload to maintain + * correct sequence tracking and generate proper ACK numbers. + * Note: Sequence nb could be the same becuase we don't intend a new seq nb */ + pcb->rcv_nxt += tcplen; + #endif /* Cope with new connection attempt after remote end crashed */ tcp_ack_now(pcb); return ERR_OK; diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 2573285f4..141df5705 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -1313,6 +1313,27 @@ #define TCP_SYNMAXRTX 6 #endif +/** + * SYN_WITH_PAYLOAD_ENABLED: Handle SYN packets with payload according to RFC standards. + * + * RFC Compliance: When enabled (set to 1), lwIP correctly processes SYN packets that + * contain payload data by setting rcv_nxt to account for both the SYN flag and the + * payload length. According to TCP RFC specifications, the ACK number should reflect + * the sequence number incremented by the size of the received payload, even in the + * rare case of a SYN packet carrying data. + * + * By default (disabled), lwIP ignores payload in SYN packets and responds with ACK=1, + * which may not comply with strict RFC interpretations. Some robustness testing tools + * and security scanners specifically check for this behavior to validate TCP stack + * correctness. + * + * Enable this for improved RFC compliance and interoperability with testing tools. + * Default is 0 (disabled for backward compatibility and typical usage). + */ +#if !defined SYN_WITH_PAYLOAD_ENABLED || defined __DOXYGEN__ +#define SYN_WITH_PAYLOAD_ENABLED 0 +#endif + /** * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. * Define to 0 if your device is low on memory.