public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH liburing v2 0/4] liburing: getsockname support
@ 2025-11-20 22:13 Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 1/4] liburing: Introduce getsockname operation Gabriel Krisman Bertazi
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Gabriel Krisman Bertazi @ 2025-11-20 22:13 UTC (permalink / raw)
  Cc: Gabriel Krisman Bertazi, io-uring, csander

This is the library counterpart for the kernel support.  Also available
at:

https://github.com/krisman/liburing -b socket

---
To:  Jens Axboe <axboe@kernel.dk>
CC: io-uring@vger.kernel.org
CC: csander@purestorage.com

Gabriel Krisman Bertazi (4):
  liburing: Introduce getsockname operation
  test/bind-listen.t: Use ephemeral port
  bind-listen.t: Add tests for getsockname
  man/io_uring_prep_getsockname.3: Add man page

 man/io_uring_prep_getsockname.3 |  76 ++++++++++++++++++
 src/include/liburing.h          |  13 +++
 src/include/liburing/io_uring.h |   1 +
 test/bind-listen.c              | 137 +++++++++++++++++++++++++++++---
 4 files changed, 215 insertions(+), 12 deletions(-)
 create mode 100644 man/io_uring_prep_getsockname.3

-- 
2.51.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH liburing v2 1/4] liburing: Introduce getsockname operation
  2025-11-20 22:13 [PATCH liburing v2 0/4] liburing: getsockname support Gabriel Krisman Bertazi
@ 2025-11-20 22:13 ` Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 2/4] test/bind-listen.t: Use ephemeral port Gabriel Krisman Bertazi
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Gabriel Krisman Bertazi @ 2025-11-20 22:13 UTC (permalink / raw)
  Cc: Gabriel Krisman Bertazi, io-uring, csander

This implements the functionality of getsockname(2) and getpeername(2)
under a single operation.

Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
 src/include/liburing.h          | 13 +++++++++++++
 src/include/liburing/io_uring.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/src/include/liburing.h b/src/include/liburing.h
index 83819eb7..1626f3bb 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -1572,6 +1572,19 @@ IOURINGINLINE void io_uring_prep_cmd_sock(struct io_uring_sqe *sqe,
 	sqe->level = level;
 }
 
+IOURINGINLINE void io_uring_prep_cmd_getsockname(struct io_uring_sqe *sqe,
+						 int fd, struct sockaddr *sockaddr,
+						 socklen_t *sockaddr_len,
+						 int peer)
+	LIBURING_NOEXCEPT
+{
+	io_uring_prep_uring_cmd(sqe, SOCKET_URING_OP_GETSOCKNAME, fd);
+
+	sqe->addr = (uintptr_t) sockaddr;
+	sqe->addr3 = (unsigned long) (uintptr_t) sockaddr_len;
+	sqe->optlen = peer;
+}
+
 IOURINGINLINE void io_uring_prep_waitid(struct io_uring_sqe *sqe,
 					idtype_t idtype,
 					id_t id,
diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index a54e5b42..8e8b8e6a 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -966,6 +966,7 @@ enum io_uring_socket_op {
 	SOCKET_URING_OP_GETSOCKOPT,
 	SOCKET_URING_OP_SETSOCKOPT,
 	SOCKET_URING_OP_TX_TIMESTAMP,
+	SOCKET_URING_OP_GETSOCKNAME,
 };
 
 /*
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH liburing v2 2/4] test/bind-listen.t: Use ephemeral port
  2025-11-20 22:13 [PATCH liburing v2 0/4] liburing: getsockname support Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 1/4] liburing: Introduce getsockname operation Gabriel Krisman Bertazi
@ 2025-11-20 22:13 ` Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 3/4] bind-listen.t: Add tests for getsockname Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 4/4] man/io_uring_prep_getsockname.3: Add man page Gabriel Krisman Bertazi
  3 siblings, 0 replies; 6+ messages in thread
From: Gabriel Krisman Bertazi @ 2025-11-20 22:13 UTC (permalink / raw)
  Cc: Gabriel Krisman Bertazi, io-uring, csander

