1/*	$OpenBSD: dup2_accept.c,v 1.3 2018/07/10 08:08:00 mpi Exp $	*/
2/*
3 * Copyright (c) 2018 Martin Pieuchot
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/socket.h>
19#include <netinet/in.h>
20
21#include <assert.h>
22#include <err.h>
23#include <errno.h>
24#include <pthread.h>
25#include <string.h>
26#include <unistd.h>
27
28#include <stdlib.h>
29
30/*
31 * Listen on localhost:TEST_PORT for a connection
32 */
33#define	TEST_PORT       9876
34
35static void *
36dupper(void *arg)
37{
38	struct sockaddr_in addr;
39	int s;
40
41	sleep(1);
42
43	s = socket(PF_INET, SOCK_STREAM, 0);
44	if (s == -1)
45		err(1, "socket");
46
47	assert(s == 5);
48
49	/*
50	 * Make sure that dup'ing a LARVAL file fails with EBUSY.
51	 *
52	 * Otherwise abort the program before calling connect(2),
53	 * this was previously panic'ing the kernel.
54	 */
55	if ((dup2(0, 4) != 4) && (errno != EBUSY))
56		err(1, "dup2");
57
58	addr.sin_family = AF_INET;
59	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
60	addr.sin_port = htons(TEST_PORT);
61
62	if (connect(5, (struct sockaddr *)&addr, sizeof(addr)) == -1)
63		err(1, "connect");
64
65	return NULL;
66}
67
68int
69main(void)
70{
71	struct sockaddr_in serv_addr;
72	struct sockaddr client_addr;
73	int error, s, len, fd;
74	pthread_t tr;
75
76	if ((error = pthread_create(&tr, NULL, dupper, NULL)))
77		errc(1, error, "pthread_create");
78
79	s = socket(PF_INET, SOCK_STREAM, 0);
80	if (s == -1)
81		err(1, "socket");
82
83	assert(s == 3);
84
85	memset(&serv_addr, 0, sizeof(serv_addr));
86	serv_addr.sin_family = AF_INET;
87	serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
88	serv_addr.sin_port = htons(TEST_PORT);
89
90	if (bind(s, (struct sockaddr *)&serv_addr, sizeof(serv_addr)))
91		err(1, "bind");
92
93	if (listen(s, 3))
94		err(1, "listen");
95
96	len = sizeof(client_addr);
97	fd = accept(s, &client_addr, &len);
98
99	return 0;
100}
101