1// SPDX-License-Identifier: GPL-2.0
2
3#include <arpa/inet.h>
4#include <error.h>
5#include <errno.h>
6#include <unistd.h>
7
8int main(void)
9{
10	int fd1, fd2, one = 1;
11	struct sockaddr_in6 bind_addr = {
12		.sin6_family = AF_INET6,
13		.sin6_port = htons(20000),
14		.sin6_flowinfo = htonl(0),
15		.sin6_addr = {},
16		.sin6_scope_id = 0,
17	};
18
19	inet_pton(AF_INET6, "::", &bind_addr.sin6_addr);
20
21	fd1 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
22	if (fd1 < 0) {
23		error(1, errno, "socket fd1");
24		return -1;
25	}
26
27	if (setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
28		error(1, errno, "setsockopt(SO_REUSEADDR) fd1");
29		goto out_err1;
30	}
31
32	if (bind(fd1, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) {
33		error(1, errno, "bind fd1");
34		goto out_err1;
35	}
36
37	if (sendto(fd1, NULL, 0, MSG_FASTOPEN, (struct sockaddr *)&bind_addr,
38		   sizeof(bind_addr))) {
39		error(1, errno, "sendto fd1");
40		goto out_err1;
41	}
42
43	fd2 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
44	if (fd2 < 0) {
45		error(1, errno, "socket fd2");
46		goto out_err1;
47	}
48
49	if (setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
50		error(1, errno, "setsockopt(SO_REUSEADDR) fd2");
51		goto out_err2;
52	}
53
54	if (bind(fd2, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) {
55		error(1, errno, "bind fd2");
56		goto out_err2;
57	}
58
59	if (sendto(fd2, NULL, 0, MSG_FASTOPEN, (struct sockaddr *)&bind_addr,
60		   sizeof(bind_addr)) != -1) {
61		error(1, errno, "sendto fd2");
62		goto out_err2;
63	}
64
65	if (listen(fd2, 0)) {
66		error(1, errno, "listen");
67		goto out_err2;
68	}
69
70	close(fd2);
71	close(fd1);
72	return 0;
73
74out_err2:
75	close(fd2);
76
77out_err1:
78	close(fd1);
79	return -1;
80}
81