diff --git a/src/session/session_manager.cpp b/src/session/session_manager.cpp index d5d0bc1..fa89eee 100644 --- a/src/session/session_manager.cpp +++ b/src/session/session_manager.cpp @@ -658,7 +658,8 @@ static struct session *session_manager_lookup_tcp_session(struct session_manager enum flow_direction dir = identify_direction_by_history(sess, key); struct tcp_half *half = &sess->tcp_halfs[dir]; - if (half->isn && half->isn != tcp_hdr_get_seq(hdr)) + if ((half->isn && half->isn != tcp_hdr_get_seq(hdr)) || // recv SYN with different ISN + ((half->history & TH_FIN) || (half->history & TH_RST))) // recv SYN after FIN or RST { // TCP port reuse, evict old session session_manager_evicte_session(mgr, sess, now, PORT_REUSE_EVICT); diff --git a/src/session/session_priv.h b/src/session/session_priv.h index e76141b..46fdbd2 100644 --- a/src/session/session_priv.h +++ b/src/session/session_priv.h @@ -24,15 +24,16 @@ extern "C" struct tcp_half { struct tcp_reassembly *assembler; - struct tcp_segment in_order; - uint32_t in_order_ref; + struct tcp_segment in_order; // current packet in order segment + uint32_t in_order_ref; // reference count of current packet in order segment - uint32_t isn; - uint32_t seq; - uint32_t ack; - uint16_t len; - uint8_t flags; - uint8_t history; + uint32_t seq; // current packet sequence number + uint32_t ack; // current packet ack number + uint16_t len; // current packet payload length + uint8_t flags; // current packet flags + + uint32_t isn; // current direction initial sequence number + uint8_t history; // current direction received flags }; /* diff --git a/src/session/session_transition.cpp b/src/session/session_transition.cpp index be75b0a..883c80c 100644 --- a/src/session/session_transition.cpp +++ b/src/session/session_transition.cpp @@ -21,19 +21,19 @@ struct session_transition * SESSION_STATE_OPENING -> SESSION_STATE_ACTIVE ( TCP_DATA | UDP_DATA ) * SESSION_STATE_OPENING -> SESSION_STATE_CLOSING ( TCP_FIN | TCP_RST | TIMEOUT ) * SESSION_STATE_OPENING -> SESSION_STATE_DISCARD ( USER_CLOSE ) - * SESSION_STATE_OPENING -> SESSION_STATE_CLOSED ( LRU_EVICT ) + * SESSION_STATE_OPENING -> SESSION_STATE_CLOSED ( LRU_EVICT | PORT_REUSE_EVICT ) * * SESSION_STATE_ACTIVE -> SESSION_STATE_ACTIVE ( NONE ) * SESSION_STATE_ACTIVE -> SESSION_STATE_CLOSING ( TCP_FIN | TCP_RST | TIMEOUT ) * SESSION_STATE_ACTIVE -> SESSION_STATE_DISCARD ( USER_CLOSE ) - * SESSION_STATE_ACTIVE -> SESSION_STATE_CLOSED ( LRU_EVICT ) + * SESSION_STATE_ACTIVE -> SESSION_STATE_CLOSED ( LRU_EVICT | PORT_REUSE_EVICT) * * SESSION_STATE_CLOSING -> SESSION_STATE_CLOSING ( NONE ) * SESSION_STATE_CLOSING -> SESSION_STATE_DISCARD ( USER_CLOSE ) - * SESSION_STATE_CLOSING -> SESSION_STATE_CLOSED ( LRU_EVICT | TIMEOUT ) + * SESSION_STATE_CLOSING -> SESSION_STATE_CLOSED ( LRU_EVICT | PORT_REUSE_EVICT | TIMEOUT ) * * SESSION_STATE_DISCARD -> SESSION_STATE_DISCARD ( NONE ) - * SESSION_STATE_DISCARD -> SESSION_STATE_CLOSED ( LRU_EVICT | TIMEOUT ) + * SESSION_STATE_DISCARD -> SESSION_STATE_CLOSED ( LRU_EVICT | PORT_REUSE_EVICT | TIMEOUT ) */ static void session_inputs_to_str(int inputs, char *buff, int len) diff --git a/src/stellar/inject.cpp b/src/stellar/inject.cpp index 39cc889..400d3c1 100644 --- a/src/stellar/inject.cpp +++ b/src/stellar/inject.cpp @@ -243,7 +243,7 @@ int build_tcp_packet(const struct packet *first, uint16_t ip_id, uint8_t ip_ttl, switch (curr->type) { case LAYER_TYPE_TCP: - trim = curr->hdr_len + curr->pld_len - sizeof(struct tcphdr) + pld_len; + trim = curr->hdr_len + curr->pld_len - sizeof(struct tcphdr) - pld_len; if (len - trim > buff_size) { return -ENOMEM; @@ -330,7 +330,7 @@ int build_udp_packet(const struct packet *first, const char *udp_pld, int pld_le switch (curr->type) { case LAYER_TYPE_UDP: - trim = curr->hdr_len + curr->pld_len - sizeof(struct udphdr) + pld_len; + trim = curr->hdr_len + curr->pld_len - sizeof(struct udphdr) - pld_len; if (len - trim > buff_size) { return -ENOMEM; diff --git a/test/packet_injector.cpp b/test/packet_injector.cpp index 5945b1e..ef73418 100644 --- a/test/packet_injector.cpp +++ b/test/packet_injector.cpp @@ -51,16 +51,23 @@ struct inject_rule static void inject_packet_plugin(struct session *sess, struct packet *pkt, struct inject_rule *rule) { + char buffer[1024] = {0}; const struct tuple6 *tuple = session_get_tuple6(sess); - if (rule->ip_type == 4 && memcmp(&tuple->src_addr.v4, &rule->v4, sizeof(struct in_addr)) && memcmp(&tuple->dst_addr.v4, &rule->v4, sizeof(struct in_addr))) + if (rule->ip_type == 4 && + memcmp(&tuple->src_addr.v4, &rule->v4, sizeof(struct in_addr)) && + memcmp(&tuple->dst_addr.v4, &rule->v4, sizeof(struct in_addr))) { return; } - if (rule->ip_type == 6 && memcmp(&tuple->src_addr.v6, &rule->v6, sizeof(struct in6_addr)) && memcmp(&tuple->dst_addr.v6, &rule->v6, sizeof(struct in6_addr))) + if (rule->ip_type == 6 && + memcmp(&tuple->src_addr.v6, &rule->v6, sizeof(struct in6_addr)) && + memcmp(&tuple->dst_addr.v6, &rule->v6, sizeof(struct in6_addr))) { return; } - if (rule->port != 0 && tuple->src_port != rule->port && tuple->dst_port != rule->port) + if (rule->port != 0 && + tuple->src_port != rule->port && + tuple->dst_port != rule->port) { return; } @@ -72,7 +79,8 @@ static void inject_packet_plugin(struct session *sess, struct packet *pkt, struc { return; } - if (session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_INJECTED_PACKETS_SUCCESS) > 0 && session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_INJECTED_PACKETS_SUCCESS) > 0) + if (session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_INJECTED_PACKETS_SUCCESS) > 0 || + session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_INJECTED_PACKETS_SUCCESS) > 0) { return; } @@ -89,6 +97,13 @@ static void inject_packet_plugin(struct session *sess, struct packet *pkt, struc EXPECT_TRUE(stellar_inject_tcp_fin(sess, FLOW_DIRECTION_S2C) > 0); break; case INJECT_TYPE_TCP_PAYLOAD: + packet_set_action(pkt, PACKET_ACTION_DROP); + snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", 5 + 5 + 2, "Hello"); + EXPECT_TRUE(stellar_inject_payload(sess, FLOW_DIRECTION_S2C, buffer, strlen(buffer)) > 0); // inject payload to client + EXPECT_TRUE(stellar_inject_payload(sess, FLOW_DIRECTION_S2C, "World\r\n", 7) > 0); + EXPECT_TRUE(stellar_inject_tcp_fin(sess, FLOW_DIRECTION_S2C) > 0); // inject FIN to client + EXPECT_TRUE(stellar_inject_tcp_rst(sess, FLOW_DIRECTION_C2S) > 0); // inject RST to server + break; case INJECT_TYPE_UDP_PAYLOAD: packet_set_action(pkt, PACKET_ACTION_DROP); EXPECT_TRUE(stellar_inject_payload(sess, FLOW_DIRECTION_C2S, "Hello Server", 12) > 0);