question

arsaalandailyUK-7019 avatar image
1 Vote"
arsaalandailyUK-7019 asked arsaalandailyUK-7019 edited

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-serverwindows-api
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, your issue is more related to socket, I will added the related tag windows-api. Thank you for your understanding.

0 Votes 0 ·

1 Answer

XiaopoYang-MSFT avatar image
1 Vote"
XiaopoYang-MSFT answered

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.




5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.