1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
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#include <errno.h>
16#include <netinet/in.h>
17#include <signal.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/socket.h>
21#include <sys/wait.h>
22#include <sigchain.h>
23#include "fortify_test.h"
24#include "test.h"
25
26#define SCTP_IP_LOOPBACK  htonl(0x7f000001)
27#define BUF_SIZE_10 (10)
28#define BUF_SIZE_100 (100)
29
30/**
31 * @tc.name     : send_and_recv_0010
32 * @tc.desc     : test send and recv normal condition
33 * @tc.level    : Level 0
34 */
35static void send_and_recv_0010(void)
36{
37    char buf[BUF_SIZE_100];
38    int sockets[2];
39
40    TEST(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0);
41    TEST(send(sockets[1], "x", 1, 0) == 1);
42    TEST(recv(sockets[0], buf, sizeof buf, 0) == 1);
43    TEST(buf[0]=='x', "'%c'\n", buf[0]);
44
45    return;
46}
47
48/**
49 * @tc.name     : send_0010
50 * @tc.desc     : test send suppress compiler optimizations
51 * @tc.level    : Level 2
52 */
53static void send_0010(void)
54{
55    struct sigaction sigabrt = {
56        .sa_handler = SignalHandler,
57    };
58    sigaction(SIGABRT, &sigabrt, NULL);
59
60    size_t data_len = atoi("11");
61    char buf[BUF_SIZE_10];
62    int status;
63    int pid = fork();
64    switch (pid) {
65        case -1:
66            t_error("fork failed: %s\n", strerror(errno));
67            break;
68        case 0:
69            send(0, buf, data_len, 0);
70            exit(0);
71        default:
72            waitpid(pid, &status, WUNTRACED);
73            TEST(WIFEXITED(status) == 0);
74            TEST(WIFSTOPPED(status) == 1);
75            TEST(WSTOPSIG(status) == SIGSTOP);
76            kill(pid, SIGCONT);
77            break;
78    }
79
80    return;
81}
82
83/**
84 * @tc.name     : recv_0010
85 * @tc.desc     : test recv suppress compiler optimizations
86 * @tc.level    : Level 2
87 */
88static void recv_0010(void)
89{
90    struct sigaction sigabrt = {
91        .sa_handler = SignalHandler,
92    };
93    sigaction(SIGABRT, &sigabrt, NULL);
94
95    size_t data_len = atoi("11");
96    char buf[BUF_SIZE_10];
97    int status;
98    int pid = fork();
99    switch (pid) {
100        case -1:
101            t_error("fork failed: %s\n", strerror(errno));
102            break;
103        case 0:
104            recv(0, buf, data_len, 0);
105            exit(0);
106        default:
107            waitpid(pid, &status, WUNTRACED);
108            TEST(WIFEXITED(status) == 0);
109            TEST(WIFSTOPPED(status) == 1);
110            TEST(WSTOPSIG(status) == SIGSTOP);
111            kill(pid, SIGCONT);
112            break;
113    }
114
115    return;
116}
117
118/**
119 * @tc.name     : sendto_and_recvfrom_0010
120 * @tc.desc     : test sendto and recvfrom normal condition
121 * @tc.level    : Level 0
122 */
123static void sendto_and_recvfrom_0010(void)
124{
125    struct sockaddr_in sa = { .sin_family = AF_INET };
126    int sendFd, recvFd, t;
127    char buf[BUF_SIZE_100];
128
129    TEST((recvFd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0);
130    TEST(bind(recvFd, (void *)&sa, sizeof sa)==0);
131    TEST(getsockname(recvFd, (void *)&sa, (socklen_t[]){sizeof sa}) == 0);
132
133    TEST(setsockopt(recvFd, SOL_SOCKET, SO_RCVTIMEO,
134        &(struct timeval){.tv_usec=1}, sizeof(struct timeval)) == 0);
135
136    TEST((sendFd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0);
137    sa.sin_addr.s_addr = SCTP_IP_LOOPBACK;
138    TEST(sendto(sendFd, "x", 1, 0, (void *)&sa, sizeof sa) == 1);
139    TEST(recvfrom(recvFd, buf, sizeof buf, 0, (void *)&sa, (socklen_t[]){sizeof sa}) == 1);
140    TEST(buf[0]=='x', "'%c'\n", buf[0]);
141
142    return;
143}
144
145/**
146 * @tc.name     : sendto_0010
147 * @tc.desc     : test sendto suppress compiler optimizations
148 * @tc.level    : Level 2
149 */
150static void sendto_0010(void)
151{
152    struct sigaction sigabrt = {
153        .sa_handler = SignalHandler,
154    };
155    sigaction(SIGABRT, &sigabrt, NULL);
156
157    size_t data_len = atoi("11");
158    char buf[BUF_SIZE_10];
159    int status;
160    int pid = fork();
161    switch (pid) {
162        case -1:
163            t_error("fork failed: %s\n", strerror(errno));
164            break;
165        case 0:
166            sendto(0, buf, data_len, 0, NULL, 0);
167            exit(0);
168        default:
169            waitpid(pid, &status, WUNTRACED);
170            TEST(WIFEXITED(status) == 0);
171            TEST(WIFSTOPPED(status) == 1);
172            TEST(WSTOPSIG(status) == SIGSTOP);
173            kill(pid, SIGCONT);
174            break;
175    }
176
177    return;
178}
179
180/**
181 * @tc.name     : recvfrom_0010
182 * @tc.desc     : test recv suppress compiler optimizations
183 * @tc.level    : Level 2
184 */
185static void recvfrom_0010(void)
186{
187    struct sigaction sigabrt = {
188        .sa_handler = SignalHandler,
189    };
190    sigaction(SIGABRT, &sigabrt, NULL);
191
192    size_t data_len = atoi("11");
193    char buf[BUF_SIZE_10];
194    int status;
195    int pid = fork();
196    switch (pid) {
197        case -1:
198            t_error("fork failed: %s\n", strerror(errno));
199            break;
200        case 0:
201            recvfrom(0, buf, data_len, 0, NULL, 0);
202            exit(0);
203        default:
204            waitpid(pid, &status, WUNTRACED);
205            TEST(WIFEXITED(status) == 0);
206            TEST(WIFSTOPPED(status) == 1);
207            TEST(WSTOPSIG(status) == SIGSTOP);
208            kill(pid, SIGCONT);
209            break;
210    }
211
212    return;
213}
214
215int main(int argc, char *argv[]) {
216    remove_all_special_handler(SIGABRT);
217    send_and_recv_0010();
218    send_0010();
219    recv_0010();
220    sendto_and_recvfrom_0010();
221    sendto_0010();
222    recvfrom_0010();
223
224    return t_status;
225}