Skip to content

Commit 467fbf4

Browse files
committed
Fix ignoring SEQ on FIN
1 parent 6769223 commit 467fbf4

File tree

3 files changed

+51
-11
lines changed

3 files changed

+51
-11
lines changed

mongoose.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4836,10 +4836,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
48364836
uint32_t rem_ip;
48374837
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
48384838
if (pkt->tcp->flags & TH_FIN) {
4839+
uint8_t flags = TH_ACK;
4840+
if (mg_ntohl(pkt->tcp->seq) != s->ack) {
4841+
MG_VERBOSE(("ignoring FIN, SEQ != ACK: %x %x", mg_ntohl(pkt->tcp->seq), s->ack));
4842+
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
4843+
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
4844+
return;
4845+
}
48394846
// If we initiated the closure, we reply with ACK upon receiving FIN
48404847
// If we didn't initiate it, we reply with FIN as part of the normal TCP
48414848
// closure process
4842-
uint8_t flags = TH_ACK;
48434849
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
48444850
s->fin_rcvd = true;
48454851
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {

src/net_builtin.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,10 +688,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
688688
uint32_t rem_ip;
689689
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
690690
if (pkt->tcp->flags & TH_FIN) {
691+
uint8_t flags = TH_ACK;
692+
if (mg_ntohl(pkt->tcp->seq) != s->ack) {
693+
MG_VERBOSE(("ignoring FIN, SEQ != ACK: %x %x", mg_ntohl(pkt->tcp->seq), s->ack));
694+
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
695+
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
696+
return;
697+
}
691698
// If we initiated the closure, we reply with ACK upon receiving FIN
692699
// If we didn't initiate it, we reply with FIN as part of the normal TCP
693700
// closure process
694-
uint8_t flags = TH_ACK;
695701
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
696702
s->fin_rcvd = true;
697703
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {

test/mip_test.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ static bool if_poll(struct mg_tcpip_if *ifp, bool s1) {
120120

121121
static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
122122
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
123-
if (!driver_data->len) return 0;
123+
if (driver_data->len == 0) return 0;
124124
if (len > driver_data->len) len = driver_data->len;
125125
memcpy(buf, driver_data->buf, len);
126126
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,
142142
t.ack = mg_htonl(ack);
143143
t.off = 5 << 4;
144144
memcpy(s_driver_data.buf, e, sizeof(*e));
145+
ip->len = mg_htons((uint16_t)(sizeof(*ip) + sizeof(struct tcp) + payload_len));
145146
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
146-
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(struct tcp));
147-
s_driver_data.len =
148-
sizeof(*e) + sizeof(*ip) + sizeof(struct tcp) + payload_len;
147+
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(t));
148+
s_driver_data.len = sizeof(*e) + sizeof(*ip) + sizeof(t) + payload_len;
149149
}
150150

151151
static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
@@ -199,13 +199,10 @@ static void test_retransmit(void) {
199199
// setting the IP header
200200
memset(&ip, 0, sizeof(ip));
201201
ip.ver = 4 << 4, ip.proto = 6;
202-
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
203202

204203
init_tcp_handshake(&e, &ip, t, &mgr);
205204

206205
// packet with seq_no = 1001
207-
ip.len =
208-
mg_htons(sizeof(struct ip) + sizeof(struct tcp) + /* TCP Payload */ 2);
209206
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 2);
210207
mg_mgr_poll(&mgr, 0);
211208
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
@@ -253,6 +250,39 @@ static void test_retransmit(void) {
253250
ASSERT((t->flags == TH_ACK));
254251
ASSERT((t->ack == mg_htonl(1005))); // OK
255252

253+
// packet with seq_no = 1005 got delayed, send FIN with seq_no = 1007
254+
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN, 0);
255+
mg_mgr_poll(&mgr, 0);
256+
start = mg_millis();
257+
while (!received_response(&s_driver_data)) {
258+
mg_mgr_poll(&mgr, 0);
259+
now = mg_millis() - start;
260+
if (now > 2 * MIP_TCP_ACK_MS)
261+
ASSERT(0); // response should have been received by now
262+
}
263+
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
264+
sizeof(struct ip));
265+
ASSERT((t->flags == TH_ACK));
266+
ASSERT((t->ack == mg_htonl(1005))); // dup ACK
267+
268+
// retransmitting packet with seq_no = 1005
269+
create_tcp_pkt(&e, &ip, 1005, 1, TH_PUSH | TH_ACK, 2);
270+
mg_mgr_poll(&mgr, 0);
271+
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
272+
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
273+
sizeof(struct ip));
274+
ASSERT((t->flags == TH_ACK));
275+
ASSERT((t->ack == mg_htonl(1007))); // OK
276+
277+
// retransmitting FIN packet with seq_no = 1007
278+
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN | TH_ACK, 0);
279+
mg_mgr_poll(&mgr, 0);
280+
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
281+
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
282+
sizeof(struct ip));
283+
ASSERT((t->flags == (TH_FIN | TH_ACK))); // check we respond with FIN ACK
284+
ASSERT((t->ack == mg_htonl(1008))); // OK
285+
256286
s_driver_data.len = 0;
257287
mg_mgr_free(&mgr);
258288
}
@@ -285,12 +315,10 @@ static void test_frag_recv_path(void) {
285315
// setting the IP header
286316
memset(&ip, 0, sizeof(ip));
287317
ip.ver = 0x45, ip.proto = 6;
288-
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
289318

290319
init_tcp_handshake(&e, &ip, t, &mgr);
291320

292321
// send fragmented TCP packet
293-
ip.len = mg_htons(sizeof(struct ip) + sizeof(struct tcp) + 1000);
294322
ip.frag |= IP_MORE_FRAGS_MSK; // setting More Fragments bit to 1
295323
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1000);
296324
s_sent_fragment = 1; // "enable" fn

0 commit comments

Comments
 (0)