enhance: imitate_tcp_packet() support setting tcp options

This commit is contained in:
luwenpeng
2024-07-02 17:55:55 +08:00
parent 5591227b9a
commit 2c0ec4072f
8 changed files with 73 additions and 16 deletions

View File

@@ -34,11 +34,11 @@ static inline void calc_packet_fingerprint(struct packet_fingerprint *finger)
finger->tcp_win = (uint16_t)(RANGE(random, 1000, 1460));
}
static void update_tcp_hdr(struct tcphdr *tcphdr, uint32_t seq, uint32_t ack, uint16_t win, uint8_t flags)
static void update_tcp_hdr(struct tcphdr *tcphdr, uint32_t seq, uint32_t ack, uint16_t win, uint8_t flags, uint16_t opts_len)
{
tcp_hdr_set_seq(tcphdr, seq);
tcp_hdr_set_ack(tcphdr, ack);
tcp_hdr_set_hdr_len(tcphdr, sizeof(struct tcphdr));
tcp_hdr_set_hdr_len(tcphdr, sizeof(struct tcphdr) + opts_len);
tcp_hdr_set_flags(tcphdr, flags);
tcp_hdr_set_window(tcphdr, win);
tcp_hdr_set_urg_ptr(tcphdr, 0);
@@ -69,10 +69,20 @@ static void update_ip6_hdr(struct ip6_hdr *ip6hdr, int trim)
ipv6_hdr_set_payload_len(ip6hdr, len - trim);
}
struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, const char *tcp_payload, uint16_t tcp_payload_len)
/*
* tcp_seq: the sequence number of the new TCP packet (in host byte order)
* tcp_ack: the acknowledgment number of the new TCP packet (in host byte order)
* tcp_options_len: the length of the options (must be a multiple of 4)
*/
struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags,
const char *tcp_options, uint16_t tcp_options_len,
const char *tcp_payload, uint16_t tcp_payload_len)
{
// check arguments
if (origin_pkt == NULL || (tcp_payload == NULL && tcp_payload_len != 0) || (tcp_payload != NULL && tcp_payload_len == 0))
if (origin_pkt == NULL ||
(tcp_options == NULL && tcp_options_len != 0) || (tcp_options != NULL && tcp_options_len == 0) ||
(tcp_payload == NULL && tcp_payload_len != 0) || (tcp_payload != NULL && tcp_payload_len == 0) ||
(tcp_options_len && tcp_options_len % 4 != 0))
{
PACKET_BUILD_LOG_ERROR("imitate TCP packet failed, invalid arguments");
return NULL;
@@ -88,7 +98,7 @@ struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_
}
// calculate the new packet length
int trim = tcp_layer->hdr_len + tcp_layer->pld_len - tcp_payload_len - sizeof(struct tcphdr);
int trim = tcp_layer->hdr_len + tcp_layer->pld_len - tcp_options_len - tcp_payload_len - sizeof(struct tcphdr);
uint16_t new_pkt_len = origin_pkt->data_len - origin_pkt->trim_len - trim;
struct packet *new_pkt = packet_new(new_pkt_len);
if (new_pkt == NULL)
@@ -100,7 +110,11 @@ struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_
// copy the data to the new packet
char *new_pkt_data = (char *)packet_get_raw_data(new_pkt);
memcpy(new_pkt_data, packet_get_raw_data(origin_pkt), tcp_layer->hdr_offset + sizeof(struct tcphdr));
memcpy(new_pkt_data + tcp_layer->hdr_offset + sizeof(struct tcphdr), tcp_payload, tcp_payload_len);
if (tcp_options_len)
{
memcpy(new_pkt_data + tcp_layer->hdr_offset + sizeof(struct tcphdr), tcp_options, tcp_options_len);
}
memcpy(new_pkt_data + tcp_layer->hdr_offset + sizeof(struct tcphdr) + tcp_options_len, tcp_payload, tcp_payload_len);
// update the headers of the new packet
struct tcphdr *tcp_hdr = NULL;
@@ -118,7 +132,7 @@ struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_
{
case LAYER_PROTO_TCP:
tcp_hdr = (struct tcphdr *)(new_pkt_data + curr_layer->hdr_offset);
update_tcp_hdr(tcp_hdr, tcp_seq, tcp_ack, finger.tcp_win, tcp_flags);
update_tcp_hdr(tcp_hdr, tcp_seq, tcp_ack, finger.tcp_win, tcp_flags, tcp_options_len);
break;
case LAYER_PROTO_UDP:
udp_hdr = (struct udphdr *)(new_pkt_data + curr_layer->hdr_offset);
@@ -154,6 +168,9 @@ struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_
}
update_ip6_hdr(ip6_hdr, trim);
break;
case LAYER_PROTO_GTP:
// TODO
break;
case LAYER_PROTO_GRE:
// TODO
break;
@@ -239,6 +256,9 @@ struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *u
}
update_ip6_hdr(ip6_hdr, trim);
break;
case LAYER_PROTO_GTP:
// TODO
break;
case LAYER_PROTO_GRE:
// TODO
break;
@@ -354,6 +374,10 @@ struct packet *craft_packet_from_scratch(const struct layer layers[], uint16_t l
ipv6_hdr_set_payload_len(ip6_hdr, layers[i].hdr_len + curr_layer_payload_len - sizeof(struct ip6_hdr));
curr_layer_payload_len += layers[i].hdr_len;
break;
case LAYER_PROTO_GTP:
// TODO
curr_layer_payload_len += layers[i].hdr_len;
break;
case LAYER_PROTO_GRE:
// TODO
curr_layer_payload_len += layers[i].hdr_len;