1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci *
3f08c3bdfSopenharmony_ci *   Copyright (c) International Business Machines  Corp., 2001
4f08c3bdfSopenharmony_ci *   Copyright (c) Cyril Hrubis <chrubis@suse.cz> 2012
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
7f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
8f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
9f08c3bdfSopenharmony_ci *   (at your option) any later version.
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
12f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
13f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
17f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
18f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19f08c3bdfSopenharmony_ci */
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci/*
22f08c3bdfSopenharmony_ci * Test Name: sendto01
23f08c3bdfSopenharmony_ci *
24f08c3bdfSopenharmony_ci * Test Description:
25f08c3bdfSopenharmony_ci *  Verify that sendto() returns the proper errno for various failure cases
26f08c3bdfSopenharmony_ci *
27f08c3bdfSopenharmony_ci * HISTORY
28f08c3bdfSopenharmony_ci *	07/2001 Ported by Wayne Boyer
29f08c3bdfSopenharmony_ci */
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_ci#include <stdio.h>
32f08c3bdfSopenharmony_ci#include <unistd.h>
33f08c3bdfSopenharmony_ci#include <errno.h>
34f08c3bdfSopenharmony_ci#include <fcntl.h>
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci#include <sys/types.h>
37f08c3bdfSopenharmony_ci#include <sys/socket.h>
38f08c3bdfSopenharmony_ci#include <sys/signal.h>
39f08c3bdfSopenharmony_ci#include <sys/un.h>
40f08c3bdfSopenharmony_ci
41f08c3bdfSopenharmony_ci#include <netinet/in.h>
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci#include "test.h"
44f08c3bdfSopenharmony_ci#include "safe_macros.h"
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cichar *TCID = "sendto01";
47f08c3bdfSopenharmony_ciint testno;
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_cistatic char buf[1024], bigbuf[128 * 1024];
50f08c3bdfSopenharmony_cistatic int s;
51f08c3bdfSopenharmony_cistatic struct sockaddr_in sin1, sin2;
52f08c3bdfSopenharmony_cistatic int sfd;
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cistruct test_case_t {		/* test case structure */
55f08c3bdfSopenharmony_ci	int domain;		/* PF_INET, PF_UNIX, ... */
56f08c3bdfSopenharmony_ci	int type;		/* SOCK_STREAM, SOCK_DGRAM ... */
57f08c3bdfSopenharmony_ci	int proto;		/* protocol number (usually 0 = default) */
58f08c3bdfSopenharmony_ci	void *buf;		/* send data buffer */
59f08c3bdfSopenharmony_ci	int buflen;		/* send's 3rd argument */
60f08c3bdfSopenharmony_ci	unsigned flags;		/* send's 4th argument */
61f08c3bdfSopenharmony_ci	struct sockaddr_in *to;	/* destination */
62f08c3bdfSopenharmony_ci	int tolen;		/* length of "to" buffer */
63f08c3bdfSopenharmony_ci	int retval;
64f08c3bdfSopenharmony_ci	int experrno;
65f08c3bdfSopenharmony_ci	void (*setup) (void);
66f08c3bdfSopenharmony_ci	void (*cleanup) (void);
67f08c3bdfSopenharmony_ci	char *desc;
68f08c3bdfSopenharmony_ci};
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_cistatic void setup(void);
71f08c3bdfSopenharmony_cistatic void setup0(void);
72f08c3bdfSopenharmony_cistatic void setup1(void);
73f08c3bdfSopenharmony_cistatic void setup2(void);
74f08c3bdfSopenharmony_cistatic void setup3(void);
75f08c3bdfSopenharmony_cistatic void cleanup(void);
76f08c3bdfSopenharmony_cistatic void cleanup0(void);
77f08c3bdfSopenharmony_cistatic void cleanup1(void);
78f08c3bdfSopenharmony_cistatic void do_child(void);
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_cistruct test_case_t tdat[] = {
81f08c3bdfSopenharmony_ci	{.domain = PF_INET,
82f08c3bdfSopenharmony_ci	 .type = SOCK_STREAM,
83f08c3bdfSopenharmony_ci	 .proto = 0,
84f08c3bdfSopenharmony_ci	 .buf = buf,
85f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
86f08c3bdfSopenharmony_ci	 .flags = 0,
87f08c3bdfSopenharmony_ci	 .to = &sin1,
88f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
89f08c3bdfSopenharmony_ci	 .retval = -1,
90f08c3bdfSopenharmony_ci	 .experrno = EBADF,
91f08c3bdfSopenharmony_ci	 .setup = setup0,
92f08c3bdfSopenharmony_ci	 .cleanup = cleanup0,
93f08c3bdfSopenharmony_ci	 .desc = "bad file descriptor"}
94f08c3bdfSopenharmony_ci	,
95f08c3bdfSopenharmony_ci	{.domain = 0,
96f08c3bdfSopenharmony_ci	 .type = 0,
97f08c3bdfSopenharmony_ci	 .proto = 0,
98f08c3bdfSopenharmony_ci	 .buf = buf,
99f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
100f08c3bdfSopenharmony_ci	 .flags = 0,
101f08c3bdfSopenharmony_ci	 .to = &sin1,
102f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
103f08c3bdfSopenharmony_ci	 .retval = -1,
104f08c3bdfSopenharmony_ci	 .experrno = ENOTSOCK,
105f08c3bdfSopenharmony_ci	 .setup = setup0,
106f08c3bdfSopenharmony_ci	 .cleanup = cleanup0,
107f08c3bdfSopenharmony_ci	 .desc = "invalid socket"}
108f08c3bdfSopenharmony_ci	,
109f08c3bdfSopenharmony_ci#ifndef UCLINUX
110f08c3bdfSopenharmony_ci	/* Skip since uClinux does not implement memory protection */
111f08c3bdfSopenharmony_ci	{.domain = PF_INET,
112f08c3bdfSopenharmony_ci	 .type = SOCK_DGRAM,
113f08c3bdfSopenharmony_ci	 .proto = 0,
114f08c3bdfSopenharmony_ci	 .buf = (void *)-1,
115f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
116f08c3bdfSopenharmony_ci	 .flags = 0,
117f08c3bdfSopenharmony_ci	 .to = &sin1,
118f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
119f08c3bdfSopenharmony_ci	 .retval = -1,
120f08c3bdfSopenharmony_ci	 .experrno = EFAULT,
121f08c3bdfSopenharmony_ci	 .setup = setup1,
122f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
123f08c3bdfSopenharmony_ci	 .desc = "invalid send buffer"}
124f08c3bdfSopenharmony_ci	,
125f08c3bdfSopenharmony_ci#endif
126f08c3bdfSopenharmony_ci	{.domain = PF_INET,
127f08c3bdfSopenharmony_ci	 .type = SOCK_STREAM,
128f08c3bdfSopenharmony_ci	 .proto = 0,
129f08c3bdfSopenharmony_ci	 .buf = buf,
130f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
131f08c3bdfSopenharmony_ci	 .flags = 0,
132f08c3bdfSopenharmony_ci	 .to = &sin2,
133f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin2),
134f08c3bdfSopenharmony_ci	 .retval = 0,
135f08c3bdfSopenharmony_ci	 .experrno = EFAULT,
136f08c3bdfSopenharmony_ci	 .setup = setup1,
137f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
138f08c3bdfSopenharmony_ci	 .desc = "connected TCP"}
139f08c3bdfSopenharmony_ci	,
140f08c3bdfSopenharmony_ci	{.domain = PF_INET,
141f08c3bdfSopenharmony_ci	 .type = SOCK_STREAM,
142f08c3bdfSopenharmony_ci	 .proto = 0,
143f08c3bdfSopenharmony_ci	 .buf = buf,
144f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
145f08c3bdfSopenharmony_ci	 .flags = 0,
146f08c3bdfSopenharmony_ci	 .to = &sin1,
147f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
148f08c3bdfSopenharmony_ci	 .retval = -1,
149f08c3bdfSopenharmony_ci	 .experrno = EPIPE,
150f08c3bdfSopenharmony_ci	 .setup = setup3,
151f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
152f08c3bdfSopenharmony_ci	 .desc = "not connected TCP"}
153f08c3bdfSopenharmony_ci	,
154f08c3bdfSopenharmony_ci	{.domain = PF_INET,
155f08c3bdfSopenharmony_ci	 .type = SOCK_DGRAM,
156f08c3bdfSopenharmony_ci	 .proto = 0,
157f08c3bdfSopenharmony_ci	 .buf = buf,
158f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
159f08c3bdfSopenharmony_ci	 .flags = 0,
160f08c3bdfSopenharmony_ci	 .to = &sin1,
161f08c3bdfSopenharmony_ci	 .tolen = -1,
162f08c3bdfSopenharmony_ci	 .retval = -1,
163f08c3bdfSopenharmony_ci	 .experrno = EINVAL,
164f08c3bdfSopenharmony_ci	 .setup = setup1,
165f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
166f08c3bdfSopenharmony_ci	 .desc = "invalid to buffer length"}
167f08c3bdfSopenharmony_ci	,
168f08c3bdfSopenharmony_ci#ifndef UCLINUX
169f08c3bdfSopenharmony_ci	/* Skip since uClinux does not implement memory protection */
170f08c3bdfSopenharmony_ci	{.domain = PF_INET,
171f08c3bdfSopenharmony_ci	 .type = SOCK_DGRAM,
172f08c3bdfSopenharmony_ci	 .proto = 0,
173f08c3bdfSopenharmony_ci	 .buf = buf,
174f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
175f08c3bdfSopenharmony_ci	 .flags = 0,
176f08c3bdfSopenharmony_ci	 .to = (struct sockaddr_in *)-1,
177f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
178f08c3bdfSopenharmony_ci	 .retval = -1,
179f08c3bdfSopenharmony_ci	 .experrno = EFAULT,
180f08c3bdfSopenharmony_ci	 .setup = setup1,
181f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
182f08c3bdfSopenharmony_ci	 .desc = "invalid to buffer"}
183f08c3bdfSopenharmony_ci	,
184f08c3bdfSopenharmony_ci#endif
185f08c3bdfSopenharmony_ci	{.domain = PF_INET,
186f08c3bdfSopenharmony_ci	 .type = SOCK_DGRAM,
187f08c3bdfSopenharmony_ci	 .proto = 0,
188f08c3bdfSopenharmony_ci	 .buf = bigbuf,
189f08c3bdfSopenharmony_ci	 .buflen = sizeof(bigbuf),
190f08c3bdfSopenharmony_ci	 .flags = 0,
191f08c3bdfSopenharmony_ci	 .to = &sin1,
192f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
193f08c3bdfSopenharmony_ci	 .retval = -1,
194f08c3bdfSopenharmony_ci	 .experrno = EMSGSIZE,
195f08c3bdfSopenharmony_ci	 .setup = setup1,
196f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
197f08c3bdfSopenharmony_ci	 .desc = "UDP message too big"}
198f08c3bdfSopenharmony_ci	,
199f08c3bdfSopenharmony_ci	{.domain = PF_INET,
200f08c3bdfSopenharmony_ci	 .type = SOCK_STREAM,
201f08c3bdfSopenharmony_ci	 .proto = 0,
202f08c3bdfSopenharmony_ci	 .buf = buf,
203f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
204f08c3bdfSopenharmony_ci	 .flags = 0,
205f08c3bdfSopenharmony_ci	 .to = &sin1,
206f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
207f08c3bdfSopenharmony_ci	 .retval = -1,
208f08c3bdfSopenharmony_ci	 .experrno = EPIPE,
209f08c3bdfSopenharmony_ci	 .setup = setup2,
210f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
211f08c3bdfSopenharmony_ci	 .desc = "local endpoint shutdown"}
212f08c3bdfSopenharmony_ci	,
213f08c3bdfSopenharmony_ci	{.domain = PF_INET,
214f08c3bdfSopenharmony_ci	 .type = SOCK_DGRAM,
215f08c3bdfSopenharmony_ci	 .proto = 0,
216f08c3bdfSopenharmony_ci	 .buf = buf,
217f08c3bdfSopenharmony_ci	 .buflen = sizeof(buf),
218f08c3bdfSopenharmony_ci	 .flags = MSG_OOB,
219f08c3bdfSopenharmony_ci	 .to = &sin1,
220f08c3bdfSopenharmony_ci	 .tolen = sizeof(sin1),
221f08c3bdfSopenharmony_ci	 .retval = -1,
222f08c3bdfSopenharmony_ci	 .experrno = EOPNOTSUPP,
223f08c3bdfSopenharmony_ci	 .setup = setup1,
224f08c3bdfSopenharmony_ci	 .cleanup = cleanup1,
225f08c3bdfSopenharmony_ci	 .desc = "invalid flags set"}
226f08c3bdfSopenharmony_ci};
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ciint TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
229f08c3bdfSopenharmony_ci
230f08c3bdfSopenharmony_ci#ifdef UCLINUX
231f08c3bdfSopenharmony_cistatic char *argv0;
232f08c3bdfSopenharmony_ci#endif
233f08c3bdfSopenharmony_ci
234f08c3bdfSopenharmony_cistatic pid_t start_server(struct sockaddr_in *sin0)
235f08c3bdfSopenharmony_ci{
236f08c3bdfSopenharmony_ci	pid_t pid;
237f08c3bdfSopenharmony_ci	socklen_t slen = sizeof(*sin0);
238f08c3bdfSopenharmony_ci
239f08c3bdfSopenharmony_ci	sin0->sin_family = AF_INET;
240f08c3bdfSopenharmony_ci	sin0->sin_port = 0; /* pick random free port */
241f08c3bdfSopenharmony_ci	sin0->sin_addr.s_addr = INADDR_ANY;
242f08c3bdfSopenharmony_ci
243f08c3bdfSopenharmony_ci	sfd = socket(PF_INET, SOCK_STREAM, 0);
244f08c3bdfSopenharmony_ci	if (sfd < 0) {
245f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "server socket failed");
246f08c3bdfSopenharmony_ci		return -1;
247f08c3bdfSopenharmony_ci	}
248f08c3bdfSopenharmony_ci	if (bind(sfd, (struct sockaddr *)sin0, sizeof(*sin0)) < 0) {
249f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "server bind failed");
250f08c3bdfSopenharmony_ci		return -1;
251f08c3bdfSopenharmony_ci	}
252f08c3bdfSopenharmony_ci	if (listen(sfd, 10) < 0) {
253f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "server listen failed");
254f08c3bdfSopenharmony_ci		return -1;
255f08c3bdfSopenharmony_ci	}
256f08c3bdfSopenharmony_ci	SAFE_GETSOCKNAME(cleanup, sfd, (struct sockaddr *)sin0, &slen);
257f08c3bdfSopenharmony_ci
258f08c3bdfSopenharmony_ci	switch ((pid = FORK_OR_VFORK())) {
259f08c3bdfSopenharmony_ci	case 0:
260f08c3bdfSopenharmony_ci#ifdef UCLINUX
261f08c3bdfSopenharmony_ci		if (self_exec(argv0, "d", sfd) < 0)
262f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, cleanup,
263f08c3bdfSopenharmony_ci				 "server self_exec failed");
264f08c3bdfSopenharmony_ci#else
265f08c3bdfSopenharmony_ci		do_child();
266f08c3bdfSopenharmony_ci#endif
267f08c3bdfSopenharmony_ci		break;
268f08c3bdfSopenharmony_ci	case -1:
269f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "server fork failed");
270f08c3bdfSopenharmony_ci	default:
271f08c3bdfSopenharmony_ci		(void)close(sfd);
272f08c3bdfSopenharmony_ci		return pid;
273f08c3bdfSopenharmony_ci	}
274f08c3bdfSopenharmony_ci
275f08c3bdfSopenharmony_ci	exit(1);
276f08c3bdfSopenharmony_ci}
277f08c3bdfSopenharmony_ci
278f08c3bdfSopenharmony_cistatic void do_child(void)
279f08c3bdfSopenharmony_ci{
280f08c3bdfSopenharmony_ci	struct sockaddr_in fsin;
281f08c3bdfSopenharmony_ci	fd_set afds, rfds;
282f08c3bdfSopenharmony_ci	int nfds, cc, fd;
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ci	FD_ZERO(&afds);
285f08c3bdfSopenharmony_ci	FD_SET(sfd, &afds);
286f08c3bdfSopenharmony_ci
287f08c3bdfSopenharmony_ci	nfds = sfd + 1;
288f08c3bdfSopenharmony_ci
289f08c3bdfSopenharmony_ci	/* accept connections until killed */
290f08c3bdfSopenharmony_ci	while (1) {
291f08c3bdfSopenharmony_ci		socklen_t fromlen;
292f08c3bdfSopenharmony_ci
293f08c3bdfSopenharmony_ci		memcpy(&rfds, &afds, sizeof(rfds));
294f08c3bdfSopenharmony_ci
295f08c3bdfSopenharmony_ci		if (select(nfds, &rfds, NULL, NULL, NULL) < 0 && errno != EINTR)
296f08c3bdfSopenharmony_ci			exit(1);
297f08c3bdfSopenharmony_ci
298f08c3bdfSopenharmony_ci		if (FD_ISSET(sfd, &rfds)) {
299f08c3bdfSopenharmony_ci			int newfd;
300f08c3bdfSopenharmony_ci
301f08c3bdfSopenharmony_ci			fromlen = sizeof(fsin);
302f08c3bdfSopenharmony_ci			newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen);
303f08c3bdfSopenharmony_ci			if (newfd >= 0) {
304f08c3bdfSopenharmony_ci				FD_SET(newfd, &afds);
305f08c3bdfSopenharmony_ci				nfds = MAX(nfds, newfd + 1);
306f08c3bdfSopenharmony_ci			}
307f08c3bdfSopenharmony_ci		}
308f08c3bdfSopenharmony_ci		for (fd = 0; fd < nfds; ++fd) {
309f08c3bdfSopenharmony_ci			if (fd != sfd && FD_ISSET(fd, &rfds)) {
310f08c3bdfSopenharmony_ci				cc = read(fd, buf, sizeof(buf));
311f08c3bdfSopenharmony_ci				if (cc == 0 || (cc < 0 && errno != EINTR)) {
312f08c3bdfSopenharmony_ci					(void)close(fd);
313f08c3bdfSopenharmony_ci					FD_CLR(fd, &afds);
314f08c3bdfSopenharmony_ci				}
315f08c3bdfSopenharmony_ci			}
316f08c3bdfSopenharmony_ci		}
317f08c3bdfSopenharmony_ci	}
318f08c3bdfSopenharmony_ci}
319f08c3bdfSopenharmony_ci
320f08c3bdfSopenharmony_ciint main(int ac, char *av[])
321f08c3bdfSopenharmony_ci{
322f08c3bdfSopenharmony_ci	int lc;
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, NULL, NULL);
325f08c3bdfSopenharmony_ci
326f08c3bdfSopenharmony_ci#ifdef UCLINUX
327f08c3bdfSopenharmony_ci	argv0 = av[0];
328f08c3bdfSopenharmony_ci	maybe_run_child(&do_child, "d", &sfd);
329f08c3bdfSopenharmony_ci#endif
330f08c3bdfSopenharmony_ci
331f08c3bdfSopenharmony_ci	setup();
332f08c3bdfSopenharmony_ci
333f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); ++lc) {
334f08c3bdfSopenharmony_ci
335f08c3bdfSopenharmony_ci		tst_count = 0;
336f08c3bdfSopenharmony_ci		for (testno = 0; testno < TST_TOTAL; ++testno) {
337f08c3bdfSopenharmony_ci			tdat[testno].setup();
338f08c3bdfSopenharmony_ci
339f08c3bdfSopenharmony_ci			TEST(sendto(s, tdat[testno].buf, tdat[testno].buflen,
340f08c3bdfSopenharmony_ci				    tdat[testno].flags,
341f08c3bdfSopenharmony_ci				    (const struct sockaddr *)tdat[testno].to,
342f08c3bdfSopenharmony_ci				    tdat[testno].tolen));
343f08c3bdfSopenharmony_ci
344f08c3bdfSopenharmony_ci			if (TEST_RETURN > 0)
345f08c3bdfSopenharmony_ci				TEST_RETURN = 0;
346f08c3bdfSopenharmony_ci
347f08c3bdfSopenharmony_ci			if (TEST_RETURN != tdat[testno].retval ||
348f08c3bdfSopenharmony_ci			    (TEST_RETURN < 0 &&
349f08c3bdfSopenharmony_ci			     TEST_ERRNO != tdat[testno].experrno)) {
350f08c3bdfSopenharmony_ci				tst_resm(TFAIL, "%s ; returned"
351f08c3bdfSopenharmony_ci					 " %ld (expected %d), errno %d (expected"
352f08c3bdfSopenharmony_ci					 " %d)", tdat[testno].desc,
353f08c3bdfSopenharmony_ci					 TEST_RETURN, tdat[testno].retval,
354f08c3bdfSopenharmony_ci					 TEST_ERRNO, tdat[testno].experrno);
355f08c3bdfSopenharmony_ci			} else {
356f08c3bdfSopenharmony_ci				tst_resm(TPASS, "%s successful",
357f08c3bdfSopenharmony_ci					 tdat[testno].desc);
358f08c3bdfSopenharmony_ci			}
359f08c3bdfSopenharmony_ci			tdat[testno].cleanup();
360f08c3bdfSopenharmony_ci		}
361f08c3bdfSopenharmony_ci	}
362f08c3bdfSopenharmony_ci	cleanup();
363f08c3bdfSopenharmony_ci
364f08c3bdfSopenharmony_ci	tst_exit();
365f08c3bdfSopenharmony_ci}
366f08c3bdfSopenharmony_ci
367f08c3bdfSopenharmony_cistatic pid_t server_pid;
368f08c3bdfSopenharmony_ci
369f08c3bdfSopenharmony_cistatic void setup(void)
370f08c3bdfSopenharmony_ci{
371f08c3bdfSopenharmony_ci	TEST_PAUSE;
372f08c3bdfSopenharmony_ci
373f08c3bdfSopenharmony_ci	server_pid = start_server(&sin1);
374f08c3bdfSopenharmony_ci
375f08c3bdfSopenharmony_ci	signal(SIGPIPE, SIG_IGN);
376f08c3bdfSopenharmony_ci}
377f08c3bdfSopenharmony_ci
378f08c3bdfSopenharmony_cistatic void cleanup(void)
379f08c3bdfSopenharmony_ci{
380f08c3bdfSopenharmony_ci	kill(server_pid, SIGKILL);
381f08c3bdfSopenharmony_ci}
382f08c3bdfSopenharmony_ci
383f08c3bdfSopenharmony_cistatic void setup0(void)
384f08c3bdfSopenharmony_ci{
385f08c3bdfSopenharmony_ci	if (tdat[testno].experrno == EBADF)
386f08c3bdfSopenharmony_ci		s = 400;
387f08c3bdfSopenharmony_ci	else if ((s = open("/dev/null", O_WRONLY)) == -1)
388f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "open(/dev/null) failed");
389f08c3bdfSopenharmony_ci}
390f08c3bdfSopenharmony_ci
391f08c3bdfSopenharmony_cistatic void cleanup0(void)
392f08c3bdfSopenharmony_ci{
393f08c3bdfSopenharmony_ci	s = -1;
394f08c3bdfSopenharmony_ci}
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_cistatic void setup1(void)
397f08c3bdfSopenharmony_ci{
398f08c3bdfSopenharmony_ci	s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type,
399f08c3bdfSopenharmony_ci			tdat[testno].proto);
400f08c3bdfSopenharmony_ci	SAFE_CONNECT(cleanup, s, (const struct sockaddr *)&sin1, sizeof(sin1));
401f08c3bdfSopenharmony_ci}
402f08c3bdfSopenharmony_ci
403f08c3bdfSopenharmony_cistatic void cleanup1(void)
404f08c3bdfSopenharmony_ci{
405f08c3bdfSopenharmony_ci	(void)close(s);
406f08c3bdfSopenharmony_ci	s = -1;
407f08c3bdfSopenharmony_ci}
408f08c3bdfSopenharmony_ci
409f08c3bdfSopenharmony_cistatic void setup2(void)
410f08c3bdfSopenharmony_ci{
411f08c3bdfSopenharmony_ci	setup1();
412f08c3bdfSopenharmony_ci	if (shutdown(s, 1) < 0)
413f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "socket setup failed connect "
414f08c3bdfSopenharmony_ci			 "test %d", testno);
415f08c3bdfSopenharmony_ci}
416f08c3bdfSopenharmony_ci
417f08c3bdfSopenharmony_cistatic void setup3(void)
418f08c3bdfSopenharmony_ci{
419f08c3bdfSopenharmony_ci	s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type,
420f08c3bdfSopenharmony_ci		        tdat[testno].proto);
421f08c3bdfSopenharmony_ci}
422