This test fails if port 8000 is already in use by something else.  Now
that we have getsockname with direct file descriptors, use an ephemeral
port instead.

Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
 test/bind-listen.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/test/bind-listen.c b/test/bind-listen.c
index 6f80f177..7c229a17 100644
--- a/test/bind-listen.c
+++ b/test/bind-listen.c
@@ -22,7 +22,6 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
 }
 
 static const char *magic = "Hello World!";
-static int use_port = 8000;
 
 enum {
 	SRV_INDEX = 0,
@@ -74,18 +73,19 @@ static int connect_client(struct io_uring *ring, unsigned short peer_port)
 	return T_SETUP_OK;
 }
 
-static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
+static int setup_srv(struct io_uring *ring)
 {
+	struct sockaddr_in server_addr;
 	struct io_uring_sqe *sqe;
 	struct io_uring_cqe *cqe;
 	struct __kernel_timespec ts;
 	int ret, val, submitted;
 	unsigned head;
 
-	memset(server_addr, 0, sizeof(struct sockaddr_in));
-	server_addr->sin_family = AF_INET;
-	server_addr->sin_port = htons(use_port++);
-	server_addr->sin_addr.s_addr = htons(INADDR_ANY);
+	memset(&server_addr, 0, sizeof(struct sockaddr_in));
+	server_addr.sin_family = AF_INET;
+	server_addr.sin_port = htons(0);
+	server_addr.sin_addr.s_addr = htons(INADDR_ANY);
 
 	sqe = io_uring_get_sqe(ring);
 	io_uring_prep_socket_direct(sqe, AF_INET, SOCK_STREAM, 0, SRV_INDEX, 0);
@@ -98,7 +98,7 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
 	sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
 
 	sqe = io_uring_get_sqe(ring);
-	io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) server_addr,
+	io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) &server_addr,
 			   sizeof(struct sockaddr_in));
 	sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
 
@@ -132,7 +132,8 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
 
 static int test_good_server(unsigned int ring_flags)
 {
-	struct sockaddr_in server_addr;
+	struct sockaddr_in saddr = {};
+	socklen_t saddr_len = sizeof(saddr);
 	struct __kernel_timespec ts;
 	struct io_uring_sqe *sqe;
 	struct io_uring_cqe *cqe;
@@ -155,13 +156,25 @@ static int test_good_server(unsigned int ring_flags)
 		return T_SETUP_SKIP;
 	}
 
-	ret = setup_srv(&ring, &server_addr);
+	ret = setup_srv(&ring);
 	if (ret != T_SETUP_OK) {
 		fprintf(stderr, "srv startup failed.\n");
 		return T_EXIT_FAIL;
 	}
 
-	if (connect_client(&ring, server_addr.sin_port) != T_SETUP_OK) {
+	sqe = io_uring_get_sqe(&ring);
+	io_uring_prep_cmd_getsockname(sqe, SRV_INDEX, (struct sockaddr*)&saddr,
+				      &saddr_len, 0);
+	sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
+	io_uring_submit(&ring);
+	io_uring_wait_cqe(&ring, &cqe);
+	if (cqe->res < 0) {
+		fprintf(stderr, "getsockname server failed. %d\n", cqe->res);
+		return T_EXIT_FAIL;
+	}
+	io_uring_cqe_seen(&ring, cqe);
+
+	if (connect_client(&ring, saddr.sin_port) != T_SETUP_OK) {
 		fprintf(stderr, "cli startup failed.\n");
 		return T_SETUP_SKIP;
 	}
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH liburing v2 3/4] bind-listen.t: Add tests for getsockname
  2025-11-20 22:13 [PATCH liburing v2 0/4] liburing: getsockname support Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 1/4] liburing: Introduce getsockname operation Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 2/4] test/bind-listen.t: Use ephemeral port Gabriel Krisman Bertazi
@ 2025-11-20 22:13 ` Gabriel Krisman Bertazi
  2025-11-20 22:13 ` [PATCH liburing v2 4/4] man/io_uring_prep_getsockname.3: Add man page Gabriel Krisman Bertazi
  3 siblings, 0 replies; 6+ messages in thread
