#include #include #include #include #include #include #include #include #include /* use the same loopback address and port for both IPV6 and IPV4 */ #define SRV_IPV6 "::1/128" #define SRV_IPV4 "127.0.0.1" #define PORT 11112 int main(int argc, char** argv) { int socket_ipv4; int socket_ipv6; int ret; if ((socket_ipv6 = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { perror("socket(ipv6)"); return 1; } if ((socket_ipv4 = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket(ipv4)"); return 1; } int enable = 1; if (setsockopt(socket_ipv6, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { perror("setsockopt(ipv6, SO_REUSEADDR = 1)"); return 1; } if (setsockopt(socket_ipv4, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { perror("setsockopt(ipv4, SO_REUSEADDR = 1)"); return 1; } /* this forces IPV6 to listen for both IPV4 and IPV6 connections; this in turn makes binding * another (IPV4) socket on the same port meaningless and results in -EADDRINUSE */ int disable = 0; if (setsockopt(socket_ipv6, IPPROTO_IPV6, IPV6_V6ONLY, &disable, sizeof(disable)) < 0) { perror("setsockopt(IPV6_V6ONLY = 0)"); return 1; } struct sockaddr_in6 address_ipv6; memset(&address_ipv6, 0, sizeof(address_ipv6)); address_ipv6.sin6_family = AF_INET6; address_ipv6.sin6_port = htons(PORT); if (inet_pton(AF_INET6, SRV_IPV6, &address_ipv6.sin6_addr) < 0) { perror("inet_pton(ipv6)"); return 1; } if (bind(socket_ipv6, (struct sockaddr*)&address_ipv6, sizeof(address_ipv6)) < 0) { perror("bind(ipv6)"); return 1; } /* we must start listening on IPV6 socket to make it active and kick in Linux rules for bind() */ if (listen(socket_ipv6, 3) < 0) { perror("listen(ipv6)"); return 1; } struct sockaddr_in address_ipv4; memset(&address_ipv4, 0, sizeof(address_ipv4)); address_ipv4.sin_family = AF_INET; address_ipv4.sin_port = htons(PORT); /* note the same port! */ if (inet_pton(AF_INET, SRV_IPV4, &address_ipv4.sin_addr) < 0) { perror("inet_pton(ipv4)"); return 1; } ret = bind(socket_ipv4, (struct sockaddr*)&address_ipv4, sizeof(address_ipv4)); if (ret != -1 || errno != EADDRINUSE) { fprintf(stderr, "bind(ipv4) was successful even though there is no IPV6_V6ONLY on same port\n"); return 1; } puts("test completed successfully"); return 0; }