diff --git a/include/stellar/packet.h b/include/stellar/packet.h index 9562dfa..d0b8814 100644 --- a/include/stellar/packet.h +++ b/include/stellar/packet.h @@ -36,7 +36,14 @@ uint16_t packet_get_raw_len(const struct packet *pkt); const char *packet_get_payload(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 *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len); diff --git a/src/packet/packet_build.cpp b/src/packet/packet_build.cpp index 16dfbb3..5ee834f 100644 --- a/src/packet/packet_build.cpp +++ b/src/packet/packet_build.cpp @@ -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; diff --git a/src/packet/packet_build.h b/src/packet/packet_build.h index 7391016..58a1a31 100644 --- a/src/packet/packet_build.h +++ b/src/packet/packet_build.h @@ -7,7 +7,14 @@ extern "C" #include -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 *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len); diff --git a/src/packet/packet_dump.cpp b/src/packet/packet_dump.cpp index 9de3e9b..b7ffc43 100644 --- a/src/packet/packet_dump.cpp +++ b/src/packet/packet_dump.cpp @@ -6,6 +6,7 @@ #include "log.h" #include "packet_dump.h" +#include "packet_utils.h" #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 -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_file_hdr file_hdr = { .magic = 0xA1B2C3D4, @@ -71,3 +75,19 @@ int packet_dump(const char *file, const char *data, uint16_t len) 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"); +} \ No newline at end of file diff --git a/src/packet/packet_dump.h b/src/packet/packet_dump.h index 68ed69e..e365f09 100644 --- a/src/packet/packet_dump.h +++ b/src/packet/packet_dump.h @@ -9,7 +9,8 @@ extern "C" // return 0: success // 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 } diff --git a/src/packet_io/dumpfile_io.cpp b/src/packet_io/dumpfile_io.cpp index c43c89f..13a7ee4 100644 --- a/src/packet_io/dumpfile_io.cpp +++ b/src/packet_io/dumpfile_io.cpp @@ -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 tuple6 tuple; - const char *data; char file[1024] = {0}; char src_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]; len = packet_get_raw_len(pkt); - data = packet_get_raw_data(pkt); stat->inject_pkts++; 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); - 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); } diff --git a/test/packet_inject/packet_inject.cpp b/test/packet_inject/packet_inject.cpp index 7578bf5..d05cdd8 100644 --- a/test/packet_inject/packet_inject.cpp +++ b/test/packet_inject/packet_inject.cpp @@ -388,7 +388,7 @@ static void imitate_and_send_tcp_packet(struct stellar *st, struct session *sess 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) { LOG_ERR("imitate TCP packet failed\n"); diff --git a/test/packet_tool/packet_tool.cpp b/test/packet_tool/packet_tool.cpp index e51d8cf..e796c1a 100644 --- a/test/packet_tool/packet_tool.cpp +++ b/test/packet_tool/packet_tool.cpp @@ -288,7 +288,7 @@ static void craft_compare(const struct runtime *rte, const struct packet *raw_pk error_out: char file[256] = {0}; 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); }