aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMosder <xmosder12@gmail.com>2026-07-28 11:14:01 +0200
committerMosder <xmosder12@gmail.com>2026-07-28 11:14:14 +0200
commit95763527e73c0d06d3887e4a2da22f627f13bfaa (patch)
tree6580af706ea8058f609644ea0db84d4d9d99ea0d
parent0b58af7bd1c0c060c55dadb33603570d0c044e14 (diff)
feat: added support for streams from both server and client (uhm, actually, there's only one stream, since TCP streams are bidirectional, blah, blah, blah...)
-rw-r--r--analyzer/analyzer.c22
-rw-r--r--analyzer/parser/find_parse_functions.h2
-rw-r--r--analyzer/parser/parser.c4
-rw-r--r--analyzer/parser/parser_defs.h1
-rw-r--r--analyzer/utils/tcp.c11
-rw-r--r--analyzer/utils/tcp.h28
6 files changed, 47 insertions, 21 deletions
diff --git a/analyzer/analyzer.c b/analyzer/analyzer.c
index aa4a645..088e6d4 100644
--- a/analyzer/analyzer.c
+++ b/analyzer/analyzer.c
@@ -7,9 +7,13 @@
#include "render.h"
#include "utils/tcp.h"
-// loop through packets received from pcap_handle and analyze the TCP stream
+// loop through packets received from pcap_handle and analyze the TCP streams
void analyzer_loop(
- TCPStream *stream, pcap_t *pcap_handle, void *state, void (*parsed_data_handler)(void *state, ParsedData *parsed_data, size_t n_parsed_data)
+ TCPStream *server_stream,
+ TCPStream *client_stream,
+ pcap_t *pcap_handle,
+ void *state,
+ void (*parsed_data_handler)(void *state, ParsedData *parsed_data, size_t n_parsed_data)
) {
// read packets from handle
struct pcap_pkthdr *packet_data;
@@ -19,7 +23,11 @@ void analyzer_loop(
TCPSegment segment = get_segment_from_packet(packet, packet_data);
// handle the new segment if it's correct one and has data in it (ignore SYN)
- if (segment.len > 0 && handle_segment(stream, segment)) {
+ if (segment.len <= 0)
+ continue;
+
+ TCPStream *stream = segment.src == SERVER ? server_stream : client_stream;
+ if (handle_segment(stream, segment)) {
// if it was added to the stream - parse it
size_t parsed_len;
size_t n_parsed_data;
@@ -64,9 +72,11 @@ void analyze_file(char *path) {
}
// analyze the file
- TCPStream stream = new_stream();
+ TCPStream server_stream = new_stream(SERVER);
+ TCPStream client_stream = new_stream(CLIENT);
int state = 0;
- analyzer_loop(&stream, handle, &state, file_parsed_data_handler);
- destroy_stream(stream);
+ analyzer_loop(&server_stream, &client_stream, handle, &state, file_parsed_data_handler);
+ destroy_stream(server_stream);
+ destroy_stream(client_stream);
pcap_close(handle);
}
diff --git a/analyzer/parser/find_parse_functions.h b/analyzer/parser/find_parse_functions.h
index e2c2acb..ffe6ef0 100644
--- a/analyzer/parser/find_parse_functions.h
+++ b/analyzer/parser/find_parse_functions.h
@@ -3,4 +3,4 @@
#include "parser/fight_results/fight_results.h"
-FindParseFunctions all_find_parse_functions[] = {{find_fight_results, parse_fight_results}};
+FindParseFunctions all_find_parse_functions[] = {{find_fight_results, parse_fight_results, SERVER}};
diff --git a/analyzer/parser/parser.c b/analyzer/parser/parser.c
index d00cd97..07980e5 100644
--- a/analyzer/parser/parser.c
+++ b/analyzer/parser/parser.c
@@ -9,6 +9,10 @@
byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_length, parse_function_t **earliest_parse_fun) {
byte_t *earliest_data = NULL;
for (size_t i = 0; i < ARR_LEN(all_find_parse_functions); i++) {
+ // ignore if not correct stream
+ if (stream->src != all_find_parse_functions[i].stream_src)
+ continue;
+
int length;
byte_t *data = all_find_parse_functions[i].find_fn(stream, stream_offset, &length);
// if it's the first found or earlier than earliest - save it
diff --git a/analyzer/parser/parser_defs.h b/analyzer/parser/parser_defs.h
index 75b0366..c64e138 100644
--- a/analyzer/parser/parser_defs.h
+++ b/analyzer/parser/parser_defs.h
@@ -37,6 +37,7 @@ typedef ParsedData parse_function_t(byte_t *data, size_t length);
typedef struct {
find_function_t *find_fn;
parse_function_t *parse_fn;
+ ConnectionSource stream_src; // which stream to look for the data
} FindParseFunctions;
#endif
diff --git a/analyzer/utils/tcp.c b/analyzer/utils/tcp.c
index 6309e64..7a79c67 100644
--- a/analyzer/utils/tcp.c
+++ b/analyzer/utils/tcp.c
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
+#include "headers/server.h"
#include "utils/memory.h"
#include "utils/tcp_seq_math.h"
@@ -50,6 +51,9 @@ TCPSegment get_segment_from_packet(const byte_t *packet, const struct pcap_pkthd
const struct ip *ip_header = (const struct ip *)(packet + eth_header_len);
int ip_header_len = ip_header->ip_hl * 4;
+ // get source
+ segment.src = ip_header->ip_src.s_addr == inet_addr(SERVER_IP) ? SERVER : CLIENT;
+
// check if it's TCP
if (ip_header->ip_p != IPPROTO_TCP)
return segment;
@@ -58,9 +62,9 @@ TCPSegment get_segment_from_packet(const byte_t *packet, const struct pcap_pkthd
const struct tcphdr *tcp_header = (const struct tcphdr *)(packet + eth_header_len + ip_header_len);
int tcp_header_len = tcp_header->th_off * 4;
- // get TCP sequence number and destination port
+ // get TCP sequence number and client port
segment.seq = ntohl(tcp_header->seq);
- segment.port = ntohs(tcp_header->th_dport);
+ segment.port = ntohs(segment.src == SERVER ? tcp_header->th_dport : tcp_header->th_sport);
// get payload
int total_header_len = eth_header_len + ip_header_len + tcp_header_len;
@@ -70,7 +74,7 @@ TCPSegment get_segment_from_packet(const byte_t *packet, const struct pcap_pkthd
return segment;
}
-TCPStream new_stream() {
+TCPStream new_stream(ConnectionSource src) {
// clang-format off
TCPStream stream = {
.data = safe_malloc(INIT_STREAM_CAPACITY),
@@ -78,6 +82,7 @@ TCPStream new_stream() {
.capacity = INIT_STREAM_CAPACITY,
.seq = 0,
.port = 0,
+ .src = src,
.pending = NULL
};
// clang-format on
diff --git a/analyzer/utils/tcp.h b/analyzer/utils/tcp.h
index 13cbb15..382c585 100644
--- a/analyzer/utils/tcp.h
+++ b/analyzer/utils/tcp.h
@@ -10,13 +10,16 @@
typedef unsigned char byte_t;
+typedef enum { SERVER, CLIENT } ConnectionSource;
+
// struct to persistently store TCP segments
// payload field is malloced and needs to be freed
typedef struct {
- byte_t *payload; // payload in the segment
- size_t len; // length of the payload
- uint32_t seq; // TCP sequence number of the segment
- uint16_t port; // destination (client) port of connection the segment was received from
+ byte_t *payload; // payload in the segment
+ size_t len; // length of the payload
+ uint32_t seq; // TCP sequence number of the segment
+ uint16_t port; // client port of connection the segment was received from
+ ConnectionSource src; // segment's source
} TCPSegment;
// get TCP segment from captured packet
@@ -29,20 +32,23 @@ extern TCPSegment get_segment_from_packet(const byte_t *packet, const struct pca
// struct that stores all the information about stream
typedef struct {
- byte_t *data; // bytes in the stream
- size_t len; // length of the stream
- size_t capacity; // capacity of the data buffer
- uint32_t seq; // TCP sequence number of the first byte in the stream
- uint16_t port; // destination (client) port of current analyzed connection
- Heap *pending; // min heap of segments yet to be added to stream (sorted by TCP sequence number)
+ byte_t *data; // bytes in the stream
+ size_t len; // length of the stream
+ size_t capacity; // capacity of the data buffer
+ uint32_t seq; // TCP sequence number of the first byte in the stream
+ uint16_t port; // client port of currently analyzed connection
+ ConnectionSource src; // stream's source
+ Heap *pending; // min heap of segments yet to be added to stream (sorted by TCP sequence number)
} TCPStream;
#define INIT_STREAM_CAPACITY 256
// initialize new stream
+// params:
+// - src - source of the stream
// returns:
// newly created TCPStream structure with initial values
-extern TCPStream new_stream();
+extern TCPStream new_stream(ConnectionSource src);
// cleanup memory allocations within stream
// params: