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
35 static void *
dupper(void * arg)36 dupper(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
68 int
main(void)69 main(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