Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #1694: Populated the SOURCE_HOST vanflow attribute in the http2… #1695

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions src/observers/http2/http2_observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

const char *HTTP_METHOD = ":method";
const char *HTTP_STATUS = ":status";
const char *X_FORWARDED_FOR = "x-forwarded-for";

ALLOC_DEFINE(qd_http2_stream_info_t);

Expand All @@ -33,7 +34,6 @@ ALLOC_DEFINE(qd_http2_stream_info_t);
*/
static qd_error_t insert_stream_info_into_hashtable(qdpo_transport_handle_t *transport_handle, qd_http2_stream_info_t *stream_info, uint32_t stream_id)
{
assert(stream_id != 0);
qd_hash_t *stream_id_hash = transport_handle->http2.stream_id_hash;
// Convert stream_id to string
char stream_id_str[11];
Expand All @@ -46,7 +46,6 @@ static qd_error_t insert_stream_info_into_hashtable(qdpo_transport_handle_t *tra
*/
static qd_error_t get_stream_info_from_hashtable(qdpo_transport_handle_t *transport_handle, qd_http2_stream_info_t **stream_info, uint32_t stream_id)
{
assert(stream_id != 0);
qd_hash_t *stream_id_hash = transport_handle->http2.stream_id_hash;
// Convert stream_id to string
char stream_id_str[11];
Expand All @@ -59,7 +58,6 @@ static qd_error_t get_stream_info_from_hashtable(qdpo_transport_handle_t *transp
*/
static qd_error_t delete_stream_info_from_hashtable(qdpo_transport_handle_t *transport_handle, uint32_t stream_id)
{
assert(stream_id != 0);
qd_hash_t *stream_id_hash = transport_handle->http2.stream_id_hash;
// Convert stream_id to string
char stream_id_str[11];
Expand Down Expand Up @@ -88,7 +86,7 @@ int on_end_headers_callback(qd_http2_decoder_connection_t *conn_state,
qdpo_transport_handle_t *transport_handle = (qdpo_transport_handle_t *) qd_http2_decoder_connection_get_context(conn_state);
qd_http2_stream_info_t *stream_info = 0;
qd_error_t error = get_stream_info_from_hashtable(transport_handle, &stream_info, stream_id);
if(error == QD_ERROR_NOT_FOUND) {
if (error == QD_ERROR_NOT_FOUND) {
qd_log(LOG_HTTP2_DECODER, QD_LOG_ERROR, "[C%"PRIu64"] on_end_headers_callback - could not find in the hashtable, stream_id=%" PRIu32, transport_handle->conn_id, stream_id);
} else {
if (!from_client) {
Expand Down Expand Up @@ -169,8 +167,7 @@ static int on_data_recv_callback(qd_http2_decoder_connection_t *conn_state,
qdpo_transport_handle_t *transport_handle = (qdpo_transport_handle_t *) qd_http2_decoder_connection_get_context(conn_state);
qd_log(LOG_HTTP2_DECODER, QD_LOG_DEBUG, "[C%"PRIu64"] on_data_recv_callback from_client=%i, end_stream=%i, num_bytes=%"PRIu32" , stream_id=%" PRIu32, transport_handle->conn_id, from_client, end_stream, num_bytes, stream_id);
qd_error_t error = get_stream_info_from_hashtable(transport_handle, &stream_info, stream_id);
assert(stream_info != 0);
if(error == QD_ERROR_NOT_FOUND) {
if (error == QD_ERROR_NOT_FOUND) {
qd_log(LOG_HTTP2_DECODER, QD_LOG_ERROR, "[C%"PRIu64"] on_data_recv_callback - could not find in the hashtable, stream_id=%" PRIu32, transport_handle->conn_id, stream_id);
}
else {
Expand All @@ -194,6 +191,18 @@ static int on_data_recv_callback(qd_http2_decoder_connection_t *conn_state,
return 0;
}

static void set_stream_vflow_attribute(qdpo_transport_handle_t *transport_handle, uint32_t stream_id, vflow_attribute_t attribute_type, const char *string_value)
{
qd_http2_stream_info_t *stream_info = 0;
qd_error_t error = get_stream_info_from_hashtable(transport_handle, &stream_info, stream_id);
if (error == QD_ERROR_NOT_FOUND) {
qd_log(LOG_HTTP2_DECODER, QD_LOG_ERROR, "[C%"PRIu64"] set_stream_vflow_attribute could not find in the hashtable, stream_id=%" PRIu32, transport_handle->conn_id, stream_id);
}
else {
vflow_set_string(stream_info->vflow, attribute_type, string_value);
}
}

/**
* This callback is called for every single header.
* We only care about the http method and the response status code.
Expand All @@ -213,26 +222,14 @@ static int on_header_recv_callback(qd_http2_decoder_connection_t *conn_state,

if (strcmp(HTTP_METHOD, (const char *)name) == 0) {
// Set the http method (GET, POST, PUT, DELETE etc) on the stream's vflow object.
qd_error_t error = get_stream_info_from_hashtable(transport_handle, &stream_info, stream_id);
assert(stream_info != 0);
qd_log(LOG_HTTP2_DECODER, QD_LOG_DEBUG, "[C%"PRIu64"] on_header_recv_callback - HTTP_METHOD=%s, stream_id=%" PRIu32, transport_handle->conn_id, (const char *)value, stream_id);
//
// Set the http request method (GET, POST etc) on the stream's vflow object.
//
if(error == QD_ERROR_NOT_FOUND) {
qd_log(LOG_HTTP2_DECODER, QD_LOG_ERROR, "[C%"PRIu64"] on_header_recv_callback - HTTP_METHOD -could not find in the hashtable, stream_id=%" PRIu32, transport_handle->conn_id, stream_id);
}
else {
vflow_set_string(stream_info->vflow, VFLOW_ATTRIBUTE_METHOD, (const char *)value);
}

set_stream_vflow_attribute(transport_handle, stream_id, VFLOW_ATTRIBUTE_METHOD, (const char *)value);
} else if (strcmp(HTTP_STATUS, (const char *)name) == 0) {
qd_error_t error = get_stream_info_from_hashtable(transport_handle, &stream_info, stream_id);
assert(stream_info != 0);
//
// We expect that the above call to get_stream_info_from_hashtable() should return a valid stream_info object.
//
if(error == QD_ERROR_NOT_FOUND) {
if (error == QD_ERROR_NOT_FOUND) {
qd_log(LOG_HTTP2_DECODER, QD_LOG_ERROR, "[C%"PRIu64"] on_header_recv_callback - HTTP_STATUS -could not find in the hashtable, stream_id=%" PRIu32, transport_handle->conn_id, stream_id);
}
else {
Expand All @@ -244,9 +241,12 @@ static int on_header_recv_callback(qd_http2_decoder_connection_t *conn_state,
//
// Set the http response status (200, 404 etc) on the stream's vflow object.
//
qd_log(LOG_HTTP2_DECODER, QD_LOG_DEBUG, "[C%"PRIu64"] on_header_recv_callback - HTTP_STATUS=%s, stream_id=%" PRIu32, transport_handle->conn_id, (const char *)value, stream_id);
vflow_set_string(stream_info->vflow, VFLOW_ATTRIBUTE_RESULT, status_code_str);
}
}
} else if (strcmp(X_FORWARDED_FOR, (const char *)name) == 0) {
set_stream_vflow_attribute(transport_handle, stream_id, VFLOW_ATTRIBUTE_SOURCE_HOST, (const char *)value);
}
return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion tests/system_tests_http_observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ def test_head_request(self):
self.assertTrue(success, f"Failed to match records {snooper_thread.get_results()}")

# Pass traffic:
_, out, _ = run_local_curl(get_address(self.router_qdra), args=['--head'])
_, out, _ = run_local_curl(get_address(self.router_qdra), args=['--head', '--header', 'X-Forwarded-For: 192.168.0.2'])
self.assertIn('HTTP/2 200', out)
self.assertIn('content-type: text/html', out)

Expand All @@ -524,6 +524,7 @@ def test_head_request(self):
('BIFLOW_APP', {'PROTOCOL': 'HTTP/2',
'METHOD': 'HEAD',
'RESULT': '200',
'SOURCE_HOST': '192.168.0.2',
'STREAM_ID': ANY_VALUE,
'END_TIME': ANY_VALUE})
]
Expand Down
Loading