You can refer to the Answer for Binding an IPv6 socket to an IPv6-mapped-IPv4-address. Wish The MSDN:IPv6-Enabled Server Code also help you.
IPV4 Client to IPV6 Server Connection Problem
I am new at IPV6 and I need to migrate my IPV4 code to dual-stack. I have two applications, one supports IPV6 (dual stack) and used at server side and the other one is IPV4 only client basically.
Note that, on same host, there are one server and multiple clients. Since the device supports dual stack, some closed applications have to use IPV4 only to communicate my server. Because of that, I am trying to use loopback IPs.
When I create a socket on server side for "::1" address, client cannot connect it by using "127.0.0.1" address. But, when I run the server on "::" address, client can connect and on sever side, I see the client IP as IPV4 mapped address (::ffff.127.0.0.1). But the thing is, I need to run the server on "::1" address because of some security concern.
Here is my code snipped on server side;
struct addrinfo hints, *result, *rp;
int rc = 0;
int sck = -1;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
rc = getaddrinfo(NULL, "9999", &hints, &result);
if (rc != 0) {
goto fail;
}
if (!result) {
goto fail;
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
sck = socket(rp->ai_family, rp->ai_socktype, 0);
if (sck == -1) {
continue;
}
int yes = 1;
if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
goto fail;
}
int v6OnlyEnabled = 0;
if (setsockopt(sck, IPPROTO_IPV6, IPV6_V6ONLY, &v6OnlyEnabled, sizeof(v6OnlyEnabled)) != 0) {
goto fail;
}
if (bind(sck, rp->ai_addr, rp->ai_addrlen) == 0) {
break; //Success
}
//Fail
close(sck);
sck = -1;
}
freeaddrinfo(result);
if (sck == -1) {
goto fail;
}
rc = listen(sck, 10);
if (rc < 0) {
//error
goto fail;
}
fail:
close(sck);
sck = -1;
and here is the client side;
struct addrinfo hints, *addr_list, *cur;
int retry = 0;
int sck = -1;
int rc = 0;
int val;
long arg;
struct pollfd pollfd;
socklen_t len = 0;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
rc = getaddrinfo(NULL, "9999", &hints, &addr_list);
if (rc != 0) {
printf("fail: %d\n", __LINE__);
goto fail;
}
for (cur = addr_list; (cur != NULL); cur = cur->ai_next) {
sck = socket(cur->ai_family, cur->ai_socktype, 0);
if (sck < 0) {
continue;
}
arg = fcntl(sck, F_GETFL, NULL);
arg |= O_NONBLOCK;
if (fcntl(sck, F_SETFL, arg) < 0) {
printf("fail: %d\n", __LINE__);
goto fail;
}
retry = 3;
while (--retry) {
//connecting
rc = connect(sck, cur->ai_addr, cur->ai_addrlen);
if (rc == 0) {
printf("OK: %d\n", __LINE__);
break;
}
pollfd.fd = sck;
pollfd.events = POLLIN | POLLOUT;
pollfd.revents = 0;
rc = poll(&pollfd, 1, 100000);
if (rc == 0) {
//timeout
printf("fail: %d\n", __LINE__);
close(sck);
sck = -1;
break;
}
len = sizeof(val);
rc = getsockopt(sck, SOL_SOCKET, SO_ERROR, (void *) (&val), &len);
if (rc < 0) {
//fail
printf("fail: %d\n", __LINE__);
close(sck);
sck = -1;
break;
}
if (val == EALREADY || val == EINPROGRESS) {
//connecting
printf("connecting: %d\n", __LINE__);
break;
}
if (val == ECONNREFUSED) {
(void)poll((void *)0, (unsigned long)0, (int)1000);
}
}
}
freeaddrinfo(addr_list);
if (sck < 0)
printf("fail %d\n", __LINE__);
fail:
close(sck);
sck = -1;
It seem disabling "IPV6_V6ONLY" option is not working. Also, I already compare "proc/sys/net/ipv6/conf/lo" and "all" folders' content. They seem same (except use_tempaddr nad mtu)
Please help me on that.
Thanks
Windows development Windows API - Win32
Windows for business Windows Server User experience Other
-
Xiaopo Yang - MSFT 12,731 Reputation points Microsoft External Staff
2021-06-24T06:38:21.11+00:00