| // SPDX-License-Identifier: GPL-2.0 |
| |
| #define _GNU_SOURCE |
| #include <sched.h> |
| |
| #include <stddef.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| |
| #include "../../kselftest_harness.h" |
| |
| FIXTURE(unix_connect) |
| { |
| int server, client; |
| int family; |
| }; |
| |
| FIXTURE_VARIANT(unix_connect) |
| { |
| int type; |
| char sun_path[8]; |
| int len; |
| int flags; |
| int err; |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, stream_pathname) |
| { |
| .type = SOCK_STREAM, |
| .sun_path = "test", |
| .len = 4 + 1, |
| .flags = 0, |
| .err = 0, |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, stream_abstract) |
| { |
| .type = SOCK_STREAM, |
| .sun_path = "\0test", |
| .len = 5, |
| .flags = 0, |
| .err = 0, |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, stream_pathname_netns) |
| { |
| .type = SOCK_STREAM, |
| .sun_path = "test", |
| .len = 4 + 1, |
| .flags = CLONE_NEWNET, |
| .err = 0, |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, stream_abstract_netns) |
| { |
| .type = SOCK_STREAM, |
| .sun_path = "\0test", |
| .len = 5, |
| .flags = CLONE_NEWNET, |
| .err = ECONNREFUSED, |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, dgram_pathname) |
| { |
| .type = SOCK_DGRAM, |
| .sun_path = "test", |
| .len = 4 + 1, |
| .flags = 0, |
| .err = 0, |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, dgram_abstract) |
| { |
| .type = SOCK_DGRAM, |
| .sun_path = "\0test", |
| .len = 5, |
| .flags = 0, |
| .err = 0, |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, dgram_pathname_netns) |
| { |
| .type = SOCK_DGRAM, |
| .sun_path = "test", |
| .len = 4 + 1, |
| .flags = CLONE_NEWNET, |
| .err = 0, |
| }; |
| |
| FIXTURE_VARIANT_ADD(unix_connect, dgram_abstract_netns) |
| { |
| .type = SOCK_DGRAM, |
| .sun_path = "\0test", |
| .len = 5, |
| .flags = CLONE_NEWNET, |
| .err = ECONNREFUSED, |
| }; |
| |
| FIXTURE_SETUP(unix_connect) |
| { |
| self->family = AF_UNIX; |
| } |
| |
| FIXTURE_TEARDOWN(unix_connect) |
| { |
| close(self->server); |
| close(self->client); |
| |
| if (variant->sun_path[0]) |
| remove("test"); |
| } |
| |
| TEST_F(unix_connect, test) |
| { |
| socklen_t addrlen; |
| struct sockaddr_un addr = { |
| .sun_family = self->family, |
| }; |
| int err; |
| |
| self->server = socket(self->family, variant->type, 0); |
| ASSERT_NE(-1, self->server); |
| |
| addrlen = offsetof(struct sockaddr_un, sun_path) + variant->len; |
| memcpy(&addr.sun_path, variant->sun_path, variant->len); |
| |
| err = bind(self->server, (struct sockaddr *)&addr, addrlen); |
| ASSERT_EQ(0, err); |
| |
| if (variant->type == SOCK_STREAM) { |
| err = listen(self->server, 32); |
| ASSERT_EQ(0, err); |
| } |
| |
| err = unshare(variant->flags); |
| ASSERT_EQ(0, err); |
| |
| self->client = socket(self->family, variant->type, 0); |
| ASSERT_LT(0, self->client); |
| |
| err = connect(self->client, (struct sockaddr *)&addr, addrlen); |
| ASSERT_EQ(variant->err, err == -1 ? errno : 0); |
| } |
| |
| TEST_HARNESS_MAIN |