| //===-- Unittests for bind ------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "src/__support/CPP/scope.h" |
| #include "src/arpa/inet/htonl.h" |
| #include "src/stdio/remove.h" |
| #include "src/sys/socket/bind.h" |
| #include "src/sys/socket/getsockname.h" |
| #include "src/sys/socket/socket.h" |
| #include "src/unistd/close.h" |
| #include "test/UnitTest/ErrnoCheckingTest.h" |
| #include "test/UnitTest/ErrnoSetterMatcher.h" |
| #include "test/UnitTest/Test.h" |
| #include "test/src/sys/socket/linux/socket_test_support.h" |
| |
| #include "hdr/netinet_in_macros.h" |
| #include "hdr/sys_socket_macros.h" |
| #include "hdr/types/sa_family_t.h" |
| #include "hdr/types/struct_sockaddr_in.h" |
| #include "hdr/types/struct_sockaddr_in6.h" |
| #include "hdr/types/struct_sockaddr_un.h" |
| |
| using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; |
| using LlvmLibcBindTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; |
| |
| TEST_F(LlvmLibcBindTest, BindLocalSocket) { |
| |
| const char *FILENAME = "bind_file.test"; |
| auto SOCK_PATH = libc_make_test_file_path(FILENAME); |
| |
| int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_DGRAM, 0); |
| ASSERT_GE(sock, 0); |
| ASSERT_ERRNO_SUCCESS(); |
| LIBC_NAMESPACE::cpp::scope_exit close_sock( |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0)); }); |
| |
| struct sockaddr_un my_addr; |
| ASSERT_TRUE(LIBC_NAMESPACE::testing::make_sockaddr_un(SOCK_PATH, my_addr)); |
| |
| ASSERT_THAT( |
| LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr), |
| sizeof(struct sockaddr_un)), |
| Succeeds(0)); |
| ASSERT_THAT(LIBC_NAMESPACE::remove(SOCK_PATH), Succeeds(0)); |
| } |
| |
| TEST_F(LlvmLibcBindTest, BindInetSocket) { |
| int sock = LIBC_NAMESPACE::socket(AF_INET, SOCK_DGRAM, 0); |
| ASSERT_GE(sock, 0); |
| ASSERT_ERRNO_SUCCESS(); |
| LIBC_NAMESPACE::cpp::scope_exit close_sock( |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0)); }); |
| |
| struct sockaddr_in my_addr; |
| my_addr.sin_family = AF_INET; |
| my_addr.sin_port = 0; |
| // Avoid expanding the htonl macro in overlay mode. |
| my_addr.sin_addr.s_addr = (LIBC_NAMESPACE::htonl)(INADDR_LOOPBACK); |
| |
| ASSERT_THAT( |
| LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr), |
| sizeof(struct sockaddr_in)), |
| Succeeds(0)); |
| |
| my_addr = {}; |
| socklen_t len = sizeof(my_addr); |
| ASSERT_THAT(LIBC_NAMESPACE::getsockname( |
| sock, reinterpret_cast<struct sockaddr *>(&my_addr), &len), |
| Succeeds(0)); |
| ASSERT_EQ(len, static_cast<socklen_t>(sizeof(struct sockaddr_in))); |
| EXPECT_EQ(my_addr.sin_family, static_cast<sa_family_t>(AF_INET)); |
| EXPECT_NE(my_addr.sin_port, static_cast<in_port_t>(0)); |
| EXPECT_EQ(my_addr.sin_addr.s_addr, (LIBC_NAMESPACE::htonl)(INADDR_LOOPBACK)); |
| } |
| |
| TEST_F(LlvmLibcBindTest, BindInet6Socket) { |
| int sock = LIBC_NAMESPACE::socket(AF_INET6, SOCK_DGRAM, 0); |
| ASSERT_GE(sock, 0); |
| ASSERT_ERRNO_SUCCESS(); |
| LIBC_NAMESPACE::cpp::scope_exit close_sock( |
| [&] { ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0)); }); |
| |
| struct sockaddr_in6 my_addr = {}; |
| my_addr.sin6_family = AF_INET6; |
| my_addr.sin6_addr = IN6ADDR_LOOPBACK_INIT; |
| |
| int result = |
| LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr), |
| sizeof(struct sockaddr_in6)); |
| if (result == -1) { |
| ASSERT_ERRNO_EQ(EADDRNOTAVAIL); // Ipv6 not available on this host. |
| return; |
| } |
| |
| my_addr = {}; |
| socklen_t len = sizeof(my_addr); |
| ASSERT_THAT(LIBC_NAMESPACE::getsockname( |
| sock, reinterpret_cast<struct sockaddr *>(&my_addr), &len), |
| Succeeds(0)); |
| ASSERT_EQ(len, static_cast<socklen_t>(sizeof(struct sockaddr_in6))); |
| EXPECT_EQ(my_addr.sin6_family, static_cast<sa_family_t>(AF_INET6)); |
| EXPECT_NE(my_addr.sin6_port, static_cast<in_port_t>(0)); |
| } |