From: Gabriel Krisman Bertazi @ 2025-11-20 22:13 UTC (permalink / raw)
  Cc: Gabriel Krisman Bertazi, io-uring, csander

Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
 test/bind-listen.c | 104 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 102 insertions(+), 2 deletions(-)

diff --git a/test/bind-listen.c b/test/bind-listen.c
index 7c229a17..22dd9a32 100644
--- a/test/bind-listen.c
+++ b/test/bind-listen.c
@@ -138,7 +138,7 @@ static int test_good_server(unsigned int ring_flags)
 	struct io_uring_sqe *sqe;
 	struct io_uring_cqe *cqe;
 	struct io_uring ring;
-	int ret;
+	int ret, port;
 	int fds[3];
 	char buf[1024];
 
@@ -179,7 +179,7 @@ static int test_good_server(unsigned int ring_flags)
 		return T_SETUP_SKIP;
 	}
 
-	/* Wait for a request */
+	/* Wait for a connection */
 	sqe = io_uring_get_sqe(&ring);
 	io_uring_prep_accept_direct(sqe, SRV_INDEX, NULL, NULL, 0, CONN_INDEX);
 	sqe->flags |= IOSQE_FIXED_FILE;
@@ -192,6 +192,30 @@ static int test_good_server(unsigned int ring_flags)
 	}
 	io_uring_cqe_seen(&ring, cqe);
 
+	/* Test that getsockname on the peer (getpeername) yields a
+         * sane result.
+	 */
+	sqe = io_uring_get_sqe(&ring);
+	saddr_len = sizeof(saddr);
+	port = saddr.sin_port;
+	io_uring_prep_cmd_getsockname(sqe, CONN_INDEX, (struct sockaddr*)&saddr,
+				      &saddr_len, 1);
+	sqe->flags |= IOSQE_FIXED_FILE;
+	io_uring_submit(&ring);
+	io_uring_wait_cqe(&ring, &cqe);
+	if (cqe->res < 0) {
+		fprintf(stderr, "getsockname client failed. %d\n", cqe->res);
+		return T_EXIT_FAIL;
+	} else {
+		if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) ||
+		    saddr.sin_port != port) {
+			fprintf(stderr, "getsockname peer got wrong address: %s:%d\n",
+				inet_ntoa(saddr.sin_addr), saddr.sin_port);
+			return T_EXIT_FAIL;
+		}
+	}
+	io_uring_cqe_seen(&ring, cqe);
+
 	sqe = io_uring_get_sqe(&ring);
 	io_uring_prep_recv(sqe, CONN_INDEX, buf, sizeof(buf), 0);
 	sqe->flags |= IOSQE_FIXED_FILE;
@@ -368,6 +392,77 @@ fail:
 	return ret;
 }
 
