From 57e6f7396139f7b9b0f1f3784481e18636b367d0 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Tue, 3 Sep 2024 20:30:15 +0200 Subject: [PATCH 01/15] transport: publish log_transport_socket_read_method() Signed-off-by: Balazs Scheidler --- lib/transport/transport-socket.c | 2 +- lib/transport/transport-socket.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/transport/transport-socket.c b/lib/transport/transport-socket.c index c7f1b4ef8f..5d4109b047 100644 --- a/lib/transport/transport-socket.c +++ b/lib/transport/transport-socket.c @@ -159,7 +159,7 @@ _extract_from_msghdr_method(LogTransportSocket *self, struct msghdr *msg, LogTra _parse_cmsg_to_aux(self, msg, aux); } -static gssize +gssize log_transport_socket_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) { LogTransportSocket *self = (LogTransportSocket *) s; diff --git a/lib/transport/transport-socket.h b/lib/transport/transport-socket.h index 091cf1e811..47ed72930a 100644 --- a/lib/transport/transport-socket.h +++ b/lib/transport/transport-socket.h @@ -37,6 +37,7 @@ struct _LogTransportSocket }; void log_transport_socket_parse_cmsg_method(LogTransportSocket *s, struct cmsghdr *cmsg, LogTransportAuxData *aux); +gssize log_transport_socket_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux); void log_transport_dgram_socket_init_instance(LogTransportSocket *self, gint fd); LogTransport *log_transport_dgram_socket_new(gint fd); From 045b89bc1c15c5465f533f8258e4fcbca7dd9459 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Wed, 4 Sep 2024 20:33:47 +0200 Subject: [PATCH 02/15] logproto-text-client: remove duplicate initialization of self->super.transport Signed-off-by: Balazs Scheidler --- lib/logproto/logproto-text-client.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/logproto/logproto-text-client.c b/lib/logproto/logproto-text-client.c index 06a9c391c0..8cad2e9a65 100644 --- a/lib/logproto/logproto-text-client.c +++ b/lib/logproto/logproto-text-client.c @@ -202,7 +202,6 @@ log_proto_text_client_init(LogProtoTextClient *self, LogTransport *transport, co self->super.process_in = log_proto_text_client_drop_input; self->super.post = log_proto_text_client_post; self->super.free_fn = log_proto_text_client_free; - self->super.transport = transport; self->next_state = -1; } From 324ed7f9423cf0f8c7e031d05d276edefda16fd1 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 15 Sep 2024 18:06:57 +0200 Subject: [PATCH 03/15] afsocket: minor consistency changes in transport_mapper_*_apply_transport() Signed-off-by: Balazs Scheidler --- modules/afsocket/transport-mapper-inet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/afsocket/transport-mapper-inet.c b/modules/afsocket/transport-mapper-inet.c index 3bf39eefbc..d65f7bce86 100644 --- a/modules/afsocket/transport-mapper-inet.c +++ b/modules/afsocket/transport-mapper-inet.c @@ -385,9 +385,9 @@ transport_mapper_network_apply_transport(TransportMapper *s, GlobalConfig *cfg) self->server_port = NETWORK_PORT; if (strcasecmp(transport, "udp") == 0) { + self->super.logproto = "dgram"; self->super.sock_type = SOCK_DGRAM; self->super.sock_proto = IPPROTO_UDP; - self->super.logproto = "dgram"; self->super.transport_name = g_strdup("bsdsyslog+udp"); } else if (strcasecmp(transport, "tcp") == 0) @@ -464,9 +464,9 @@ transport_mapper_syslog_apply_transport(TransportMapper *s, GlobalConfig *cfg) else self->server_port = SYSLOG_TRANSPORT_UDP_PORT; + self->super.logproto = "dgram"; self->super.sock_type = SOCK_DGRAM; self->super.sock_proto = IPPROTO_UDP; - self->super.logproto = "dgram"; self->super.transport_name = g_strdup("rfc5426"); } else if (strcasecmp(transport, "tcp") == 0) From 7590a315fec5c68c65df1a7989ac6253dcec48f3 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Wed, 11 Sep 2024 16:52:06 +0200 Subject: [PATCH 04/15] transport: rename MultiTransport to TransportStack Signed-off-by: Balazs Scheidler --- lib/logproto/logproto-proxied-text-server.c | 4 +- lib/transport/CMakeLists.txt | 4 +- lib/transport/Makefile.am | 4 +- lib/transport/tests/CMakeLists.txt | 2 +- lib/transport/tests/Makefile.am | 10 ++--- ...ultitransport.c => test_transport_stack.c} | 43 +++++++++---------- .../{multitransport.c => transport-stack.c} | 34 +++++++-------- .../{multitransport.h => transport-stack.h} | 17 ++++---- modules/afsocket/transport-mapper-inet.c | 8 ++-- 9 files changed, 62 insertions(+), 64 deletions(-) rename lib/transport/tests/{test_multitransport.c => test_transport_stack.c} (67%) rename lib/transport/{multitransport.c => transport-stack.c} (76%) rename lib/transport/{multitransport.h => transport-stack.h} (71%) diff --git a/lib/logproto/logproto-proxied-text-server.c b/lib/logproto/logproto-proxied-text-server.c index 569311e66d..814dac2044 100644 --- a/lib/logproto/logproto-proxied-text-server.c +++ b/lib/logproto/logproto-proxied-text-server.c @@ -27,7 +27,7 @@ #include #include "messages.h" #include "logproto-proxied-text-server.h" -#include "transport/multitransport.h" +#include "transport/transport-stack.h" #include "transport/transport-factory-tls.h" #include "str-utils.h" @@ -496,7 +496,7 @@ _fetch_into_proxy_buffer(LogProtoProxiedTextServer *self) static gboolean _switch_to_tls(LogProtoProxiedTextServer *self) { - if (!multitransport_switch((MultiTransport *)self->super.super.super.transport, TRANSPORT_FACTORY_TLS_ID)) + if (!log_transport_stack_switch((LogTransportStack *)self->super.super.super.transport, TRANSPORT_FACTORY_TLS_ID)) { msg_error("proxied-tls failed to switch to TLS"); return FALSE; diff --git a/lib/transport/CMakeLists.txt b/lib/transport/CMakeLists.txt index 5bdb5add14..d82f013a53 100644 --- a/lib/transport/CMakeLists.txt +++ b/lib/transport/CMakeLists.txt @@ -7,7 +7,7 @@ set(TRANSPORT_HEADERS transport/transport-socket.h transport/transport-udp-socket.h transport/transport-factory.h - transport/multitransport.h + transport/transport-stack.h transport/transport-factory-tls.h transport/transport-factory-socket.h transport/tls-context.h @@ -23,7 +23,7 @@ set(TRANSPORT_SOURCES transport/transport-socket.c transport/transport-udp-socket.c transport/transport-tls.c - transport/multitransport.c + transport/transport-stack.c transport/transport-factory-tls.c transport/transport-factory-socket.c transport/tls-context.c diff --git a/lib/transport/Makefile.am b/lib/transport/Makefile.am index c1ebbde8fa..44e6be3a9e 100644 --- a/lib/transport/Makefile.am +++ b/lib/transport/Makefile.am @@ -11,7 +11,7 @@ transportinclude_HEADERS = \ lib/transport/transport-socket.h \ lib/transport/transport-udp-socket.h \ lib/transport/transport-factory.h \ - lib/transport/multitransport.h \ + lib/transport/transport-stack.h \ lib/transport/transport-factory-tls.h \ lib/transport/transport-factory-socket.h \ lib/transport/tls-context.h \ @@ -25,7 +25,7 @@ transport_sources = \ lib/transport/transport-pipe.c \ lib/transport/transport-socket.c \ lib/transport/transport-udp-socket.c \ - lib/transport/multitransport.c \ + lib/transport/transport-stack.c \ lib/transport/transport-factory-tls.c \ lib/transport/transport-factory-socket.c \ lib/transport/tls-context.c \ diff --git a/lib/transport/tests/CMakeLists.txt b/lib/transport/tests/CMakeLists.txt index ab6df6606d..3c03604983 100644 --- a/lib/transport/tests/CMakeLists.txt +++ b/lib/transport/tests/CMakeLists.txt @@ -1,3 +1,3 @@ add_unit_test(CRITERION TARGET test_aux_data) add_unit_test(CRITERION TARGET test_transport_factory) -add_unit_test(CRITERION TARGET test_multitransport) +add_unit_test(CRITERION TARGET test_transport_stack) diff --git a/lib/transport/tests/Makefile.am b/lib/transport/tests/Makefile.am index 799c6c0e3c..d3d45695fb 100644 --- a/lib/transport/tests/Makefile.am +++ b/lib/transport/tests/Makefile.am @@ -1,7 +1,7 @@ lib_transport_tests_TESTS = \ lib/transport/tests/test_aux_data \ lib/transport/tests/test_transport_factory \ - lib/transport/tests/test_multitransport + lib/transport/tests/test_transport_stack EXTRA_DIST += lib/transport/tests/CMakeLists.txt @@ -19,8 +19,8 @@ lib_transport_tests_test_transport_factory_LDADD = $(TEST_LDADD) lib_transport_tests_test_transport_factory_SOURCES = \ lib/transport/tests/test_transport_factory.c -lib_transport_tests_test_multitransport_CFLAGS = $(TEST_CFLAGS) \ +lib_transport_tests_test_transport_stack_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/transport/tests -lib_transport_tests_test_multitransport_LDADD = $(TEST_LDADD) -lib_transport_tests_test_multitransport_SOURCES = \ - lib/transport/tests/test_multitransport.c +lib_transport_tests_test_transport_stack_LDADD = $(TEST_LDADD) +lib_transport_tests_test_transport_stack_SOURCES = \ + lib/transport/tests/test_transport_stack.c diff --git a/lib/transport/tests/test_multitransport.c b/lib/transport/tests/test_transport_stack.c similarity index 67% rename from lib/transport/tests/test_multitransport.c rename to lib/transport/tests/test_transport_stack.c index d6d045965d..b1b34d2a36 100644 --- a/lib/transport/tests/test_multitransport.c +++ b/lib/transport/tests/test_transport_stack.c @@ -23,7 +23,7 @@ #include -#include "transport/multitransport.h" +#include "transport/transport-stack.h" #include "transport/transport-factory.h" #include "apphook.h" @@ -72,39 +72,38 @@ return &self->super; \ } \ -TestSuite(multitransport, .init = app_startup, .fini = app_shutdown); +TestSuite(transport_stack, .init = app_startup, .fini = app_shutdown); DEFINE_TEST_TRANSPORT_WITH_FACTORY(Fake, fake); DEFINE_TEST_TRANSPORT_WITH_FACTORY(Default, default); DEFINE_TEST_TRANSPORT_WITH_FACTORY(Unregistered, unregistered); -Test(multitransport, test_switch_transport) +Test(transport_stack, test_switch_transport) { TransportFactory *default_factory = default_transport_factory_new(); TransportFactory *fake_factory = fake_transport_factory_new(); gint fd = -2; - MultiTransport *multi_transport = (MultiTransport *) multitransport_new(default_factory, fd); + LogTransportStack *transport_stack = (LogTransportStack *) log_transport_stack_new(default_factory, fd); - cr_expect_eq(multi_transport->active_transport->read, default_read); - cr_expect_eq(multi_transport->active_transport->write, default_write); - cr_expect_str_eq(multi_transport->active_transport->name, "default"); + cr_expect_eq(transport_stack->active_transport->read, default_read); + cr_expect_eq(transport_stack->active_transport->write, default_write); + cr_expect_str_eq(transport_stack->active_transport->name, "default"); - multitransport_add_factory(multi_transport, fake_factory); - cr_expect_not(multitransport_contains_factory(multi_transport, "unregistered")); - cr_expect(multitransport_contains_factory(multi_transport, "fake")); - cr_expect_not(multitransport_switch(multi_transport, "unregistered")); - cr_expect_eq(multi_transport->active_transport->read, default_read); - cr_expect_eq(multi_transport->active_transport->write, default_write); - cr_expect_eq(multi_transport->active_transport_factory, default_factory); - cr_expect_str_eq(multi_transport->active_transport->name, "default"); + log_transport_stack_add_factory(transport_stack, fake_factory); + cr_expect_not(log_transport_stack_contains_factory(transport_stack, "unregistered")); + cr_expect(log_transport_stack_contains_factory(transport_stack, "fake")); + cr_expect_not(log_transport_stack_switch(transport_stack, "unregistered")); + cr_expect_eq(transport_stack->active_transport->read, default_read); + cr_expect_eq(transport_stack->active_transport->write, default_write); + cr_expect_eq(transport_stack->active_transport_factory, default_factory); + cr_expect_str_eq(transport_stack->active_transport->name, "default"); - cr_expect(multitransport_switch(multi_transport, "fake")); - cr_expect_eq(multi_transport->active_transport->read, fake_read); - cr_expect_eq(multi_transport->active_transport->write, fake_write); - cr_expect_eq(multi_transport->active_transport_factory, fake_factory); - cr_expect_str_eq(multi_transport->active_transport->name, "fake"); + cr_expect(log_transport_stack_switch(transport_stack, "fake")); + cr_expect_eq(transport_stack->active_transport->read, fake_read); + cr_expect_eq(transport_stack->active_transport->write, fake_write); + cr_expect_eq(transport_stack->active_transport_factory, fake_factory); + cr_expect_str_eq(transport_stack->active_transport->name, "fake"); - log_transport_free(&multi_transport->super); + log_transport_free(&transport_stack->super); } - diff --git a/lib/transport/multitransport.c b/lib/transport/transport-stack.c similarity index 76% rename from lib/transport/multitransport.c rename to lib/transport/transport-stack.c index 530b19b087..35b0736bf2 100644 --- a/lib/transport/multitransport.c +++ b/lib/transport/transport-stack.c @@ -22,17 +22,17 @@ * */ -#include "transport/multitransport.h" +#include "transport/transport-stack.h" #include "messages.h" void -multitransport_add_factory(MultiTransport *self, TransportFactory *transport_factory) +log_transport_stack_add_factory(LogTransportStack *self, TransportFactory *transport_factory) { g_hash_table_insert(self->registry, (gpointer) transport_factory->id, transport_factory); } static void -_do_transport_switch(MultiTransport *self, LogTransport *new_transport, const TransportFactory *new_transport_factory) +_do_transport_switch(LogTransportStack *self, LogTransport *new_transport, const TransportFactory *new_transport_factory) { self->super.fd = log_transport_release_fd(self->active_transport); self->super.cond = new_transport->cond; @@ -42,7 +42,7 @@ _do_transport_switch(MultiTransport *self, LogTransport *new_transport, const Tr } static const TransportFactory * -_lookup_transport_factory(MultiTransport *self, const gchar *factory_id) +_lookup_transport_factory(LogTransportStack *self, const gchar *factory_id) { const TransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); @@ -72,7 +72,7 @@ _construct_transport(const TransportFactory *factory, gint fd) } gboolean -multitransport_switch(MultiTransport *self, const gchar *factory_id) +log_transport_stack_switch(LogTransportStack *self, const gchar *factory_id) { msg_debug("Transport switch requested", evt_tag_str("active-transport", self->active_transport->name), @@ -95,7 +95,7 @@ multitransport_switch(MultiTransport *self, const gchar *factory_id) } gboolean -multitransport_contains_factory(MultiTransport *self, const gchar *factory_id) +log_transport_stack_contains_factory(LogTransportStack *self, const gchar *factory_id) { const TransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); @@ -103,9 +103,9 @@ multitransport_contains_factory(MultiTransport *self, const gchar *factory_id) } static gssize -_multitransport_write(LogTransport *s, gpointer buf, gsize count) +_log_transport_stack_write(LogTransport *s, gpointer buf, gsize count) { - MultiTransport *self = (MultiTransport *)s; + LogTransportStack *self = (LogTransportStack *)s; gssize r = log_transport_write(self->active_transport, buf, count); self->super.cond = self->active_transport->cond; @@ -113,9 +113,9 @@ _multitransport_write(LogTransport *s, gpointer buf, gsize count) } static gssize -_multitransport_read(LogTransport *s, gpointer buf, gsize count, LogTransportAuxData *aux) +_log_transport_stack_read(LogTransport *s, gpointer buf, gsize count, LogTransportAuxData *aux) { - MultiTransport *self = (MultiTransport *)s; + LogTransportStack *self = (LogTransportStack *)s; gssize r = log_transport_read(self->active_transport, buf, count, aux); self->super.cond = self->active_transport->cond; @@ -123,9 +123,9 @@ _multitransport_read(LogTransport *s, gpointer buf, gsize count, LogTransportAux } static void -_multitransport_free(LogTransport *s) +_log_transport_stack_free(LogTransport *s) { - MultiTransport *self = (MultiTransport *)s; + LogTransportStack *self = (LogTransportStack *)s; s->fd = log_transport_release_fd(self->active_transport); log_transport_free(self->active_transport); g_hash_table_unref(self->registry); @@ -133,14 +133,14 @@ _multitransport_free(LogTransport *s) } LogTransport * -multitransport_new(TransportFactory *default_transport_factory, gint fd) +log_transport_stack_new(TransportFactory *default_transport_factory, gint fd) { - MultiTransport *self = g_new0(MultiTransport, 1); + LogTransportStack *self = g_new0(LogTransportStack, 1); log_transport_init_instance(&self->super, fd); - self->super.read = _multitransport_read; - self->super.write = _multitransport_write; - self->super.free_fn = _multitransport_free; + self->super.read = _log_transport_stack_read; + self->super.write = _log_transport_stack_write; + self->super.free_fn = _log_transport_stack_free; self->registry = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) transport_factory_free); self->active_transport = transport_factory_construct_transport(default_transport_factory, fd); self->active_transport_factory = default_transport_factory; diff --git a/lib/transport/multitransport.h b/lib/transport/transport-stack.h similarity index 71% rename from lib/transport/multitransport.h rename to lib/transport/transport-stack.h index 66dc31ef5c..dfb714586b 100644 --- a/lib/transport/multitransport.h +++ b/lib/transport/transport-stack.h @@ -22,15 +22,15 @@ * */ -#ifndef MULTITRANSPORT_H_INCLUDED -#define MULTITRANSPORT_H_INCLUDED +#ifndef TRANSPORT_STACK_H_INCLUDED +#define TRANSPORT_STACK_H_INCLUDED #include "transport/logtransport.h" #include "transport/transport-factory.h" -typedef struct _MultiTransport MultiTransport; +typedef struct _LogTransportStack LogTransportStack; -struct _MultiTransport +struct _LogTransportStack { LogTransport super; GHashTable *registry; @@ -38,10 +38,9 @@ struct _MultiTransport const TransportFactory *active_transport_factory; }; -LogTransport *multitransport_new(TransportFactory *default_transport_factory, gint fd); -void multitransport_add_factory(MultiTransport *self, TransportFactory *); -gboolean multitransport_switch(MultiTransport *self, const gchar *id); -gboolean multitransport_contains_factory(MultiTransport *self, const gchar *id); +LogTransport *log_transport_stack_new(TransportFactory *default_transport_factory, gint fd); +void log_transport_stack_add_factory(LogTransportStack *self, TransportFactory *); +gboolean log_transport_stack_switch(LogTransportStack *self, const gchar *id); +gboolean log_transport_stack_contains_factory(LogTransportStack *self, const gchar *id); #endif - diff --git a/modules/afsocket/transport-mapper-inet.c b/modules/afsocket/transport-mapper-inet.c index d65f7bce86..fee33bdda1 100644 --- a/modules/afsocket/transport-mapper-inet.c +++ b/modules/afsocket/transport-mapper-inet.c @@ -26,7 +26,7 @@ #include "messages.h" #include "stats/stats-registry.h" #include "transport/transport-tls.h" -#include "transport/multitransport.h" +#include "transport/transport-stack.h" #include "transport/transport-factory-tls.h" #include "transport/transport-factory-socket.h" #include "transport/transport-udp-socket.h" @@ -89,7 +89,7 @@ static LogTransport * _construct_multitransport_with_tls_factory(TransportMapperInet *self, gint fd) { TransportFactory *default_factory = transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); - return multitransport_new(default_factory, fd); + return log_transport_stack_new(default_factory, fd); } static LogTransport * @@ -113,7 +113,7 @@ _construct_multitransport_with_plain_tcp_factory(TransportMapperInet *self, gint { TransportFactory *default_factory = transport_factory_socket_new(self->super.sock_type); - return multitransport_new(default_factory, fd); + return log_transport_stack_new(default_factory, fd); } static LogTransport * @@ -122,7 +122,7 @@ _construct_multitransport_with_plain_and_tls_factories(TransportMapperInet *self LogTransport *transport = _construct_multitransport_with_plain_tcp_factory(self, fd); TransportFactory *tls_factory = transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); - multitransport_add_factory((MultiTransport *)transport, tls_factory); + log_transport_stack_add_factory((LogTransportStack *)transport, tls_factory); return transport; } From 615d59d8a3430627a984a0d31fa1c3bace9e93bc Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 14 Sep 2024 17:03:57 +0200 Subject: [PATCH 05/15] transport: rename TransfortFactory to LogTransportFactory Signed-off-by: Balazs Scheidler --- lib/transport/tests/test_transport_factory.c | 12 ++++----- lib/transport/tests/test_transport_stack.c | 10 ++++---- lib/transport/transport-factory-socket.c | 10 ++++---- lib/transport/transport-factory-socket.h | 8 +++--- lib/transport/transport-factory-tls.c | 26 ++++++++++---------- lib/transport/transport-factory-tls.h | 12 ++++----- lib/transport/transport-factory.h | 24 +++++++++--------- lib/transport/transport-stack.c | 22 ++++++++--------- lib/transport/transport-stack.h | 6 ++--- modules/afsocket/transport-mapper-inet.c | 6 ++--- 10 files changed, 68 insertions(+), 68 deletions(-) diff --git a/lib/transport/tests/test_transport_factory.c b/lib/transport/tests/test_transport_factory.c index 326a9bfb93..ce43c2ba0d 100644 --- a/lib/transport/tests/test_transport_factory.c +++ b/lib/transport/tests/test_transport_factory.c @@ -66,11 +66,11 @@ _fake_transport_new(void) struct _FakeTransportFactory { - TransportFactory super; + LogTransportFactory super; }; static LogTransport * -_transport_factory_construct(const TransportFactory *s, gint fd) +_transport_factory_construct(const LogTransportFactory *s, gint fd) { LogTransport *fake_transport = _fake_transport_new(); log_transport_init_instance(fake_transport, fd); @@ -79,7 +79,7 @@ _transport_factory_construct(const TransportFactory *s, gint fd) return fake_transport; } -TransportFactory * +LogTransportFactory * _fake_transport_factory_new(void) { FakeTransportFactory *instance = g_new0(FakeTransportFactory, 1); @@ -92,15 +92,15 @@ TestSuite(transport_factory, .init = app_startup, .fini = app_shutdown); Test(transport_factory, fake_transport_factory) { - TransportFactory *fake_factory = _fake_transport_factory_new(); + LogTransportFactory *fake_factory = _fake_transport_factory_new(); cr_expect_not_null(fake_factory->id); gint fd = 11; - FakeTransport *fake_transport = (FakeTransport *) transport_factory_construct_transport(fake_factory, fd); + FakeTransport *fake_transport = (FakeTransport *) log_transport_factory_construct_transport(fake_factory, fd); cr_expect_eq(fake_transport->constructed, TRUE); cr_expect_eq(fake_transport->super.read, _fake_read); cr_expect_eq(fake_transport->super.write, _fake_write); log_transport_free(&fake_transport->super); - transport_factory_free(fake_factory); + log_transport_factory_free(fake_factory); } diff --git a/lib/transport/tests/test_transport_stack.c b/lib/transport/tests/test_transport_stack.c index b1b34d2a36..257593b4d9 100644 --- a/lib/transport/tests/test_transport_stack.c +++ b/lib/transport/tests/test_transport_stack.c @@ -54,16 +54,16 @@ } \ struct TypePrefix ## TransportFactory_\ { \ - TransportFactory super; \ + LogTransportFactory super; \ }; \ static LogTransport * \ - FunPrefix ## _factory_construct(const TransportFactory *s, gint fd) \ + FunPrefix ## _factory_construct(const LogTransportFactory *s, gint fd) \ {\ LogTransport *transport = FunPrefix ## _transport_new(); \ log_transport_init_instance(transport, fd); \ return transport; \ } \ - TransportFactory * \ + LogTransportFactory * \ FunPrefix ## _transport_factory_new(void) \ { \ TypePrefix ## TransportFactory *self = g_new0(TypePrefix ## TransportFactory, 1); \ @@ -80,8 +80,8 @@ DEFINE_TEST_TRANSPORT_WITH_FACTORY(Unregistered, unregistered); Test(transport_stack, test_switch_transport) { - TransportFactory *default_factory = default_transport_factory_new(); - TransportFactory *fake_factory = fake_transport_factory_new(); + LogTransportFactory *default_factory = default_transport_factory_new(); + LogTransportFactory *fake_factory = fake_transport_factory_new(); gint fd = -2; LogTransportStack *transport_stack = (LogTransportStack *) log_transport_stack_new(default_factory, fd); diff --git a/lib/transport/transport-factory-socket.c b/lib/transport/transport-factory-socket.c index e61e7b7f2a..b06ca9eb05 100644 --- a/lib/transport/transport-factory-socket.c +++ b/lib/transport/transport-factory-socket.c @@ -27,21 +27,21 @@ #include "transport/transport-udp-socket.h" static LogTransport * -_construct_transport_dgram(const TransportFactory *s, gint fd) +_construct_transport_dgram(const LogTransportFactory *s, gint fd) { return log_transport_udp_socket_new(fd); } static LogTransport * -_construct_transport_stream(const TransportFactory *s, gint fd) +_construct_transport_stream(const LogTransportFactory *s, gint fd) { return log_transport_stream_socket_new(fd); } -TransportFactory * -transport_factory_socket_new(int sock_type) +LogTransportFactory * +log_transport_factory_socket_new(int sock_type) { - TransportFactorySocket *self = g_new0(TransportFactorySocket, 1); + LogTransportFactorySocket *self = g_new0(LogTransportFactorySocket, 1); if (sock_type == SOCK_DGRAM) self->super.construct_transport = _construct_transport_dgram; diff --git a/lib/transport/transport-factory-socket.h b/lib/transport/transport-factory-socket.h index 70ca075f48..5ace093245 100644 --- a/lib/transport/transport-factory-socket.h +++ b/lib/transport/transport-factory-socket.h @@ -28,15 +28,15 @@ #include "transport/transport-factory.h" #include "transport/transport-socket.h" -typedef struct _TransportFactorySocket TransportFactorySocket; +typedef struct _LogTransportFactorySocket LogTransportFactorySocket; -struct _TransportFactorySocket +struct _LogTransportFactorySocket { - TransportFactory super; + LogTransportFactory super; }; #define TRANSPORT_FACTORY_SOCKET_ID "socket" -TransportFactory *transport_factory_socket_new(gint sock_type); +LogTransportFactory *log_transport_factory_socket_new(gint sock_type); #endif diff --git a/lib/transport/transport-factory-tls.c b/lib/transport/transport-factory-tls.c index b29c78a6f9..58b96054ef 100644 --- a/lib/transport/transport-factory-tls.c +++ b/lib/transport/transport-factory-tls.c @@ -27,9 +27,9 @@ #include "transport/transport-tls.h" static LogTransport * -_construct_transport(const TransportFactory *s, gint fd) +_construct_transport(const LogTransportFactory *s, gint fd) { - TransportFactoryTLS *self = (TransportFactoryTLS *)s; + LogTransportFactoryTLS *self = (LogTransportFactoryTLS *)s; TLSSession *tls_session = tls_context_setup_session(self->tls_context); if (!tls_session) @@ -43,32 +43,32 @@ _construct_transport(const TransportFactory *s, gint fd) } void -transport_factory_tls_enable_compression(TransportFactory *s) +log_transport_factory_tls_enable_compression(LogTransportFactory *s) { - TransportFactoryTLS *self = (TransportFactoryTLS *)s; + LogTransportFactoryTLS *self = (LogTransportFactoryTLS *)s; self->allow_compress = TRUE; } void -transport_factory_tls_disable_compression(TransportFactory *s) +log_transport_factory_tls_disable_compression(LogTransportFactory *s) { - TransportFactoryTLS *self = (TransportFactoryTLS *)s; + LogTransportFactoryTLS *self = (LogTransportFactoryTLS *)s; self->allow_compress = FALSE; } static void -_free(TransportFactory *s) +_free(LogTransportFactory *s) { - TransportFactoryTLS *self = (TransportFactoryTLS *)s; + LogTransportFactoryTLS *self = (LogTransportFactoryTLS *)s; tls_context_unref(self->tls_context); if (self->tls_verifier) tls_verifier_unref(self->tls_verifier); } -TransportFactory * -transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags) +LogTransportFactory * +log_transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags) { - TransportFactoryTLS *instance = g_new0(TransportFactoryTLS, 1); + LogTransportFactoryTLS *instance = g_new0(LogTransportFactoryTLS, 1); instance->tls_context = tls_context_ref(ctx); instance->tls_verifier = tls_verifier ? tls_verifier_ref(tls_verifier) : NULL; @@ -78,9 +78,9 @@ transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 fl instance->super.free_fn = _free; if (flags & TMI_ALLOW_COMPRESS) - transport_factory_tls_enable_compression((TransportFactory *)instance); + log_transport_factory_tls_enable_compression((LogTransportFactory *)instance); else - transport_factory_tls_disable_compression((TransportFactory *)instance); + log_transport_factory_tls_disable_compression((LogTransportFactory *)instance); return &instance->super; } diff --git a/lib/transport/transport-factory-tls.h b/lib/transport/transport-factory-tls.h index f95009947a..4c9f9560f7 100644 --- a/lib/transport/transport-factory-tls.h +++ b/lib/transport/transport-factory-tls.h @@ -28,20 +28,20 @@ #include "transport/transport-factory.h" #include "transport/tls-context.h" -typedef struct _TransportFactoryTLS TransportFactoryTLS; +typedef struct _LogTransportFactoryTLS LogTransportFactoryTLS; -struct _TransportFactoryTLS +struct _LogTransportFactoryTLS { - TransportFactory super; + LogTransportFactory super; TLSContext *tls_context; TLSVerifier *tls_verifier; gboolean allow_compress; }; -TransportFactory *transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags); +LogTransportFactory *log_transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags); -void transport_factory_tls_enable_compression(TransportFactory *); -void transport_factory_tls_disable_compression(TransportFactory *); +void log_transport_factory_tls_enable_compression(LogTransportFactory *); +void log_transport_factory_tls_disable_compression(LogTransportFactory *); #define TRANSPORT_FACTORY_TLS_ID "tls" diff --git a/lib/transport/transport-factory.h b/lib/transport/transport-factory.h index cd284f7591..56b62a4164 100644 --- a/lib/transport/transport-factory.h +++ b/lib/transport/transport-factory.h @@ -27,24 +27,24 @@ #include "transport/logtransport.h" -/* TransportFactory is an interface for representing - * concrete TransportFactory instances - * Each TransportFactory has +/* LogTransportFactory is an interface for representing + * concrete LogTransportFactory instances + * Each LogTransportFactory has * - a reference to a unique id * - a construct method for creating new LogTransport instances * - a destroy method for releasing resources that are needed for construct() */ -typedef struct _TransportFactory TransportFactory; +typedef struct _LogTransportFactory LogTransportFactory; -struct _TransportFactory +struct _LogTransportFactory { const gchar *id; - LogTransport *(*construct_transport)(const TransportFactory *self, gint fd); - void (*free_fn)(TransportFactory *self); + LogTransport *(*construct_transport)(const LogTransportFactory *self, gint fd); + void (*free_fn)(LogTransportFactory *self); }; -static inline LogTransport -*transport_factory_construct_transport(const TransportFactory *self, gint fd) +static inline LogTransport * +log_transport_factory_construct_transport(const LogTransportFactory *self, gint fd) { g_assert(self->construct_transport); @@ -55,7 +55,7 @@ static inline LogTransport } static inline void -transport_factory_free(TransportFactory *self) +log_transport_factory_free(LogTransportFactory *self) { if (self->free_fn) self->free_fn(self); @@ -63,9 +63,9 @@ transport_factory_free(TransportFactory *self) } static inline const gchar * -transport_factory_get_id(const TransportFactory *self) +log_transport_factory_get_id(const LogTransportFactory *self) { - /* each concrete TransportFactory has to have an id + /* each concrete LogTransportFactory has to have an id */ g_assert(self->id); return self->id; diff --git a/lib/transport/transport-stack.c b/lib/transport/transport-stack.c index 35b0736bf2..3b1d6f7e00 100644 --- a/lib/transport/transport-stack.c +++ b/lib/transport/transport-stack.c @@ -26,13 +26,13 @@ #include "messages.h" void -log_transport_stack_add_factory(LogTransportStack *self, TransportFactory *transport_factory) +log_transport_stack_add_factory(LogTransportStack *self, LogTransportFactory *transport_factory) { g_hash_table_insert(self->registry, (gpointer) transport_factory->id, transport_factory); } static void -_do_transport_switch(LogTransportStack *self, LogTransport *new_transport, const TransportFactory *new_transport_factory) +_do_transport_switch(LogTransportStack *self, LogTransport *new_transport, const LogTransportFactory *new_transport_factory) { self->super.fd = log_transport_release_fd(self->active_transport); self->super.cond = new_transport->cond; @@ -41,10 +41,10 @@ _do_transport_switch(LogTransportStack *self, LogTransport *new_transport, const self->active_transport_factory = new_transport_factory; } -static const TransportFactory * +static const LogTransportFactory * _lookup_transport_factory(LogTransportStack *self, const gchar *factory_id) { - const TransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); + const LogTransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); if (!factory) { @@ -57,9 +57,9 @@ _lookup_transport_factory(LogTransportStack *self, const gchar *factory_id) } static LogTransport * -_construct_transport(const TransportFactory *factory, gint fd) +_construct_transport(const LogTransportFactory *factory, gint fd) { - LogTransport *transport = transport_factory_construct_transport(factory, fd); + LogTransport *transport = log_transport_factory_construct_transport(factory, fd); if (!transport) { @@ -78,7 +78,7 @@ log_transport_stack_switch(LogTransportStack *self, const gchar *factory_id) evt_tag_str("active-transport", self->active_transport->name), evt_tag_str("requested-transport", factory_id)); - const TransportFactory *transport_factory = _lookup_transport_factory(self, factory_id); + const LogTransportFactory *transport_factory = _lookup_transport_factory(self, factory_id); if (!transport_factory) return FALSE; @@ -97,7 +97,7 @@ log_transport_stack_switch(LogTransportStack *self, const gchar *factory_id) gboolean log_transport_stack_contains_factory(LogTransportStack *self, const gchar *factory_id) { - const TransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); + const LogTransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); return (factory != NULL); } @@ -133,7 +133,7 @@ _log_transport_stack_free(LogTransport *s) } LogTransport * -log_transport_stack_new(TransportFactory *default_transport_factory, gint fd) +log_transport_stack_new(LogTransportFactory *default_transport_factory, gint fd) { LogTransportStack *self = g_new0(LogTransportStack, 1); @@ -141,8 +141,8 @@ log_transport_stack_new(TransportFactory *default_transport_factory, gint fd) self->super.read = _log_transport_stack_read; self->super.write = _log_transport_stack_write; self->super.free_fn = _log_transport_stack_free; - self->registry = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) transport_factory_free); - self->active_transport = transport_factory_construct_transport(default_transport_factory, fd); + self->registry = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) log_transport_factory_free); + self->active_transport = log_transport_factory_construct_transport(default_transport_factory, fd); self->active_transport_factory = default_transport_factory; return &self->super; diff --git a/lib/transport/transport-stack.h b/lib/transport/transport-stack.h index dfb714586b..cf91fb4953 100644 --- a/lib/transport/transport-stack.h +++ b/lib/transport/transport-stack.h @@ -35,11 +35,11 @@ struct _LogTransportStack LogTransport super; GHashTable *registry; LogTransport *active_transport; - const TransportFactory *active_transport_factory; + const LogTransportFactory *active_transport_factory; }; -LogTransport *log_transport_stack_new(TransportFactory *default_transport_factory, gint fd); -void log_transport_stack_add_factory(LogTransportStack *self, TransportFactory *); +LogTransport *log_transport_stack_new(LogTransportFactory *default_transport_factory, gint fd); +void log_transport_stack_add_factory(LogTransportStack *self, LogTransportFactory *); gboolean log_transport_stack_switch(LogTransportStack *self, const gchar *id); gboolean log_transport_stack_contains_factory(LogTransportStack *self, const gchar *id); diff --git a/modules/afsocket/transport-mapper-inet.c b/modules/afsocket/transport-mapper-inet.c index fee33bdda1..ad8ee76296 100644 --- a/modules/afsocket/transport-mapper-inet.c +++ b/modules/afsocket/transport-mapper-inet.c @@ -88,7 +88,7 @@ transport_mapper_inet_apply_transport_method(TransportMapper *s, GlobalConfig *c static LogTransport * _construct_multitransport_with_tls_factory(TransportMapperInet *self, gint fd) { - TransportFactory *default_factory = transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); + LogTransportFactory *default_factory = log_transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); return log_transport_stack_new(default_factory, fd); } @@ -111,7 +111,7 @@ _construct_tls_transport(TransportMapperInet *self, gint fd) static LogTransport * _construct_multitransport_with_plain_tcp_factory(TransportMapperInet *self, gint fd) { - TransportFactory *default_factory = transport_factory_socket_new(self->super.sock_type); + LogTransportFactory *default_factory = log_transport_factory_socket_new(self->super.sock_type); return log_transport_stack_new(default_factory, fd); } @@ -121,7 +121,7 @@ _construct_multitransport_with_plain_and_tls_factories(TransportMapperInet *self { LogTransport *transport = _construct_multitransport_with_plain_tcp_factory(self, fd); - TransportFactory *tls_factory = transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); + LogTransportFactory *tls_factory = log_transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); log_transport_stack_add_factory((LogTransportStack *)transport, tls_factory); return transport; From a49cfdce3fa74e9d9c896e71ad5b019ecfb48ddd Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 15 Sep 2024 06:59:22 +0200 Subject: [PATCH 06/15] transport: merge transport-factory.h into transport-stack.h These are interdependent interfaces and LogTransportStack will be the sole user of LogTransportFactory. Signed-off-by: Balazs Scheidler --- lib/transport/CMakeLists.txt | 1 - lib/transport/Makefile.am | 1 - lib/transport/tests/CMakeLists.txt | 1 - lib/transport/tests/Makefile.am | 7 -- lib/transport/tests/test_transport_factory.c | 106 ------------------- lib/transport/tests/test_transport_stack.c | 1 - lib/transport/transport-factory-socket.h | 2 +- lib/transport/transport-factory-tls.h | 2 +- lib/transport/transport-factory.h | 74 ------------- lib/transport/transport-stack.h | 45 +++++++- 10 files changed, 46 insertions(+), 194 deletions(-) delete mode 100644 lib/transport/tests/test_transport_factory.c delete mode 100644 lib/transport/transport-factory.h diff --git a/lib/transport/CMakeLists.txt b/lib/transport/CMakeLists.txt index d82f013a53..e8f27a977f 100644 --- a/lib/transport/CMakeLists.txt +++ b/lib/transport/CMakeLists.txt @@ -6,7 +6,6 @@ set(TRANSPORT_HEADERS transport/transport-pipe.h transport/transport-socket.h transport/transport-udp-socket.h - transport/transport-factory.h transport/transport-stack.h transport/transport-factory-tls.h transport/transport-factory-socket.h diff --git a/lib/transport/Makefile.am b/lib/transport/Makefile.am index 44e6be3a9e..a8c3b71cc9 100644 --- a/lib/transport/Makefile.am +++ b/lib/transport/Makefile.am @@ -10,7 +10,6 @@ transportinclude_HEADERS = \ lib/transport/transport-pipe.h \ lib/transport/transport-socket.h \ lib/transport/transport-udp-socket.h \ - lib/transport/transport-factory.h \ lib/transport/transport-stack.h \ lib/transport/transport-factory-tls.h \ lib/transport/transport-factory-socket.h \ diff --git a/lib/transport/tests/CMakeLists.txt b/lib/transport/tests/CMakeLists.txt index 3c03604983..34120c56d1 100644 --- a/lib/transport/tests/CMakeLists.txt +++ b/lib/transport/tests/CMakeLists.txt @@ -1,3 +1,2 @@ add_unit_test(CRITERION TARGET test_aux_data) -add_unit_test(CRITERION TARGET test_transport_factory) add_unit_test(CRITERION TARGET test_transport_stack) diff --git a/lib/transport/tests/Makefile.am b/lib/transport/tests/Makefile.am index d3d45695fb..3c97dc38ba 100644 --- a/lib/transport/tests/Makefile.am +++ b/lib/transport/tests/Makefile.am @@ -1,6 +1,5 @@ lib_transport_tests_TESTS = \ lib/transport/tests/test_aux_data \ - lib/transport/tests/test_transport_factory \ lib/transport/tests/test_transport_stack EXTRA_DIST += lib/transport/tests/CMakeLists.txt @@ -13,12 +12,6 @@ lib_transport_tests_test_aux_data_LDADD = $(TEST_LDADD) lib_transport_tests_test_aux_data_SOURCES = \ lib/transport/tests/test_aux_data.c -lib_transport_tests_test_transport_factory_CFLAGS = $(TEST_CFLAGS) \ - -I${top_srcdir}/lib/transport/tests -lib_transport_tests_test_transport_factory_LDADD = $(TEST_LDADD) -lib_transport_tests_test_transport_factory_SOURCES = \ - lib/transport/tests/test_transport_factory.c - lib_transport_tests_test_transport_stack_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/transport/tests lib_transport_tests_test_transport_stack_LDADD = $(TEST_LDADD) diff --git a/lib/transport/tests/test_transport_factory.c b/lib/transport/tests/test_transport_factory.c deleted file mode 100644 index ce43c2ba0d..0000000000 --- a/lib/transport/tests/test_transport_factory.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2002-2018 Balabit - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ - -#include - -#include "transport/transport-factory.h" -#include "apphook.h" - -typedef struct _FakeTransport FakeTransport; -typedef struct _FakeTransportFactory FakeTransportFactory; - -struct _FakeTransport -{ - LogTransport super; - gboolean constructed; -}; - -static gssize -_fake_read(LogTransport *s, gpointer buf, gsize count, LogTransportAuxData *auc) -{ - return count; -} - -static gssize -_fake_write(LogTransport *s, const gpointer buf, gsize count) -{ - return count; -} - -static void -_fake_free(LogTransport *s) -{ -} - -LogTransport * -_fake_transport_new(void) -{ - FakeTransport *instance = g_new0(FakeTransport, 1); - - instance->super.read = _fake_read; - instance->super.write = _fake_write; - instance->constructed = TRUE; - - return &instance->super; -} - -struct _FakeTransportFactory -{ - LogTransportFactory super; -}; - -static LogTransport * -_transport_factory_construct(const LogTransportFactory *s, gint fd) -{ - LogTransport *fake_transport = _fake_transport_new(); - log_transport_init_instance(fake_transport, fd); - fake_transport->free_fn = _fake_free; - - return fake_transport; -} - -LogTransportFactory * -_fake_transport_factory_new(void) -{ - FakeTransportFactory *instance = g_new0(FakeTransportFactory, 1); - instance->super.id = "fake"; - instance->super.construct_transport = _transport_factory_construct; - return &instance->super; -} - -TestSuite(transport_factory, .init = app_startup, .fini = app_shutdown); - -Test(transport_factory, fake_transport_factory) -{ - LogTransportFactory *fake_factory = _fake_transport_factory_new(); - cr_expect_not_null(fake_factory->id); - - gint fd = 11; - FakeTransport *fake_transport = (FakeTransport *) log_transport_factory_construct_transport(fake_factory, fd); - cr_expect_eq(fake_transport->constructed, TRUE); - cr_expect_eq(fake_transport->super.read, _fake_read); - cr_expect_eq(fake_transport->super.write, _fake_write); - log_transport_free(&fake_transport->super); - - log_transport_factory_free(fake_factory); -} diff --git a/lib/transport/tests/test_transport_stack.c b/lib/transport/tests/test_transport_stack.c index 257593b4d9..9f4e1546aa 100644 --- a/lib/transport/tests/test_transport_stack.c +++ b/lib/transport/tests/test_transport_stack.c @@ -24,7 +24,6 @@ #include #include "transport/transport-stack.h" -#include "transport/transport-factory.h" #include "apphook.h" #define DEFINE_TEST_TRANSPORT_WITH_FACTORY(TypePrefix, FunPrefix) \ diff --git a/lib/transport/transport-factory-socket.h b/lib/transport/transport-factory-socket.h index 5ace093245..791f16972c 100644 --- a/lib/transport/transport-factory-socket.h +++ b/lib/transport/transport-factory-socket.h @@ -25,7 +25,7 @@ #ifndef TRANSPORT_FACTORY_SOCKET_H_INCLUDED #define TRANSPORT_FACTORY_SOCKET_H_INCLUDED -#include "transport/transport-factory.h" +#include "transport/transport-stack.h" #include "transport/transport-socket.h" typedef struct _LogTransportFactorySocket LogTransportFactorySocket; diff --git a/lib/transport/transport-factory-tls.h b/lib/transport/transport-factory-tls.h index 4c9f9560f7..aa73ca7f2a 100644 --- a/lib/transport/transport-factory-tls.h +++ b/lib/transport/transport-factory-tls.h @@ -25,7 +25,7 @@ #ifndef TRANSPORT_FACTORY_TLS_H_INCLUDED #define TRANSPORT_FACTORY_TLS_H_INCLUDED -#include "transport/transport-factory.h" +#include "transport/transport-stack.h" #include "transport/tls-context.h" typedef struct _LogTransportFactoryTLS LogTransportFactoryTLS; diff --git a/lib/transport/transport-factory.h b/lib/transport/transport-factory.h deleted file mode 100644 index 56b62a4164..0000000000 --- a/lib/transport/transport-factory.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2002-2018 Balabit - * Copyright (c) 2018 Laszlo Budai - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ - -#ifndef TRANSPORT_FACTORY_H_INCLUDED -#define TRANSPORT_FACTORY_H_INCLUDED - -#include "transport/logtransport.h" - -/* LogTransportFactory is an interface for representing - * concrete LogTransportFactory instances - * Each LogTransportFactory has - * - a reference to a unique id - * - a construct method for creating new LogTransport instances - * - a destroy method for releasing resources that are needed for construct() - */ -typedef struct _LogTransportFactory LogTransportFactory; - -struct _LogTransportFactory -{ - const gchar *id; - LogTransport *(*construct_transport)(const LogTransportFactory *self, gint fd); - void (*free_fn)(LogTransportFactory *self); -}; - -static inline LogTransport * -log_transport_factory_construct_transport(const LogTransportFactory *self, gint fd) -{ - g_assert(self->construct_transport); - - LogTransport *transport = self->construct_transport(self, fd); - transport->name = self->id; - - return transport; -} - -static inline void -log_transport_factory_free(LogTransportFactory *self) -{ - if (self->free_fn) - self->free_fn(self); - g_free(self); -} - -static inline const gchar * -log_transport_factory_get_id(const LogTransportFactory *self) -{ - /* each concrete LogTransportFactory has to have an id - */ - g_assert(self->id); - return self->id; -} - -#endif diff --git a/lib/transport/transport-stack.h b/lib/transport/transport-stack.h index cf91fb4953..eab13e6a2d 100644 --- a/lib/transport/transport-stack.h +++ b/lib/transport/transport-stack.h @@ -26,7 +26,50 @@ #define TRANSPORT_STACK_H_INCLUDED #include "transport/logtransport.h" -#include "transport/transport-factory.h" + +/* LogTransportFactory is an interface for representing + * concrete LogTransportFactory instances + * Each LogTransportFactory has + * - a reference to a unique id + * - a construct method for creating new LogTransport instances + * - a destroy method for releasing resources that are needed for construct() + */ +typedef struct _LogTransportFactory LogTransportFactory; + +struct _LogTransportFactory +{ + const gchar *id; + LogTransport *(*construct_transport)(const LogTransportFactory *self, gint fd); + void (*free_fn)(LogTransportFactory *self); +}; + +static inline LogTransport * +log_transport_factory_construct_transport(const LogTransportFactory *self, gint fd) +{ + g_assert(self->construct_transport); + + LogTransport *transport = self->construct_transport(self, fd); + transport->name = self->id; + + return transport; +} + +static inline void +log_transport_factory_free(LogTransportFactory *self) +{ + if (self->free_fn) + self->free_fn(self); + g_free(self); +} + +static inline const gchar * +log_transport_factory_get_id(const LogTransportFactory *self) +{ + /* each concrete LogTransportFactory has to have an id + */ + g_assert(self->id); + return self->id; +} typedef struct _LogTransportStack LogTransportStack; From f5d38667a7a95d933495c6bf18528b86fe1e4828 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 15 Sep 2024 06:49:15 +0200 Subject: [PATCH 07/15] transport: initialize transport->name Instead of relying on the factory to initialize name, initialize it through the normal constructor path. Signed-off-by: Balazs Scheidler --- lib/transport/logtransport.c | 3 ++- lib/transport/logtransport.h | 2 +- lib/transport/tests/test_transport_stack.c | 2 +- lib/transport/transport-file.c | 2 +- lib/transport/transport-pipe.c | 1 + lib/transport/transport-socket.c | 8 ++++---- lib/transport/transport-stack.c | 2 +- lib/transport/transport-stack.h | 1 - lib/transport/transport-tls.c | 1 + libtest/mock-transport.c | 2 +- modules/affile/transport-prockmsg.c | 2 +- modules/afstreams/afstreams.c | 2 +- 12 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/transport/logtransport.c b/lib/transport/logtransport.c index ba2b6b0ce5..7117efb73a 100644 --- a/lib/transport/logtransport.c +++ b/lib/transport/logtransport.c @@ -39,8 +39,9 @@ log_transport_free_method(LogTransport *s) } void -log_transport_init_instance(LogTransport *self, gint fd) +log_transport_init_instance(LogTransport *self, const gchar *name, gint fd) { + self->name = name; self->fd = fd; self->cond = 0; self->free_fn = log_transport_free_method; diff --git a/lib/transport/logtransport.h b/lib/transport/logtransport.h index e4d970ba08..3a4f6bbca4 100644 --- a/lib/transport/logtransport.h +++ b/lib/transport/logtransport.h @@ -59,7 +59,7 @@ log_transport_read(LogTransport *self, gpointer buf, gsize count, LogTransportAu return self->read(self, buf, count, aux); } -void log_transport_init_instance(LogTransport *s, gint fd); +void log_transport_init_instance(LogTransport *s, const gchar *name, gint fd); void log_transport_free_method(LogTransport *s); void log_transport_free(LogTransport *s); gint log_transport_release_fd(LogTransport *s); diff --git a/lib/transport/tests/test_transport_stack.c b/lib/transport/tests/test_transport_stack.c index 9f4e1546aa..9f0f3da087 100644 --- a/lib/transport/tests/test_transport_stack.c +++ b/lib/transport/tests/test_transport_stack.c @@ -59,7 +59,7 @@ FunPrefix ## _factory_construct(const LogTransportFactory *s, gint fd) \ {\ LogTransport *transport = FunPrefix ## _transport_new(); \ - log_transport_init_instance(transport, fd); \ + log_transport_init_instance(transport, # FunPrefix, fd); \ return transport; \ } \ LogTransportFactory * \ diff --git a/lib/transport/transport-file.c b/lib/transport/transport-file.c index f939c3fc98..7068849938 100644 --- a/lib/transport/transport-file.c +++ b/lib/transport/transport-file.c @@ -83,7 +83,7 @@ log_transport_file_writev_method(LogTransport *self, struct iovec *iov, gint iov void log_transport_file_init_instance(LogTransportFile *self, gint fd) { - log_transport_init_instance(&self->super, fd); + log_transport_init_instance(&self->super, "file", fd); self->super.read = log_transport_file_read_method; self->super.write = log_transport_file_write_method; self->super.writev = log_transport_file_writev_method; diff --git a/lib/transport/transport-pipe.c b/lib/transport/transport-pipe.c index 49a6fa2b5c..37f65cc181 100644 --- a/lib/transport/transport-pipe.c +++ b/lib/transport/transport-pipe.c @@ -75,6 +75,7 @@ log_transport_pipe_new(gint fd) LogTransportFile *self = g_new0(LogTransportFile, 1); log_transport_file_init_instance(self, fd); + self->super.name = "pipe"; self->super.write = log_transport_pipe_write_method; return &self->super; } diff --git a/lib/transport/transport-socket.c b/lib/transport/transport-socket.c index 5d4109b047..6907f4d399 100644 --- a/lib/transport/transport-socket.c +++ b/lib/transport/transport-socket.c @@ -207,9 +207,9 @@ log_transport_socket_write_method(LogTransport *s, const gpointer buf, gsize buf } static void -log_transport_socket_init_instance(LogTransportSocket *self, gint fd) +log_transport_socket_init_instance(LogTransportSocket *self, const gchar *name, gint fd) { - log_transport_init_instance(&self->super, fd); + log_transport_init_instance(&self->super, name, fd); self->super.read = log_transport_socket_read_method; self->super.write = log_transport_socket_write_method; self->address_family = _determine_address_family(fd); @@ -256,7 +256,7 @@ log_transport_dgram_socket_write_method(LogTransport *s, const gpointer buf, gsi void log_transport_dgram_socket_init_instance(LogTransportSocket *self, gint fd) { - log_transport_socket_init_instance(self, fd); + log_transport_socket_init_instance(self, "dgram-socket", fd); self->super.read = log_transport_dgram_socket_read_method; self->super.write = log_transport_dgram_socket_write_method; } @@ -281,7 +281,7 @@ log_transport_stream_socket_free_method(LogTransport *s) void log_transport_stream_socket_init_instance(LogTransportSocket *self, gint fd) { - log_transport_socket_init_instance(self, fd); + log_transport_socket_init_instance(self, "stream-socket", fd); self->super.free_fn = log_transport_stream_socket_free_method; } diff --git a/lib/transport/transport-stack.c b/lib/transport/transport-stack.c index 3b1d6f7e00..8dd404bfef 100644 --- a/lib/transport/transport-stack.c +++ b/lib/transport/transport-stack.c @@ -137,7 +137,7 @@ log_transport_stack_new(LogTransportFactory *default_transport_factory, gint fd) { LogTransportStack *self = g_new0(LogTransportStack, 1); - log_transport_init_instance(&self->super, fd); + log_transport_init_instance(&self->super, "transport_stack", fd); self->super.read = _log_transport_stack_read; self->super.write = _log_transport_stack_write; self->super.free_fn = _log_transport_stack_free; diff --git a/lib/transport/transport-stack.h b/lib/transport/transport-stack.h index eab13e6a2d..a6a223060d 100644 --- a/lib/transport/transport-stack.h +++ b/lib/transport/transport-stack.h @@ -49,7 +49,6 @@ log_transport_factory_construct_transport(const LogTransportFactory *self, gint g_assert(self->construct_transport); LogTransport *transport = self->construct_transport(self, fd); - transport->name = self->id; return transport; } diff --git a/lib/transport/transport-tls.c b/lib/transport/transport-tls.c index 2091d0ad33..53bebe8753 100644 --- a/lib/transport/transport-tls.c +++ b/lib/transport/transport-tls.c @@ -246,6 +246,7 @@ log_transport_tls_new(TLSSession *tls_session, gint fd) LogTransportTLS *self = g_new0(LogTransportTLS, 1); log_transport_stream_socket_init_instance(&self->super, fd); + self->super.super.name = "tls"; self->super.super.cond = 0; self->super.super.read = log_transport_tls_read_method; self->super.super.write = log_transport_tls_write_method; diff --git a/libtest/mock-transport.c b/libtest/mock-transport.c index de41855ec1..8ad2929145 100644 --- a/libtest/mock-transport.c +++ b/libtest/mock-transport.c @@ -345,7 +345,7 @@ log_transport_mock_init(LogTransportMock *self, const gchar *read_buffer1, gssiz const gchar *buffer; gssize length; - log_transport_init_instance(&self->super, 0); + log_transport_init_instance(&self->super, "mock", 0); self->super.read = log_transport_mock_read_method; self->super.write = log_transport_mock_write_method; self->super.writev = log_transport_mock_writev_method; diff --git a/modules/affile/transport-prockmsg.c b/modules/affile/transport-prockmsg.c index 0d00833b2a..e1a1ddb64c 100644 --- a/modules/affile/transport-prockmsg.c +++ b/modules/affile/transport-prockmsg.c @@ -67,7 +67,7 @@ log_transport_prockmsg_new(gint fd, gint timeout) { LogTransportDevice *self = g_new0(LogTransportDevice, 1); - log_transport_init_instance(&self->super, fd); + log_transport_init_instance(&self->super, "prockmsg", fd); self->timeout = timeout; self->super.read = log_transport_prockmsg_read_method; self->super.write = NULL; diff --git a/modules/afstreams/afstreams.c b/modules/afstreams/afstreams.c index 36756c408a..c1cae4744f 100644 --- a/modules/afstreams/afstreams.c +++ b/modules/afstreams/afstreams.c @@ -93,7 +93,7 @@ log_transport_streams_new(gint fd) { LogTransport *self = g_new0(LogTransport, 1); - log_transport_init_instance(self, fd); + log_transport_init_instance(self, "sun-streams", fd); self->cond = G_IO_IN; self->read = log_transport_streams_read; self->free_fn = log_transport_free_method; From 083096e5a4a4fcd0a677754b42a3ac97ce6c4b73 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Tue, 17 Sep 2024 10:45:56 +0200 Subject: [PATCH 08/15] transport: change LogTransportStack (ex MultiTransport) to represent a stack of LogTransports Instead of trying to reuse the LogTransport interface and hide cases where we need multiple swappable LogTransports, let's introduce a LogTransportStack, that explicitly tracks all such LogTransports, takes care of their lifecycle and allows them to be swapped during a connection. To be used for HA Proxy protocol support. Signed-off-by: Balazs Scheidler --- lib/logproto/logproto-buffered-server.c | 17 ++- lib/logproto/logproto-client.c | 4 +- lib/logproto/logproto-client.h | 4 +- lib/logproto/logproto-framed-server.c | 10 +- lib/logproto/logproto-proxied-text-server.c | 16 ++- lib/logproto/logproto-record-server.c | 5 +- lib/logproto/logproto-server.c | 14 +- lib/logproto/logproto-server.h | 4 +- lib/logproto/logproto-text-client.c | 17 ++- lib/logproto/logproto.h | 2 +- lib/transport/logtransport.c | 16 --- lib/transport/logtransport.h | 1 - lib/transport/tests/test_transport_stack.c | 48 +++---- lib/transport/transport-factory-socket.c | 14 +- lib/transport/transport-factory-socket.h | 4 +- lib/transport/transport-factory-tls.c | 16 +-- lib/transport/transport-factory-tls.h | 8 +- lib/transport/transport-stack.c | 150 +++++++------------- lib/transport/transport-stack.h | 104 ++++++++++---- modules/affile/logproto-file-writer.c | 18 +-- modules/afsocket/afsocket-dest.c | 17 +-- modules/afsocket/afsocket-source.c | 21 +-- modules/afsocket/transport-mapper-inet.c | 79 +++-------- modules/afsocket/transport-mapper-unix.c | 14 +- modules/afsocket/transport-mapper.h | 11 +- 25 files changed, 284 insertions(+), 330 deletions(-) diff --git a/lib/logproto/logproto-buffered-server.c b/lib/logproto/logproto-buffered-server.c index a624d36ec2..ac61b108c0 100644 --- a/lib/logproto/logproto-buffered-server.c +++ b/lib/logproto/logproto-buffered-server.c @@ -179,9 +179,10 @@ log_proto_buffered_server_apply_state(LogProtoBufferedServer *self, PersistEntry struct stat st; gint64 ofs = 0; LogProtoBufferedServerState *state; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); gint fd; - fd = self->super.transport->fd; + fd = transport->fd; self->persist_handle = handle; if (fstat(fd, &st) < 0) @@ -254,7 +255,7 @@ log_proto_buffered_server_apply_state(LogProtoBufferedServer *self, PersistEntry raw_buffer = g_alloca(state->raw_buffer_size); } - rc = log_transport_read(self->super.transport, raw_buffer, state->raw_buffer_size, NULL); + rc = log_transport_read(transport, raw_buffer, state->raw_buffer_size, NULL); if (rc != state->raw_buffer_size) { msg_notice("Error re-reading buffer contents of the file to be continued, restarting from the beginning", @@ -586,8 +587,9 @@ LogProtoPrepareAction log_proto_buffered_server_prepare(LogProtoServer *s, GIOCondition *cond, gint *timeout G_GNUC_UNUSED) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); - *cond = self->super.transport->cond; + *cond = transport->cond; /* if there's no pending I/O in the transport layer, then we want to do a read */ if (*cond == 0) @@ -600,7 +602,9 @@ static gint log_proto_buffered_server_read_data_method(LogProtoBufferedServer *self, guchar *buf, gsize len, LogTransportAuxData *aux) { - return log_transport_read(self->super.transport, buf, len, aux); + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); + + return log_transport_read(transport, buf, len, aux); } static void @@ -816,7 +820,7 @@ log_proto_buffered_server_fetch_into_buffer(LogProtoBufferedServer *self) { /* an error occurred while reading */ msg_error("I/O error occurred while reading", - evt_tag_int(EVT_TAG_FD, self->super.transport->fd), + evt_tag_int(EVT_TAG_FD, self->super.transport_stack.fd), evt_tag_error(EVT_TAG_OSERROR)); result = G_IO_STATUS_ERROR; } @@ -825,7 +829,7 @@ log_proto_buffered_server_fetch_into_buffer(LogProtoBufferedServer *self) { /* EOF read */ msg_trace("EOF occurred while reading", - evt_tag_int(EVT_TAG_FD, self->super.transport->fd)); + evt_tag_int(EVT_TAG_FD, self->super.transport_stack.fd)); if (state->raw_buffer_leftover_size > 0) { msg_error("EOF read on a channel with leftovers from previous character conversion, dropping input"); @@ -1080,7 +1084,6 @@ log_proto_buffered_server_init(LogProtoBufferedServer *self, LogTransport *trans self->super.prepare = log_proto_buffered_server_prepare; self->super.fetch = log_proto_buffered_server_fetch; self->super.free_fn = log_proto_buffered_server_free_method; - self->super.transport = transport; self->super.restart_with_state = log_proto_buffered_server_restart_with_state; self->super.validate_options = log_proto_buffered_server_validate_options_method; self->convert = (GIConv) -1; diff --git a/lib/logproto/logproto-client.c b/lib/logproto/logproto-client.c index b252e413ac..14f8673e58 100644 --- a/lib/logproto/logproto-client.c +++ b/lib/logproto/logproto-client.c @@ -38,7 +38,7 @@ log_proto_client_validate_options_method(LogProtoClient *s) void log_proto_client_free_method(LogProtoClient *s) { - log_transport_free(s->transport); + log_transport_stack_deinit(&s->transport_stack); } void @@ -55,7 +55,7 @@ log_proto_client_init(LogProtoClient *self, LogTransport *transport, const LogPr self->validate_options = log_proto_client_validate_options_method; self->free_fn = log_proto_client_free_method; self->options = options; - self->transport = transport; + log_transport_stack_init(&self->transport_stack, transport); } void diff --git a/lib/logproto/logproto-client.h b/lib/logproto/logproto-client.h index ca2607793a..a6246283d7 100644 --- a/lib/logproto/logproto-client.h +++ b/lib/logproto/logproto-client.h @@ -66,7 +66,7 @@ struct _LogProtoClient { LogProtoStatus status; const LogProtoClientOptions *options; - LogTransport *transport; + LogTransportStack transport_stack; /* FIXME: rename to something else */ gboolean (*prepare)(LogProtoClient *s, gint *fd, GIOCondition *cond, gint *timeout); LogProtoStatus (*post)(LogProtoClient *s, LogMessage *logmsg, guchar *msg, gsize msg_len, gboolean *consumed); @@ -165,7 +165,7 @@ static inline gint log_proto_client_get_fd(LogProtoClient *s) { /* FIXME: Layering violation */ - return s->transport->fd; + return s->transport_stack.fd; } static inline void diff --git a/lib/logproto/logproto-framed-server.c b/lib/logproto/logproto-framed-server.c index a8f6d0109b..369dba2a7a 100644 --- a/lib/logproto/logproto-framed-server.c +++ b/lib/logproto/logproto-framed-server.c @@ -69,8 +69,9 @@ static LogProtoPrepareAction log_proto_framed_server_prepare(LogProtoServer *s, GIOCondition *cond, gint *timeout G_GNUC_UNUSED) { LogProtoFramedServer *self = (LogProtoFramedServer *) s; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); - *cond = self->super.transport->cond; + *cond = transport->cond; /* there is a half message in our buffer so try to wait */ if (!self->half_message_in_buffer) @@ -96,6 +97,7 @@ static gboolean log_proto_framed_server_fetch_data(LogProtoFramedServer *self, gboolean *may_read, LogProtoStatus *status) { + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); gint rc; *status = LPS_SUCCESS; @@ -109,7 +111,7 @@ log_proto_framed_server_fetch_data(LogProtoFramedServer *self, gboolean *may_rea return FALSE; log_transport_aux_data_reinit(&self->buffer_aux); - rc = log_transport_read(self->super.transport, &self->buffer[self->buffer_end], self->buffer_size - self->buffer_end, + rc = log_transport_read(transport, &self->buffer[self->buffer_end], self->buffer_size - self->buffer_end, &self->buffer_aux); if (rc < 0) @@ -117,7 +119,7 @@ log_proto_framed_server_fetch_data(LogProtoFramedServer *self, gboolean *may_rea if (errno != EAGAIN) { msg_error("Error reading RFC6587 style framed data", - evt_tag_int("fd", self->super.transport->fd), + evt_tag_int("fd", transport->fd), evt_tag_error("error")); *status = LPS_ERROR; } @@ -132,7 +134,7 @@ log_proto_framed_server_fetch_data(LogProtoFramedServer *self, gboolean *may_rea if (rc == 0) { msg_trace("EOF occurred while reading", - evt_tag_int(EVT_TAG_FD, self->super.transport->fd)); + evt_tag_int(EVT_TAG_FD, transport->fd)); *status = LPS_EOF; return FALSE; } diff --git a/lib/logproto/logproto-proxied-text-server.c b/lib/logproto/logproto-proxied-text-server.c index 814dac2044..7775541ffd 100644 --- a/lib/logproto/logproto-proxied-text-server.c +++ b/lib/logproto/logproto-proxied-text-server.c @@ -344,10 +344,12 @@ _parse_proxy_header(LogProtoProxiedTextServer *self) static LogProtoStatus _fetch_chunk(LogProtoProxiedTextServer *self, gsize upto_bytes) { + LogTransport *transport = log_transport_stack_get_active(&self->super.super.super.transport_stack); + g_assert(upto_bytes < sizeof(self->proxy_header_buff)); if (self->proxy_header_buff_len < upto_bytes) { - gssize rc = log_transport_read(self->super.super.super.transport, + gssize rc = log_transport_read(transport, &(self->proxy_header_buff[self->proxy_header_buff_len]), upto_bytes - self->proxy_header_buff_len, NULL); if (rc < 0) @@ -357,7 +359,7 @@ _fetch_chunk(LogProtoProxiedTextServer *self, gsize upto_bytes) else { msg_error("I/O error occurred while reading proxy header", - evt_tag_int(EVT_TAG_FD, self->super.super.super.transport->fd), + evt_tag_int(EVT_TAG_FD, transport->fd), evt_tag_error(EVT_TAG_OSERROR)); return LPS_ERROR; } @@ -441,6 +443,7 @@ _is_proxy_version_v2(LogProtoProxiedTextServer *self) static inline LogProtoStatus _fetch_into_proxy_buffer(LogProtoProxiedTextServer *self) { + LogTransport *transport = log_transport_stack_get_active(&self->super.super.super.transport_stack); LogProtoStatus status; switch (self->header_fetch_state) @@ -469,7 +472,7 @@ _fetch_into_proxy_buffer(LogProtoProxiedTextServer *self) else { msg_error("Unable to determine PROXY protocol version", - evt_tag_int(EVT_TAG_FD, self->super.super.super.transport->fd)); + evt_tag_int(EVT_TAG_FD, transport->fd)); return LPS_ERROR; } g_assert_not_reached(); @@ -496,7 +499,7 @@ _fetch_into_proxy_buffer(LogProtoProxiedTextServer *self) static gboolean _switch_to_tls(LogProtoProxiedTextServer *self) { - if (!log_transport_stack_switch((LogTransportStack *)self->super.super.super.transport, TRANSPORT_FACTORY_TLS_ID)) + if (!log_transport_stack_switch(&self->super.super.super.transport_stack, LOG_TRANSPORT_TLS)) { msg_error("proxied-tls failed to switch to TLS"); return FALSE; @@ -510,10 +513,11 @@ static LogProtoPrepareAction log_proto_proxied_text_server_prepare(LogProtoServer *s, GIOCondition *cond, gint *timeout) { LogProtoProxiedTextServer *self = (LogProtoProxiedTextServer *) s; + LogTransport *transport = log_transport_stack_get_active(&s->transport_stack); - *cond = s->transport->cond; + *cond = transport->cond; - if(self->handshake_done) + if (self->handshake_done) return log_proto_text_server_prepare_method(s, cond, timeout); /* if there's no pending I/O in the transport layer, then we want to do a read */ diff --git a/lib/logproto/logproto-record-server.c b/lib/logproto/logproto-record-server.c index 8b6ace1b7f..ed72351b8f 100644 --- a/lib/logproto/logproto-record-server.c +++ b/lib/logproto/logproto-record-server.c @@ -54,16 +54,17 @@ static gint log_proto_record_server_read_data(LogProtoBufferedServer *s, guchar *buf, gsize len, LogTransportAuxData *aux) { LogProtoRecordServer *self = (LogProtoRecordServer *) s; + LogTransport *transport = log_transport_stack_get_active(&self->super.super.transport_stack); gint rc; /* assert that we have enough space in the buffer to read record_size bytes */ g_assert(len >= self->record_size); len = self->record_size; - rc = log_transport_read(self->super.super.transport, buf, len, aux); + rc = log_transport_read(transport, buf, len, aux); if (rc > 0 && rc != self->record_size) { msg_error("Record size was set, and couldn't read enough bytes", - evt_tag_int(EVT_TAG_FD, self->super.super.transport->fd), + evt_tag_int(EVT_TAG_FD, transport->fd), evt_tag_int("record_size", self->record_size), evt_tag_int("read", rc)); errno = EIO; diff --git a/lib/logproto/logproto-server.c b/lib/logproto/logproto-server.c index 0a31c3230e..c6ab65407f 100644 --- a/lib/logproto/logproto-server.c +++ b/lib/logproto/logproto-server.c @@ -122,17 +122,17 @@ log_proto_server_validate_options_method(LogProtoServer *s) } void -log_proto_server_free_method(LogProtoServer *s) +log_proto_server_free_method(LogProtoServer *self) { - log_transport_free(s->transport); + log_transport_stack_deinit(&self->transport_stack); } void -log_proto_server_free(LogProtoServer *s) +log_proto_server_free(LogProtoServer *self) { - if (s->free_fn) - s->free_fn(s); - g_free(s); + if (self->free_fn) + self->free_fn(self); + g_free(self); } void @@ -141,7 +141,7 @@ log_proto_server_init(LogProtoServer *self, LogTransport *transport, const LogPr self->validate_options = log_proto_server_validate_options_method; self->free_fn = log_proto_server_free_method; self->options = options; - self->transport = transport; + log_transport_stack_init(&self->transport_stack, transport); } gboolean diff --git a/lib/logproto/logproto-server.h b/lib/logproto/logproto-server.h index 705de49ce5..db782ecf07 100644 --- a/lib/logproto/logproto-server.h +++ b/lib/logproto/logproto-server.h @@ -78,7 +78,7 @@ struct _LogProtoServer { LogProtoStatus status; const LogProtoServerOptions *options; - LogTransport *transport; + LogTransportStack transport_stack; AckTracker *ack_tracker; LogProtoServerWakeupCallback wakeup_callback; @@ -144,7 +144,7 @@ log_proto_server_get_fd(LogProtoServer *s) /* FIXME: Layering violation, as transport may not be fd based at all. * But LogReader assumes it is. */ - return s->transport->fd; + return s->transport_stack.fd; } static inline void diff --git a/lib/logproto/logproto-text-client.c b/lib/logproto/logproto-text-client.c index 8cad2e9a65..eb28411fdd 100644 --- a/lib/logproto/logproto-text-client.c +++ b/lib/logproto/logproto-text-client.c @@ -30,9 +30,10 @@ static gboolean log_proto_text_client_prepare(LogProtoClient *s, gint *fd, GIOCondition *cond, gint *timeout) { LogProtoTextClient *self = (LogProtoTextClient *) s; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); - *fd = self->super.transport->fd; - *cond = self->super.transport->cond; + *fd = transport->fd; + *cond = transport->cond; /* if there's no pending I/O in the transport layer, then we want to do a write */ if (*cond == 0) @@ -50,23 +51,24 @@ static LogProtoStatus log_proto_text_client_drop_input(LogProtoClient *s) { LogProtoTextClient *self = (LogProtoTextClient *) s; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); guchar buf[1024]; gint rc = -1; do { - rc = log_transport_read(self->super.transport, buf, sizeof(buf), NULL); + rc = log_transport_read(transport, buf, sizeof(buf), NULL); } while (rc > 0); if (rc == -1 && errno != EAGAIN) { - msg_error("Error reading data", evt_tag_int("fd", self->super.transport->fd), evt_tag_error("error")); + msg_error("Error reading data", evt_tag_int("fd", transport->fd), evt_tag_error("error")); return LPS_ERROR; } else if (rc == 0) { - msg_error("EOF occurred while idle", evt_tag_int("fd", log_proto_client_get_fd(&self->super))); + msg_error("EOF occurred while idle", evt_tag_int("fd", transport->fd)); return LPS_ERROR; } @@ -77,6 +79,7 @@ static LogProtoStatus log_proto_text_client_flush(LogProtoClient *s) { LogProtoTextClient *self = (LogProtoTextClient *) s; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); gint rc; if (!self->partial) @@ -87,13 +90,13 @@ log_proto_text_client_flush(LogProtoClient *s) /* attempt to flush previously buffered data */ gint len = self->partial_len - self->partial_pos; - rc = log_transport_write(self->super.transport, &self->partial[self->partial_pos], len); + rc = log_transport_write(transport, &self->partial[self->partial_pos], len); if (rc < 0) { if (errno != EAGAIN && errno != EINTR) { msg_error("I/O error occurred while writing", - evt_tag_int("fd", self->super.transport->fd), + evt_tag_int("fd", transport->fd), evt_tag_error(EVT_TAG_OSERROR)); return LPS_ERROR; } diff --git a/lib/logproto/logproto.h b/lib/logproto/logproto.h index 6ec618de74..5d7e74a635 100644 --- a/lib/logproto/logproto.h +++ b/lib/logproto/logproto.h @@ -25,7 +25,7 @@ #ifndef LOGPROTO_H_INCLUDED #define LOGPROTO_H_INCLUDED -#include "transport/logtransport.h" +#include "transport/transport-stack.h" #define RFC6587_MAX_FRAME_LEN_DIGITS 10 diff --git a/lib/transport/logtransport.c b/lib/transport/logtransport.c index 7117efb73a..61fd5f11b4 100644 --- a/lib/transport/logtransport.c +++ b/lib/transport/logtransport.c @@ -30,12 +30,6 @@ void log_transport_free_method(LogTransport *s) { - if (s->fd != -1) - { - msg_trace("Closing log transport fd", - evt_tag_int("fd", s->fd)); - close(s->fd); - } } void @@ -53,13 +47,3 @@ log_transport_free(LogTransport *self) self->free_fn(self); g_free(self); } - -gint -log_transport_release_fd(LogTransport *s) -{ - gint fd = s->fd; - s->fd = -1; - - return fd; -} - diff --git a/lib/transport/logtransport.h b/lib/transport/logtransport.h index 3a4f6bbca4..c6d7e00f32 100644 --- a/lib/transport/logtransport.h +++ b/lib/transport/logtransport.h @@ -62,6 +62,5 @@ log_transport_read(LogTransport *self, gpointer buf, gsize count, LogTransportAu void log_transport_init_instance(LogTransport *s, const gchar *name, gint fd); void log_transport_free_method(LogTransport *s); void log_transport_free(LogTransport *s); -gint log_transport_release_fd(LogTransport *s); #endif diff --git a/lib/transport/tests/test_transport_stack.c b/lib/transport/tests/test_transport_stack.c index 9f0f3da087..353a66c327 100644 --- a/lib/transport/tests/test_transport_stack.c +++ b/lib/transport/tests/test_transport_stack.c @@ -44,11 +44,13 @@ return count; \ }\ LogTransport * \ - FunPrefix ## _transport_new(void) \ + FunPrefix ## _transport_new(gint fd) \ { \ TypePrefix ## Transport *self = g_new0(TypePrefix ## Transport, 1); \ + log_transport_init_instance(&self->super, # FunPrefix, -1); \ self->super.read = FunPrefix ## _read; \ self->super.write = FunPrefix ## _write; \ + self->super.fd = fd; \ return &self->super; \ } \ struct TypePrefix ## TransportFactory_\ @@ -56,17 +58,16 @@ LogTransportFactory super; \ }; \ static LogTransport * \ - FunPrefix ## _factory_construct(const LogTransportFactory *s, gint fd) \ + FunPrefix ## _factory_construct(const LogTransportFactory *s, LogTransportStack *stack) \ {\ - LogTransport *transport = FunPrefix ## _transport_new(); \ - log_transport_init_instance(transport, # FunPrefix, fd); \ + LogTransport *transport = FunPrefix ## _transport_new(stack->fd); \ return transport; \ } \ LogTransportFactory * \ FunPrefix ## _transport_factory_new(void) \ { \ TypePrefix ## TransportFactory *self = g_new0(TypePrefix ## TransportFactory, 1); \ - self->super.id = #FunPrefix; \ + log_transport_factory_init_instance(&self->super, LOG_TRANSPORT_TLS); \ self->super.construct_transport = FunPrefix ## _factory_construct; \ return &self->super; \ } \ @@ -75,34 +76,31 @@ TestSuite(transport_stack, .init = app_startup, .fini = app_shutdown); DEFINE_TEST_TRANSPORT_WITH_FACTORY(Fake, fake); DEFINE_TEST_TRANSPORT_WITH_FACTORY(Default, default); -DEFINE_TEST_TRANSPORT_WITH_FACTORY(Unregistered, unregistered); Test(transport_stack, test_switch_transport) { - LogTransportFactory *default_factory = default_transport_factory_new(); LogTransportFactory *fake_factory = fake_transport_factory_new(); gint fd = -2; - LogTransportStack *transport_stack = (LogTransportStack *) log_transport_stack_new(default_factory, fd); + LogTransportStack stack; + log_transport_stack_init(&stack, default_transport_new(fd)); - cr_expect_eq(transport_stack->active_transport->read, default_read); - cr_expect_eq(transport_stack->active_transport->write, default_write); - cr_expect_str_eq(transport_stack->active_transport->name, "default"); + cr_assert(stack.fd == fd); - log_transport_stack_add_factory(transport_stack, fake_factory); - cr_expect_not(log_transport_stack_contains_factory(transport_stack, "unregistered")); - cr_expect(log_transport_stack_contains_factory(transport_stack, "fake")); - cr_expect_not(log_transport_stack_switch(transport_stack, "unregistered")); - cr_expect_eq(transport_stack->active_transport->read, default_read); - cr_expect_eq(transport_stack->active_transport->write, default_write); - cr_expect_eq(transport_stack->active_transport_factory, default_factory); - cr_expect_str_eq(transport_stack->active_transport->name, "default"); + LogTransport *active_transport = log_transport_stack_get_active(&stack); - cr_expect(log_transport_stack_switch(transport_stack, "fake")); - cr_expect_eq(transport_stack->active_transport->read, fake_read); - cr_expect_eq(transport_stack->active_transport->write, fake_write); - cr_expect_eq(transport_stack->active_transport_factory, fake_factory); - cr_expect_str_eq(transport_stack->active_transport->name, "fake"); + cr_expect_eq(active_transport->read, default_read); + cr_expect_eq(active_transport->write, default_write); + cr_expect_str_eq(active_transport->name, "default"); - log_transport_free(&transport_stack->super); + log_transport_stack_add_factory(&stack, fake_factory); + + cr_expect(log_transport_stack_switch(&stack, LOG_TRANSPORT_TLS)); + active_transport = log_transport_stack_get_active(&stack); + + cr_expect_eq(active_transport->read, fake_read); + cr_expect_eq(active_transport->write, fake_write); + cr_expect_str_eq(active_transport->name, "fake"); + + log_transport_stack_deinit(&stack); } diff --git a/lib/transport/transport-factory-socket.c b/lib/transport/transport-factory-socket.c index b06ca9eb05..9813bad3be 100644 --- a/lib/transport/transport-factory-socket.c +++ b/lib/transport/transport-factory-socket.c @@ -27,29 +27,29 @@ #include "transport/transport-udp-socket.h" static LogTransport * -_construct_transport_dgram(const LogTransportFactory *s, gint fd) +_construct_transport_dgram(const LogTransportFactory *s, LogTransportStack *stack) { - return log_transport_udp_socket_new(fd); + return log_transport_udp_socket_new(stack->fd); } static LogTransport * -_construct_transport_stream(const LogTransportFactory *s, gint fd) +_construct_transport_stream(const LogTransportFactory *s, LogTransportStack *stack) { - return log_transport_stream_socket_new(fd); + return log_transport_stream_socket_new(stack->fd); } LogTransportFactory * -log_transport_factory_socket_new(int sock_type) +transport_factory_socket_new(int sock_type) { LogTransportFactorySocket *self = g_new0(LogTransportFactorySocket, 1); + log_transport_factory_init_instance(&self->super, LOG_TRANSPORT_SOCKET); + if (sock_type == SOCK_DGRAM) self->super.construct_transport = _construct_transport_dgram; else self->super.construct_transport = _construct_transport_stream; - self->super.id = TRANSPORT_FACTORY_SOCKET_ID; - return &self->super; } diff --git a/lib/transport/transport-factory-socket.h b/lib/transport/transport-factory-socket.h index 791f16972c..5866411548 100644 --- a/lib/transport/transport-factory-socket.h +++ b/lib/transport/transport-factory-socket.h @@ -35,8 +35,6 @@ struct _LogTransportFactorySocket LogTransportFactory super; }; -#define TRANSPORT_FACTORY_SOCKET_ID "socket" - -LogTransportFactory *log_transport_factory_socket_new(gint sock_type); +LogTransportFactory *transport_factory_socket_new(gint sock_type); #endif diff --git a/lib/transport/transport-factory-tls.c b/lib/transport/transport-factory-tls.c index 58b96054ef..3a137c9114 100644 --- a/lib/transport/transport-factory-tls.c +++ b/lib/transport/transport-factory-tls.c @@ -27,7 +27,7 @@ #include "transport/transport-tls.h" static LogTransport * -_construct_transport(const LogTransportFactory *s, gint fd) +_construct_transport(const LogTransportFactory *s, LogTransportStack *stack) { LogTransportFactoryTLS *self = (LogTransportFactoryTLS *)s; TLSSession *tls_session = tls_context_setup_session(self->tls_context); @@ -39,18 +39,18 @@ _construct_transport(const LogTransportFactory *s, gint fd) tls_session_set_verifier(tls_session, self->tls_verifier); - return log_transport_tls_new(tls_session, fd); + return log_transport_tls_new(tls_session, stack->fd); } void -log_transport_factory_tls_enable_compression(LogTransportFactory *s) +transport_factory_tls_enable_compression(LogTransportFactory *s) { LogTransportFactoryTLS *self = (LogTransportFactoryTLS *)s; self->allow_compress = TRUE; } void -log_transport_factory_tls_disable_compression(LogTransportFactory *s) +transport_factory_tls_disable_compression(LogTransportFactory *s) { LogTransportFactoryTLS *self = (LogTransportFactoryTLS *)s; self->allow_compress = FALSE; @@ -66,21 +66,21 @@ _free(LogTransportFactory *s) } LogTransportFactory * -log_transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags) +transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags) { LogTransportFactoryTLS *instance = g_new0(LogTransportFactoryTLS, 1); + log_transport_factory_init_instance(&instance->super, LOG_TRANSPORT_TLS); instance->tls_context = tls_context_ref(ctx); instance->tls_verifier = tls_verifier ? tls_verifier_ref(tls_verifier) : NULL; - instance->super.id = TRANSPORT_FACTORY_TLS_ID; instance->super.construct_transport = _construct_transport; instance->super.free_fn = _free; if (flags & TMI_ALLOW_COMPRESS) - log_transport_factory_tls_enable_compression((LogTransportFactory *)instance); + transport_factory_tls_enable_compression((LogTransportFactory *)instance); else - log_transport_factory_tls_disable_compression((LogTransportFactory *)instance); + transport_factory_tls_disable_compression((LogTransportFactory *)instance); return &instance->super; } diff --git a/lib/transport/transport-factory-tls.h b/lib/transport/transport-factory-tls.h index aa73ca7f2a..217a250215 100644 --- a/lib/transport/transport-factory-tls.h +++ b/lib/transport/transport-factory-tls.h @@ -38,11 +38,9 @@ struct _LogTransportFactoryTLS gboolean allow_compress; }; -LogTransportFactory *log_transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags); +LogTransportFactory *transport_factory_tls_new(TLSContext *ctx, TLSVerifier *tls_verifier, guint32 flags); -void log_transport_factory_tls_enable_compression(LogTransportFactory *); -void log_transport_factory_tls_disable_compression(LogTransportFactory *); - -#define TRANSPORT_FACTORY_TLS_ID "tls" +void transport_factory_tls_enable_compression(LogTransportFactory *); +void transport_factory_tls_disable_compression(LogTransportFactory *); #endif diff --git a/lib/transport/transport-stack.c b/lib/transport/transport-stack.c index 8dd404bfef..6b3ab04683 100644 --- a/lib/transport/transport-stack.c +++ b/lib/transport/transport-stack.c @@ -25,125 +25,81 @@ #include "transport/transport-stack.h" #include "messages.h" -void -log_transport_stack_add_factory(LogTransportStack *self, LogTransportFactory *transport_factory) -{ - g_hash_table_insert(self->registry, (gpointer) transport_factory->id, transport_factory); -} +#include -static void -_do_transport_switch(LogTransportStack *self, LogTransport *new_transport, const LogTransportFactory *new_transport_factory) +void +log_transport_factory_init_instance(LogTransportFactory *self, LogTransportIndex index) { - self->super.fd = log_transport_release_fd(self->active_transport); - self->super.cond = new_transport->cond; - log_transport_free(self->active_transport); - self->active_transport = new_transport; - self->active_transport_factory = new_transport_factory; + memset(self, 0, sizeof(*self)); + self->index = index; } -static const LogTransportFactory * -_lookup_transport_factory(LogTransportStack *self, const gchar *factory_id) +void +log_transport_stack_add_factory(LogTransportStack *self, LogTransportFactory *transport_factory) { - const LogTransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); - - if (!factory) - { - msg_error("Requested transport not found", - evt_tag_str("transport", factory_id)); - return NULL; - } - - return factory; + gint index = transport_factory->index; + g_assert(self->transport_factories[index] == NULL); + self->transport_factories[index] = transport_factory; } -static LogTransport * -_construct_transport(const LogTransportFactory *factory, gint fd) +void +log_transport_stack_add_transport(LogTransportStack *self, gint index, LogTransport *transport) { - LogTransport *transport = log_transport_factory_construct_transport(factory, fd); - - if (!transport) - { - msg_error("Failed to construct transport", - evt_tag_str("transport", factory->id)); - return NULL; - } - - return transport; + g_assert(self->transports[index] == NULL); + self->transports[index] = transport; + if (self->fd == -1) + self->fd = transport->fd; + else + g_assert(self->fd == transport->fd); } gboolean -log_transport_stack_switch(LogTransportStack *self, const gchar *factory_id) +log_transport_stack_switch(LogTransportStack *self, gint index) { - msg_debug("Transport switch requested", - evt_tag_str("active-transport", self->active_transport->name), - evt_tag_str("requested-transport", factory_id)); + LogTransport *active_transport = log_transport_stack_get_active(self); + LogTransport *requested_transport = log_transport_stack_get_transport(self, index); - const LogTransportFactory *transport_factory = _lookup_transport_factory(self, factory_id); - if (!transport_factory) - return FALSE; + g_assert(requested_transport != NULL); - LogTransport *transport = _construct_transport(transport_factory, self->super.fd); - if (!transport) - return FALSE; + msg_debug("Transport switch requested", + evt_tag_str("active-transport", active_transport ? active_transport->name : "none"), + evt_tag_str("requested-transport", requested_transport->name)); - _do_transport_switch(self, transport, transport_factory); + /* FIXME: is this cond initialization really needed? */ + if (active_transport) + requested_transport->cond = active_transport->cond; + self->active_transport = index; + active_transport = log_transport_stack_get_active(self); - msg_debug("Transport switch succeeded", - evt_tag_str("new-active-transport", self->active_transport->name)); + msg_debug("Transport switch successful", + evt_tag_str("new-active-transport", active_transport->name)); return TRUE; } -gboolean -log_transport_stack_contains_factory(LogTransportStack *self, const gchar *factory_id) -{ - const LogTransportFactory *factory = g_hash_table_lookup(self->registry, factory_id); - - return (factory != NULL); -} - -static gssize -_log_transport_stack_write(LogTransport *s, gpointer buf, gsize count) -{ - LogTransportStack *self = (LogTransportStack *)s; - gssize r = log_transport_write(self->active_transport, buf, count); - self->super.cond = self->active_transport->cond; - - return r; -} - -static gssize -_log_transport_stack_read(LogTransport *s, gpointer buf, gsize count, LogTransportAuxData *aux) -{ - LogTransportStack *self = (LogTransportStack *)s; - gssize r = log_transport_read(self->active_transport, buf, count, aux); - self->super.cond = self->active_transport->cond; - - return r; -} - -static void -_log_transport_stack_free(LogTransport *s) +void +log_transport_stack_init(LogTransportStack *self, LogTransport *initial_transport) { - LogTransportStack *self = (LogTransportStack *)s; - s->fd = log_transport_release_fd(self->active_transport); - log_transport_free(self->active_transport); - g_hash_table_unref(self->registry); - log_transport_free_method(s); + memset(self, 0, sizeof(*self)); + self->fd = -1; + if (initial_transport) + log_transport_stack_add_transport(self, LOG_TRANSPORT_INITIAL, initial_transport); } -LogTransport * -log_transport_stack_new(LogTransportFactory *default_transport_factory, gint fd) +void +log_transport_stack_deinit(LogTransportStack *self) { - LogTransportStack *self = g_new0(LogTransportStack, 1); - - log_transport_init_instance(&self->super, "transport_stack", fd); - self->super.read = _log_transport_stack_read; - self->super.write = _log_transport_stack_write; - self->super.free_fn = _log_transport_stack_free; - self->registry = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) log_transport_factory_free); - self->active_transport = log_transport_factory_construct_transport(default_transport_factory, fd); - self->active_transport_factory = default_transport_factory; - - return &self->super; + if (self->fd != -1) + { + msg_trace("Closing log transport fd", + evt_tag_int("fd", self->fd)); + close(self->fd); + } + for (gint i = 0; i < LOG_TRANSPORT__MAX; i++) + { + if (self->transports[i]) + log_transport_free(self->transports[i]); + if (self->transport_factories[i]) + log_transport_factory_free(self->transport_factories[i]); + } } diff --git a/lib/transport/transport-stack.h b/lib/transport/transport-stack.h index a6a223060d..a53fca18ee 100644 --- a/lib/transport/transport-stack.h +++ b/lib/transport/transport-stack.h @@ -27,28 +27,35 @@ #include "transport/logtransport.h" -/* LogTransportFactory is an interface for representing - * concrete LogTransportFactory instances - * Each LogTransportFactory has - * - a reference to a unique id - * - a construct method for creating new LogTransport instances - * - a destroy method for releasing resources that are needed for construct() - */ +typedef struct _LogTransportStack LogTransportStack; typedef struct _LogTransportFactory LogTransportFactory; +typedef enum +{ + /* this is a special index for simple cases where we only use a single + * LogTransport which never changes */ + LOG_TRANSPORT_INITIAL, + LOG_TRANSPORT_SOCKET, + LOG_TRANSPORT_TLS, + LOG_TRANSPORT_HAPROXY, + LOG_TRANSPORT_GZIP, + LOG_TRANSPORT_NONE, + LOG_TRANSPORT__MAX = LOG_TRANSPORT_NONE, +} LogTransportIndex; + struct _LogTransportFactory { - const gchar *id; - LogTransport *(*construct_transport)(const LogTransportFactory *self, gint fd); + gint index; + LogTransport *(*construct_transport)(const LogTransportFactory *self, LogTransportStack *stack); void (*free_fn)(LogTransportFactory *self); }; static inline LogTransport * -log_transport_factory_construct_transport(const LogTransportFactory *self, gint fd) +log_transport_factory_construct_transport(const LogTransportFactory *self, LogTransportStack *stack) { g_assert(self->construct_transport); - LogTransport *transport = self->construct_transport(self, fd); + LogTransport *transport = self->construct_transport(self, stack); return transport; } @@ -61,28 +68,71 @@ log_transport_factory_free(LogTransportFactory *self) g_free(self); } -static inline const gchar * -log_transport_factory_get_id(const LogTransportFactory *self) -{ - /* each concrete LogTransportFactory has to have an id - */ - g_assert(self->id); - return self->id; -} +void log_transport_factory_init_instance(LogTransportFactory *self, LogTransportIndex index); -typedef struct _LogTransportStack LogTransportStack; +/* LogTransportStack + * + * This is a struct embedded into a LogProto instance and represents a + * combination of LogTransport instances that somehow work together. + * LogTransportStack allows "switching" between LogTransport instances so we + * can implement changes on the transport layer mid stream. Such a change + * would be for example the switch to the TLS transport after a STARTTLS. + * + * It is also possible to stack log transports, e.g. LogTransportAdapter + * would add some further processing on top of another. A use case here is + * the HAProxy implementation, which reads the proxy header from + * LogTransportSocket, processes it and then allows the LogProto + * implementation to interact with the peer. + * + * LogTransportStack ensures that all LogTransport instances are freed at + * the same time, so there's no need to keep references around. It also + * manages the closing of the underlying file descriptor. + * + * Right now, transports are identified using the LOG_TRANSPORT_XXXX enum, + * meaning that any new "layer" we can potentially push to the transport + * stack will need a new element in the enumeration. Although this is a bit + * of a layering violation and prevents new LogTransport implementations + * coming from plugins, it is only an easy to change implementation detail, + * which is perfectly fine with all transports provided by the core itself. + * + * A layer in the stack is either instantiated by the caller and pushed to + * the stack _OR_ it is instantiated automatically by LogTransportStack + * using the LogTransportFactory interface. + */ struct _LogTransportStack { - LogTransport super; - GHashTable *registry; - LogTransport *active_transport; - const LogTransportFactory *active_transport_factory; + gint active_transport; + gint fd; + LogTransport *transports[LOG_TRANSPORT__MAX]; + LogTransportFactory *transport_factories[LOG_TRANSPORT__MAX]; }; -LogTransport *log_transport_stack_new(LogTransportFactory *default_transport_factory, gint fd); +static inline LogTransport * +log_transport_stack_get_transport(LogTransportStack *self, gint index) +{ + if (self->transports[index]) + return self->transports[index]; + + if (self->transport_factories[index]) + { + self->transports[index] = log_transport_factory_construct_transport(self->transport_factories[index], self); + return self->transports[index]; + } + return NULL; +} + +static inline LogTransport * +log_transport_stack_get_active(LogTransportStack *self) +{ + return log_transport_stack_get_transport(self, self->active_transport); +} + void log_transport_stack_add_factory(LogTransportStack *self, LogTransportFactory *); -gboolean log_transport_stack_switch(LogTransportStack *self, const gchar *id); -gboolean log_transport_stack_contains_factory(LogTransportStack *self, const gchar *id); +void log_transport_stack_add_transport(LogTransportStack *self, gint index, LogTransport *); +gboolean log_transport_stack_switch(LogTransportStack *self, gint index); + +void log_transport_stack_init(LogTransportStack *self, LogTransport *initial_transport); +void log_transport_stack_deinit(LogTransportStack *self); #endif diff --git a/modules/affile/logproto-file-writer.c b/modules/affile/logproto-file-writer.c index 5662015f76..afec4d9ee9 100644 --- a/modules/affile/logproto-file-writer.c +++ b/modules/affile/logproto-file-writer.c @@ -48,10 +48,11 @@ typedef struct _LogProtoFileWriter static inline gboolean _flush_partial(LogProtoFileWriter *self, LogProtoStatus *status) { + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); /* there is still some data from the previous file writing process */ gint len = self->partial_len - self->partial_pos; - gssize rc = log_transport_write(self->super.transport, self->partial + self->partial_pos, len); + gssize rc = log_transport_write(transport, self->partial + self->partial_pos, len); if (rc > 0 && self->fsync) fsync(self->fd); @@ -66,7 +67,7 @@ _flush_partial(LogProtoFileWriter *self, LogProtoStatus *status) log_proto_client_msg_rewind(&self->super); msg_error("I/O error occurred while writing", - evt_tag_int("fd", self->super.transport->fd), + evt_tag_int("fd", transport->fd), evt_tag_error(EVT_TAG_OSERROR)); *status = LPS_ERROR; @@ -138,6 +139,7 @@ static LogProtoStatus log_proto_file_writer_flush(LogProtoClient *s) { LogProtoFileWriter *self = (LogProtoFileWriter *)s; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); if (self->partial) { @@ -150,10 +152,10 @@ log_proto_file_writer_flush(LogProtoClient *s) if (self->buf_count == 0) return LPS_SUCCESS; - gssize rc = log_transport_writev(self->super.transport, self->buffer, self->buf_count); + gssize rc = log_transport_writev(transport, self->buffer, self->buf_count); if (rc > 0 && self->fsync) - fsync(self->fd); + fsync(transport->fd); if (rc < 0) { @@ -162,7 +164,7 @@ log_proto_file_writer_flush(LogProtoClient *s) log_proto_client_msg_rewind(&self->super); msg_error("I/O error occurred while writing", - evt_tag_int("fd", self->super.transport->fd), + evt_tag_int("fd", transport->fd), evt_tag_error(EVT_TAG_OSERROR)); return LPS_ERROR; } @@ -233,9 +235,10 @@ static gboolean log_proto_file_writer_prepare(LogProtoClient *s, gint *fd, GIOCondition *cond, gint *timeout) { LogProtoFileWriter *self = (LogProtoFileWriter *) s; + LogTransport *transport = log_transport_stack_get_active(&self->super.transport_stack); - *fd = self->super.transport->fd; - *cond = self->super.transport->cond; + *fd = transport->fd; + *cond = transport->cond; /* if there's no pending I/O in the transport layer, then we want to do a write */ if (*cond == 0) @@ -265,7 +268,6 @@ log_proto_file_writer_new(LogTransport *transport, const LogProtoClientOptions * struct iovec)*flush_lines); log_proto_client_init(&self->super, transport, options); - self->fd = transport->fd; self->buf_size = flush_lines; self->fsync = fsync_; self->super.prepare = log_proto_file_writer_prepare; diff --git a/modules/afsocket/afsocket-dest.c b/modules/afsocket/afsocket-dest.c index 2e1fcf4c7d..24a2d1d029 100644 --- a/modules/afsocket/afsocket-dest.c +++ b/modules/afsocket/afsocket-dest.c @@ -251,17 +251,10 @@ _update_legacy_connection_persist_name(AFSocketDestDriver *self) return persist_state_move_entry(cfg->state, legacy_persist_name, current_persist_name); } -static LogTransport * -afsocket_dd_construct_transport(AFSocketDestDriver *self, gint fd) -{ - return transport_mapper_construct_log_transport(self->transport_mapper, fd); -} - static gboolean afsocket_dd_connected(AFSocketDestDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); - LogTransport *transport; LogProtoClient *proto; gchar buf1[256], buf2[256]; @@ -273,11 +266,13 @@ afsocket_dd_connected(AFSocketDestDriver *self) evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf1, sizeof(buf1), GSA_FULL))); - transport = afsocket_dd_construct_transport(self, self->fd); - if (!transport) - return FALSE; + proto = log_proto_client_factory_construct(self->proto_factory, NULL, &self->writer_options.proto_options.super); - proto = log_proto_client_factory_construct(self->proto_factory, transport, &self->writer_options.proto_options.super); + if (!transport_mapper_setup_stack(self->transport_mapper, &proto->transport_stack, self->fd)) + { + log_proto_client_free(proto); + return FALSE; + } log_proto_client_restart_with_state(proto, cfg->state, afsocket_dd_format_connections_name(self)); log_writer_reopen(self->writer, proto); diff --git a/modules/afsocket/afsocket-source.c b/modules/afsocket/afsocket-source.c index 104829800c..456b25060a 100644 --- a/modules/afsocket/afsocket-source.c +++ b/modules/afsocket/afsocket-source.c @@ -145,32 +145,25 @@ afsocket_sc_format_name(AFSocketSourceConnection *self) return _format_sc_name(self, GSA_FULL); } -static LogTransport * -afsocket_sc_construct_transport(AFSocketSourceConnection *self, gint fd) -{ - return transport_mapper_construct_log_transport(self->owner->transport_mapper, fd); -} - static gboolean afsocket_sc_init(LogPipe *s) { AFSocketSourceConnection *self = (AFSocketSourceConnection *) s; - LogTransport *transport; LogProtoServer *proto; gboolean restored_kept_alive_source = !!self->reader; if (!restored_kept_alive_source) { - transport = afsocket_sc_construct_transport(self, self->sock); - /* transport_mapper_inet_construct_log_transport() can return NULL on TLS errors */ - if (!transport) - return FALSE; - - proto = log_proto_server_factory_construct(self->owner->proto_factory, transport, + proto = log_proto_server_factory_construct(self->owner->proto_factory, NULL, &self->owner->reader_options.proto_options.super); if (!proto) { - log_transport_free(transport); + return FALSE; + } + + if (!transport_mapper_setup_stack(self->owner->transport_mapper, &proto->transport_stack, self->sock)) + { + log_proto_server_free(proto); return FALSE; } diff --git a/modules/afsocket/transport-mapper-inet.c b/modules/afsocket/transport-mapper-inet.c index ad8ee76296..336d0a85c8 100644 --- a/modules/afsocket/transport-mapper-inet.c +++ b/modules/afsocket/transport-mapper-inet.c @@ -85,76 +85,40 @@ transport_mapper_inet_apply_transport_method(TransportMapper *s, GlobalConfig *c return transport_mapper_inet_validate_tls_options(self); } -static LogTransport * -_construct_multitransport_with_tls_factory(TransportMapperInet *self, gint fd) -{ - LogTransportFactory *default_factory = log_transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); - return log_transport_stack_new(default_factory, fd); -} - -static LogTransport * -_construct_tls_transport(TransportMapperInet *self, gint fd) -{ - if (self->super.create_multitransport) - return _construct_multitransport_with_tls_factory(self, fd); - - TLSSession *tls_session = tls_context_setup_session(self->tls_context); - if (!tls_session) - return NULL; - - tls_session_configure_allow_compress(tls_session, self->flags & TMI_ALLOW_COMPRESS); - tls_session_set_verifier(tls_session, self->tls_verifier); - - return log_transport_tls_new(tls_session, fd); -} - -static LogTransport * -_construct_multitransport_with_plain_tcp_factory(TransportMapperInet *self, gint fd) -{ - LogTransportFactory *default_factory = log_transport_factory_socket_new(self->super.sock_type); - - return log_transport_stack_new(default_factory, fd); -} - -static LogTransport * -_construct_multitransport_with_plain_and_tls_factories(TransportMapperInet *self, gint fd) +static gboolean +_setup_socket_transport(TransportMapperInet *self, LogTransportStack *stack) { - LogTransport *transport = _construct_multitransport_with_plain_tcp_factory(self, fd); - - LogTransportFactory *tls_factory = log_transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags); - log_transport_stack_add_factory((LogTransportStack *)transport, tls_factory); - - return transport; + log_transport_stack_add_factory(stack, transport_factory_socket_new(self->super.sock_type)); + return TRUE; } -static LogTransport * -_construct_plain_tcp_transport(TransportMapperInet *self, gint fd) +static gboolean +_setup_tls_transport(TransportMapperInet *self, LogTransportStack *stack) { - if (self->super.create_multitransport) - return _construct_multitransport_with_plain_tcp_factory(self, fd); - - if (self->super.sock_type == SOCK_DGRAM) - return log_transport_udp_socket_new(fd); - else - return log_transport_stream_socket_new(fd); + log_transport_stack_add_factory(stack, transport_factory_tls_new(self->tls_context, self->tls_verifier, self->flags)); + return TRUE; } -static LogTransport * -transport_mapper_inet_construct_log_transport(TransportMapper *s, gint fd) +static gboolean +transport_mapper_inet_setup_stack(TransportMapper *s, LogTransportStack *stack) { TransportMapperInet *self = (TransportMapperInet *) s; + LogTransportIndex initial_transport_index = LOG_TRANSPORT_SOCKET; - if (self->tls_context && _is_tls_required(self)) - { - return _construct_tls_transport(self, fd); - } + if (!_setup_socket_transport(self, stack)) + return FALSE; if (self->tls_context) { - return _construct_multitransport_with_plain_and_tls_factories(self, fd); + /* if TLS context is set up (either required or optional), add a TLS transport */ + if (!_setup_tls_transport(self, stack)) + return FALSE; + if (_is_tls_required(self)) + initial_transport_index = LOG_TRANSPORT_TLS; } - return _construct_plain_tcp_transport(self, fd); + log_transport_stack_switch(stack, initial_transport_index); + return TRUE; } static gboolean @@ -288,14 +252,13 @@ transport_mapper_inet_init_instance(TransportMapperInet *self, const gchar *tran { transport_mapper_init_instance(&self->super, transport); self->super.apply_transport = transport_mapper_inet_apply_transport_method; - self->super.construct_log_transport = transport_mapper_inet_construct_log_transport; + self->super.setup_stack = transport_mapper_inet_setup_stack; self->super.init = transport_mapper_inet_init; self->super.async_init = transport_mapper_inet_async_init; self->super.free_fn = transport_mapper_inet_free_method; self->super.address_family = AF_INET; } - TransportMapperInet * transport_mapper_inet_new_instance(const gchar *transport) { diff --git a/modules/afsocket/transport-mapper-unix.c b/modules/afsocket/transport-mapper-unix.c index ca14f4d713..13c1ee86a9 100644 --- a/modules/afsocket/transport-mapper-unix.c +++ b/modules/afsocket/transport-mapper-unix.c @@ -34,13 +34,17 @@ struct _TransportMapperUnix TransportMapper super; }; -static LogTransport * -_construct_log_transport(TransportMapper *s, gint fd) +static gboolean +_setup_stack(TransportMapper *s, LogTransportStack *stack) { + LogTransport *transport; if (s->sock_type == SOCK_DGRAM) - return log_transport_unix_dgram_socket_new(fd); + transport = log_transport_unix_dgram_socket_new(stack->fd); else - return log_transport_unix_stream_socket_new(fd); + transport = log_transport_unix_stream_socket_new(stack->fd); + log_transport_stack_add_transport(stack, LOG_TRANSPORT_SOCKET, transport); + log_transport_stack_switch(stack, LOG_TRANSPORT_SOCKET); + return TRUE; } static TransportMapperUnix * @@ -49,7 +53,7 @@ transport_mapper_unix_new_instance(const gchar *transport, gint sock_type) TransportMapperUnix *self = g_new0(TransportMapperUnix, 1); transport_mapper_init_instance(&self->super, transport); - self->super.construct_log_transport = _construct_log_transport; + self->super.setup_stack = _setup_stack; self->super.address_family = AF_UNIX; self->super.sock_type = sock_type; return self; diff --git a/modules/afsocket/transport-mapper.h b/modules/afsocket/transport-mapper.h index 057f321e9c..0f998fa141 100644 --- a/modules/afsocket/transport-mapper.h +++ b/modules/afsocket/transport-mapper.h @@ -25,7 +25,7 @@ #define TRANSPORT_MAPPER_H_INCLUDED #include "socket-options.h" -#include "transport/logtransport.h" +#include "transport/transport-stack.h" #include "gsockaddr.h" typedef struct _TransportMapper TransportMapper; @@ -52,7 +52,7 @@ struct _TransportMapper gint stats_source; gboolean (*apply_transport)(TransportMapper *self, GlobalConfig *cfg); - LogTransport *(*construct_log_transport)(TransportMapper *self, gint fd); + gboolean (*setup_stack)(TransportMapper *self, LogTransportStack *stack); gboolean (*init)(TransportMapper *self); gboolean (*async_init)(TransportMapper *self, TransportMapperAsyncInitCB func, gpointer arg); void (*free_fn)(TransportMapper *self); @@ -96,10 +96,11 @@ transport_mapper_apply_transport(TransportMapper *self, GlobalConfig *cfg) return result; } -static inline LogTransport * -transport_mapper_construct_log_transport(TransportMapper *self, gint fd) +static inline gboolean +transport_mapper_setup_stack(TransportMapper *self, LogTransportStack *stack, gint fd) { - return self->construct_log_transport(self, fd); + stack->fd = fd; + return self->setup_stack(self, stack); } static inline gboolean From 12db622acbc9214b02ed038339fd4ad2748f6516 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 7 Sep 2024 19:53:51 +0200 Subject: [PATCH 09/15] transport: add LogTransportAdapter Signed-off-by: Balazs Scheidler --- lib/transport/CMakeLists.txt | 2 + lib/transport/Makefile.am | 2 + lib/transport/transport-adapter.c | 64 +++++++++++++++++++++++++++++++ lib/transport/transport-adapter.h | 44 +++++++++++++++++++++ tests/copyright/policy | 1 + 5 files changed, 113 insertions(+) create mode 100644 lib/transport/transport-adapter.c create mode 100644 lib/transport/transport-adapter.h diff --git a/lib/transport/CMakeLists.txt b/lib/transport/CMakeLists.txt index e8f27a977f..a99427d7c7 100644 --- a/lib/transport/CMakeLists.txt +++ b/lib/transport/CMakeLists.txt @@ -1,6 +1,7 @@ set(TRANSPORT_HEADERS transport/logtransport.h transport/transport-aux-data.h + transport/transport-adapter.h transport/transport-tls.h transport/transport-file.h transport/transport-pipe.h @@ -17,6 +18,7 @@ set(TRANSPORT_HEADERS set(TRANSPORT_SOURCES transport/logtransport.c transport/transport-aux-data.c + transport/transport-adapter.c transport/transport-file.c transport/transport-pipe.c transport/transport-socket.c diff --git a/lib/transport/Makefile.am b/lib/transport/Makefile.am index a8c3b71cc9..71828872d1 100644 --- a/lib/transport/Makefile.am +++ b/lib/transport/Makefile.am @@ -5,6 +5,7 @@ EXTRA_DIST += lib/transport/CMakeLists.txt transportinclude_HEADERS = \ lib/transport/logtransport.h \ lib/transport/transport-aux-data.h \ + lib/transport/transport-adapter.h \ lib/transport/transport-tls.h \ lib/transport/transport-file.h \ lib/transport/transport-pipe.h \ @@ -20,6 +21,7 @@ transportinclude_HEADERS = \ transport_sources = \ lib/transport/logtransport.c \ lib/transport/transport-aux-data.c \ + lib/transport/transport-adapter.c \ lib/transport/transport-file.c \ lib/transport/transport-pipe.c \ lib/transport/transport-socket.c \ diff --git a/lib/transport/transport-adapter.c b/lib/transport/transport-adapter.c new file mode 100644 index 0000000000..74f3039ac1 --- /dev/null +++ b/lib/transport/transport-adapter.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Balazs Scheidler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#include "transport-adapter.h" + +gssize +log_transport_adapter_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) +{ + LogTransportAdapter *self = (LogTransportAdapter *) s; + LogTransport *transport = log_transport_stack_get_transport(self->stack, self->base_index); + + return log_transport_read(transport, buf, buflen, aux); +} + +gssize +log_transport_adapter_write_method(LogTransport *s, const gpointer buf, gsize count) +{ + LogTransportAdapter *self = (LogTransportAdapter *) s; + LogTransport *transport = log_transport_stack_get_transport(self->stack, self->base_index); + + return log_transport_write(transport, buf, count); +} + +gssize +log_transport_adapter_writev_method(LogTransport *s, struct iovec *iov, gint iov_count) +{ + LogTransportAdapter *self = (LogTransportAdapter *) s; + LogTransport *transport = log_transport_stack_get_transport(self->stack, self->base_index); + + return log_transport_writev(transport, iov, iov_count); +} + +void +log_transport_adapter_init_instance(LogTransportAdapter *self, const gchar *name, + LogTransportStack *stack, LogTransportIndex base_index) +{ + log_transport_init_instance(&self->super, name, stack->fd); + self->super.read = log_transport_adapter_read_method; + self->super.write = log_transport_adapter_write_method; + self->super.writev = log_transport_adapter_writev_method; + + self->stack = stack; + self->base_index = base_index; +} diff --git a/lib/transport/transport-adapter.h b/lib/transport/transport-adapter.h new file mode 100644 index 0000000000..fbc3122100 --- /dev/null +++ b/lib/transport/transport-adapter.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Balazs Scheidler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#ifndef TRANSPORT_ADAPTER_H_INCLUDED +#define TRANSPORT_ADAPTER_H_INCLUDED + +#include "transport-stack.h" + +typedef struct _LogTransportAdapter LogTransportAdapter; +struct _LogTransportAdapter +{ + LogTransport super; + LogTransportStack *stack; + LogTransportIndex base_index; +}; + +gssize log_transport_adapter_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux); +gssize log_transport_adapter_write_method(LogTransport *s, const gpointer buf, gsize count); +gssize log_transport_adapter_writev_method(LogTransport *s, struct iovec *iov, gint iov_count); + +void log_transport_adapter_init_instance(LogTransportAdapter *self, const gchar *name, + LogTransportStack *stack, LogTransportIndex base); + +#endif diff --git a/tests/copyright/policy b/tests/copyright/policy index 0b3a44acd5..a35599de30 100644 --- a/tests/copyright/policy +++ b/tests/copyright/policy @@ -119,6 +119,7 @@ libtest/filterx-lib\.[ch] lib/generic-number\.[ch] lib/tests/test_generic_number\.c lib/severity-aliases\.table +lib/transport/transport-adapter\.[ch] syslog-ng-ctl/commands/log-level.[ch] modules/afsocket/afsocket-signals.h syslog-ng-ctl/commands/healthcheck.[ch] From 79862a6ecc7f6c9486e8118c96db7d62f806d678 Mon Sep 17 00:00:00 2001 From: Alex Becker Date: Wed, 5 Jul 2023 16:56:24 +0200 Subject: [PATCH 10/15] transport: add transport-haproxy implementation This patch is based on the LogTransport implementation in github.com/syslog-ng/syslog-ng, which in turn is based on my original implementation of proxy support as a LogProto class. Signed-off-by: Alex Becker Signed-off-by: Hofi Signed-off-by: Balazs Scheidler --- lib/transport/CMakeLists.txt | 3 + lib/transport/Makefile.am | 2 + lib/transport/tests/CMakeLists.txt | 1 + lib/transport/tests/Makefile.am | 9 +- lib/transport/tests/test_transport_haproxy.c | 173 ++++++ lib/transport/transport-haproxy.c | 597 +++++++++++++++++++ lib/transport/transport-haproxy.h | 31 + 7 files changed, 815 insertions(+), 1 deletion(-) create mode 100644 lib/transport/tests/test_transport_haproxy.c create mode 100644 lib/transport/transport-haproxy.c create mode 100644 lib/transport/transport-haproxy.h diff --git a/lib/transport/CMakeLists.txt b/lib/transport/CMakeLists.txt index a99427d7c7..3440688717 100644 --- a/lib/transport/CMakeLists.txt +++ b/lib/transport/CMakeLists.txt @@ -6,6 +6,8 @@ set(TRANSPORT_HEADERS transport/transport-file.h transport/transport-pipe.h transport/transport-socket.h + transport/transport-socket-proxy.h + transport/transport-socket-proxy-private.h transport/transport-udp-socket.h transport/transport-stack.h transport/transport-factory-tls.h @@ -22,6 +24,7 @@ set(TRANSPORT_SOURCES transport/transport-file.c transport/transport-pipe.c transport/transport-socket.c + transport/transport-socket-proxy.c transport/transport-udp-socket.c transport/transport-tls.c transport/transport-stack.c diff --git a/lib/transport/Makefile.am b/lib/transport/Makefile.am index 71828872d1..fd2d56eda6 100644 --- a/lib/transport/Makefile.am +++ b/lib/transport/Makefile.am @@ -10,6 +10,7 @@ transportinclude_HEADERS = \ lib/transport/transport-file.h \ lib/transport/transport-pipe.h \ lib/transport/transport-socket.h \ + lib/transport/transport-haproxy.h \ lib/transport/transport-udp-socket.h \ lib/transport/transport-stack.h \ lib/transport/transport-factory-tls.h \ @@ -25,6 +26,7 @@ transport_sources = \ lib/transport/transport-file.c \ lib/transport/transport-pipe.c \ lib/transport/transport-socket.c \ + lib/transport/transport-haproxy.c \ lib/transport/transport-udp-socket.c \ lib/transport/transport-stack.c \ lib/transport/transport-factory-tls.c \ diff --git a/lib/transport/tests/CMakeLists.txt b/lib/transport/tests/CMakeLists.txt index 34120c56d1..246b953bfa 100644 --- a/lib/transport/tests/CMakeLists.txt +++ b/lib/transport/tests/CMakeLists.txt @@ -1,2 +1,3 @@ add_unit_test(CRITERION TARGET test_aux_data) add_unit_test(CRITERION TARGET test_transport_stack) +add_unit_test(LIBTEST CRITERION TARGET test_transport_haproxy) diff --git a/lib/transport/tests/Makefile.am b/lib/transport/tests/Makefile.am index 3c97dc38ba..09d88a914d 100644 --- a/lib/transport/tests/Makefile.am +++ b/lib/transport/tests/Makefile.am @@ -1,6 +1,7 @@ lib_transport_tests_TESTS = \ lib/transport/tests/test_aux_data \ - lib/transport/tests/test_transport_stack + lib/transport/tests/test_transport_stack \ + lib/transport/tests/test_transport_haproxy EXTRA_DIST += lib/transport/tests/CMakeLists.txt @@ -17,3 +18,9 @@ lib_transport_tests_test_transport_stack_CFLAGS = $(TEST_CFLAGS) \ lib_transport_tests_test_transport_stack_LDADD = $(TEST_LDADD) lib_transport_tests_test_transport_stack_SOURCES = \ lib/transport/tests/test_transport_stack.c + +lib_transport_tests_test_transport_haproxy_CFLAGS = $(TEST_CFLAGS) \ + -I${top_srcdir}/lib/transport/tests +lib_transport_tests_test_transport_haproxy_LDADD = $(TEST_LDADD) +lib_transport_tests_test_transport_haproxy_SOURCES = \ + lib/transport/tests/test_transport_haproxy.c diff --git a/lib/transport/tests/test_transport_haproxy.c b/lib/transport/tests/test_transport_haproxy.c new file mode 100644 index 0000000000..7ec90e3fa2 --- /dev/null +++ b/lib/transport/tests/test_transport_haproxy.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2020-2023 One Identity + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#include +#include +#include "libtest/mock-transport.h" + +#include "transport/transport-haproxy.h" + +#include "apphook.h" +#include "cfg.h" + +static void +setup(void) +{ + app_startup(); + configuration = cfg_new_snippet(); +} + +static void +teardown(void) +{ + if (configuration) + cfg_free(configuration); + app_shutdown(); +} + +static void +concat_nv(const gchar *name, const gchar *value, gsize value_len, gpointer user_data) +{ + GString *aux_nv_concated = user_data; + g_string_append_printf(aux_nv_concated, "%s=%s ", name, value); +} + +TestSuite(log_transport_proxy, .init = setup, .fini = teardown); + +typedef struct +{ + const gchar *proxy_header; + gboolean valid; + const gchar *aux_values; + gint proxy_header_len; +} ProtocolHeaderTestParams; + +ParameterizedTestParameters(log_transport_proxy, test_proxy_protocol_parse_header) +{ + static ProtocolHeaderTestParams test_params[] = + { + /* SUCCESS */ + { "PROXY UNKNOWN\r\n", TRUE, "" }, + { "PROXY UNKNOWN extra ignored parameters\r\n", TRUE, "" }, + { + "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE, + .aux_values = "PROXIED_SRCIP=1.1.1.1 PROXIED_DSTIP=2.2.2.2 " + "PROXIED_SRCPORT=3333 PROXIED_DSTPORT=4444 " + "PROXIED_IP_VERSION=4 " + }, + { + "PROXY TCP6 ::1 ::2 3333 4444\r\n", TRUE, + .aux_values = "PROXIED_SRCIP=::1 PROXIED_DSTIP=::2 " + "PROXIED_SRCPORT=3333 PROXIED_DSTPORT=4444 " + "PROXIED_IP_VERSION=6 " + }, + + /* INVALID PROTO */ + { "PROXY UNKNOWN\n", TRUE }, // WRONG TERMINATION BUT PERMISSIVE IMPLEMENTATION + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\n", TRUE }, // WRONG TERMINATION BUT PERMISSIVE IMPLEMENTATION + { "PROXY UNKNOWN\r", FALSE }, // WRONG TERMINATION + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r", FALSE }, // WRONG TERMINATION + { "PROXY\r\n", FALSE }, + { "PROXY TCP4\r\n", FALSE }, + { "PROXY TCP4 1.1.1.1\r\n", FALSE }, + { "PROXY TCP4 1.1.1.1 2.2.2.2\r\n", FALSE }, + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333\r\n", FALSE }, + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444 extra param\r\n", TRUE }, + + /* EXTRA WHITESPACE - PERMISSIVE */ + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444 \r\n", TRUE }, + + /* EXTRA WHITESPACE BEFORE PARAMETERS */ + { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", FALSE }, + + /* INVALID ARGUMENTS - PERMISSIVE */ + { "PROXY TCP6 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, // WRONG IP PROTO + { "PROXY TCP4 ::1 ::2 3333 4444\r\n", TRUE }, // WRONG IP PROTO + { "PROXY TCP4 1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, // WRONG IP + { "PROXY TCP4 1.1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, // WRONG IP + { "PROXY TCP6 ::1::0 ::1 3333 4444\r\n", TRUE }, // WRONG IP + { "PROXY TCP4 1.1.1.1 2.2.2.2 33333 0\r\n", TRUE }, // WRONG PORT + { "PROXY TCP4 1.1.1.1 2.2.2.2 33333 -1\r\n", TRUE }, // WRONG PORT + { "PROXY TCP4 1.1.1.1 2.2.2.2 33333 65536\r\n", TRUE }, // WRONG PORT + + /* INVALID ARGUMENT(S)*/ + { "PROXY TCP3 1.1.1.1 2.2.2.2 3333 4444\r\n", FALSE}, // WRONG IP PROTO + + { "invalid header\r\n", FALSE}, // WRONG header + + /* TOO LONG */ + { + "PROXY TCP4 padpadpadpadpadpadpadpadpadpadpadpadpad" + "padpadpadpadpadpadpadpadpadpadpadpadpadpadpadpadpad" + "padpadpadpadpadpadpadpadpadpadpadpadpadpadpadpadpad", FALSE + }, + /* proxy v2 */ + { + "\r\n\r\n\0\r\nQUIT\n!\21\0\f\1\1\1\1\2\2\2\2\2025\255\234", TRUE, + .aux_values = "PROXIED_SRCIP=1.1.1.1 PROXIED_DSTIP=2.2.2.2 PROXIED_SRCPORT=33333 PROXIED_DSTPORT=44444 PROXIED_IP_VERSION=4 ", + .proxy_header_len = 28 + }, + }; + + return cr_make_param_array(ProtocolHeaderTestParams, test_params, G_N_ELEMENTS(test_params)); +} + +ParameterizedTest(ProtocolHeaderTestParams *params, log_transport_proxy, test_proxy_protocol_parse_header) +{ + gint proxy_header_len = params->proxy_header_len ? : strlen(params->proxy_header); + LogTransportStack stack; + LogTransport *mock = log_transport_mock_stream_new(params->proxy_header, proxy_header_len, NULL); + LogTransportAuxData aux; + gchar buf[1024]; + gssize rc; + + log_transport_stack_init(&stack, mock); + LogTransport *transport = log_transport_haproxy_new(&stack, LOG_TRANSPORT_INITIAL, LOG_TRANSPORT_NONE); + + do + { + log_transport_aux_data_init(&aux); + rc = log_transport_read(transport, buf, sizeof(buf), &aux); + } + while (rc == -1 && errno == EAGAIN); + + cr_assert_eq(rc == 0, params->valid, + "This should be %s: \n>>%.*s<<\n (rc=%d, errno=%d)", params->valid ? "valid" : "invalid", proxy_header_len, + params->proxy_header, (gint) rc, errno); + + if (rc == 0 && params->aux_values) + { + GString *aux_nv_concated = g_string_new(NULL); + log_transport_aux_data_foreach(&aux, concat_nv, aux_nv_concated); + cr_assert_str_eq(aux_nv_concated->str, params->aux_values); + g_string_free(aux_nv_concated, TRUE); + } + + + log_transport_free(transport); + log_transport_stack_deinit(&stack); +} diff --git a/lib/transport/transport-haproxy.c b/lib/transport/transport-haproxy.c new file mode 100644 index 0000000000..95421c9855 --- /dev/null +++ b/lib/transport/transport-haproxy.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2020-2023 One Identity LLC. + * Copyright (c) 2022 Balazs Scheidler + * Copyright (c) 2024 Balazs Scheidler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#include "transport/transport-haproxy.h" + +#include +#include +#include +#include +#include + +#include "messages.h" +#include "str-utils.h" + +#define IP_BUF_SIZE 64 + +/* This class implements: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt */ + +/* the size of the buffer we use to fetch the PROXY header into */ +#define PROXY_PROTO_HDR_BUFFER_SIZE 1500 + +typedef struct _LogTransportHAProxy LogTransportHAProxy; +struct _LogTransportHAProxy +{ + LogTransportAdapter super; + LogTransportIndex switch_to; + + /* Info received from the proxy that should be added as LogTransportAuxData to + * any message received through this server instance. */ + struct + { + gboolean unknown; + + gchar src_ip[IP_BUF_SIZE]; + gchar dst_ip[IP_BUF_SIZE]; + + int ip_version; + int src_port; + int dst_port; + } info; + + /* Flag to only process proxy header once */ + gboolean proxy_header_processed; + + enum + { + LPPTS_INITIAL, + LPPTS_DETERMINE_VERSION, + LPPTS_PROXY_V1_READ_LINE, + LPPTS_PROXY_V2_READ_HEADER, + LPPTS_PROXY_V2_READ_PAYLOAD, + } header_fetch_state; + + /* 0 unknown, 1 or 2 indicate proxy header version */ + gint proxy_header_version; + guchar proxy_header_buff[PROXY_PROTO_HDR_BUFFER_SIZE]; + gsize proxy_header_buff_len; +}; + + + +/* This class implements: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt */ + +/* PROXYv1 line without newlines or terminating zero character. The + * protocol specification contains the number 108 that includes both the + * CRLF sequence and the NUL */ +#define PROXY_PROTO_HDR_MAX_LEN_RFC 105 + +/* the amount of bytes we need from the client to detect protocol version */ +#define PROXY_PROTO_HDR_MAGIC_LEN 5 + +typedef enum +{ + STATUS_SUCCESS, + STATUS_ERROR, + STATUS_EOF, + STATUS_AGAIN, +} Status; + +struct proxy_hdr_v2 +{ + uint8_t sig[12]; /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */ + uint8_t ver_cmd; /* protocol version and command */ + uint8_t fam; /* protocol family and address */ + uint16_t len; /* number of following bytes part of the header */ +}; + +union proxy_addr +{ + struct + { + /* for TCP/UDP over IPv4, len = 12 */ + uint32_t src_addr; + uint32_t dst_addr; + uint16_t src_port; + uint16_t dst_port; + } ipv4_addr; + struct + { + /* for TCP/UDP over IPv6, len = 36 */ + uint8_t src_addr[16]; + uint8_t dst_addr[16]; + uint16_t src_port; + uint16_t dst_port; + } ipv6_addr; + struct + { + /* for AF_UNIX sockets, len = 216 */ + uint8_t src_addr[108]; + uint8_t dst_addr[108]; + } unix_addr; +}; + +#define PROXY_HDR_TCP4 "PROXY TCP4 " +#define PROXY_HDR_TCP6 "PROXY TCP6 " +#define PROXY_HDR_UNKNOWN "PROXY UNKNOWN" + +static gboolean +_check_proxy_v1_header_length(const guchar *msg, gsize msg_len) +{ + if (msg_len > PROXY_PROTO_HDR_MAX_LEN_RFC) + { + msg_error("PROXY proto header length exceeds max length defined by the specification", + evt_tag_long("length", msg_len), + evt_tag_str("header", (const gchar *)msg)); + return FALSE; + } + + return TRUE; +} + +static gboolean +_check_proxy_v1_header(const guchar *msg, gsize msg_len, const gchar *expected_header, gsize *header_len) +{ + gsize expected_header_length = strlen(expected_header); + + if (msg_len < expected_header_length) + return FALSE; + + *header_len = expected_header_length; + return strncmp((const gchar *)msg, expected_header, expected_header_length) == 0; +} + +static gboolean +_is_proxy_v1_proto_tcp4(const guchar *msg, gsize msg_len, gsize *header_len) +{ + return _check_proxy_v1_header(msg, msg_len, PROXY_HDR_TCP4, header_len); +} + +static gboolean +_is_proxy_v1_proto_tcp6(const guchar *msg, gsize msg_len, gsize *header_len) +{ + return _check_proxy_v1_header(msg, msg_len, PROXY_HDR_TCP6, header_len); +} + +static gboolean +_is_proxy_v1_unknown(const guchar *msg, gsize msg_len, gsize *header_len) +{ + return _check_proxy_v1_header(msg, msg_len, PROXY_HDR_UNKNOWN, header_len); +} + +static gboolean +_parse_proxy_v1_unknown_header(LogTransportHAProxy *self, const guchar *msg, gsize msg_len) +{ + if (msg_len == 0) + return TRUE; + + msg_warning("PROXY UNKNOWN header contains unexpected parameters", + evt_tag_mem("parameters", msg, msg_len)); + + return TRUE; +} + +static gboolean +_parse_proxy_v1_tcp_header(LogTransportHAProxy *self, const guchar *msg, gsize msg_len) +{ + if (msg_len == 0) + return FALSE; + + GString *params_str = g_string_new_len((const gchar *)msg, msg_len); + gboolean result = FALSE; + msg_debug("PROXY header params", evt_tag_str("params", (const gchar *)msg)); + + gchar **params = strsplit(params_str->str, ' ', 5); + gint params_n = g_strv_length(params); + if (params_n < 4) + goto ret; + + g_strlcpy(self->info.src_ip, params[0], IP_BUF_SIZE); + g_strlcpy(self->info.dst_ip, params[1], IP_BUF_SIZE); + + self->info.src_port = atoi(params[2]); + if (self->info.src_port > 65535 || self->info.src_port < 0) + msg_warning("PROXT TCP header contains invalid src port", evt_tag_str("src port", params[2])); + + self->info.dst_port = atoi(params[3]); + if (self->info.dst_port > 65535 || self->info.dst_port < 0) + msg_warning("PROXT TCP header contains invalid dst port", evt_tag_str("dst port", params[2])); + + if (params_n > 4) + msg_warning("PROXY TCP header contains unexpected paramaters", evt_tag_str("parameters", params[4])); + + result = TRUE; +ret: + if (params) + g_strfreev(params); + g_string_free(params_str, TRUE); + + return result; +} + +static gboolean +_extract_proxy_v1_header(LogTransportHAProxy *self, guchar **msg, gsize *msg_len) +{ + if (self->proxy_header_buff[self->proxy_header_buff_len - 1] == '\n') + self->proxy_header_buff_len--; + + if (self->proxy_header_buff[self->proxy_header_buff_len - 1] == '\r') + self->proxy_header_buff_len--; + + self->proxy_header_buff[self->proxy_header_buff_len] = 0; + *msg = self->proxy_header_buff; + *msg_len = self->proxy_header_buff_len; + return TRUE; +} + +static gboolean +_parse_proxy_v1_header(LogTransportHAProxy *self) +{ + guchar *proxy_line; + gsize proxy_line_len; + + if (!_extract_proxy_v1_header(self, &proxy_line, &proxy_line_len)) + return FALSE; + + + gsize header_len = 0; + + if (!_check_proxy_v1_header_length(proxy_line, proxy_line_len)) + return FALSE; + + if (_is_proxy_v1_unknown(proxy_line, proxy_line_len, &header_len)) + { + self->info.unknown = TRUE; + return _parse_proxy_v1_unknown_header(self, proxy_line + header_len, proxy_line_len - header_len); + } + + if (_is_proxy_v1_proto_tcp4(proxy_line, proxy_line_len, &header_len)) + { + self->info.ip_version = 4; + return _parse_proxy_v1_tcp_header(self, proxy_line + header_len, proxy_line_len - header_len); + } + + if (_is_proxy_v1_proto_tcp6(proxy_line, proxy_line_len, &header_len)) + { + self->info.ip_version = 6; + return _parse_proxy_v1_tcp_header(self, proxy_line + header_len, proxy_line_len - header_len); + } + + return FALSE; +} + +static gboolean +_parse_proxy_v2_proxy_address(LogTransportHAProxy *self, struct proxy_hdr_v2 *proxy_hdr, + union proxy_addr *proxy_addr) +{ + gint address_family = (proxy_hdr->fam & 0xF0) >> 4; + gint proxy_header_len = ntohs(proxy_hdr->len); + + if (address_family == 1 && proxy_header_len >= sizeof(proxy_addr->ipv4_addr)) + { + /* AF_INET */ + inet_ntop(AF_INET, (gchar *) &proxy_addr->ipv4_addr.src_addr, self->info.src_ip, sizeof(self->info.src_ip)); + inet_ntop(AF_INET, (gchar *) &proxy_addr->ipv4_addr.dst_addr, self->info.dst_ip, sizeof(self->info.dst_ip)); + self->info.src_port = ntohs(proxy_addr->ipv4_addr.src_port); + self->info.dst_port = ntohs(proxy_addr->ipv4_addr.dst_port); + self->info.ip_version = 4; + return TRUE; + } + else if (address_family == 2 && proxy_header_len >= sizeof(proxy_addr->ipv6_addr)) + { + /* AF_INET6 */ + inet_ntop(AF_INET6, (gchar *) &proxy_addr->ipv6_addr.src_addr, self->info.src_ip, sizeof(self->info.src_ip)); + inet_ntop(AF_INET6, (gchar *) &proxy_addr->ipv6_addr.dst_addr, self->info.dst_ip, sizeof(self->info.dst_ip)); + self->info.src_port = ntohs(proxy_addr->ipv6_addr.src_port); + self->info.dst_port = ntohs(proxy_addr->ipv6_addr.dst_port); + self->info.ip_version = 6; + return TRUE; + } + else if (address_family == 0) + { + /* AF_UNSPEC */ + self->info.unknown = TRUE; + return TRUE; + } + + msg_error("PROXYv2 header does not have enough bytes to represent endpoint addresses or unknown address_family", + evt_tag_int("proxy_header_len", proxy_header_len), + evt_tag_int("address_family", address_family)); + return FALSE; +} + +static gboolean +_parse_proxy_v2_header(LogTransportHAProxy *self) +{ + struct proxy_hdr_v2 *proxy_hdr = (struct proxy_hdr_v2 *) self->proxy_header_buff; + union proxy_addr *proxy_addr = (union proxy_addr *)(proxy_hdr + 1); + + /* is this proxy v2 */ + if ((proxy_hdr->ver_cmd & 0xF0) != 0x20) + return FALSE; + + if ((proxy_hdr->ver_cmd & 0xF) == 0) + { + /* LOCAL connection */ + return TRUE; + } + else if ((proxy_hdr->ver_cmd & 0xF) == 1) + { + /* PROXY connection */ + return _parse_proxy_v2_proxy_address(self, proxy_hdr, proxy_addr); + } + + return FALSE; +} + +gboolean +_parse_proxy_header(LogTransportHAProxy *self) +{ + if (self->proxy_header_version == 1) + return _parse_proxy_v1_header(self); + else if (self->proxy_header_version == 2) + return _parse_proxy_v2_header(self); + else + g_assert_not_reached(); +} + +static Status +_fetch_chunk(LogTransportHAProxy *self, gsize upto_bytes) +{ + g_assert(upto_bytes < sizeof(self->proxy_header_buff)); + if (self->proxy_header_buff_len < upto_bytes) + { + gssize rc = log_transport_adapter_read_method(&self->super.super, + &(self->proxy_header_buff[self->proxy_header_buff_len]), + upto_bytes - self->proxy_header_buff_len, NULL); + if (rc < 0) + { + if (errno == EAGAIN) + return STATUS_AGAIN; + else + { + msg_error("I/O error occurred while reading proxy header", + evt_tag_error(EVT_TAG_OSERROR)); + return STATUS_ERROR; + } + } + /* EOF without data */ + if (rc == 0) + { + return STATUS_EOF; + } + + self->proxy_header_buff_len += rc; + } + if (self->proxy_header_buff_len == upto_bytes) + return STATUS_SUCCESS; + return STATUS_AGAIN; +} + +static inline Status +_fetch_until_newline(LogTransportHAProxy *self) +{ + /* leave 1 character for terminating zero. We should have plenty of space + * in our buffer, as the longest line we need to fetch is 107 bytes + * including the line terminator characters. */ + + while (self->proxy_header_buff_len < sizeof(self->proxy_header_buff) - 1) + { + Status status = _fetch_chunk(self, self->proxy_header_buff_len + 1); + + if (status != STATUS_SUCCESS) + return status; + + if (self->proxy_header_buff[self->proxy_header_buff_len - 1] == '\n') + { + return STATUS_SUCCESS; + } + } + + msg_error("PROXY proto header with invalid header length", + evt_tag_int("max_parsable_length", sizeof(self->proxy_header_buff)-1), + evt_tag_int("max_length_by_spec", PROXY_PROTO_HDR_MAX_LEN_RFC), + evt_tag_long("length", self->proxy_header_buff_len), + evt_tag_str("header", (const gchar *)self->proxy_header_buff)); + return STATUS_ERROR; +} + +static Status +_fetch_proxy_v2_payload(LogTransportHAProxy *self) +{ + struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *) self->proxy_header_buff; + gsize proxy_header_len = sizeof(*hdr) + ntohs(hdr->len); + + if (proxy_header_len > sizeof(self->proxy_header_buff)) + { + msg_error("PROXYv2 proto header with invalid header length", + evt_tag_int("max_parsable_length", sizeof(self->proxy_header_buff)), + evt_tag_long("length", proxy_header_len)); + return STATUS_ERROR; + } + + return _fetch_chunk(self, proxy_header_len); +} + +static gboolean +_is_proxy_version_v1(LogTransportHAProxy *self) +{ + if (self->proxy_header_buff_len < PROXY_PROTO_HDR_MAGIC_LEN) + return FALSE; + + return memcmp(self->proxy_header_buff, "PROXY", PROXY_PROTO_HDR_MAGIC_LEN) == 0; +} + +static gboolean +_is_proxy_version_v2(LogTransportHAProxy *self) +{ + if (self->proxy_header_buff_len < PROXY_PROTO_HDR_MAGIC_LEN) + return FALSE; + + return memcmp(self->proxy_header_buff, "\x0D\x0A\x0D\x0A\x00", PROXY_PROTO_HDR_MAGIC_LEN) == 0; +} + +static inline Status +_fetch_into_proxy_buffer(LogTransportHAProxy *self) +{ + Status status; + + switch (self->header_fetch_state) + { + case LPPTS_INITIAL: + self->header_fetch_state = LPPTS_DETERMINE_VERSION; + /* fallthrough */ + case LPPTS_DETERMINE_VERSION: + status = _fetch_chunk(self, PROXY_PROTO_HDR_MAGIC_LEN); + + if (status != STATUS_SUCCESS) + return status; + + if (_is_proxy_version_v1(self)) + { + self->header_fetch_state = LPPTS_PROXY_V1_READ_LINE; + self->proxy_header_version = 1; + goto process_proxy_v1; + } + else if (_is_proxy_version_v2(self)) + { + self->header_fetch_state = LPPTS_PROXY_V2_READ_HEADER; + self->proxy_header_version = 2; + goto process_proxy_v2; + } + else + { + msg_error("Unable to determine PROXY protocol version"); + return STATUS_ERROR; + } + g_assert_not_reached(); + + case LPPTS_PROXY_V1_READ_LINE: + +process_proxy_v1: + return _fetch_until_newline(self); + case LPPTS_PROXY_V2_READ_HEADER: +process_proxy_v2: + status = _fetch_chunk(self, sizeof(struct proxy_hdr_v2)); + if (status != STATUS_SUCCESS) + return status; + + self->header_fetch_state = LPPTS_PROXY_V2_READ_PAYLOAD; + /* fallthrough */ + case LPPTS_PROXY_V2_READ_PAYLOAD: + return _fetch_proxy_v2_payload(self); + default: + g_assert_not_reached(); + } +} + +static Status +_proccess_proxy_header(LogTransportHAProxy *self) +{ + Status status = _fetch_into_proxy_buffer(self); + + self->proxy_header_processed = (status == STATUS_SUCCESS); + if (status != STATUS_SUCCESS) + return status; + + gboolean parsable = _parse_proxy_header(self); + + msg_debug("PROXY protocol header received", + evt_tag_int("version", self->proxy_header_version), + self->proxy_header_version == 1 + ? evt_tag_mem("header", self->proxy_header_buff, self->proxy_header_buff_len) + : evt_tag_str("header", "")); + + if (parsable) + { + msg_trace("PROXY protocol header parsed successfully"); + + return STATUS_SUCCESS; + } + else + { + msg_error("Error parsing PROXY protocol header"); + return STATUS_ERROR; + } +} + +static void +_augment_aux_data(LogTransportHAProxy *self, LogTransportAuxData *aux) +{ + gchar buf1[8]; + gchar buf2[8]; + gchar buf3[8]; + + if (self->info.unknown) + return; + + snprintf(buf1, 8, "%i", self->info.src_port); + snprintf(buf2, 8, "%i", self->info.dst_port); + snprintf(buf3, 8, "%i", self->info.ip_version); + + log_transport_aux_data_add_nv_pair(aux, "PROXIED_SRCIP", self->info.src_ip); + log_transport_aux_data_add_nv_pair(aux, "PROXIED_DSTIP", self->info.dst_ip); + log_transport_aux_data_add_nv_pair(aux, "PROXIED_SRCPORT", buf1); + log_transport_aux_data_add_nv_pair(aux, "PROXIED_DSTPORT", buf2); + log_transport_aux_data_add_nv_pair(aux, "PROXIED_IP_VERSION", buf3); + + return; +} + +static gssize +_haproxy_read(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) +{ + LogTransportHAProxy *self = (LogTransportHAProxy *)s; + + if (!self->proxy_header_processed) + { + Status status = _proccess_proxy_header(self); + if (status != STATUS_SUCCESS) + { + if (status == STATUS_ERROR || status == STATUS_EOF) + errno = EINVAL; + else if (status == STATUS_AGAIN) + errno = EAGAIN; + return -1; + } + if (self->switch_to != LOG_TRANSPORT_NONE) + self->super.base_index = self->switch_to; + } + + _augment_aux_data(self, aux); + return log_transport_adapter_read_method(s, buf, buflen, aux); +} + +LogTransport * +log_transport_haproxy_new(LogTransportStack *stack, LogTransportIndex base, LogTransportIndex switch_to) +{ + LogTransportHAProxy *self = g_new0(LogTransportHAProxy, 1); + + log_transport_adapter_init_instance(&self->super, "haproxy", stack, base); + self->super.super.read = _haproxy_read; + self->switch_to = switch_to; + + return &self->super.super; +} diff --git a/lib/transport/transport-haproxy.h b/lib/transport/transport-haproxy.h new file mode 100644 index 0000000000..6830df8f80 --- /dev/null +++ b/lib/transport/transport-haproxy.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2023 One Identity LLC. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#ifndef TRANSPORT_HAPROXY_H_INCLUDED +#define TRANSPORT_HAPROXY_H_INCLUDED + +#include "transport-adapter.h" + +LogTransport *log_transport_haproxy_new(LogTransportStack *stack, LogTransportIndex base, LogTransportIndex flip); + +#endif From 241638681c2441f443c844c2a49627a8c09f0a64 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 15 Sep 2024 19:24:46 +0200 Subject: [PATCH 11/15] transport: use the new LogTransport based HAProxy implementation Signed-off-by: Balazs Scheidler --- lib/logproto/logproto-builtins.c | 5 -- lib/logproto/logproto-client.h | 1 - lib/logproto/logproto-server.h | 1 - lib/transport/CMakeLists.txt | 5 +- modules/afsocket/afsocket-dest.c | 2 - modules/afsocket/afsocket-source.c | 2 - modules/afsocket/transport-mapper-inet.c | 72 +++++++++++++++++++++++- modules/afsocket/transport-mapper-inet.h | 1 + modules/afsocket/transport-mapper.h | 2 - 9 files changed, 74 insertions(+), 17 deletions(-) diff --git a/lib/logproto/logproto-builtins.c b/lib/logproto/logproto-builtins.c index 1a8229bdbd..d21eb1d1d1 100644 --- a/lib/logproto/logproto-builtins.c +++ b/lib/logproto/logproto-builtins.c @@ -24,7 +24,6 @@ #include "logproto-dgram-server.h" #include "logproto-text-client.h" #include "logproto-text-server.h" -#include "logproto-proxied-text-server.h" #include "logproto-framed-client.h" #include "logproto-framed-server.h" #include "plugin.h" @@ -38,8 +37,6 @@ DEFINE_LOG_PROTO_SERVER(log_proto_dgram); DEFINE_LOG_PROTO_CLIENT(log_proto_text); DEFINE_LOG_PROTO_SERVER(log_proto_text); DEFINE_LOG_PROTO_SERVER(log_proto_text_with_nuls); -DEFINE_LOG_PROTO_SERVER(log_proto_proxied_text); -DEFINE_LOG_PROTO_SERVER(log_proto_proxied_text_tls_passthrough, .use_multitransport = TRUE); DEFINE_LOG_PROTO_CLIENT(log_proto_framed); DEFINE_LOG_PROTO_SERVER(log_proto_framed); @@ -51,8 +48,6 @@ static Plugin framed_server_plugins[] = LOG_PROTO_CLIENT_PLUGIN(log_proto_text, "text"), LOG_PROTO_SERVER_PLUGIN(log_proto_text, "text"), LOG_PROTO_SERVER_PLUGIN(log_proto_text_with_nuls, "text-with-nuls"), - LOG_PROTO_SERVER_PLUGIN(log_proto_proxied_text, "proxied-tcp"), - LOG_PROTO_SERVER_PLUGIN(log_proto_proxied_text_tls_passthrough, "proxied-tls-passthrough"), LOG_PROTO_CLIENT_PLUGIN(log_proto_framed, "framed"), LOG_PROTO_SERVER_PLUGIN(log_proto_framed, "framed"), }; diff --git a/lib/logproto/logproto-client.h b/lib/logproto/logproto-client.h index a6246283d7..314ece0ad8 100644 --- a/lib/logproto/logproto-client.h +++ b/lib/logproto/logproto-client.h @@ -219,7 +219,6 @@ struct _LogProtoClientFactory { LogProtoClient *(*construct)(LogTransport *transport, const LogProtoClientOptions *options); gint default_inet_port; - gboolean use_multitransport; gboolean stateful; }; diff --git a/lib/logproto/logproto-server.h b/lib/logproto/logproto-server.h index db782ecf07..3a54f66972 100644 --- a/lib/logproto/logproto-server.h +++ b/lib/logproto/logproto-server.h @@ -213,7 +213,6 @@ struct _LogProtoServerFactory { LogProtoServer *(*construct)(LogTransport *transport, const LogProtoServerOptions *options); gint default_inet_port; - gboolean use_multitransport; }; static inline LogProtoServer * diff --git a/lib/transport/CMakeLists.txt b/lib/transport/CMakeLists.txt index 3440688717..3f0fdf292b 100644 --- a/lib/transport/CMakeLists.txt +++ b/lib/transport/CMakeLists.txt @@ -6,8 +6,7 @@ set(TRANSPORT_HEADERS transport/transport-file.h transport/transport-pipe.h transport/transport-socket.h - transport/transport-socket-proxy.h - transport/transport-socket-proxy-private.h + transport/transport-haproxy.h transport/transport-udp-socket.h transport/transport-stack.h transport/transport-factory-tls.h @@ -24,7 +23,7 @@ set(TRANSPORT_SOURCES transport/transport-file.c transport/transport-pipe.c transport/transport-socket.c - transport/transport-socket-proxy.c + transport/transport-haproxy.c transport/transport-udp-socket.c transport/transport-tls.c transport/transport-stack.c diff --git a/modules/afsocket/afsocket-dest.c b/modules/afsocket/afsocket-dest.c index 24a2d1d029..974179af42 100644 --- a/modules/afsocket/afsocket-dest.c +++ b/modules/afsocket/afsocket-dest.c @@ -419,8 +419,6 @@ afsocket_dd_setup_proto_factory(AFSocketDestDriver *self) return FALSE; } - self->transport_mapper->create_multitransport = self->proto_factory->use_multitransport; - return TRUE; } diff --git a/modules/afsocket/afsocket-source.c b/modules/afsocket/afsocket-source.c index 456b25060a..b6dd787890 100644 --- a/modules/afsocket/afsocket-source.c +++ b/modules/afsocket/afsocket-source.c @@ -963,8 +963,6 @@ afsocket_sd_setup_transport(AFSocketSourceDriver *self) return FALSE; } - self->transport_mapper->create_multitransport = self->proto_factory->use_multitransport; - afsocket_sd_setup_reader_options(self); return TRUE; } diff --git a/modules/afsocket/transport-mapper-inet.c b/modules/afsocket/transport-mapper-inet.c index 336d0a85c8..0a8859a9f7 100644 --- a/modules/afsocket/transport-mapper-inet.c +++ b/modules/afsocket/transport-mapper-inet.c @@ -29,6 +29,7 @@ #include "transport/transport-stack.h" #include "transport/transport-factory-tls.h" #include "transport/transport-factory-socket.h" +#include "transport/transport-haproxy.h" #include "transport/transport-udp-socket.h" #include "secret-storage/secret-storage.h" @@ -99,6 +100,15 @@ _setup_tls_transport(TransportMapperInet *self, LogTransportStack *stack) return TRUE; } +static gboolean +_setup_haproxy_transport(TransportMapperInet *self, LogTransportStack *stack, + LogTransportIndex base_index, LogTransportIndex switch_to) +{ + log_transport_stack_add_transport(stack, LOG_TRANSPORT_HAPROXY, + log_transport_haproxy_new(stack, base_index, switch_to)); + return TRUE; +} + static gboolean transport_mapper_inet_setup_stack(TransportMapper *s, LogTransportStack *stack) { @@ -117,6 +127,19 @@ transport_mapper_inet_setup_stack(TransportMapper *s, LogTransportStack *stack) initial_transport_index = LOG_TRANSPORT_TLS; } + if (self->proxied) + { + LogTransportIndex switch_to; + + if (self->tls_context && !_is_tls_required(self)) + switch_to = LOG_TRANSPORT_TLS; + else + switch_to = LOG_TRANSPORT_NONE; + if (!_setup_haproxy_transport(self, stack, initial_transport_index, switch_to)) + return FALSE; + initial_transport_index = LOG_TRANSPORT_HAPROXY; + } + log_transport_stack_switch(stack, initial_transport_index); return TRUE; } @@ -368,14 +391,32 @@ transport_mapper_network_apply_transport(TransportMapper *s, GlobalConfig *cfg) self->require_tls = TRUE; self->super.transport_name = g_strdup("bsdsyslog+tls"); } + else if (strcasecmp(transport, "proxied-tcp") == 0) + { + self->super.logproto = "text"; + self->super.sock_type = SOCK_STREAM; + self->super.sock_proto = IPPROTO_TCP; + self->proxied = TRUE; + self->super.transport_name = g_strdup("bsdsyslog+proxied-tcp"); + } else if (strcasecmp(transport, "proxied-tls") == 0) { - self->super.logproto = "proxied-tcp"; + self->super.logproto = "text"; self->super.sock_type = SOCK_STREAM; self->super.sock_proto = IPPROTO_TCP; + self->proxied = TRUE; self->require_tls = TRUE; self->super.transport_name = g_strdup("bsdsyslog+proxied-tls"); } + else if (strcasecmp(transport, "proxied-tls-passthrough") == 0) + { + self->super.logproto = "text"; + self->super.sock_type = SOCK_STREAM; + self->super.sock_proto = IPPROTO_TCP; + self->proxied = TRUE; + self->allow_tls = TRUE; + self->super.transport_name = g_strdup("bsdsyslog+proxied-tls-passthrough"); + } else { self->super.logproto = self->super.transport; @@ -456,6 +497,35 @@ transport_mapper_syslog_apply_transport(TransportMapper *s, GlobalConfig *cfg) self->require_tls = TRUE; self->super.transport_name = g_strdup("rfc5425"); } + else if (strcasecmp(transport, "proxied-tcp") == 0) + { + self->server_port = SYSLOG_TRANSPORT_TCP_PORT; + self->super.logproto = "framed"; + self->super.sock_type = SOCK_STREAM; + self->super.sock_proto = IPPROTO_TCP; + self->proxied = TRUE; + self->super.transport_name = g_strdup("rfc6587+proxied-tcp"); + } + else if (strcasecmp(transport, "proxied-tls") == 0) + { + self->server_port = SYSLOG_TRANSPORT_TCP_PORT; + self->super.logproto = "framed"; + self->super.sock_type = SOCK_STREAM; + self->super.sock_proto = IPPROTO_TCP; + self->proxied = TRUE; + self->require_tls = TRUE; + self->super.transport_name = g_strdup("rfc5425+proxied-tls"); + } + else if (strcasecmp(transport, "proxied-tls-passthrough") == 0) + { + self->server_port = SYSLOG_TRANSPORT_TCP_PORT; + self->super.logproto = "framed"; + self->super.sock_type = SOCK_STREAM; + self->super.sock_proto = IPPROTO_TCP; + self->proxied = TRUE; + self->allow_tls = TRUE; + self->super.transport_name = g_strdup("rfc5425+proxied-tls-passthrough"); + } else { self->super.logproto = self->super.transport; diff --git a/modules/afsocket/transport-mapper-inet.h b/modules/afsocket/transport-mapper-inet.h index 8770261c3a..f3356b5970 100644 --- a/modules/afsocket/transport-mapper-inet.h +++ b/modules/afsocket/transport-mapper-inet.h @@ -36,6 +36,7 @@ typedef struct _TransportMapperInet gboolean require_tls; gboolean allow_tls; gboolean require_tls_when_has_tls_context; + gboolean proxied; TLSContext *tls_context; TLSVerifier *tls_verifier; gpointer secret_store_cb_data; diff --git a/modules/afsocket/transport-mapper.h b/modules/afsocket/transport-mapper.h index 0f998fa141..3569a7581e 100644 --- a/modules/afsocket/transport-mapper.h +++ b/modules/afsocket/transport-mapper.h @@ -42,8 +42,6 @@ struct _TransportMapper gint sock_type; /* protocol parameter for the socket() call, 0 for default or IPPROTO_XXX for specific transports */ gint sock_proto; - /* when a proto needs a Multitransport instance */ - gboolean create_multitransport; const gchar *logproto; /* the user visible summary of the transport, to be put into $TRANSPORT */ From 59a01cf19e84bedca7150f9b2249a32cf2510f20 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 15 Sep 2024 18:20:14 +0200 Subject: [PATCH 12/15] logproto: Remove proxied-text-server Signed-off-by: Alex Becker Signed-off-by: Hofi --- lib/logproto/CMakeLists.txt | 2 - lib/logproto/Makefile.am | 2 - lib/logproto/logproto-proxied-text-server.c | 651 -------------------- lib/logproto/logproto-proxied-text-server.h | 33 - lib/logproto/tests/CMakeLists.txt | 3 +- lib/logproto/tests/Makefile.am | 3 +- lib/logproto/tests/test-proxy-proto.c | 269 -------- 7 files changed, 2 insertions(+), 961 deletions(-) delete mode 100644 lib/logproto/logproto-proxied-text-server.c delete mode 100644 lib/logproto/logproto-proxied-text-server.h delete mode 100644 lib/logproto/tests/test-proxy-proto.c diff --git a/lib/logproto/CMakeLists.txt b/lib/logproto/CMakeLists.txt index d7043fdf10..7348b63824 100644 --- a/lib/logproto/CMakeLists.txt +++ b/lib/logproto/CMakeLists.txt @@ -11,7 +11,6 @@ set(LOGPROTO_HEADERS logproto/logproto-server.h logproto/logproto-text-client.h logproto/logproto-text-server.h - logproto/logproto-proxied-text-server.h PARENT_SCOPE) set(LOGPROTO_SOURCES @@ -26,7 +25,6 @@ set(LOGPROTO_SOURCES logproto/logproto-server.c logproto/logproto-text-client.c logproto/logproto-text-server.c - logproto/logproto-proxied-text-server.c PARENT_SCOPE) add_test_subdirectory(tests) diff --git a/lib/logproto/Makefile.am b/lib/logproto/Makefile.am index 321b4b689a..da02d8f723 100644 --- a/lib/logproto/Makefile.am +++ b/lib/logproto/Makefile.am @@ -11,7 +11,6 @@ logprotoinclude_HEADERS = \ lib/logproto/logproto-framed-server.h \ lib/logproto/logproto-text-client.h \ lib/logproto/logproto-text-server.h \ - lib/logproto/logproto-proxied-text-server.h \ lib/logproto/logproto-multiline-server.h \ lib/logproto/logproto-record-server.h \ lib/logproto/logproto-builtins.h \ @@ -26,7 +25,6 @@ logproto_sources = \ lib/logproto/logproto-framed-server.c \ lib/logproto/logproto-text-client.c \ lib/logproto/logproto-text-server.c \ - lib/logproto/logproto-proxied-text-server.c \ lib/logproto/logproto-multiline-server.c \ lib/logproto/logproto-record-server.c \ lib/logproto/logproto-builtins.c diff --git a/lib/logproto/logproto-proxied-text-server.c b/lib/logproto/logproto-proxied-text-server.c deleted file mode 100644 index 7775541ffd..0000000000 --- a/lib/logproto/logproto-proxied-text-server.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright (c) 2020 One Identity - * Copyright (c) 2022 Balazs Scheidler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ - - -#include -#include -#include "messages.h" -#include "logproto-proxied-text-server.h" -#include "transport/transport-stack.h" -#include "transport/transport-factory-tls.h" -#include "str-utils.h" - -#define IP_BUF_SIZE 64 - -/* This file implements: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt */ - -/* PROXYv1 line without newlines or terminating zero character. The - * protocol specification contains the number 108 that includes both the - * CRLF sequence and the NUL */ -#define PROXY_PROTO_HDR_MAX_LEN_RFC 105 - -/* the size of the buffer we use to fetch the PROXY header into */ -#define PROXY_PROTO_HDR_BUFFER_SIZE 1500 - -/* the amount of bytes we need from the client to detect protocol version */ -#define PROXY_PROTO_HDR_MAGIC_LEN 5 - -typedef struct _LogProtoProxiedTextServer -{ - LogProtoTextServer super; - - // Info received from the proxied that should be added as LogTransportAuxData to - // any message received through this server instance. - struct - { - gboolean unknown; - - gchar src_ip[IP_BUF_SIZE]; - gchar dst_ip[IP_BUF_SIZE]; - - int ip_version; - int src_port; - int dst_port; - } info; - - // Flag to only run handshake() once - gboolean handshake_done; - gboolean has_to_switch_to_tls; - - enum - { - LPPTS_INITIAL, - LPPTS_DETERMINE_VERSION, - LPPTS_PROXY_V1_READ_LINE, - LPPTS_PROXY_V2_READ_HEADER, - LPPTS_PROXY_V2_READ_PAYLOAD, - } header_fetch_state; - - /* 0 unknown, 1 or 2 indicate proxy header version */ - gint proxy_header_version; - guchar proxy_header_buff[PROXY_PROTO_HDR_BUFFER_SIZE]; - gsize proxy_header_buff_len; -} LogProtoProxiedTextServer; - - -struct proxy_hdr_v2 -{ - uint8_t sig[12]; /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */ - uint8_t ver_cmd; /* protocol version and command */ - uint8_t fam; /* protocol family and address */ - uint16_t len; /* number of following bytes part of the header */ -}; - -union proxy_addr -{ - struct - { - /* for TCP/UDP over IPv4, len = 12 */ - uint32_t src_addr; - uint32_t dst_addr; - uint16_t src_port; - uint16_t dst_port; - } ipv4_addr; - struct - { - /* for TCP/UDP over IPv6, len = 36 */ - uint8_t src_addr[16]; - uint8_t dst_addr[16]; - uint16_t src_port; - uint16_t dst_port; - } ipv6_addr; - struct - { - /* for AF_UNIX sockets, len = 216 */ - uint8_t src_addr[108]; - uint8_t dst_addr[108]; - } unix_addr; -}; - -#define PROXY_HDR_TCP4 "PROXY TCP4 " -#define PROXY_HDR_TCP6 "PROXY TCP6 " -#define PROXY_HDR_UNKNOWN "PROXY UNKNOWN" - -static gboolean -_check_proxy_v1_header_length(const guchar *msg, gsize msg_len) -{ - if (msg_len > PROXY_PROTO_HDR_MAX_LEN_RFC) - { - msg_error("PROXY proto header length exceeds max length defined by the specification", - evt_tag_long("length", msg_len), - evt_tag_str("header", (const gchar *)msg)); - return FALSE; - } - - return TRUE; -} - -static gboolean -_check_proxy_v1_header(const guchar *msg, gsize msg_len, const gchar *expected_header, gsize *header_len) -{ - gsize expected_header_length = strlen(expected_header); - - if (msg_len < expected_header_length) - return FALSE; - - *header_len = expected_header_length; - return strncmp((const gchar *)msg, expected_header, expected_header_length) == 0; -} - -static gboolean -_is_proxy_v1_proto_tcp4(const guchar *msg, gsize msg_len, gsize *header_len) -{ - return _check_proxy_v1_header(msg, msg_len, PROXY_HDR_TCP4, header_len); -} - -static gboolean -_is_proxy_v1_proto_tcp6(const guchar *msg, gsize msg_len, gsize *header_len) -{ - return _check_proxy_v1_header(msg, msg_len, PROXY_HDR_TCP6, header_len); -} - -static gboolean -_is_proxy_v1_unknown(const guchar *msg, gsize msg_len, gsize *header_len) -{ - return _check_proxy_v1_header(msg, msg_len, PROXY_HDR_UNKNOWN, header_len); -} - -static gboolean -_parse_proxy_v1_unknown_header(LogProtoProxiedTextServer *self, const guchar *msg, gsize msg_len) -{ - if (msg_len == 0) - return TRUE; - - msg_warning("PROXY UNKNOWN header contains unexpected parameters", - evt_tag_mem("parameters", msg, msg_len)); - - return TRUE; -} - -static gboolean -_parse_proxy_v1_tcp_header(LogProtoProxiedTextServer *self, const guchar *msg, gsize msg_len) -{ - if (msg_len == 0) - return FALSE; - - GString *params_str = g_string_new_len((const gchar *)msg, msg_len); - gboolean result = FALSE; - msg_debug("PROXY header params", evt_tag_str("params", (const gchar *)msg)); - - gchar **params = strsplit(params_str->str, ' ', 5); - gint params_n = g_strv_length(params); - if (params_n < 4) - goto ret; - - g_strlcpy(self->info.src_ip, params[0], IP_BUF_SIZE); - g_strlcpy(self->info.dst_ip, params[1], IP_BUF_SIZE); - - self->info.src_port = atoi(params[2]); - if (self->info.src_port > 65535 || self->info.src_port < 0) - msg_warning("PROXT TCP header contains invalid src port", evt_tag_str("src port", params[2])); - - self->info.dst_port = atoi(params[3]); - if (self->info.dst_port > 65535 || self->info.dst_port < 0) - msg_warning("PROXT TCP header contains invalid dst port", evt_tag_str("dst port", params[2])); - - if (params_n > 4) - msg_warning("PROXY TCP header contains unexpected paramaters", evt_tag_str("parameters", params[4])); - - result = TRUE; -ret: - if (params) - g_strfreev(params); - g_string_free(params_str, TRUE); - - return result; -} - -static gboolean -_extract_proxy_v1_header(LogProtoProxiedTextServer *self, guchar **msg, gsize *msg_len) -{ - if (self->proxy_header_buff[self->proxy_header_buff_len - 1] == '\n') - self->proxy_header_buff_len--; - - if (self->proxy_header_buff[self->proxy_header_buff_len - 1] == '\r') - self->proxy_header_buff_len--; - - self->proxy_header_buff[self->proxy_header_buff_len] = 0; - *msg = self->proxy_header_buff; - *msg_len = self->proxy_header_buff_len; - return TRUE; -} - -static gboolean -_parse_proxy_v1_header(LogProtoProxiedTextServer *self) -{ - guchar *proxy_line; - gsize proxy_line_len; - - if (!_extract_proxy_v1_header(self, &proxy_line, &proxy_line_len)) - return FALSE; - - - gsize header_len = 0; - - if (!_check_proxy_v1_header_length(proxy_line, proxy_line_len)) - return FALSE; - - if (_is_proxy_v1_unknown(proxy_line, proxy_line_len, &header_len)) - { - self->info.unknown = TRUE; - return _parse_proxy_v1_unknown_header(self, proxy_line + header_len, proxy_line_len - header_len); - } - - if (_is_proxy_v1_proto_tcp4(proxy_line, proxy_line_len, &header_len)) - { - self->info.ip_version = 4; - return _parse_proxy_v1_tcp_header(self, proxy_line + header_len, proxy_line_len - header_len); - } - - if (_is_proxy_v1_proto_tcp6(proxy_line, proxy_line_len, &header_len)) - { - self->info.ip_version = 6; - return _parse_proxy_v1_tcp_header(self, proxy_line + header_len, proxy_line_len - header_len); - } - - return FALSE; -} - -static gboolean -_parse_proxy_v2_proxy_address(LogProtoProxiedTextServer *self, struct proxy_hdr_v2 *proxy_hdr, - union proxy_addr *proxy_addr) -{ - gint address_family = (proxy_hdr->fam & 0xF0) >> 4; - gint proxy_header_len = ntohs(proxy_hdr->len); - - if (address_family == 1 && proxy_header_len >= sizeof(proxy_addr->ipv4_addr)) - { - /* AF_INET */ - inet_ntop(AF_INET, (gchar *) &proxy_addr->ipv4_addr.src_addr, self->info.src_ip, sizeof(self->info.src_ip)); - inet_ntop(AF_INET, (gchar *) &proxy_addr->ipv4_addr.dst_addr, self->info.dst_ip, sizeof(self->info.dst_ip)); - self->info.src_port = ntohs(proxy_addr->ipv4_addr.src_port); - self->info.dst_port = ntohs(proxy_addr->ipv4_addr.dst_port); - self->info.ip_version = 4; - return TRUE; - } - else if (address_family == 2 && proxy_header_len >= sizeof(proxy_addr->ipv6_addr)) - { - /* AF_INET6 */ - inet_ntop(AF_INET6, (gchar *) &proxy_addr->ipv6_addr.src_addr, self->info.src_ip, sizeof(self->info.src_ip)); - inet_ntop(AF_INET6, (gchar *) &proxy_addr->ipv6_addr.dst_addr, self->info.dst_ip, sizeof(self->info.dst_ip)); - self->info.src_port = ntohs(proxy_addr->ipv6_addr.src_port); - self->info.dst_port = ntohs(proxy_addr->ipv6_addr.dst_port); - self->info.ip_version = 6; - } - else if (address_family == 0) - { - /* AF_UNSPEC */ - self->info.unknown = TRUE; - return TRUE; - } - - msg_error("PROXYv2 header does not have enough bytes to represent endpoint addresses or unknown address_family", - evt_tag_int("proxy_header_len", proxy_header_len), - evt_tag_int("address_family", address_family)); - return FALSE; -} - -static gboolean -_parse_proxy_v2_header(LogProtoProxiedTextServer *self) -{ - struct proxy_hdr_v2 *proxy_hdr = (struct proxy_hdr_v2 *) self->proxy_header_buff; - union proxy_addr *proxy_addr = (union proxy_addr *)(proxy_hdr + 1); - - /* is this proxy v2 */ - if ((proxy_hdr->ver_cmd & 0xF0) != 0x20) - return FALSE; - - if ((proxy_hdr->ver_cmd & 0xF) == 0) - { - /* LOCAL connection */ - return TRUE; - } - else if ((proxy_hdr->ver_cmd & 0xF) == 1) - { - /* PROXY connection */ - return _parse_proxy_v2_proxy_address(self, proxy_hdr, proxy_addr); - } - - return FALSE; -} - -static gboolean -_parse_proxy_header(LogProtoProxiedTextServer *self) -{ - if (self->proxy_header_version == 1) - return _parse_proxy_v1_header(self); - else if (self->proxy_header_version == 2) - return _parse_proxy_v2_header(self); - else - g_assert_not_reached(); -} - -static LogProtoStatus -_fetch_chunk(LogProtoProxiedTextServer *self, gsize upto_bytes) -{ - LogTransport *transport = log_transport_stack_get_active(&self->super.super.super.transport_stack); - - g_assert(upto_bytes < sizeof(self->proxy_header_buff)); - if (self->proxy_header_buff_len < upto_bytes) - { - gssize rc = log_transport_read(transport, - &(self->proxy_header_buff[self->proxy_header_buff_len]), - upto_bytes - self->proxy_header_buff_len, NULL); - if (rc < 0) - { - if (errno == EAGAIN) - return LPS_AGAIN; - else - { - msg_error("I/O error occurred while reading proxy header", - evt_tag_int(EVT_TAG_FD, transport->fd), - evt_tag_error(EVT_TAG_OSERROR)); - return LPS_ERROR; - } - } - /* EOF without data */ - if (rc == 0) - { - return LPS_EOF; - } - - self->proxy_header_buff_len += rc; - } - if (self->proxy_header_buff_len == upto_bytes) - return LPS_SUCCESS; - return LPS_AGAIN; -} - -static inline LogProtoStatus -_fetch_until_newline(LogProtoProxiedTextServer *self) -{ - /* leave 1 character for terminating zero. We should have plenty of space - * in our buffer, as the longest line we need to fetch is 107 bytes - * including the line terminator characters. */ - - while (self->proxy_header_buff_len < sizeof(self->proxy_header_buff) - 1) - { - LogProtoStatus status = _fetch_chunk(self, self->proxy_header_buff_len + 1); - - if (status != LPS_SUCCESS) - return status; - - if (self->proxy_header_buff[self->proxy_header_buff_len - 1] == '\n') - { - return LPS_SUCCESS; - } - } - - msg_error("PROXY proto header with invalid header length", - evt_tag_int("max_parsable_length", sizeof(self->proxy_header_buff)-1), - evt_tag_int("max_length_by_spec", PROXY_PROTO_HDR_MAX_LEN_RFC), - evt_tag_long("length", self->proxy_header_buff_len), - evt_tag_str("header", (const gchar *)self->proxy_header_buff)); - return LPS_ERROR; -} - -static LogProtoStatus -_fetch_proxy_v2_payload(LogProtoProxiedTextServer *self) -{ - struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *) self->proxy_header_buff; - gint proxy_header_len = ntohs(hdr->len); - - if (self->proxy_header_buff_len + proxy_header_len > sizeof(self->proxy_header_buff)) - { - msg_error("PROXYv2 proto header with invalid header length", - evt_tag_int("max_parsable_length", sizeof(self->proxy_header_buff)), - evt_tag_long("length", proxy_header_len)); - return LPS_ERROR; - } - - return _fetch_chunk(self, self->proxy_header_buff_len + proxy_header_len); -} - -static gboolean -_is_proxy_version_v1(LogProtoProxiedTextServer *self) -{ - if (self->proxy_header_buff_len < PROXY_PROTO_HDR_MAGIC_LEN) - return FALSE; - - return memcmp(self->proxy_header_buff, "PROXY", PROXY_PROTO_HDR_MAGIC_LEN) == 0; -} - -static gboolean -_is_proxy_version_v2(LogProtoProxiedTextServer *self) -{ - if (self->proxy_header_buff_len < PROXY_PROTO_HDR_MAGIC_LEN) - return FALSE; - - return memcmp(self->proxy_header_buff, "\x0D\x0A\x0D\x0A\x00", PROXY_PROTO_HDR_MAGIC_LEN) == 0; -} - -static inline LogProtoStatus -_fetch_into_proxy_buffer(LogProtoProxiedTextServer *self) -{ - LogTransport *transport = log_transport_stack_get_active(&self->super.super.super.transport_stack); - LogProtoStatus status; - - switch (self->header_fetch_state) - { - case LPPTS_INITIAL: - self->header_fetch_state = LPPTS_DETERMINE_VERSION; - /* fallthrough */ - case LPPTS_DETERMINE_VERSION: - status = _fetch_chunk(self, PROXY_PROTO_HDR_MAGIC_LEN); - - if (status != LPS_SUCCESS) - return status; - - if (_is_proxy_version_v1(self)) - { - self->header_fetch_state = LPPTS_PROXY_V1_READ_LINE; - self->proxy_header_version = 1; - goto process_proxy_v1; - } - else if (_is_proxy_version_v2(self)) - { - self->header_fetch_state = LPPTS_PROXY_V2_READ_HEADER; - self->proxy_header_version = 2; - goto process_proxy_v2; - } - else - { - msg_error("Unable to determine PROXY protocol version", - evt_tag_int(EVT_TAG_FD, transport->fd)); - return LPS_ERROR; - } - g_assert_not_reached(); - - case LPPTS_PROXY_V1_READ_LINE: - -process_proxy_v1: - return _fetch_until_newline(self); - case LPPTS_PROXY_V2_READ_HEADER: -process_proxy_v2: - status = _fetch_chunk(self, sizeof(struct proxy_hdr_v2)); - if (status != LPS_SUCCESS) - return status; - - self->header_fetch_state = LPPTS_PROXY_V2_READ_PAYLOAD; - /* fallthrough */ - case LPPTS_PROXY_V2_READ_PAYLOAD: - return _fetch_proxy_v2_payload(self); - default: - g_assert_not_reached(); - } -} - -static gboolean -_switch_to_tls(LogProtoProxiedTextServer *self) -{ - if (!log_transport_stack_switch(&self->super.super.super.transport_stack, LOG_TRANSPORT_TLS)) - { - msg_error("proxied-tls failed to switch to TLS"); - return FALSE; - } - - msg_debug("proxied-tls switch to TLS: OK"); - return TRUE; -} - -static LogProtoPrepareAction -log_proto_proxied_text_server_prepare(LogProtoServer *s, GIOCondition *cond, gint *timeout) -{ - LogProtoProxiedTextServer *self = (LogProtoProxiedTextServer *) s; - LogTransport *transport = log_transport_stack_get_active(&s->transport_stack); - - *cond = transport->cond; - - if (self->handshake_done) - return log_proto_text_server_prepare_method(s, cond, timeout); - - /* if there's no pending I/O in the transport layer, then we want to do a read */ - if (*cond == 0) - *cond = G_IO_IN; - - return LPPA_POLL_IO; -} - -static LogProtoStatus -log_proto_proxied_text_server_handshake(LogProtoServer *s, gboolean *handshake_finished) -{ - LogProtoProxiedTextServer *self = (LogProtoProxiedTextServer *) s; - - LogProtoStatus status = _fetch_into_proxy_buffer(self); - - self->handshake_done = *handshake_finished = (status == LPS_SUCCESS); - if (status != LPS_SUCCESS) - return status; - - gboolean parsable = _parse_proxy_header(self); - - msg_debug("PROXY protocol header received", - evt_tag_int("version", self->proxy_header_version), - self->proxy_header_version == 1 - ? evt_tag_mem("header", self->proxy_header_buff, self->proxy_header_buff_len) - : evt_tag_str("header", "")); - - if (parsable) - { - msg_trace("PROXY protocol header parsed successfully"); - - if (self->has_to_switch_to_tls && !_switch_to_tls(self)) - return LPS_ERROR; - - return LPS_SUCCESS; - } - else - { - msg_error("Error parsing PROXY protocol header"); - return LPS_ERROR; - } -} - -static void -_augment_aux_data(LogProtoProxiedTextServer *self, LogTransportAuxData *aux) -{ - gchar buf1[8]; - gchar buf2[8]; - gchar buf3[8]; - - if (self->info.unknown) - return; - - snprintf(buf1, 8, "%i", self->info.src_port); - snprintf(buf2, 8, "%i", self->info.dst_port); - snprintf(buf3, 8, "%i", self->info.ip_version); - - log_transport_aux_data_add_nv_pair(aux, "PROXIED_SRCIP", self->info.src_ip); - log_transport_aux_data_add_nv_pair(aux, "PROXIED_DSTIP", self->info.dst_ip); - log_transport_aux_data_add_nv_pair(aux, "PROXIED_SRCPORT", buf1); - log_transport_aux_data_add_nv_pair(aux, "PROXIED_DSTPORT", buf2); - log_transport_aux_data_add_nv_pair(aux, "PROXIED_IP_VERSION", buf3); - - return; -} - -static LogProtoStatus -log_proto_proxied_text_server_fetch(LogProtoServer *s, const guchar **msg, gsize *msg_len, gboolean *may_read, - LogTransportAuxData *aux, Bookmark *bookmark) -{ - LogProtoProxiedTextServer *self = (LogProtoProxiedTextServer *) s; - - LogProtoStatus status = log_proto_buffered_server_fetch(&self->super.super.super, msg, msg_len, may_read, aux, - bookmark); - - if (status != LPS_SUCCESS) - return status; - - _augment_aux_data(self, aux); - - return LPS_SUCCESS; -} - -static void -log_proto_proxied_text_server_free(LogProtoServer *s) -{ - LogProtoProxiedTextServer *self = (LogProtoProxiedTextServer *) s; - - msg_debug("Freeing PROXY protocol source driver", evt_tag_printf("driver", "%p", self)); - - log_proto_text_server_free(&self->super.super.super); - - return; -} - -static void -log_proto_proxied_text_server_init(LogProtoProxiedTextServer *self, LogTransport *transport, - const LogProtoServerOptions *options) -{ - msg_info("Initializing PROXY protocol source driver", evt_tag_printf("driver", "%p", self)); - - log_proto_text_server_init(&self->super, transport, options); - - self->super.super.super.prepare = log_proto_proxied_text_server_prepare; - self->super.super.super.handshake = log_proto_proxied_text_server_handshake; - self->super.super.super.fetch = log_proto_proxied_text_server_fetch; - self->super.super.super.free_fn = log_proto_proxied_text_server_free; - - return; -} - -LogProtoServer * -log_proto_proxied_text_server_new(LogTransport *transport, const LogProtoServerOptions *options) -{ - LogProtoProxiedTextServer *self = g_new0(LogProtoProxiedTextServer, 1); - log_proto_proxied_text_server_init(self, transport, options); - - return &self->super.super.super; -} - - -LogProtoServer * -log_proto_proxied_text_tls_passthrough_server_new(LogTransport *transport, const LogProtoServerOptions *options) -{ - LogProtoProxiedTextServer *self = (LogProtoProxiedTextServer *) log_proto_proxied_text_server_new(transport, options); - - self->has_to_switch_to_tls = TRUE; - - return &self->super.super.super; -} diff --git a/lib/logproto/logproto-proxied-text-server.h b/lib/logproto/logproto-proxied-text-server.h deleted file mode 100644 index dcad0504c6..0000000000 --- a/lib/logproto/logproto-proxied-text-server.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2020 One Identity - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ - -#ifndef LOGPROTO_PROXIED_TEXT_SERVER -#define LOGPROTO_PROXIED_TEXT_SERVER - -#include "logproto-text-server.h" - -LogProtoServer *log_proto_proxied_text_server_new(LogTransport *transport, const LogProtoServerOptions *options); -LogProtoServer *log_proto_proxied_text_tls_passthrough_server_new(LogTransport *transport, - const LogProtoServerOptions *options); - -#endif diff --git a/lib/logproto/tests/CMakeLists.txt b/lib/logproto/tests/CMakeLists.txt index 5c427cb9d3..c94913854a 100644 --- a/lib/logproto/tests/CMakeLists.txt +++ b/lib/logproto/tests/CMakeLists.txt @@ -6,8 +6,7 @@ set(TEST_LOGPROTO_SOURCES test-dgram-server.c test-framed-server.c test-indented-multiline-server.c - test-regexp-multiline-server.c - test-proxy-proto.c) + test-regexp-multiline-server.c) add_unit_test(LIBTEST CRITERION TARGET test_logproto diff --git a/lib/logproto/tests/Makefile.am b/lib/logproto/tests/Makefile.am index 6795e15c10..8dcb10a91d 100644 --- a/lib/logproto/tests/Makefile.am +++ b/lib/logproto/tests/Makefile.am @@ -18,8 +18,7 @@ lib_logproto_tests_test_logproto_SOURCES = \ lib/logproto/tests/test-dgram-server.c \ lib/logproto/tests/test-framed-server.c \ lib/logproto/tests/test-indented-multiline-server.c \ - lib/logproto/tests/test-regexp-multiline-server.c \ - lib/logproto/tests/test-proxy-proto.c + lib/logproto/tests/test-regexp-multiline-server.c lib_logproto_tests_test_findeom_CFLAGS = \ $(TEST_CFLAGS) \ diff --git a/lib/logproto/tests/test-proxy-proto.c b/lib/logproto/tests/test-proxy-proto.c deleted file mode 100644 index 76b55131c8..0000000000 --- a/lib/logproto/tests/test-proxy-proto.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2020 One Identity - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ -#include -#include -#include "libtest/mock-transport.h" -#include "libtest/proto_lib.h" - -#include "logproto/logproto-proxied-text-server.h" -#include - -typedef struct -{ - const gchar *proxy_header; - gboolean valid; -} ProtocolHeaderTestParams; - -ParameterizedTestParameters(log_proto, test_proxy_protocol_parse_header) -{ - static ProtocolHeaderTestParams test_params[] = - { - /* SUCCESS */ - { "PROXY UNKNOWN\r\n", TRUE }, - { "PROXY UNKNOWN extra ignored parameters\r\n", TRUE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, - { "PROXY TCP6 ::1 ::2 3333 4444\r\n", TRUE }, - - /* INVALID PROTO */ - { "PROXY UNKNOWN\n", TRUE }, // WRONG TERMINATION - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\n", TRUE }, // WRONG TERMINATION - { "PROXY UNKNOWN\r", FALSE }, // WRONG TERMINATION - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r", FALSE }, // WRONG TERMINATION - { "PROXY\r\n", FALSE }, - { "PROXY TCP4\r\n", FALSE }, - { "PROXY TCP4 1.1.1.1\r\n", FALSE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2\r\n", FALSE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333\r\n", FALSE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444 extra param\r\n", TRUE}, - - /* EXTRA WHITESPACE - PERMISSIVE */ - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444 \r\n", TRUE }, - - /* EXTRA WHITESPACE BEFORE PARAMETERS */ - { "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", FALSE }, - - - /* INVALID ARGUMENTS - PERMISSIVE */ - { "PROXY TCP6 1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, // WRONG IP PROTO - { "PROXY TCP4 ::1 ::2 3333 4444\r\n", TRUE }, // WRONG IP PROTO - { "PROXY TCP4 1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, // WRONG IP - { "PROXY TCP4 1.1.1.1.1 2.2.2.2 3333 4444\r\n", TRUE }, // WRONG IP - { "PROXY TCP6 ::1::0 ::1 3333 4444\r\n", TRUE }, // WRONG IP - { "PROXY TCP4 1.1.1.1 2.2.2.2 33333 0\r\n", TRUE }, // WRONG PORT - { "PROXY TCP4 1.1.1.1 2.2.2.2 33333 -1\r\n", TRUE }, // WRONG PORT - { "PROXY TCP4 1.1.1.1 2.2.2.2 33333 65536\r\n", TRUE }, // WRONG PORT - - /* INVALID ARGUMENT(S)*/ - { "PROXY TCP3 1.1.1.1 2.2.2.2 3333 4444\r\n", FALSE}, // WRONG IP PROTO - - - { - "PROXY TCP4 padpadpadpadpadpadpadpadpadpadpadpadpad" - "padpadpadpadpadpadpadpadpadpadpadpadpadpadpadpadpad" - "padpadpadpadpadpadpadpadpadpadpadpadpadpadpadpadpad", FALSE - } // TOO LONG - }; - - return cr_make_param_array(ProtocolHeaderTestParams, test_params, G_N_ELEMENTS(test_params)); -} - -ParameterizedTest(ProtocolHeaderTestParams *params, log_proto, test_proxy_protocol_parse_header) -{ - LogProtoServer *proto = log_proto_proxied_text_server_new(log_transport_mock_records_new(params->proxy_header, - -1, LTM_EOF), - get_inited_proto_server_options()); - - gboolean handshake_finished = FALSE; - gboolean valid = log_proto_server_handshake(proto, &handshake_finished) == LPS_SUCCESS; - - if (valid) - cr_assert(handshake_finished == TRUE); - - cr_assert_eq(valid, params->valid, - "This should be %s: %s", params->valid ? "valid" : "invalid", params->proxy_header); - - log_proto_server_free(proto); -} - -Test(log_proto, test_proxy_protocol_handshake_and_fetch_success) -{ - LogTransport *transport = log_transport_mock_records_new("PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", -1, - "test message\n", -1, - LTM_EOF); - LogProtoServer *proto = log_proto_proxied_text_server_new(transport, get_inited_proto_server_options()); - - gboolean handshake_finished = FALSE; - cr_assert_eq(log_proto_server_handshake(proto, &handshake_finished), LPS_SUCCESS); - cr_assert(handshake_finished == TRUE); - assert_proto_server_fetch(proto, "test message", -1); - - log_proto_server_free(proto); -} - -Test(log_proto, test_proxy_protocol_handshake_failed) -{ - LogTransport *transport = log_transport_mock_records_new("invalid header\r\n", -1, - "test message\n", -1, - LTM_EOF); - LogProtoServer *proto = log_proto_proxied_text_server_new(transport, get_inited_proto_server_options()); - - gboolean handshake_finished = FALSE; - cr_assert_eq(log_proto_server_handshake(proto, &handshake_finished), LPS_ERROR); - cr_assert(handshake_finished == FALSE); - - log_proto_server_free(proto); -} - -static void -get_aux_data_from_next_message(LogProtoServer *proto, LogTransportAuxData *aux) -{ - LogProtoStatus status; - - const guchar *msg = NULL; - gsize msg_len = 0; - Bookmark bookmark; - gboolean may_read = TRUE; - - do - { - log_transport_aux_data_init(aux); - status = log_proto_server_fetch(proto, &msg, &msg_len, &may_read, aux, &bookmark); - if (status == LPS_AGAIN) - status = LPS_SUCCESS; - } - while (status == LPS_SUCCESS && msg == NULL && may_read); -} - -static void -concat_nv(const gchar *name, const gchar *value, gsize value_len, gpointer user_data) -{ - GString *aux_nv_concated = user_data; - g_string_append_printf(aux_nv_concated, "%s:%s ", name, value); -} - -Test(log_proto, test_proxy_protocol_aux_data) -{ - const gchar *expected = "PROXIED_SRCIP:1.1.1.1 PROXIED_DSTIP:2.2.2.2 " - "PROXIED_SRCPORT:3333 PROXIED_DSTPORT:4444 " - "PROXIED_IP_VERSION:4 "; - LogTransport *transport = log_transport_mock_records_new("PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n", -1, - "test message\n", -1, - LTM_EOF); - LogProtoServer *proto = log_proto_proxied_text_server_new(transport, get_inited_proto_server_options()); - - gboolean handshake_finished = FALSE; - cr_assert_eq(log_proto_server_handshake(proto, &handshake_finished), LPS_SUCCESS); - cr_assert(handshake_finished == TRUE); - - LogTransportAuxData aux; - log_transport_aux_data_init(&aux); - get_aux_data_from_next_message(proto, &aux); - - GString *aux_nv_concated = g_string_new(NULL); - log_transport_aux_data_foreach(&aux, concat_nv, aux_nv_concated); - cr_assert_str_eq(aux_nv_concated->str, expected); - - g_string_free(aux_nv_concated, TRUE); - log_transport_aux_data_destroy(&aux); - log_proto_server_free(proto); -} - -Test(log_proto, test_proxy_protocol_v2_parse_header) -{ - const gchar *expected = "PROXIED_SRCIP:1.1.1.1 PROXIED_DSTIP:2.2.2.2 " - "PROXIED_SRCPORT:33333 PROXIED_DSTPORT:44444 " - "PROXIED_IP_VERSION:4 "; - LogProtoServer *proto = log_proto_proxied_text_server_new(log_transport_mock_records_new( - "\r\n\r\n\0\r\nQUIT\n!\21\0\f\1\1\1\1\2\2\2\2\2025\255\234", 28, - "test_message\n", -1, - LTM_EOF - ), - get_inited_proto_server_options()); - - gboolean handshake_finished = FALSE; - cr_assert_eq(log_proto_server_handshake(proto, &handshake_finished), LPS_SUCCESS, "Proxy protocol v2 parsing failed"); - cr_assert(handshake_finished == TRUE); - - LogTransportAuxData aux; - log_transport_aux_data_init(&aux); - get_aux_data_from_next_message(proto, &aux); - - GString *aux_nv_concated = g_string_new(NULL); - log_transport_aux_data_foreach(&aux, concat_nv, aux_nv_concated); - cr_assert_str_eq(aux_nv_concated->str, expected); - - g_string_free(aux_nv_concated, TRUE); - log_transport_aux_data_destroy(&aux); - log_proto_server_free(proto); -} - -Test(log_proto, test_proxy_protocol_header_partial_read) -{ - LogTransportMock *transport = (LogTransportMock *) log_transport_mock_records_new(LTM_EOF); - const char *proxy_header_segments[] = {"P", "ROXY TCP4 ", "1.1.1.1 ", "2.2.2.2 3333 ", "4444\r\n"}; - size_t length = G_N_ELEMENTS(proxy_header_segments); - - for(size_t i = 0; i < length; i++) - { - log_transport_mock_inject_data(transport, proxy_header_segments[i], -1); - log_transport_mock_inject_data(transport, LTM_INJECT_ERROR(EAGAIN)); - } - - log_transport_mock_inject_data(transport, "test message\n", -1); - - LogProtoServer *proto = log_proto_proxied_text_server_new((LogTransport *) transport, - get_inited_proto_server_options()); - - gboolean handshake_finished = FALSE; - for(size_t i = 0; i < length; i++) - { - cr_assert_eq(log_proto_server_handshake(proto, &handshake_finished), LPS_AGAIN); - cr_assert(handshake_finished == FALSE); - } - - cr_assert_eq(log_proto_server_handshake(proto, &handshake_finished), LPS_SUCCESS); - cr_assert(handshake_finished == TRUE); - - - - const gchar *expected = "PROXIED_SRCIP:1.1.1.1 PROXIED_DSTIP:2.2.2.2 " - "PROXIED_SRCPORT:3333 PROXIED_DSTPORT:4444 " - "PROXIED_IP_VERSION:4 "; - LogTransportAuxData aux; - log_transport_aux_data_init(&aux); - get_aux_data_from_next_message(proto, &aux); - - GString *aux_nv_concated = g_string_new(NULL); - log_transport_aux_data_foreach(&aux, concat_nv, aux_nv_concated); - cr_assert_str_eq(aux_nv_concated->str, expected); - - g_string_free(aux_nv_concated, TRUE); - log_transport_aux_data_destroy(&aux); - - log_proto_server_free(proto); - -} From 98f0791cab3c0660d2ca919b9a1168e2d2299d0a Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Wed, 18 Sep 2024 12:14:51 +0200 Subject: [PATCH 13/15] transport: eliminate transport-factory-socket Signed-off-by: Balazs Scheidler --- lib/transport/CMakeLists.txt | 2 - lib/transport/Makefile.am | 2 - lib/transport/transport-factory-socket.c | 55 ------------------------ lib/transport/transport-factory-socket.h | 40 ----------------- modules/afsocket/transport-mapper-inet.c | 7 ++- 5 files changed, 5 insertions(+), 101 deletions(-) delete mode 100644 lib/transport/transport-factory-socket.c delete mode 100644 lib/transport/transport-factory-socket.h diff --git a/lib/transport/CMakeLists.txt b/lib/transport/CMakeLists.txt index 3f0fdf292b..ab9ee96086 100644 --- a/lib/transport/CMakeLists.txt +++ b/lib/transport/CMakeLists.txt @@ -10,7 +10,6 @@ set(TRANSPORT_HEADERS transport/transport-udp-socket.h transport/transport-stack.h transport/transport-factory-tls.h - transport/transport-factory-socket.h transport/tls-context.h transport/tls-verifier.h transport/tls-session.h @@ -28,7 +27,6 @@ set(TRANSPORT_SOURCES transport/transport-tls.c transport/transport-stack.c transport/transport-factory-tls.c - transport/transport-factory-socket.c transport/tls-context.c transport/tls-verifier.c transport/tls-session.c diff --git a/lib/transport/Makefile.am b/lib/transport/Makefile.am index fd2d56eda6..dd455d6565 100644 --- a/lib/transport/Makefile.am +++ b/lib/transport/Makefile.am @@ -14,7 +14,6 @@ transportinclude_HEADERS = \ lib/transport/transport-udp-socket.h \ lib/transport/transport-stack.h \ lib/transport/transport-factory-tls.h \ - lib/transport/transport-factory-socket.h \ lib/transport/tls-context.h \ lib/transport/tls-verifier.h \ lib/transport/tls-session.h @@ -30,7 +29,6 @@ transport_sources = \ lib/transport/transport-udp-socket.c \ lib/transport/transport-stack.c \ lib/transport/transport-factory-tls.c \ - lib/transport/transport-factory-socket.c \ lib/transport/tls-context.c \ lib/transport/tls-verifier.c \ lib/transport/tls-session.c diff --git a/lib/transport/transport-factory-socket.c b/lib/transport/transport-factory-socket.c deleted file mode 100644 index 9813bad3be..0000000000 --- a/lib/transport/transport-factory-socket.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2002-2018 Balabit - * Copyright (c) 2018 Laszlo Budai - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ - -#include "transport/transport-factory-socket.h" -#include "transport/transport-socket.h" -#include "transport/transport-udp-socket.h" - -static LogTransport * -_construct_transport_dgram(const LogTransportFactory *s, LogTransportStack *stack) -{ - return log_transport_udp_socket_new(stack->fd); -} - -static LogTransport * -_construct_transport_stream(const LogTransportFactory *s, LogTransportStack *stack) -{ - return log_transport_stream_socket_new(stack->fd); -} - -LogTransportFactory * -transport_factory_socket_new(int sock_type) -{ - LogTransportFactorySocket *self = g_new0(LogTransportFactorySocket, 1); - - log_transport_factory_init_instance(&self->super, LOG_TRANSPORT_SOCKET); - - if (sock_type == SOCK_DGRAM) - self->super.construct_transport = _construct_transport_dgram; - else - self->super.construct_transport = _construct_transport_stream; - - return &self->super; -} - diff --git a/lib/transport/transport-factory-socket.h b/lib/transport/transport-factory-socket.h deleted file mode 100644 index 5866411548..0000000000 --- a/lib/transport/transport-factory-socket.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2002-2018 Balabit - * Copyright (c) 2018 Laszlo Budai - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ - -#ifndef TRANSPORT_FACTORY_SOCKET_H_INCLUDED -#define TRANSPORT_FACTORY_SOCKET_H_INCLUDED - -#include "transport/transport-stack.h" -#include "transport/transport-socket.h" - -typedef struct _LogTransportFactorySocket LogTransportFactorySocket; - -struct _LogTransportFactorySocket -{ - LogTransportFactory super; -}; - -LogTransportFactory *transport_factory_socket_new(gint sock_type); - -#endif diff --git a/modules/afsocket/transport-mapper-inet.c b/modules/afsocket/transport-mapper-inet.c index 0a8859a9f7..4552e66084 100644 --- a/modules/afsocket/transport-mapper-inet.c +++ b/modules/afsocket/transport-mapper-inet.c @@ -28,8 +28,8 @@ #include "transport/transport-tls.h" #include "transport/transport-stack.h" #include "transport/transport-factory-tls.h" -#include "transport/transport-factory-socket.h" #include "transport/transport-haproxy.h" +#include "transport/transport-socket.h" #include "transport/transport-udp-socket.h" #include "secret-storage/secret-storage.h" @@ -89,7 +89,10 @@ transport_mapper_inet_apply_transport_method(TransportMapper *s, GlobalConfig *c static gboolean _setup_socket_transport(TransportMapperInet *self, LogTransportStack *stack) { - log_transport_stack_add_factory(stack, transport_factory_socket_new(self->super.sock_type)); + log_transport_stack_add_transport(stack, LOG_TRANSPORT_SOCKET, + self->super.sock_type == SOCK_DGRAM + ? log_transport_udp_socket_new(stack->fd) + : log_transport_stream_socket_new(stack->fd)); return TRUE; } From d0a98db8c4e17d07595086d55f290faaf640d30b Mon Sep 17 00:00:00 2001 From: Hofi Date: Wed, 6 Dec 2023 15:58:52 +0100 Subject: [PATCH 14/15] light: Added syslog() source and handling of the latest version of 'proxied' loggen parameter Signed-off-by: Hofi --- tests/light/src/Makefile.am | 1 + tests/light/src/helpers/loggen/loggen.py | 3 + .../statements/sources/syslog_source.py | 56 +++++++++++++++++++ .../src/syslog_ng_config/syslog_ng_config.py | 4 ++ 4 files changed, 64 insertions(+) create mode 100644 tests/light/src/syslog_ng_config/statements/sources/syslog_source.py diff --git a/tests/light/src/Makefile.am b/tests/light/src/Makefile.am index 66e9678e01..83860891b1 100644 --- a/tests/light/src/Makefile.am +++ b/tests/light/src/Makefile.am @@ -65,6 +65,7 @@ EXTRA_DIST += \ tests/light/src/syslog_ng_config/statements/sources/__init__.py \ tests/light/src/syslog_ng_config/statements/sources/internal_source.py \ tests/light/src/syslog_ng_config/statements/sources/network_source.py \ + tests/light/src/syslog_ng_config/statements/sources/syslog_source.py \ tests/light/src/syslog_ng_config/statements/sources/source_driver.py \ tests/light/src/syslog_ng_config/syslog_ng_config.py \ tests/light/src/syslog_ng/console_log_reader.py \ diff --git a/tests/light/src/helpers/loggen/loggen.py b/tests/light/src/helpers/loggen/loggen.py index 2b0f52329e..9199ddf050 100644 --- a/tests/light/src/helpers/loggen/loggen.py +++ b/tests/light/src/helpers/loggen/loggen.py @@ -92,6 +92,9 @@ def __decode_start_parameters( if proxied is True: start_parameters.append("--proxied") + if proxied == 1 or proxied == 2: + start_parameters.append("--proxied={}".format(proxied)) + if proxy_src_ip is not None: start_parameters.append("--proxy-src-ip={}".format(proxy_src_ip)) diff --git a/tests/light/src/syslog_ng_config/statements/sources/syslog_source.py b/tests/light/src/syslog_ng_config/statements/sources/syslog_source.py new file mode 100644 index 0000000000..20a43d9e1e --- /dev/null +++ b/tests/light/src/syslog_ng_config/statements/sources/syslog_source.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +############################################################################# +# Copyright (c) 2015-2020 Balabit +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As an additional exemption you are allowed to compile & link against the +# OpenSSL libraries as published by the OpenSSL project. See the file +# COPYING for details. +# +############################################################################# +from src.driver_io.network.network_io import NetworkIO +from src.syslog_ng_config.statements.sources.source_driver import SourceDriver + + +def map_transport(transport): + mapping = { + "tcp": NetworkIO.Transport.TCP, + "udp": NetworkIO.Transport.UDP, + "tls": NetworkIO.Transport.TLS, + "proxied-tcp": NetworkIO.Transport.PROXIED_TCP, + "proxied-tls": NetworkIO.Transport.PROXIED_TLS, + "proxied-tls-passthrough": NetworkIO.Transport.PROXIED_TLS_PASSTHROUGH, + } + transport = transport.replace("_", "-").replace("'", "").replace('"', "").lower() + + return mapping[transport] + + +def create_io(options): + ip = options["ip"] if "ip" in options else "localhost" + transport = options["transport"] if "transport" in options else "tcp" + + return NetworkIO(ip, options["port"], map_transport(transport)) + + +class SyslogSource(SourceDriver): + def __init__(self, **options): + self.io = create_io(options) + + self.driver_name = "syslog" + super(SyslogSource, self).__init__(options=options) + + def write_log(self, formatted_content, rate=None): + self.io.write(formatted_content, rate=rate) diff --git a/tests/light/src/syslog_ng_config/syslog_ng_config.py b/tests/light/src/syslog_ng_config/syslog_ng_config.py index b5e8c383cd..b6be6046e0 100644 --- a/tests/light/src/syslog_ng_config/syslog_ng_config.py +++ b/tests/light/src/syslog_ng_config/syslog_ng_config.py @@ -48,6 +48,7 @@ from src.syslog_ng_config.statements.sources.file_source import FileSource from src.syslog_ng_config.statements.sources.internal_source import InternalSource from src.syslog_ng_config.statements.sources.network_source import NetworkSource +from src.syslog_ng_config.statements.sources.syslog_source import SyslogSource from src.syslog_ng_config.statements.template.template import Template from src.syslog_ng_config.statements.template.template import TemplateFunction from src.syslog_ng_ctl.prometheus_stats_handler import PrometheusStatsHandler @@ -120,6 +121,9 @@ def create_internal_source(self, **options): def create_network_source(self, **options): return NetworkSource(**options) + def create_syslog_source(self, **options): + return SyslogSource(**options) + def create_rewrite_set(self, template, **options): return Set(template, **options) From 1774231332417e19b62c5268aee01c3cd0b5c169 Mon Sep 17 00:00:00 2001 From: Hofi Date: Wed, 6 Dec 2023 16:00:57 +0100 Subject: [PATCH 15/15] light: Added proxied network() and syslog() source tested that all use loggen with proper `proxied` switches Signed-off-by: Hofi --- tests/light/functional_tests/Makefile.am | 4 +- .../proxyprotocol/test_pp_network.py | 121 +++++++++++++++++ .../proxyprotocol/test_pp_tls.py | 53 -------- .../proxyprotocol/test_pp_tls_passthrough.py | 69 ---------- .../test_pp_tls_with_passphrase.py | 55 -------- .../proxyprotocol/test_pp_syslog.py | 123 ++++++++++++++++++ 6 files changed, 245 insertions(+), 180 deletions(-) create mode 100644 tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_network.py delete mode 100644 tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls.py delete mode 100644 tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_passthrough.py delete mode 100644 tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_with_passphrase.py create mode 100644 tests/light/functional_tests/source_drivers/syslog_source/proxyprotocol/test_pp_syslog.py diff --git a/tests/light/functional_tests/Makefile.am b/tests/light/functional_tests/Makefile.am index b99e05a01d..c7c55b0eb9 100644 --- a/tests/light/functional_tests/Makefile.am +++ b/tests/light/functional_tests/Makefile.am @@ -52,9 +52,7 @@ EXTRA_DIST += \ tests/light/functional_tests/source_drivers/internal_source/test_internal_acceptance.py \ tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_acceptance.py \ tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_reload.py \ - tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_passthrough.py \ - tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls.py \ - tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_with_passphrase.py \ + tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_network.py \ tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_with_multiple_clients.py \ tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_with_simple_tcp_connection.py \ tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_with_syslog_proto.py \ diff --git a/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_network.py b/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_network.py new file mode 100644 index 0000000000..2ffbae7d91 --- /dev/null +++ b/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_network.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +############################################################################# +# Copyright (c) 2020 One Identity +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As an additional exemption you are allowed to compile & link against the +# OpenSSL libraries as published by the OpenSSL project. See the file +# COPYING for details. +# +############################################################################# +from pathlib import Path + +from src.common.blocking import wait_until_true +from src.common.file import copy_shared_file +from src.common.file import File +from src.common.random_id import get_unique_id + + +def _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, transport, input_messages, number_of_messages, expected_messages, template=None, password=None): + if password: + server_key_path = copy_shared_file(testcase_parameters, "server-protected-asdfg.key") + server_cert_path = copy_shared_file(testcase_parameters, "server-protected-asdfg.crt") + else: + server_key_path = copy_shared_file(testcase_parameters, "server.key") + server_cert_path = copy_shared_file(testcase_parameters, "server.crt") + output_file = "output.log" + use_ssl = True if "tls" in transport else None + use_inet = None if use_ssl else True + use_passthrough = True if "passthrough" in transport else None + + if (use_ssl): + network_source = config.create_network_source( + ip="localhost", + port=port_allocator(), + transport=transport, + flags="no-parse", + tls={ + "key-file": server_key_path, + "cert-file": server_cert_path, + "peer-verify": '"optional-untrusted"', + }, + ) + else: + network_source = config.create_network_source( + ip="localhost", + port=port_allocator(), + transport=transport, + flags="no-parse", + ) + + if (template): + file_destination = config.create_file_destination(file_name=output_file, template=template) + else: + file_destination = config.create_file_destination(file_name=output_file) + config.create_logpath(statements=[network_source, file_destination]) + + syslog_ng.start(config) + if password is not None: + syslog_ng_ctl.credentials_add(credential=server_key_path, secret=password) + + loggen_input_file_path = Path("loggen_input_{}.txt".format(get_unique_id())) + loggen_input_file = File(loggen_input_file_path) + loggen_input_file.write_content_and_close(input_messages) + loggen.start( + network_source.options["ip"], network_source.options["port"], number=number_of_messages, + inet=use_inet, + use_ssl=use_ssl, + read_file=str(loggen_input_file_path), + dont_parse=True, + proxied=1, + proxied_tls_passthrough=use_passthrough, + proxy_src_ip="1.1.1.1", proxy_dst_ip="2.2.2.2", proxy_src_port="3333", proxy_dst_port="4444", + ) + # seems proxy header is counted in get_sent_message_count(), so we need '-1' + wait_until_true(lambda: loggen.get_sent_message_count() == number_of_messages - 1) + + assert file_destination.read_log() == expected_messages + + +def test_pp_network_tcp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "message 0\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tcp"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE) + + +def test_pp_network_tls(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "message 0\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tls"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE) + + +def test_pp_network_tls_with_passphrase(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "message 0\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tls"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE, password="asdfg") + + +def test_pp_network_tls_passthrough(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "message 0\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tls-passthrough"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE) diff --git a/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls.py b/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls.py deleted file mode 100644 index b2f777ef9d..0000000000 --- a/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -############################################################################# -# Copyright (c) 2020 One Identity -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 as published -# by the Free Software Foundation, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -# As an additional exemption you are allowed to compile & link against the -# OpenSSL libraries as published by the OpenSSL project. See the file -# COPYING for details. -# -############################################################################# -from src.common.file import copy_shared_file - -TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' -INPUT_MESSAGES = "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n" \ - "message 0" -EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 message 0\n" - - -def test_pp_tls(config, syslog_ng, port_allocator, loggen, testcase_parameters): - server_key_path = copy_shared_file(testcase_parameters, "server.key") - server_cert_path = copy_shared_file(testcase_parameters, "server.crt") - - network_source = config.create_network_source( - ip="localhost", - port=port_allocator(), - transport='"proxied-tls"', - flags="no-parse", - tls={ - "key-file": server_key_path, - "cert-file": server_cert_path, - "peer-verify": '"optional-untrusted"', - }, - ) - file_destination = config.create_file_destination(file_name="output.log", template=TEMPLATE) - config.create_logpath(statements=[network_source, file_destination]) - - syslog_ng.start(config) - - network_source.write_log(INPUT_MESSAGES) - - assert file_destination.read_log() == EXPECTED_MESSAGES diff --git a/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_passthrough.py b/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_passthrough.py deleted file mode 100644 index d0ed88c89c..0000000000 --- a/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_passthrough.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -############################################################################# -# Copyright (c) 2020 One Identity -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 as published -# by the Free Software Foundation, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -# As an additional exemption you are allowed to compile & link against the -# OpenSSL libraries as published by the OpenSSL project. See the file -# COPYING for details. -# -############################################################################# -from pathlib import Path - -from src.common.blocking import wait_until_true -from src.common.file import copy_shared_file -from src.common.file import File -from src.common.random_id import get_unique_id - -TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' -INPUT_MESSAGES = "message 0\n\n" -EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 message 0\n" -NUMBER_OF_MESSAGES = 1 - - -def test_pp_tls_passthrough(config, syslog_ng, port_allocator, loggen, testcase_parameters): - server_key_path = copy_shared_file(testcase_parameters, "server.key") - server_cert_path = copy_shared_file(testcase_parameters, "server.crt") - - network_source = config.create_network_source( - ip="localhost", - port=port_allocator(), - transport='"proxied-tls-passthrough"', - flags="no-parse", - tls={ - "key-file": server_key_path, - "cert-file": server_cert_path, - "peer-verify": '"optional-untrusted"', - }, - ) - - file_destination = config.create_file_destination(file_name="output.log", template=TEMPLATE) - config.create_logpath(statements=[network_source, file_destination]) - - syslog_ng.start(config) - - loggen_input_file_path = Path("loggen_input_{}.txt".format(get_unique_id())) - loggen_input_file = File(loggen_input_file_path) - loggen_input_file.write_content_and_close(INPUT_MESSAGES) - - loggen.start( - network_source.options["ip"], network_source.options["port"], number=NUMBER_OF_MESSAGES, - use_ssl=True, proxied_tls_passthrough=True, read_file=str(loggen_input_file_path), - dont_parse=True, proxy_src_ip="1.1.1.1", proxy_dst_ip="2.2.2.2", proxy_src_port="3333", - proxy_dst_port="4444", - ) - - wait_until_true(lambda: loggen.get_sent_message_count() == NUMBER_OF_MESSAGES) - assert file_destination.read_log() == EXPECTED_MESSAGES diff --git a/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_with_passphrase.py b/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_with_passphrase.py deleted file mode 100644 index 280c4c02ba..0000000000 --- a/tests/light/functional_tests/source_drivers/network_source/proxyprotocol/test_pp_tls_with_passphrase.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -############################################################################# -# Copyright (c) 2020 One Identity -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 as published -# by the Free Software Foundation, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -# As an additional exemption you are allowed to compile & link against the -# OpenSSL libraries as published by the OpenSSL project. See the file -# COPYING for details. -# -############################################################################# -from src.common.file import copy_shared_file - -TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' -INPUT_MESSAGES = "PROXY TCP4 1.1.1.1 2.2.2.2 3333 4444\r\n" \ - "message 0" -EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 message 0\n" - - -def test_pp_tls_with_passphrase(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): - server_key_path = copy_shared_file(testcase_parameters, "server-protected-asdfg.key") - server_cert_path = copy_shared_file(testcase_parameters, "server-protected-asdfg.crt") - - network_source = config.create_network_source( - ip="localhost", - port=port_allocator(), - transport='"proxied-tls"', - flags="no-parse", - tls={ - "key-file": server_key_path, - "cert-file": server_cert_path, - "peer-verify": '"optional-untrusted"', - }, - ) - file_destination = config.create_file_destination(file_name="output.log", template=TEMPLATE) - config.create_logpath(statements=[network_source, file_destination]) - - syslog_ng.start(config) - - syslog_ng_ctl.credentials_add(credential=server_key_path, secret="asdfg") - - network_source.write_log(INPUT_MESSAGES) - - assert file_destination.read_log() == EXPECTED_MESSAGES diff --git a/tests/light/functional_tests/source_drivers/syslog_source/proxyprotocol/test_pp_syslog.py b/tests/light/functional_tests/source_drivers/syslog_source/proxyprotocol/test_pp_syslog.py new file mode 100644 index 0000000000..c8cffb71e1 --- /dev/null +++ b/tests/light/functional_tests/source_drivers/syslog_source/proxyprotocol/test_pp_syslog.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +############################################################################# +# Copyright (c) 2020 One Identity +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As an additional exemption you are allowed to compile & link against the +# OpenSSL libraries as published by the OpenSSL project. See the file +# COPYING for details. +# +############################################################################# +from pathlib import Path + +from src.common.blocking import wait_until_true +from src.common.file import copy_shared_file +from src.common.file import File +from src.common.random_id import get_unique_id + + +def _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, transport, input_messages, number_of_messages, expected_messages, template=None, password=None): + if password: + server_key_path = copy_shared_file(testcase_parameters, "server-protected-asdfg.key") + server_cert_path = copy_shared_file(testcase_parameters, "server-protected-asdfg.crt") + else: + server_key_path = copy_shared_file(testcase_parameters, "server.key") + server_cert_path = copy_shared_file(testcase_parameters, "server.crt") + output_file = "output.log" + use_ssl = True if "tls" in transport else None + use_inet = None if use_ssl else True + use_passthrough = True if "passthrough" in transport else None + + if (use_ssl): + syslog_source = config.create_syslog_source( + ip="localhost", + port=port_allocator(), + transport=transport, + flags="no-parse", + tls={ + "key-file": server_key_path, + "cert-file": server_cert_path, + "peer-verify": '"optional-untrusted"', + }, + ) + else: + syslog_source = config.create_syslog_source( + ip="localhost", + port=port_allocator(), + transport=transport, + flags="no-parse", + ) + if template: + file_destination = config.create_file_destination(file_name=output_file, template=template) + else: + file_destination = config.create_file_destination(file_name=output_file) + config.create_logpath(statements=[syslog_source, file_destination]) + + syslog_ng.start(config) + if password is not None: + syslog_ng_ctl.credentials_add(credential=server_key_path, secret=password) + + loggen_input_file_path = Path("loggen_input_{}.txt".format(get_unique_id())) + loggen_input_file = File(loggen_input_file_path) + loggen_input_file.write_content_and_close(input_messages) + loggen.start( + syslog_source.options["ip"], syslog_source.options["port"], + number=number_of_messages, + dont_parse=True, + read_file=str(loggen_input_file_path), + syslog_proto=True, + inet=use_inet, + use_ssl=use_ssl, + proxied=1, + proxied_tls_passthrough=use_passthrough, + proxy_src_ip="1.1.1.1", proxy_dst_ip="2.2.2.2", proxy_src_port="3333", proxy_dst_port="4444", + ) + + # seems proxy header is counted in get_sent_message_count(), so we need '-1' + wait_until_true(lambda: loggen.get_sent_message_count() == number_of_messages - 1) + + assert file_destination.read_log() == expected_messages + + +def test_pp_syslog_tcp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "53 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\r\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tcp"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE) + + +def test_pp_syslog_tls(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "53 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\r\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tls"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE) + + +def test_pp_syslog_tls_with_passphrase(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "53 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\r\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tls"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE, password="asdfg") + + +def test_pp_syslog_tls_passthrough(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters): + TEMPLATE = r'"${PROXIED_SRCIP} ${PROXIED_DSTIP} ${PROXIED_SRCPORT} ${PROXIED_DSTPORT} ${PROXIED_IP_VERSION} ${MESSAGE}\n"' + INPUT_MESSAGES = "53 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\r\n" + EXPECTED_MESSAGES = "1.1.1.1 2.2.2.2 3333 4444 4 <2>Oct 11 22:14:15 myhostname sshd[1234]: message 0\n" + NUMBER_OF_MESSAGES = 2 + _test_pp(config, syslog_ng, syslog_ng_ctl, port_allocator, loggen, testcase_parameters, '"proxied-tls-passthrough"', INPUT_MESSAGES, NUMBER_OF_MESSAGES, EXPECTED_MESSAGES, TEMPLATE)