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 | |
8 | int 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 (listen(fd1, 0)) { |
38 | error(1, errno, "listen" ); |
39 | goto out_err1; |
40 | } |
41 | |
42 | fd2 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP); |
43 | if (fd2 < 0) { |
44 | error(1, errno, "socket fd2" ); |
45 | goto out_err1; |
46 | } |
47 | |
48 | if (connect(fd2, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) { |
49 | error(1, errno, "bind fd2" ); |
50 | goto out_err2; |
51 | } |
52 | |
53 | close(fd2); |
54 | close(fd1); |
55 | return 0; |
56 | |
57 | out_err2: |
58 | close(fd2); |
59 | out_err1: |
60 | close(fd1); |
61 | return -1; |
62 | } |
63 | |