1 #include <ccan/net/net.h>
2 #include <ccan/net/net.c>
3 #include <ccan/tap/tap.h>
9 static unsigned int server(int protocol, int type)
14 struct sockaddr_in ipv4;
15 struct sockaddr_in6 ipv6;
17 socklen_t addlen = sizeof(addr);
19 sock = socket(protocol, type, 0);
21 /* Bind to free port. */
24 /* Figure out what port it gave us. */
25 getsockname(sock, &addr.addr, &addlen);
32 fd = accept(sock, NULL, 0);
34 err(1, "Accepting from socket %i", sock);
36 ret = write(fd, "Yay!", strlen("Yay!"));
37 if (ret != strlen("Yay!"))
38 err(1, "Write returned %i", ret);
42 return ntohs(protocol == AF_INET
43 ? addr.ipv4.sin_port : addr.ipv6.sin6_port);
46 static bool we_faked_double = false;
48 /* Get a localhost on ipv4 and IPv6. Fake it if we have to. */
49 static struct addrinfo* double_addr_lookup(char* buf)
51 struct addrinfo *addr, *addr2;
53 addr = net_client_lookup("localhost", buf, AF_UNSPEC, SOCK_STREAM);
57 /* If we only got one, we need to fake up the other one. */
59 addr2 = addr->ai_next;
61 we_faked_double = true;
64 if (addr->ai_family == AF_INET) {
65 /* These are the names I found on my Ubuntu system. */
66 addr2 = net_client_lookup("ip6-localhost", buf,
67 AF_UNSPEC, SOCK_STREAM);
69 addr2 = net_client_lookup("localhost6", buf,
72 } else if (addr->ai_family == AF_INET6)
73 /* IPv6 only? This is a guess... */
74 addr2 = net_client_lookup("ip4-localhost", buf,
75 AF_UNSPEC, SOCK_STREAM);
78 addr->ai_next = addr2;
84 /* One IPv4 and one IPv6? */
85 if (addr->ai_family == AF_INET && addr2->ai_family == AF_INET6)
87 if (addr->ai_family == AF_INET6 && addr2->ai_family == AF_INET)
92 static void double_addr_free(struct addrinfo* addr)
94 struct addrinfo *addr2;
95 if (we_faked_double) {
96 addr2 = addr->ai_next;
106 struct addrinfo *addr;
108 struct sockaddr saddr;
114 port = server(AF_INET, SOCK_STREAM);
115 sprintf(buf, "%u", port);
117 addr = double_addr_lookup(buf);
119 fd = net_connect(addr);
122 slen = sizeof(saddr);
123 ok1(getsockname(fd, &saddr, &slen) == 0);
124 diag("family = %d", saddr.sa_family);
125 ok1(saddr.sa_family == AF_INET);
126 status = read(fd, buf, sizeof(buf));
127 ok(status == strlen("Yay!"),
128 "Read returned %i (%s)", status, strerror(errno));
129 ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
131 double_addr_free(addr);
133 port = server(AF_INET6, SOCK_STREAM);
134 sprintf(buf, "%u", port);
136 addr = double_addr_lookup(buf);
138 fd = net_connect(addr);
141 slen = sizeof(saddr);
142 ok1(getsockname(fd, &saddr, &slen) == 0);
143 ok1(saddr.sa_family == AF_INET6);
144 status = read(fd, buf, sizeof(buf));
145 ok(status == strlen("Yay!"),
146 "Read returned %i (%s)", status, strerror(errno));
147 ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
149 double_addr_free(addr);
152 ok1(WIFEXITED(status));
153 ok1(WEXITSTATUS(status) == 0);
155 /* This exits depending on whether all tests passed */
156 return exit_status();