12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- #include <arpa/inet.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <unistd.h>
- /* 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;
- }
|