mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-08 16:11:18 +00:00
Fix ignoring SEQ on FIN
This commit is contained in:
1 parent
6769223ce1
commit
467fbf4bb4
3 files changed
+51
-11
No files matched your search
+7
-1
@@ -4836,10 +4836,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
|||||||
uint32_t rem_ip;
|
uint32_t rem_ip;
|
||||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (pkt->tcp->flags & TH_FIN) {
|
if (pkt->tcp->flags & TH_FIN) {
|
||||||
|
uint8_t flags = TH_ACK;
|
||||||
|
if (mg_ntohl(pkt->tcp->seq) != s->ack) {
|
||||||
|
MG_VERBOSE(("ignoring FIN, SEQ != ACK: %x %x", mg_ntohl(pkt->tcp->seq), s->ack));
|
||||||
|
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||||
|
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// If we initiated the closure, we reply with ACK upon receiving FIN
|
// If we initiated the closure, we reply with ACK upon receiving FIN
|
||||||
// If we didn't initiate it, we reply with FIN as part of the normal TCP
|
// If we didn't initiate it, we reply with FIN as part of the normal TCP
|
||||||
// closure process
|
// closure process
|
||||||
uint8_t flags = TH_ACK;
|
|
||||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
||||||
s->fin_rcvd = true;
|
s->fin_rcvd = true;
|
||||||
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
||||||
|
|||||||
+7
-1
@@ -688,10 +688,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
|||||||
uint32_t rem_ip;
|
uint32_t rem_ip;
|
||||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
if (pkt->tcp->flags & TH_FIN) {
|
if (pkt->tcp->flags & TH_FIN) {
|
||||||
|
uint8_t flags = TH_ACK;
|
||||||
|
if (mg_ntohl(pkt->tcp->seq) != s->ack) {
|
||||||
|
MG_VERBOSE(("ignoring FIN, SEQ != ACK: %x %x", mg_ntohl(pkt->tcp->seq), s->ack));
|
||||||
|
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||||
|
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// If we initiated the closure, we reply with ACK upon receiving FIN
|
// If we initiated the closure, we reply with ACK upon receiving FIN
|
||||||
// If we didn't initiate it, we reply with FIN as part of the normal TCP
|
// If we didn't initiate it, we reply with FIN as part of the normal TCP
|
||||||
// closure process
|
// closure process
|
||||||
uint8_t flags = TH_ACK;
|
|
||||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
||||||
s->fin_rcvd = true;
|
s->fin_rcvd = true;
|
||||||
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
||||||
|
|||||||
+37
-9
@@ -120,7 +120,7 @@ static bool if_poll(struct mg_tcpip_if *ifp, bool s1) {
|
|||||||
|
|
||||||
static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||||
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
||||||
if (!driver_data->len) return 0;
|
if (driver_data->len == 0) return 0;
|
||||||
if (len > driver_data->len) len = driver_data->len;
|
if (len > driver_data->len) len = driver_data->len;
|
||||||
memcpy(buf, driver_data->buf, len);
|
memcpy(buf, driver_data->buf, len);
|
||||||
driver_data->len = 0; // cleaning up the buffer
|
driver_data->len = 0; // cleaning up the buffer
|
||||||
@@ -142,10 +142,10 @@ static void create_tcp_pkt(struct eth *e, struct ip *ip, uint32_t seq,
|
|||||||
t.ack = mg_htonl(ack);
|
t.ack = mg_htonl(ack);
|
||||||
t.off = 5 << 4;
|
t.off = 5 << 4;
|
||||||
memcpy(s_driver_data.buf, e, sizeof(*e));
|
memcpy(s_driver_data.buf, e, sizeof(*e));
|
||||||
|
ip->len = mg_htons((uint16_t)(sizeof(*ip) + sizeof(struct tcp) + payload_len));
|
||||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(struct tcp));
|
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(t));
|
||||||
s_driver_data.len =
|
s_driver_data.len = sizeof(*e) + sizeof(*ip) + sizeof(t) + payload_len;
|
||||||
sizeof(*e) + sizeof(*ip) + sizeof(struct tcp) + payload_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
|
static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
|
||||||
@@ -199,13 +199,10 @@ static void test_retransmit(void) {
|
|||||||
// setting the IP header
|
// setting the IP header
|
||||||
memset(&ip, 0, sizeof(ip));
|
memset(&ip, 0, sizeof(ip));
|
||||||
ip.ver = 4 << 4, ip.proto = 6;
|
ip.ver = 4 << 4, ip.proto = 6;
|
||||||
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
|
||||||
|
|
||||||
init_tcp_handshake(&e, &ip, t, &mgr);
|
init_tcp_handshake(&e, &ip, t, &mgr);
|
||||||
|
|
||||||
// packet with seq_no = 1001
|
// packet with seq_no = 1001
|
||||||
ip.len =
|
|
||||||
mg_htons(sizeof(struct ip) + sizeof(struct tcp) + /* TCP Payload */ 2);
|
|
||||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 2);
|
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 2);
|
||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
@@ -253,6 +250,39 @@ static void test_retransmit(void) {
|
|||||||
ASSERT((t->flags == TH_ACK));
|
ASSERT((t->flags == TH_ACK));
|
||||||
ASSERT((t->ack == mg_htonl(1005))); // OK
|
ASSERT((t->ack == mg_htonl(1005))); // OK
|
||||||
|
|
||||||
|
// packet with seq_no = 1005 got delayed, send FIN with seq_no = 1007
|
||||||
|
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN, 0);
|
||||||
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
start = mg_millis();
|
||||||
|
while (!received_response(&s_driver_data)) {
|
||||||
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
now = mg_millis() - start;
|
||||||
|
if (now > 2 * MIP_TCP_ACK_MS)
|
||||||
|
ASSERT(0); // response should have been received by now
|
||||||
|
}
|
||||||
|
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||||
|
sizeof(struct ip));
|
||||||
|
ASSERT((t->flags == TH_ACK));
|
||||||
|
ASSERT((t->ack == mg_htonl(1005))); // dup ACK
|
||||||
|
|
||||||
|
// retransmitting packet with seq_no = 1005
|
||||||
|
create_tcp_pkt(&e, &ip, 1005, 1, TH_PUSH | TH_ACK, 2);
|
||||||
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
|
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||||
|
sizeof(struct ip));
|
||||||
|
ASSERT((t->flags == TH_ACK));
|
||||||
|
ASSERT((t->ack == mg_htonl(1007))); // OK
|
||||||
|
|
||||||
|
// retransmitting FIN packet with seq_no = 1007
|
||||||
|
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN | TH_ACK, 0);
|
||||||
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
|
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||||
|
sizeof(struct ip));
|
||||||
|
ASSERT((t->flags == (TH_FIN | TH_ACK))); // check we respond with FIN ACK
|
||||||
|
ASSERT((t->ack == mg_htonl(1008))); // OK
|
||||||
|
|
||||||
s_driver_data.len = 0;
|
s_driver_data.len = 0;
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
}
|
}
|
||||||
@@ -285,12 +315,10 @@ static void test_frag_recv_path(void) {
|
|||||||
// setting the IP header
|
// setting the IP header
|
||||||
memset(&ip, 0, sizeof(ip));
|
memset(&ip, 0, sizeof(ip));
|
||||||
ip.ver = 0x45, ip.proto = 6;
|
ip.ver = 0x45, ip.proto = 6;
|
||||||
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
|
||||||
|
|
||||||
init_tcp_handshake(&e, &ip, t, &mgr);
|
init_tcp_handshake(&e, &ip, t, &mgr);
|
||||||
|
|
||||||
// send fragmented TCP packet
|
// send fragmented TCP packet
|
||||||
ip.len = mg_htons(sizeof(struct ip) + sizeof(struct tcp) + 1000);
|
|
||||||
ip.frag |= IP_MORE_FRAGS_MSK; // setting More Fragments bit to 1
|
ip.frag |= IP_MORE_FRAGS_MSK; // setting More Fragments bit to 1
|
||||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1000);
|
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1000);
|
||||||
s_sent_fragment = 1; // "enable" fn
|
s_sent_fragment = 1; // "enable" fn
|
||||||
|
|||||||
Reference in new issue
Block a user