From d58177c50bb36a712c645fe8c13d126ebadbdc7f Mon Sep 17 00:00:00 2001
From: Matus Fabian <matfabia@cisco.com>
Date: Thu, 8 Aug 2024 12:50:32 +0200
Subject: http: authority-form target parsing/serializing

Type: improvement
Change-Id: Ifb90818a3526d3d4030a66b1ef7eebedfe97978f
Signed-off-by: Matus Fabian <matfabia@cisco.com>
---
 src/plugins/http/CMakeLists.txt |  1 +
 src/plugins/http/http.h         | 52 +++++++++++++++++++++++++++++++++++++++++
 src/plugins/http/http_test.c    | 34 +++++++++++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 src/plugins/http/http_test.c

(limited to 'src')

diff --git a/src/plugins/http/CMakeLists.txt b/src/plugins/http/CMakeLists.txt
index d9cd84a3955..c51a7dce36d 100644
--- a/src/plugins/http/CMakeLists.txt
+++ b/src/plugins/http/CMakeLists.txt
@@ -16,4 +16,5 @@ add_vpp_plugin(http
   http.c
   http_buffer.c
   http_timer.c
+  http_test.c
 )
diff --git a/src/plugins/http/http.h b/src/plugins/http/http.h
index 63d05860099..19147904bfd 100644
--- a/src/plugins/http/http.h
+++ b/src/plugins/http/http.h
@@ -921,6 +921,58 @@ http_serialize_headers (http_header_t *headers)
   return headers_buf;
 }
 
+typedef struct
+{
+  ip46_address_t ip;
+  u16 port;
+  u8 is_ip4;
+} http_uri_t;
+
+always_inline int
+http_parse_authority_form_target (u8 *target, http_uri_t *authority)
+{
+  unformat_input_t input;
+  u32 port;
+  int rv = 0;
+
+  unformat_init_vector (&input, vec_dup (target));
+  if (unformat (&input, "[%U]:%d", unformat_ip6_address, &authority->ip.ip6,
+		&port))
+    {
+      authority->port = clib_host_to_net_u16 (port);
+      authority->is_ip4 = 0;
+    }
+  else if (unformat (&input, "%U:%d", unformat_ip4_address, &authority->ip.ip4,
+		     &port))
+    {
+      authority->port = clib_host_to_net_u16 (port);
+      authority->is_ip4 = 1;
+    }
+  /* TODO reg-name resolution */
+  else
+    {
+      clib_warning ("unsupported format '%v'", target);
+      rv = -1;
+    }
+  unformat_free (&input);
+  return rv;
+}
+
+always_inline u8 *
+http_serialize_authority_form_target (http_uri_t *authority)
+{
+  u8 *s;
+
+  if (authority->is_ip4)
+    s = format (0, "%U:%d", format_ip4_address, &authority->ip.ip4,
+		clib_net_to_host_u16 (authority->port));
+  else
+    s = format (0, "[%U]:%d", format_ip6_address, &authority->ip.ip6,
+		clib_net_to_host_u16 (authority->port));
+
+  return s;
+}
+
 #endif /* SRC_PLUGINS_HTTP_HTTP_H_ */
 
 /*
diff --git a/src/plugins/http/http_test.c b/src/plugins/http/http_test.c
new file mode 100644
index 00000000000..1f2f21dd19a
--- /dev/null
+++ b/src/plugins/http/http_test.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright(c) 2024 Cisco Systems, Inc.
+ */
+
+#include <http/http.h>
+
+static clib_error_t *
+test_http_authority_command_fn (vlib_main_t *vm, unformat_input_t *input,
+				vlib_cli_command_t *cmd)
+{
+  u8 *target = 0;
+  http_uri_t authority;
+  int rv;
+
+  if (!unformat (input, "%v", &target))
+    return clib_error_return (0, "error: no input provided");
+
+  rv = http_parse_authority_form_target (target, &authority);
+  vec_free (target);
+  if (rv)
+    return clib_error_return (0, "error: parsing failed");
+
+  target = http_serialize_authority_form_target (&authority);
+  vlib_cli_output (vm, "%v", target);
+  vec_free (target);
+
+  return 0;
+}
+
+VLIB_CLI_COMMAND (test_http_authority_command) = {
+  .path = "test http authority-form",
+  .short_help = "test dns authority-form",
+  .function = test_http_authority_command_fn,
+};
-- 
cgit