Signed-off-by: Gabriel Krisman Bertazi --- 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