+static int test_bad_sockname(void)
+{
+	struct sockaddr_in saddr;
+	socklen_t saddr_len;
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+	struct io_uring ring;
+	int sock = -1, err;
+	int ret = T_EXIT_FAIL;
+
+	memset(&saddr, 0, sizeof(struct sockaddr_in));
+	saddr.sin_family = AF_INET;
+	saddr.sin_port = htons(8001);
+	saddr.sin_addr.s_addr = htons(INADDR_ANY);
+
+	err = t_create_ring(1, &ring, 0);
+	if (err < 0) {
+		fprintf(stderr, "queue_init: %d\n", err);
+		return T_SETUP_SKIP;
+	}
+
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	if (sock < 0) {
+		perror("socket");
+		goto fail;
+	}
+
+	err = t_bind_ephemeral_port(sock, &saddr);
+	if (err) {
+		fprintf(stderr, "bind: %s\n", strerror(-err));
+		goto fail;
+	}
+
+	/* getsockname on a !socket fd.  with getsockname(2), this would
+	 * return -ENOTSOCK, but we can't do it in an io_uring_cmd.
+	 */
+	sqe = io_uring_get_sqe(&ring);
+	saddr_len = sizeof(saddr);
+	io_uring_prep_cmd_getsockname(sqe, 1, (struct sockaddr*)&saddr, &saddr_len, 0);
+	err = io_uring_submit(&ring);
+	if (err < 0)
+		goto fail;
+	err = io_uring_wait_cqe(&ring, &cqe);
+	if (err)
+		goto fail;
+	if (cqe->res != -ENOTSUP)
+		goto fail;
+	io_uring_cqe_seen(&ring, cqe);
+
+	/* getsockname with weird parameters */
+	sqe = io_uring_get_sqe(&ring);
+	io_uring_prep_cmd_getsockname(sqe, sock, (struct sockaddr*)&saddr,
+				      &saddr_len, 3);
+	err = io_uring_submit(&ring);
+	if (err < 0)
+		goto fail;
+	err = io_uring_wait_cqe(&ring, &cqe);
+	if (err)
+		goto fail;
+	if (cqe->res != -EINVAL)
+		goto fail;
+	io_uring_cqe_seen(&ring, cqe);
+
+	ret = T_EXIT_PASS;
+fail:
+	io_uring_queue_exit(&ring);
+	if (sock != -1)
+		close(sock);
+	return ret;
+}
+
 int main(int argc, char *argv[])
 {
 	struct io_uring_probe *probe;
@@ -417,5 +512,10 @@ int main(int argc, char *argv[])
 		return T_EXIT_FAIL;
 	}
 
+	ret = test_bad_sockname();
+	if (ret) {
+		fprintf(stderr, "bad sockname failed\n");
+		return T_EXIT_FAIL;
+	}
 	return T_EXIT_PASS;
 }
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH liburing v2 4/4] man/io_uring_prep_getsockname.3: Add man page
  2025-11-20 22:13 [PATCH liburing v2 0/4] liburing: getsockname support Gabriel Krisman Bertazi
                   ` (2 preceding siblings ...)
  2025-11-20 22:13 ` [PATCH liburing v2 3/4] bind-listen.t: Add tests for getsockname Gabriel Krisman Bertazi
@ 2025-11-20 22:13 ` Gabriel Krisman Bertazi
  3 siblings, 0 replies; 6+ messages in thread
From: Gabriel Krisman Bertazi @ 2025-11-20 22:13 UTC (permalink / raw)
  Cc: Gabriel Krisman Bertazi, io-uring, csander

Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
 man/io_uring_prep_getsockname.3 | 76 +++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)
 create mode 100644 man/io_uring_prep_getsockname.3

diff --git a/man/io_uring_prep_getsockname.3 b/man/io_uring_prep_getsockname.3
new file mode 100644
index 00000000..71e65f1d
--- /dev/null
+++ b/man/io_uring_prep_getsockname.3
@@ -0,0 +1,76 @@
+.\" Copyright (C) 2024 SUSE LLC.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+.TH io_uring_prep_getsockname 3 "Oct 23, 2025" "liburing-2.11" "liburing Manual"
+.SH NAME
+io_uring_prep_getsockname \- prepare a getsockname or getpeername request
+.SH SYNOPSIS
+.nf
+.B #include <sys/socket.h>
+.B #include <liburing.h>
+.PP
+.BI "void io_uring_prep_getsockname(struct io_uring_sqe *" sqe ","
+.BI "                          int " sockfd ","
+.BI "                          struct sockaddr *" sockaddr ","
+.BI "                          socklen_t *" sockaddr_len ","
+.BI "                          int " peer ");"
+.fi
+.SH DESCRIPTION
+The
+.BR io_uring_prep_getsockname (3)
+function prepares a getsockname/getpeername request.
+The submission queue entry
+.I sqe
+is setup to fetch the locally bound address or peer address of the socket
+file descriptor pointed by
+.IR sockfd.
+The parameter
+.IR sockaddr
+points to a region of size
+.IR sockaddr_len
+where the output is written.
+.IR sockaddr_len
+is modified by the kernel to indicate how many bytes were written.
+The output address is the locally bound address if
+.IR peer
+is set to 0
+or the peer address if
+.IR peer
+is set to 1.
+
+This function prepares an async
+.BR getsockname (2)
+or
+.BR getpeername (2)
+request. See those man pages for details.
+
+.SH RETURN VALUE
+None
+.SH ERRORS
+The CQE
+.I res
+field will contain the result of the operation. See the related man page for
+details on possible values. Note that where synchronous system calls will return
+.B -1
+on failure and set
+.I errno
+to the actual error value, io_uring never uses
+.IR errno .
+Instead it returns the negated
+.I errno
+directly in the CQE
+.I res
+field.
+.BR
+Differently from the equivalent system calls, if the user attempts to
+use this operation on a non-socket file descriptor, the CQE error result
+is
+.IR ENOTSUP
+instead of
+.IR ENOSOCK.
+.SH SEE ALSO
+.BR io_uring_get_sqe (3),
+.BR io_uring_submit (3),
+.BR io_uring_prep_getsockname (2)
+.BR io_uring_prep_getpeername (2)
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH liburing v2 1/4] liburing: Introduce getsockname operation
  2025-11-25 21:27 [PATCH liburing v2 0/4] liburing: getsockname support Gabriel Krisman Bertazi
@ 2025-11-25 21:27 ` Gabriel Krisman Bertazi
  0 siblings, 0 replies; 6+ messages in thread
