enhance: imitate_tcp_packet() support setting tcp options
This commit is contained in:
@@ -36,7 +36,14 @@ uint16_t packet_get_raw_len(const struct packet *pkt);
|
|||||||
const char *packet_get_payload(const struct packet *pkt);
|
const char *packet_get_payload(const struct packet *pkt);
|
||||||
uint16_t packet_get_payload_len(const struct packet *pkt);
|
uint16_t packet_get_payload_len(const struct packet *pkt);
|
||||||
|
|
||||||
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);
|
||||||
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
||||||
struct packet *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len);
|
struct packet *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len);
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ static inline void calc_packet_fingerprint(struct packet_fingerprint *finger)
|
|||||||
finger->tcp_win = (uint16_t)(RANGE(random, 1000, 1460));
|
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_seq(tcphdr, seq);
|
||||||
tcp_hdr_set_ack(tcphdr, ack);
|
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_flags(tcphdr, flags);
|
||||||
tcp_hdr_set_window(tcphdr, win);
|
tcp_hdr_set_window(tcphdr, win);
|
||||||
tcp_hdr_set_urg_ptr(tcphdr, 0);
|
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);
|
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
|
// 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");
|
PACKET_BUILD_LOG_ERROR("imitate TCP packet failed, invalid arguments");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -88,7 +98,7 @@ struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calculate the new packet length
|
// 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;
|
uint16_t new_pkt_len = origin_pkt->data_len - origin_pkt->trim_len - trim;
|
||||||
struct packet *new_pkt = packet_new(new_pkt_len);
|
struct packet *new_pkt = packet_new(new_pkt_len);
|
||||||
if (new_pkt == NULL)
|
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
|
// copy the data to the new packet
|
||||||
char *new_pkt_data = (char *)packet_get_raw_data(new_pkt);
|
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, 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
|
// update the headers of the new packet
|
||||||
struct tcphdr *tcp_hdr = NULL;
|
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:
|
case LAYER_PROTO_TCP:
|
||||||
tcp_hdr = (struct tcphdr *)(new_pkt_data + curr_layer->hdr_offset);
|
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;
|
break;
|
||||||
case LAYER_PROTO_UDP:
|
case LAYER_PROTO_UDP:
|
||||||
udp_hdr = (struct udphdr *)(new_pkt_data + curr_layer->hdr_offset);
|
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);
|
update_ip6_hdr(ip6_hdr, trim);
|
||||||
break;
|
break;
|
||||||
|
case LAYER_PROTO_GTP:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
case LAYER_PROTO_GRE:
|
case LAYER_PROTO_GRE:
|
||||||
// TODO
|
// TODO
|
||||||
break;
|
break;
|
||||||
@@ -239,6 +256,9 @@ struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *u
|
|||||||
}
|
}
|
||||||
update_ip6_hdr(ip6_hdr, trim);
|
update_ip6_hdr(ip6_hdr, trim);
|
||||||
break;
|
break;
|
||||||
|
case LAYER_PROTO_GTP:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
case LAYER_PROTO_GRE:
|
case LAYER_PROTO_GRE:
|
||||||
// TODO
|
// TODO
|
||||||
break;
|
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));
|
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;
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
break;
|
break;
|
||||||
|
case LAYER_PROTO_GTP:
|
||||||
|
// TODO
|
||||||
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
break;
|
||||||
case LAYER_PROTO_GRE:
|
case LAYER_PROTO_GRE:
|
||||||
// TODO
|
// TODO
|
||||||
curr_layer_payload_len += layers[i].hdr_len;
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
|||||||
@@ -7,7 +7,14 @@ extern "C"
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
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);
|
||||||
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
||||||
struct packet *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len);
|
struct packet *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "packet_dump.h"
|
#include "packet_dump.h"
|
||||||
|
#include "packet_utils.h"
|
||||||
|
|
||||||
#define PACKET_DUMP_LOG_ERROR(format, ...) LOG_ERROR("packet dump", format, ##__VA_ARGS__)
|
#define PACKET_DUMP_LOG_ERROR(format, ...) LOG_ERROR("packet dump", format, ##__VA_ARGS__)
|
||||||
|
|
||||||
@@ -30,8 +31,11 @@ struct pcap_file_hdr
|
|||||||
|
|
||||||
// return 0: success
|
// return 0: success
|
||||||
// return -1: failed
|
// return -1: failed
|
||||||
int packet_dump(const char *file, const char *data, uint16_t len)
|
int packet_dump_pcap(const struct packet *pkt, const char *file)
|
||||||
{
|
{
|
||||||
|
const char *data = packet_get_raw_data(pkt);
|
||||||
|
uint16_t len = packet_get_raw_len(pkt);
|
||||||
|
|
||||||
struct pcap_pkt_hdr pkt_hdr = {0};
|
struct pcap_pkt_hdr pkt_hdr = {0};
|
||||||
struct pcap_file_hdr file_hdr = {
|
struct pcap_file_hdr file_hdr = {
|
||||||
.magic = 0xA1B2C3D4,
|
.magic = 0xA1B2C3D4,
|
||||||
@@ -71,3 +75,19 @@ int packet_dump(const char *file, const char *data, uint16_t len)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void packet_dump_hex(const struct packet *pkt, int fd)
|
||||||
|
{
|
||||||
|
const char *data = packet_get_raw_data(pkt);
|
||||||
|
uint16_t len = packet_get_raw_len(pkt);
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (i % 16 == 0)
|
||||||
|
{
|
||||||
|
dprintf(fd, "\n");
|
||||||
|
}
|
||||||
|
dprintf(fd, "%02x ", (unsigned char)data[i]);
|
||||||
|
}
|
||||||
|
dprintf(fd, "\n");
|
||||||
|
}
|
||||||
@@ -9,7 +9,8 @@ extern "C"
|
|||||||
|
|
||||||
// return 0: success
|
// return 0: success
|
||||||
// return -1: failed
|
// return -1: failed
|
||||||
int packet_dump(const char *file, const char *data, uint16_t len);
|
int packet_dump_pcap(const struct packet *pkt, const char *file);
|
||||||
|
void packet_dump_hex(const struct packet *pkt, int fd);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -390,7 +390,6 @@ int dumpfile_io_inject(struct dumpfile_io *handle, uint16_t thr_idx, struct pack
|
|||||||
struct packet_io_stat *stat = &handle->stat[thr_idx];
|
struct packet_io_stat *stat = &handle->stat[thr_idx];
|
||||||
struct tuple6 tuple;
|
struct tuple6 tuple;
|
||||||
|
|
||||||
const char *data;
|
|
||||||
char file[1024] = {0};
|
char file[1024] = {0};
|
||||||
char src_addr[INET6_ADDRSTRLEN] = {0};
|
char src_addr[INET6_ADDRSTRLEN] = {0};
|
||||||
char dst_addr[INET6_ADDRSTRLEN] = {0};
|
char dst_addr[INET6_ADDRSTRLEN] = {0};
|
||||||
@@ -399,7 +398,6 @@ int dumpfile_io_inject(struct dumpfile_io *handle, uint16_t thr_idx, struct pack
|
|||||||
{
|
{
|
||||||
pkt = &pkts[i];
|
pkt = &pkts[i];
|
||||||
len = packet_get_raw_len(pkt);
|
len = packet_get_raw_len(pkt);
|
||||||
data = packet_get_raw_data(pkt);
|
|
||||||
|
|
||||||
stat->inject_pkts++;
|
stat->inject_pkts++;
|
||||||
stat->inject_bytes += len;
|
stat->inject_bytes += len;
|
||||||
@@ -425,7 +423,7 @@ int dumpfile_io_inject(struct dumpfile_io *handle, uint16_t thr_idx, struct pack
|
|||||||
}
|
}
|
||||||
snprintf(file, sizeof(file), "%s/inject-%s:%u-%s:%u-%lu.pcap", handle->work_dir, src_addr, ntohs(tuple.src_port), dst_addr, ntohs(tuple.dst_port), stat->inject_pkts);
|
snprintf(file, sizeof(file), "%s/inject-%s:%u-%s:%u-%lu.pcap", handle->work_dir, src_addr, ntohs(tuple.src_port), dst_addr, ntohs(tuple.dst_port), stat->inject_pkts);
|
||||||
|
|
||||||
if (packet_dump(file, data, len) == -1)
|
if (packet_dump_pcap(pkt, file) == -1)
|
||||||
{
|
{
|
||||||
PACKET_IO_LOG_ERROR("unable to dump pcap file: %s", file);
|
PACKET_IO_LOG_ERROR("unable to dump pcap file: %s", file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ static void imitate_and_send_tcp_packet(struct stellar *st, struct session *sess
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct packet *imitate_pkt = imitate_tcp_packet(origin_pkt, tcp_seq, tcp_ack, tcp_flags, tcp_payload, tcp_payload_len);
|
struct packet *imitate_pkt = imitate_tcp_packet(origin_pkt, tcp_seq, tcp_ack, tcp_flags, NULL, 0, tcp_payload, tcp_payload_len);
|
||||||
if (imitate_pkt == NULL)
|
if (imitate_pkt == NULL)
|
||||||
{
|
{
|
||||||
LOG_ERR("imitate TCP packet failed\n");
|
LOG_ERR("imitate TCP packet failed\n");
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ static void craft_compare(const struct runtime *rte, const struct packet *raw_pk
|
|||||||
error_out:
|
error_out:
|
||||||
char file[256] = {0};
|
char file[256] = {0};
|
||||||
snprintf(file, sizeof(file), "craft%lu.pcap", rte->pcap_count);
|
snprintf(file, sizeof(file), "craft%lu.pcap", rte->pcap_count);
|
||||||
packet_dump(file, new_pkt_data, new_pkt_len);
|
packet_dump_pcap(new_pkt, file);
|
||||||
packet_free(new_pkt);
|
packet_free(new_pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user