From f6f40bd3f01ccd8a25587bd517f49db3efdfb5ec Mon Sep 17 00:00:00 2001 From: Ganesh Murthy Date: Thu, 12 Dec 2024 11:02:57 -0500 Subject: [PATCH] =?UTF-8?q?Fixes=20#1694:=20Populated=20the=20SOURCE=5FHOS?= =?UTF-8?q?T=20vanflow=20attribute=20in=20the=20http2=E2=80=A6=20(#1695)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #1694: Populated the SOURCE_HOST vanflow attribute in the http2 adaptor * Fixed formatting in if statement * Removed stream asserts --- src/observers/http2/http2_observer.c | 40 ++++++++++++++-------------- tests/system_tests_http_observer.py | 3 ++- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/observers/http2/http2_observer.c b/src/observers/http2/http2_observer.c index edc16dc98..a50248315 100644 --- a/src/observers/http2/http2_observer.c +++ b/src/observers/http2/http2_observer.c @@ -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); @@ -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]; @@ -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]; @@ -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]; @@ -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) { @@ -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 { @@ -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. @@ -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 { @@ -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; } diff --git a/tests/system_tests_http_observer.py b/tests/system_tests_http_observer.py index 10891d992..864a6b81b 100644 --- a/tests/system_tests_http_observer.py +++ b/tests/system_tests_http_observer.py @@ -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) @@ -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}) ]