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 = 8005;
41 static const char *PEER_IP = "192.168.100.5";
42 static const char *SERVER_MSG = "===Hi, I'm Server.===";
43 static const char *PEER_MSG = "===Hi, I'm Peer.===";
44 static const int TRY_COUNT = 5;
45 static const int DATA_LEN = 128;
46 static const int IpLen = 16;
47
TcpClient(void)48 static int TcpClient(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
56 peer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
57 if (peer < 0) {
58 return EXIT_CODE_ERRNO_1;
59 }
60
61 server_addr.sin_family = AF_INET;
62 server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
63 server_addr.sin_port = htons(SERVER_PORT);
64 (void)memset_s(&(server_addr.sin_zero), sizeof(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
65
66 do {
67 sleep(1);
68 ret = connect(peer, const_cast<struct sockaddr *>(reinterpret_cast<struct sockaddr *>(&server_addr)),
69 sizeof(struct sockaddr));
70 } while (ret !=0 && (try_count--));
71
72 if (ret < 0) {
73 (void)close(peer);
74 printf("[ERR][%s:%d] connect failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
75 return EXIT_CODE_ERRNO_2;
76 }
77
78 ret = send(peer, PEER_MSG, strlen(PEER_MSG) + 1, 0);
79 if (ret < 0) {
80 (void)close(peer);
81 printf("[ERR][%s:%d] send failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
82 return EXIT_CODE_ERRNO_3;
83 }
84
85 ret = recv(peer, recv_data, sizeof(recv_data), 0);
86 if (ret < 0) {
87 (void)close(peer);
88 printf("[ERR][%s:%d] recv failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
89 return EXIT_CODE_ERRNO_4;
90 }
91 (void)close(peer);
92
93 ret = strcmp(recv_data, SERVER_MSG);
94 if (ret != 0) {
95 return EXIT_CODE_ERRNO_5;
96 }
97 return 0;
98 }
99
TcpServer(void)100 static int TcpServer(void)
101 {
102 int ret = 0;
103 int server;
104 int peer;
105 char recv_data[DATA_LEN];
106 struct sockaddr_in server_addr;
107
108 server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
109 if (server < 0) {
110 return EXIT_CODE_ERRNO_1;
111 }
112
113 server_addr.sin_family = AF_INET;
114 server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
115 server_addr.sin_port = htons(SERVER_PORT);
116 (void)memset_s(&(server_addr.sin_zero), sizeof(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
117
118 ret = bind(server, const_cast<struct sockaddr *>(reinterpret_cast<struct sockaddr *>(&server_addr)),
119 sizeof(struct sockaddr));
120 if (ret != 0) {
121 printf("[ERR][%s:%d] bind failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
122 return EXIT_CODE_ERRNO_2;
123 }
124
125 ret = listen(server, 1);
126 if (ret < 0) {
127 printf("[ERR][%s:%d] listen failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
128 return EXIT_CODE_ERRNO_3;
129 }
130
131 peer = accept(server, nullptr, nullptr);
132 if (peer < 0) {
133 printf("[ERR][%s:%d] accept failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
134 return EXIT_CODE_ERRNO_4;
135 }
136
137 (void)close(server);
138
139 ret = recv(peer, recv_data, sizeof(recv_data), 0);
140 if (ret < 0) {
141 printf("[ERR][%s:%d] recv failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
142 return EXIT_CODE_ERRNO_5;
143 }
144
145 ret = strcmp(recv_data, PEER_MSG);
146 if (ret != 0) {
147 return EXIT_CODE_ERRNO_6;
148 }
149
150 ret = send(peer, SERVER_MSG, strlen(SERVER_MSG) + 1, 0);
151 if (ret < 0) {
152 printf("[ERR][%s:%d] send failed, %s!\n", __FUNCTION__, __LINE__, strerror(errno));
153 return EXIT_CODE_ERRNO_7;
154 }
155
156 (void)close(peer);
157 return 0;
158 }
159
TcpClientThread(void * arg)160 static void *TcpClientThread(void *arg)
161 {
162 char newIp[IpLen] = {NULL};
163 int ret = NetContainerResetNetAddr(IFNAME, PEER_IP, NETMASK, GW);
164 if (ret != 0) {
165 return (void *)(intptr_t)EXIT_CODE_ERRNO_1;
166 }
167
168 ret = NetContainerGetLocalIP(IFNAME, newIp, IpLen);
169 if (ret != 0) {
170 return (void *)(intptr_t)EXIT_CODE_ERRNO_2;
171 }
172
173 if (strncmp(PEER_IP, newIp, strlen(PEER_IP)) != 0) {
174 return (void *)(intptr_t)EXIT_CODE_ERRNO_3;
175 }
176 printf("######## [%s:%d] %s: %s ########\n", __FUNCTION__, __LINE__, IFNAME, newIp);
177
178 ret = TcpClient();
179 return (void *)(intptr_t)ret;
180 }
181
ChildFunc(void * arg)182 static int ChildFunc(void *arg)
183 {
184 char newIp[IpLen] = {NULL};
185 int ret = NetContainerResetNetAddr(IFNAME, SERVER_IP, NETMASK, GW);
186 if (ret != 0) {
187 return EXIT_CODE_ERRNO_8;
188 }
189
190 ret = NetContainerGetLocalIP(IFNAME, newIp, IpLen);
191 if (ret != 0) {
192 return EXIT_CODE_ERRNO_9;
193 }
194
195 if (strncmp(SERVER_IP, newIp, strlen(SERVER_IP)) != 0) {
196 return EXIT_CODE_ERRNO_10;
197 }
198
199 printf("######## [%s:%d] %s: %s ########\n", __FUNCTION__, __LINE__, IFNAME, newIp);
200 return TcpServer();
201 }
202
ItNetContainer009(void)203 VOID ItNetContainer009(void)
204 {
205 int ret = 0;
206 int status;
207 void *tret = nullptr;
208 pthread_t srv;
209 pthread_attr_t attr;
210
211 char *stack = (char *)mmap(nullptr, STACK_SIZE, PROT_READ | PROT_WRITE, CLONE_STACK_MMAP_FLAG, -1, 0);
212 EXPECT_STRNE(stack, nullptr);
213 char *stackTop = stack + STACK_SIZE;
214
215 int arg = CHILD_FUNC_ARG;
216 int pid = clone(ChildFunc, stackTop, SIGCHLD | CLONE_NEWNET, &arg);
217 ASSERT_NE(pid, -1);
218
219 ret = pthread_attr_init(&attr);
220 ASSERT_EQ(ret, 0);
221
222 ret = pthread_create(&srv, &attr, TcpClientThread, nullptr);
223 ASSERT_EQ(ret, 0);
224
225 ret = pthread_join(srv, &tret);
226 ASSERT_EQ(ret, 0);
227
228 ret = (uintptr_t)tret;
229 ASSERT_EQ(ret, 0);
230
231 ret = pthread_attr_destroy(&attr);
232 ASSERT_EQ(ret, 0);
233
234 ret = waitpid(pid, &status, 0);
235 ASSERT_EQ(ret, pid);
236
237 int exitCode = WEXITSTATUS(status);
238 ASSERT_EQ(exitCode, 0);
239 }
240