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++)
122 /* Simple UDP test. */
123 addr = net_server_lookup(TEST_PORT, AF_UNSPEC, SOCK_DGRAM);
125 num_fds = net_bind(addr, fds);
126 ok1(num_fds == 1 || num_fds == 2);
129 for (i = 0; i < num_fds; i++)
131 do_connect(AF_UNSPEC, SOCK_DGRAM);
135 i = wait_for_readable(fds, num_fds);
139 ret = recvfrom(fd, buf, strlen("Yay!"), 0,
140 (void *)&remote_addr, &addlen);
141 ok1(ret == strlen("Yay!"));
142 ok1(memcmp(buf, "Yay!", ret) == 0);
143 ret = sendto(fd, "metoo", strlen("metoo"), 0,
144 (void *)&remote_addr, addlen);
145 ok1(ret == strlen("metoo"));
146 ok1(wait(&status) >= 0);
147 ok1(WIFEXITED(status));
148 ok1(WEXITSTATUS(status) == 0);
150 for (i = 0; i < num_fds; i++)
153 /* This seems like a Linux-only extension */
155 /* Try to force separate sockets for IPv4/IPv6, if we can. */
164 addr = net_server_lookup(TEST_PORT, AF_UNSPEC, SOCK_STREAM);
166 num_fds = net_bind(addr, fds);
171 for (i = 0; i < num_fds; i++)
173 do_connect(AF_INET, SOCK_STREAM);
174 do_connect(AF_INET6, SOCK_STREAM);
178 i = wait_for_readable(fds, num_fds);
180 fd = accept(fds[i], NULL, NULL);
183 ret = read(fd, buf, strlen("Yay!"));
184 ok1(ret == strlen("Yay!"));
185 ok1(memcmp(buf, "Yay!", ret) == 0);
186 ret = write(fd, "metoo", strlen("metoo"));
187 ok1(ret == strlen("metoo"));
190 j = wait_for_readable(fds, num_fds);
193 fd = accept(fds[j], NULL, NULL);
196 ret = read(fd, buf, strlen("Yay!"));
197 ok1(ret == strlen("Yay!"));
198 ok1(memcmp(buf, "Yay!", ret) == 0);
199 ret = write(fd, "metoo", strlen("metoo"));
200 ok1(ret == strlen("metoo"));
202 ok1(wait(&status) >= 0);
203 ok1(WIFEXITED(status));
204 ok1(WEXITSTATUS(status) == 0);
207 skip(16, "No support for IPv6-only binding");
209 for (i = 0; i < num_fds; i++)
212 /* This exits depending on whether all tests passed */
213 return exit_status();