($INBOX_DIR/description missing)
 help / color / mirror / Atom feed
From: Ram Subramanian <ram.subramanian@getcruise.com>
To: ell@lists.linux.dev
Cc: Ram Subramanian <ram.subramanian@getcruise.com>,
	Ramon Ribeiro <rhpr@cesar.org.br>
Subject: [PATCH 1/2] dbus: add dbus-over-tcp support
Date: Mon, 13 May 2024 10:58:25 -0700	[thread overview]
Message-ID: <20240513175826.2363352-1-ram.subramanian@getcruise.com> (raw)

l_dbus_new() will now accept tcp endpoints, however it will only accept
a numeric address for 'host'; it will not resolve hostnames. This is so
we can avoid a potential long, blocking call to getaddrinfo().

The connect() call to the host is also non-blocking. This means that
auth will not happen until you start the event loop (with a call to
l_main_run() et. al.).

Co-authored-by: Ramon Ribeiro <rhpr@cesar.org.br>
---
 ell/dbus.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 111 insertions(+)

diff --git a/ell/dbus.c b/ell/dbus.c
index d610532..22deaba 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -15,8 +15,10 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <netdb.h>
 #include <errno.h>
 
 #include "util.h"
@@ -1133,6 +1135,112 @@ static struct l_dbus *setup_unix(char *params)
 	return setup_dbus1(fd, guid);
 }
 
+static bool setup_tcp_cb(struct l_io *io, void *user_data)
+{
+	static const unsigned char creds = 0x00;
+	struct l_dbus *dbus = user_data;
+	struct l_dbus_classic *classic;
+	ssize_t written;
+	int fd = l_io_get_fd(io);
+
+	/* Send special credentials-passing nul byte */
+	written = L_TFR(send(fd, &creds, 1, 0));
+	if (written < 1) {
+		l_util_debug(dbus->debug_handler, dbus->debug_handler,
+						"error writing NUL byte");
+		close(fd);
+		return false;
+	}
+
+	dbus->driver = &classic_ops;
+	dbus->negotiate_unix_fd = false;
+	dbus->support_unix_fd = false;
+
+	classic = l_container_of(dbus, struct l_dbus_classic, super);
+	classic->match_strings = l_hashmap_new();
+	classic->auth_command = l_strdup("AUTH ANONYMOUS\r\n");
+	classic->auth_state = WAITING_FOR_OK;
+
+	l_io_set_read_handler(dbus->io, auth_read_handler, dbus, NULL);
+	l_io_set_write_handler(dbus->io, auth_write_handler, dbus, NULL);
+
+	return auth_write_handler(dbus->io, dbus);
+}
+
+static struct l_dbus *setup_tcp(char *params)
+{
+	char *host = NULL;
+	char *port = NULL;
+	char *family = NULL;
+	struct addrinfo hints = { 0 };
+	struct addrinfo *res;
+	struct addrinfo *iter;
+	struct l_dbus *dbus;
+
+	while (params) {
+		char *key = strsep(&params, ",");
+		char *value;
+
+		value = strchr(key, '=');
+		if (!value)
+			continue;
+
+		*value++ = '\0';
+
+		if (!strcmp(key, "host"))
+			host = value;
+		else if (!strcmp(key, "port"))
+			port = value;
+		else if (!strcmp(key, "family"))
+			family = value;
+	}
+
+	if (!host || !port)
+		return NULL;
+
+	if (!family)
+		hints.ai_family = AF_UNSPEC;
+	else if (!strcmp(family, "ipv4"))
+		hints.ai_family = AF_INET;
+	else if (!strcmp(family, "ipv6"))
+		hints.ai_family = AF_INET6;
+	else
+		return NULL;
+
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+	hints.ai_protocol = IPPROTO_TCP;
+
+	if (getaddrinfo(host, port, &hints, &res) != 0)
+		return NULL;
+
+	for (iter = res; iter; iter = iter->ai_next) {
+		int fd;
+		struct l_dbus_classic *classic;
+
+		fd = socket(iter->ai_family, iter->ai_socktype | SOCK_NONBLOCK,
+					iter->ai_protocol);
+		if (fd < 0)
+			continue;
+
+		if (connect(fd, iter->ai_addr, iter->ai_addrlen) < 0) {
+			if (errno != EINPROGRESS) {
+				close(fd);
+				continue;
+			}
+		}
+
+		classic = l_new(struct l_dbus_classic, 1);
+		dbus = &classic->super;
+		dbus_init(dbus, fd);
+		l_io_set_write_handler(dbus->io, setup_tcp_cb, dbus, NULL);
+		break;
+	}
+
+	freeaddrinfo(res);
+	return dbus;
+}
+
 static struct l_dbus *setup_address(const char *address)
 {
 	struct l_dbus *dbus = NULL;
@@ -1155,6 +1263,9 @@ static struct l_dbus *setup_address(const char *address)
 			/* Function will modify params string */
 			dbus = setup_unix(params);
 			break;
+		} else if (!strcmp(transport, "tcp")) {
+			dbus = setup_tcp(params);
+			break;
 		}
 	}
 
-- 
2.43.2


-- 


*Confidentiality Note:* We care about protecting our proprietary 
information, confidential material, and trade secrets. This message may 
contain some or all of those things. Cruise will suffer material harm if 
anyone other than the intended recipient disseminates or takes any action 
based on this message. If you have received this message (including any 
attachments) in error, please delete it immediately and notify the sender 
promptly.

             reply	other threads:[~2024-05-13 17:58 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-13 17:58 Ram Subramanian [this message]
2024-05-13 17:58 ` [PATCH 2/2] unit: add testing for dbus-over-tcp Ram Subramanian
2024-05-16 19:36   ` Denis Kenzior
2024-05-16 19:33 ` [PATCH 1/2] dbus: add dbus-over-tcp support Denis Kenzior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240513175826.2363352-1-ram.subramanian@getcruise.com \
    --to=ram.subramanian@getcruise.com \
    --cc=ell@lists.linux.dev \
    --cc=rhpr@cesar.org.br \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).