1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <net/if.h>
33 #include <net/route.h>
34 #include "It_container_test.h"
35
36 static const char *NETMASK = "255.255.255.0";
37 static const char *GW = "192.168.100.1";
38 static const char *IFNAME = "veth0";
39 static const char *SERVER_IP = "192.168.100.6";
40 static const int SERVER_PORT = 8000;
41 static const char *PEER_IP = "192.168.100.5";
42 static const int PEER_PORT = 8001;
43 static const int DATA_LEN = 128;
44 static const char *SERVER_MSG = "===Hi, I'm Server.===";
45 static const char *PEER_MSG = "===Hi, I'm Peer.===";
46 static const int TRY_COUNT = 5;
47
UdpClient(void)48 static int UdpClient(void)
49 {
50 int ret = 0;
51 int peer;
52 int try_count = TRY_COUNT;
53 char recv_data[DATA_LEN];
54 struct sockaddr_in server_addr;
55 struct sockaddr_in peer_addr;
56
57 peer = socket(AF_INET, SOCK_DGRAM, 0);
58 if (peer < 0) {
59 return EXIT_CODE_ERRNO_1;
60 }
61
62 server_addr.sin_family = AF_INET;
63 server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
64 server_addr.sin_port = htons(SERVER_PORT);
65 (void)memset_s(&(server_addr.sin_zero), sizeof(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
66
67 peer_addr.sin_family = AF_INET;
68 peer_addr.sin_addr.s_addr = inet_addr(PEER_IP);
69 peer_addr.sin_port = htons(PEER_PORT);
70 (void)memset_s(&(peer_addr.sin_zero), sizeof(peer_addr.sin_zero), 0, sizeof(peer_addr.sin_zero));
71
72 ret = bind(peer, const_cast<struct sockaddr *>(reinterpret_cast<struct sockaddr *>(&peer_addr)),
73 sizeof(struct sockaddr));
74 if (ret != 0) {
75 return EXIT_CODE_ERRNO_2;
76 }
77
78 timeval tv = {1, 0};
79 ret = setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO, const_cast<void *>(reinterpret_cast<void *>(&tv)), sizeof(timeval));
80
81 /* loop try util server is ready */
82 while (try_count--) {
83 ret = sendto(peer, PEER_MSG, strlen(PEER_MSG) + 1, 0,
84 const_cast<struct sockaddr *>(reinterpret_cast<struct sockaddr *>(&server_addr)),
85 (socklen_t)sizeof(server_addr));
86 if (ret == -1) {
87 continue;
88 }
89 ret = recvfrom(peer, recv_data, DATA_LEN, 0, nullptr, nullptr);
90 if (ret != -1) {
91 break;
92 }
93 }
94 if (ret < 0) {
95 return EXIT_CODE_ERRNO_3;
96 }
97
98 (void)close(peer);
99
100 ret = strcmp(recv_data, SERVER_MSG);
101 if (ret != 0) {
102 return EXIT_CODE_ERRNO_4;
103 }
104
105 return 0;
106 }
107
ChildFunc(void * arg)108 static int ChildFunc(void *arg)
109 {
110 int ret = NetContainerResetNetAddr(IFNAME, PEER_IP, NETMASK, GW);
111 if (ret != 0) {
112 return EXIT_CODE_ERRNO_1;
113 }
114
115 return UdpClient();
116 }
117
UdpServer(void)118 static int UdpServer(void)
119 {
120 int ret = 0;
121 int server;
122 int try_count = TRY_COUNT;
123 char recv_data[DATA_LEN];
124 struct sockaddr_in server_addr;
125 struct sockaddr_in peer_addr;
126 socklen_t peer_addr_len = sizeof(struct sockaddr);
127
128 server = socket(AF_INET, SOCK_DGRAM, 0);
129 if (server < 0) {
130 return EXIT_CODE_ERRNO_1;
131 }
132
133 server_addr.sin_family = AF_INET;
134 server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
135 server_addr.sin_port = htons(SERVER_PORT);
136 (void)memset_s(&(server_addr.sin_zero), sizeof(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
137
138 ret = bind(server, const_cast<struct sockaddr *>(reinterpret_cast<struct sockaddr *>(&server_addr)),
139 sizeof(struct sockaddr));
140 if (ret != 0) {
141 return EXIT_CODE_ERRNO_2;
142 }
143
144 ret = recvfrom(server, recv_data, DATA_LEN, 0, reinterpret_cast<struct sockaddr *>(&peer_addr), &peer_addr_len);
145 if (ret < 0) {
146 return EXIT_CODE_ERRNO_3;
147 }
148
149 ret = sendto(server, SERVER_MSG, strlen(SERVER_MSG) + 1, 0,
150 const_cast<struct sockaddr *>(reinterpret_cast<struct sockaddr *>(&peer_addr)), peer_addr_len);
151 if (ret < 0) {
152 return EXIT_CODE_ERRNO_4;
153 }
154
155 (void)close(server);
156
157 ret = strcmp(recv_data, PEER_MSG);
158 if (ret != 0) {
159 return EXIT_CODE_ERRNO_5;
160 }
161
162 return ret;
163 }
164
UdpServerThread(void * arg)165 static void *UdpServerThread(void *arg)
166 {
167 int ret = NetContainerResetNetAddr(IFNAME, SERVER_IP, NETMASK, GW);
168 if (ret != 0) {
169 return (void *)(intptr_t)ret;
170 }
171
172 ret = UdpServer();
173
174 return (void *)(intptr_t)ret;
175 }
176
ItNetContainer005(void)177 void ItNetContainer005(void)
178 {
179 int ret = 0;
180 int status;
181 void *tret = nullptr;
182 pthread_t srv;
183 pthread_attr_t attr;
184
185 ret = pthread_attr_init(&attr);
186 ASSERT_EQ(ret, 0);
187
188 ret = pthread_create(&srv, &attr, UdpServerThread, nullptr);
189 ASSERT_EQ(ret, 0);
190
191 char *stack = (char *)mmap(nullptr, STACK_SIZE, PROT_READ | PROT_WRITE, CLONE_STACK_MMAP_FLAG, -1, 0);
192 EXPECT_STRNE(stack, nullptr);
193 char *stackTop = stack + STACK_SIZE;
194
195 int arg = CHILD_FUNC_ARG;
196 auto pid = clone(ChildFunc, stackTop, SIGCHLD | CLONE_NEWNET, &arg);
197 ASSERT_NE(pid, -1);
198
199 ret = waitpid(pid, &status, 0);
200 ASSERT_EQ(ret, pid);
201
202 int exitCode = WEXITSTATUS(status);
203 ASSERT_EQ(exitCode, 0);
204
205 ret = pthread_join(srv, &tret);
206 ASSERT_EQ(ret, 0);
207
208 ret = pthread_attr_destroy(&attr);
209 ASSERT_EQ(ret, 0);
210 }
211