1 #include <ccan/net/net.h>
2 #include <ccan/tap/tap.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
16 static int my_setsockopt(int sockfd, int level, int optname,
17 const void *optval, socklen_t optlen)
20 setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6_only,
22 ret = setsockopt(sockfd, level, optname, optval, optlen);
25 #define setsockopt my_setsockopt
28 #include <ccan/net/net.c>
30 #define TEST_PORT "65001"
32 static void do_connect(int family, int type)
35 struct addrinfo *addr;
40 addr = net_client_lookup(NULL, TEST_PORT, family, type);
41 fd = net_connect(addr);
43 err(1, "Failed net_connect");
46 ret = write(fd, "Yay!", strlen("Yay!"));
47 if (ret != strlen("Yay!"))
48 err(1, "Write returned %i", ret);
49 ret = read(fd, buf, sizeof(buf));
51 err(1, "Read returned %i", ret);
52 if (memcmp(buf, "metoo", ret) != 0)
53 err(1, "Read returned '%.*s'", ret, buf);
57 static int wait_for_readable(int fds[2], int num_fds)
63 for (i = 0; i < num_fds; i++) {
69 select(max_fd+1, &set, NULL, NULL, NULL);
70 for (i = 0; i < num_fds; i++) {
71 if (FD_ISSET(fds[i], &set))
79 struct addrinfo *addr;
80 int fds[2], num_fds, i, fd, status, ret;
84 struct sockaddr_in ipv4;
85 struct sockaddr_in6 ipv6;
87 socklen_t addlen = sizeof(remote_addr);
91 /* Simple TCP test. */
92 addr = net_server_lookup(TEST_PORT, AF_UNSPEC, SOCK_STREAM);
94 num_fds = net_bind(addr, fds);
95 ok1(num_fds == 1 || num_fds == 2);
98 for (i = 0; i < num_fds; i++)
100 do_connect(AF_UNSPEC, SOCK_STREAM);
104 i = wait_for_readable(fds, num_fds);
106 fd = accept(fds[i], NULL, NULL);
109 ret = read(fd, buf, strlen("Yay!"));
110 ok1(ret == strlen("Yay!"));
111 ok1(memcmp(buf, "Yay!", ret) == 0);
112 ret = write(fd, "metoo", strlen("metoo"));
113 ok1(ret == strlen("metoo"));
114 ok1(wait(&status) != -1);
115 ok1(WIFEXITED(status));
116 ok1(WEXITSTATUS(status) == 0);
118 for (i = 0; i < num_fds; i++)
121 /* Simple UDP test. */
122 addr = net_server_lookup(TEST_PORT, AF_UNSPEC, SOCK_DGRAM);
124 num_fds = net_bind(addr, fds);
125 ok1(num_fds == 1 || num_fds == 2);
128 for (i = 0; i < num_fds; i++)
130 do_connect(AF_UNSPEC, SOCK_DGRAM);
134 i = wait_for_readable(fds, num_fds);
138 ret = recvfrom(fd, buf, strlen("Yay!"), 0,
139 (void *)&remote_addr, &addlen);
140 ok1(ret == strlen("Yay!"));
141 ok1(memcmp(buf, "Yay!", ret) == 0);
142 ret = sendto(fd, "metoo", strlen("metoo"), 0,
143 (void *)&remote_addr, addlen);
144 ok1(ret == strlen("metoo"));
145 ok1(wait(&status) >= 0);
146 ok1(WIFEXITED(status));
147 ok1(WEXITSTATUS(status) == 0);
149 for (i = 0; i < num_fds; i++)
152 /* This seems like a Linux-only extension */
154 /* Try to force separate sockets for IPv4/IPv6, if we can. */
162 addr = net_server_lookup(TEST_PORT, AF_UNSPEC, SOCK_STREAM);
164 num_fds = net_bind(addr, fds);
169 for (i = 0; i < num_fds; i++)
171 do_connect(AF_INET, SOCK_STREAM);
172 do_connect(AF_INET6, SOCK_STREAM);
176 i = wait_for_readable(fds, num_fds);
178 fd = accept(fds[i], NULL, NULL);
181 ret = read(fd, buf, strlen("Yay!"));
182 ok1(ret == strlen("Yay!"));
183 ok1(memcmp(buf, "Yay!", ret) == 0);
184 ret = write(fd, "metoo", strlen("metoo"));
185 ok1(ret == strlen("metoo"));
188 j = wait_for_readable(fds, num_fds);
191 fd = accept(fds[j], NULL, NULL);
194 ret = read(fd, buf, strlen("Yay!"));
195 ok1(ret == strlen("Yay!"));
196 ok1(memcmp(buf, "Yay!", ret) == 0);
197 ret = write(fd, "metoo", strlen("metoo"));
198 ok1(ret == strlen("metoo"));
200 ok1(wait(&status) >= 0);
201 ok1(WIFEXITED(status));
202 ok1(WEXITSTATUS(status) == 0);
205 skip(16, "No support for IPv6-only binding");
207 for (i = 0; i < num_fds; i++)
210 /* This exits depending on whether all tests passed */
211 return exit_status();