1/*
2 * Copyright (C) 2024 HiHope Open Source Organization.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <cerrno>
17#include <cstdio>
18#include <cstdlib>
19#include <string>
20#include <fcntl.h>
21#include <unistd.h>
22#include <vector>
23#include <arpa/inet.h>
24#include <gtest/gtest.h>
25#include <netinet/in.h>
26#include <sys/stat.h>
27#include <sys/socket.h>
28#include <sys/types.h>
29#include "securec.h"
30
31using namespace testing::ext;
32
33class HatsBindTest : public testing::Test {
34public:
35    static void SetUpTestCase();
36    static void TearDownTestCase();
37    void SetUp();
38    void TearDown();
39private:
40};
41void HatsBindTest::SetUp()
42{
43}
44void HatsBindTest::TearDown()
45{
46}
47void HatsBindTest::SetUpTestCase()
48{
49}
50void HatsBindTest::TearDownTestCase()
51{
52}
53
54static const int BAD_SOCKET_FD = -1;
55static const int TEST_PORT = 21356;
56static const char *TEST_LOCAL_IP = "127.0.0.1";
57static const char *TEST_BAD_IP = "192.168.10.3";
58
59/*
60 * @tc.number : SUB_KERNEL_SYSCALL_BIND_0100
61 * @tc.name   : BindSockfdTwice_0001
62 * @tc.desc   : bind the same socket fd twice failed, errno EINVAL.
63 * @tc.size   : MediumTest
64 * @tc.type   : Function
65 * @tc.level  : Level 2
66 */
67HWTEST_F(HatsBindTest, BindSockfdTwice_0001, Function | MediumTest | Level2)
68{
69    int ret;
70    int socketFd = -1;
71    int32_t optVal = 1;
72    struct sockaddr_in serAddr = {
73        .sin_family = AF_INET,
74        .sin_port = htons(TEST_PORT),
75        .sin_addr = {
76            .s_addr = inet_addr(TEST_LOCAL_IP),
77        }
78    };
79
80    socketFd = socket(AF_INET, SOCK_STREAM, 0);
81    EXPECT_TRUE(socketFd > 0);
82
83    ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
84    EXPECT_EQ(ret, 0);
85
86    ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
87    EXPECT_EQ(ret, 0);
88
89    errno = 0;
90    ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
91    EXPECT_EQ(ret, -1);
92    EXPECT_EQ(errno, EINVAL);
93
94    close(socketFd);
95}
96
97/*
98 * @tc.number : SUB_KERNEL_SYSCALL_BIND_0200
99 * @tc.name   : BindInvalidSockfdFailed_0002
100 * @tc.desc   : bind the invalid socket fd failed.
101 * @tc.size   : MediumTest
102 * @tc.type   : Function
103 * @tc.level  : Level 2
104 */
105HWTEST_F(HatsBindTest, BindInvalidSockfdFailed_0002, Function | MediumTest | Level2)
106{
107    int ret;
108    struct sockaddr_in serAddr = {
109        .sin_family = AF_INET,
110        .sin_port = htons(TEST_PORT),
111        .sin_addr = {
112            .s_addr = inet_addr(TEST_LOCAL_IP),
113        }
114    };
115
116    errno = 0;
117    ret = bind(BAD_SOCKET_FD, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
118    EXPECT_EQ(ret, -1);
119    EXPECT_EQ(errno, EBADF);
120
121    errno = 0;
122    ret = bind(STDIN_FILENO, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
123    EXPECT_EQ(ret, -1);
124    EXPECT_EQ(errno, ENOTSOCK);
125}
126
127/*
128 * @tc.number : SUB_KERNEL_SYSCALL_BIND_0300
129 * @tc.name   : BindInvalidIPFailed_0003
130 * @tc.desc   : bind the invalid ip addr failed.
131 * @tc.size   : MediumTest
132 * @tc.type   : Function
133 * @tc.level  : Level 2
134 */
135HWTEST_F(HatsBindTest, BindInvalidIPFailed_0003, Function | MediumTest | Level2)
136{
137    int ret;
138    int32_t optVal = 1;
139    int socketFd = -1;
140    struct sockaddr_in serAddr = {
141        .sin_family = AF_INET,
142        .sin_port = htons(TEST_PORT),
143        .sin_addr = {
144            .s_addr = inet_addr(TEST_BAD_IP),
145        }
146    };
147
148    socketFd = socket(AF_INET, SOCK_STREAM, 0);
149    EXPECT_TRUE(socketFd > 0);
150
151    ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
152    EXPECT_EQ(ret, 0);
153
154    errno = 0;
155    ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
156    EXPECT_EQ(ret, -1);
157    EXPECT_EQ(errno, EADDRNOTAVAIL);
158
159    errno = 0;
160    ret = bind(socketFd, nullptr, sizeof(serAddr));
161    EXPECT_EQ(ret, -1);
162    EXPECT_EQ(errno, EFAULT);
163
164    close(socketFd);
165}
166
167/*
168 * @tc.number : SUB_KERNEL_SYSCALL_BIND_0400
169 * @tc.name   : BindErrorIPAddrLen_0004
170 * @tc.desc   : bind addr len >= sizeof(serAddr) success, otherwise errno EINVAL.
171 * @tc.size   : MediumTest
172 * @tc.type   : Function
173 * @tc.level  : Level 2
174 */
175HWTEST_F(HatsBindTest, BindErrorIPAddrLen_0004, Function | MediumTest | Level2)
176{
177    int ret;
178    int32_t optVal = 1;
179    int socketFd = -1;
180    struct sockaddr_in serAddr = {
181        .sin_family = AF_INET,
182        .sin_port = htons(TEST_PORT),
183        .sin_addr = {
184            .s_addr = inet_addr(TEST_LOCAL_IP),
185        }
186    };
187
188    socketFd = socket(AF_INET, SOCK_STREAM, 0);
189    EXPECT_TRUE(socketFd > 0);
190
191    ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
192    EXPECT_EQ(ret, 0);
193
194    errno = 0;
195    ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), -1);
196    EXPECT_EQ(ret, -1);
197    EXPECT_EQ(errno, EINVAL);
198
199    errno = 0;
200    ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr) - 1);
201    EXPECT_EQ(ret, -1);
202    EXPECT_EQ(errno, EINVAL);
203
204    errno = 0;
205    ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr) + 1);
206    EXPECT_EQ(ret, 0);
207
208    close(socketFd);
209}
210
211/*
212 * @tc.number : SUB_KERNEL_SYSCALL_BIND_0500
213 * @tc.name   : BindUsedPortFailed_0005
214 * @tc.desc   : bind the used port, errno EINVAL.
215 * @tc.size   : MediumTest
216 * @tc.type   : Function
217 * @tc.level  : Level 2
218 */
219HWTEST_F(HatsBindTest, BindUsedPortFailed_0005, Function | MediumTest | Level2)
220{
221    int ret;
222    int socketFd = -1;
223    int socketFd2 = -1;
224    int32_t optVal = 1;
225    struct sockaddr_in serAddr = {
226        .sin_family = AF_INET,
227        .sin_port = htons(TEST_PORT),
228        .sin_addr = {
229            .s_addr = inet_addr(TEST_LOCAL_IP),
230        }
231    };
232
233    socketFd = socket(AF_INET, SOCK_STREAM, 0);
234    EXPECT_TRUE(socketFd > 0);
235
236    ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
237    EXPECT_EQ(ret, 0);
238
239    errno = 0;
240    ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
241    EXPECT_EQ(ret, 0);
242    EXPECT_EQ(errno, 0);
243
244    socketFd2 = socket(AF_INET, SOCK_STREAM, 0);
245    EXPECT_TRUE(socketFd > 0);
246
247    errno = 0;
248    ret = bind(socketFd2, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
249    EXPECT_EQ(ret, -1);
250    EXPECT_EQ(errno, EADDRINUSE);
251
252    close(socketFd);
253    close(socketFd2);
254}
255