aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols/source_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/protocols/source_engine.c')
-rw-r--r--src/lib/protocols/source_engine.c68
1 files changed, 41 insertions, 27 deletions
diff --git a/src/lib/protocols/source_engine.c b/src/lib/protocols/source_engine.c
index 8d92f537e..96d285a07 100644
--- a/src/lib/protocols/source_engine.c
+++ b/src/lib/protocols/source_engine.c
@@ -1,7 +1,7 @@
/*
* source_engine.c
*
- * Source Engine Protocol
+ * Source Engine Protocol (Valve’s A2S protocol)
*
* Copyright (C) 2023 - ntop.org
*
@@ -45,45 +45,59 @@ static void ndpi_search_source_engine(struct ndpi_detection_module_struct *ndpi_
struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct const * const packet = &ndpi_struct->packet;
- char const source_engine_query[] = "Source Engine Query";
- size_t const source_engine_query_len = strlen(source_engine_query);
NDPI_LOG_DBG(ndpi_struct, "search Source Engine\n");
- if (packet->payload_packet_len < source_engine_query_len + 1 /* '\0' */)
- {
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- return;
- }
+ /* https://developer.valvesoftware.com/wiki/Server_queries */
- if (packet->payload[packet->payload_packet_len - 1] != '\0')
+ /* A2S request */
+ if (current_pkt_from_client_to_server(ndpi_struct, flow) &&
+ (packet->payload_packet_len > 8 && packet->payload_packet_len < 30) &&
+ get_u_int32_t(packet->payload, 0) == 0xFFFFFFFF)
{
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- return;
+ if (packet->payload[4] == 'T' || /* A2S_INFO */
+ packet->payload[4] == 'U' || /* A2S_PLAYER */
+ packet->payload[4] == 'V') /* A2S_RULES */
+ {
+ ndpi_int_source_engine_add_connection(ndpi_struct, flow);
+ return;
+ }
}
- if (strncmp((char const *)&packet->payload[packet->payload_packet_len - source_engine_query_len - 1],
- source_engine_query, source_engine_query_len) != 0)
+ /* A2S response */
+ if (current_pkt_from_server_to_client(ndpi_struct, flow))
{
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- return;
+ /* Challenge response */
+ if (packet->payload_packet_len == 9 &&
+ get_u_int32_t(packet->payload, 0) == 0xFFFFFFFF &&
+ packet->payload[4] == 'A')
+ {
+ ndpi_int_source_engine_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if (packet->payload_packet_len > 30 && /* A reasonable length for euristics */
+ get_u_int32_t(packet->payload, 0) == 0xFFFFFFFF)
+ {
+ if (packet->payload[4] == 'I' || /* A2S_INFO */
+ packet->payload[4] == 'D' || /* A2S_PLAYER */
+ packet->payload[4] == 'E') /* A2S_RULES */
+ {
+ ndpi_int_source_engine_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
}
- ndpi_int_source_engine_add_connection(ndpi_struct, flow);
+ NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
}
/* ***************************************************** */
-void init_source_engine_dissector(struct ndpi_detection_module_struct *ndpi_struct,
- u_int32_t *id)
+void init_source_engine_dissector(struct ndpi_detection_module_struct *ndpi_struct)
{
- ndpi_set_bitmask_protocol_detection("Source_Engine", ndpi_struct, *id,
- NDPI_PROTOCOL_SOURCE_ENGINE,
- ndpi_search_source_engine,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
- SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK
- );
-
- *id += 1;
+ register_dissector("Source_Engine", ndpi_struct,
+ ndpi_search_source_engine,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ 1, NDPI_PROTOCOL_SOURCE_ENGINE);
}