From: Gabriel Krisman Bertazi @ 2025-11-25 21:27 UTC (permalink / raw)
  To: axboe; +Cc: io-uring, Gabriel Krisman Bertazi, csander

This implements the functionality of getsockname(2) and getpeername(2)
under a single operation.

Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
 src/include/liburing.h          | 13 +++++++++++++
 src/include/liburing/io_uring.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/src/include/liburing.h b/src/include/liburing.h
index 83819eb7..1626f3bb 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -1572,6 +1572,19 @@ IOURINGINLINE void io_uring_prep_cmd_sock(struct io_uring_sqe *sqe,
 	sqe->level = level;
 }
 
+IOURINGINLINE void io_uring_prep_cmd_getsockname(struct io_uring_sqe *sqe,
+						 int fd, struct sockaddr *sockaddr,
+						 socklen_t *sockaddr_len,
+						 int peer)
+	LIBURING_NOEXCEPT
+{
+	io_uring_prep_uring_cmd(sqe, SOCKET_URING_OP_GETSOCKNAME, fd);
+
+	sqe->addr = (uintptr_t) sockaddr;
+	sqe->addr3 = (unsigned long) (uintptr_t) sockaddr_len;
+	sqe->optlen = peer;
+}
+
 IOURINGINLINE void io_uring_prep_waitid(struct io_uring_sqe *sqe,
 					idtype_t idtype,
 					id_t id,
diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index a54e5b42..8e8b8e6a 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -966,6 +966,7 @@ enum io_uring_socket_op {
 	SOCKET_URING_OP_GETSOCKOPT,
 	SOCKET_URING_OP_SETSOCKOPT,
 	SOCKET_URING_OP_TX_TIMESTAMP,
+	SOCKET_URING_OP_GETSOCKNAME,
 };
 
 /*
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-11-25 21:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-20 22:13 [PATCH liburing v2 0/4] liburing: getsockname support Gabriel Krisman Bertazi
2025-11-20 22:13 ` [PATCH liburing v2 1/4] liburing: Introduce getsockname operation Gabriel Krisman Bertazi
2025-11-20 22:13 ` [PATCH liburing v2 2/4] test/bind-listen.t: Use ephemeral port Gabriel Krisman Bertazi
2025-11-20 22:13 ` [PATCH liburing v2 3/4] bind-listen.t: Add tests for getsockname Gabriel Krisman Bertazi
2025-11-20 22:13 ` [PATCH liburing v2 4/4] man/io_uring_prep_getsockname.3: Add man page Gabriel Krisman Bertazi
  -- strict thread matches above, loose matches on Subject: below --
2025-11-25 21:27 [PATCH liburing v2 0/4] liburing: getsockname support Gabriel Krisman Bertazi
2025-11-25 21:27 ` [PATCH liburing v2 1/4] liburing: Introduce getsockname operation Gabriel Krisman Bertazi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox