getaddrinfo - connect UDP IPv6 to IPv4

  • Thread starter Thread starter JohannesWilde
  • Start date Start date
J

JohannesWilde

Guest
Hi there,


I tried to connect a local IPv6 UDP socket to a remote IPv4 IP, as follows:


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <iostream>



#include <winsock2.h>

#include <Ws2tcpip.h>

#include <io.h>





int getUdpAddrInfo_(const std::string &ip, const std::string &port, addrinfo **result)

{

struct addrinfo hints;

memset(&hints, 0, sizeof(struct addrinfo));

hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */

hints.ai_family = AF_UNSPEC; /* Allow IPv4 and IPv6 */

// For Linux and Windows Vista onwards, further specify options

hints.ai_flags = (AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG); /* For wildcard IP address */

hints.ai_protocol = IPPROTO_UDP; /* UDP protocol */

hints.ai_canonname = NULL;

hints.ai_addr = NULL;

hints.ai_next = NULL;



int const s = getaddrinfo(

/* ip */ ip.data(),

/* port */ port.data(),

/* hints */ &hints,

/* list */ result);

return s;

}





int main( int argc, char *argv[])

{

WORD wVersionRequested = MAKEWORD(2, 2);

WSADATA wsaData;

int const wsaStartupStatus = WSAStartup(wVersionRequested, &wsaData);



std::string const ipLocal("::");

std::string const portLocal("1234");



std::string const ipRemote("127.0.0.1");

std::string const portRemote("2345");



struct addrinfo *result;

int s = getUdpAddrInfo_(ipLocal, portLocal, &result);

if (s != 0)

{

exit(1);

}



SOCKET connectedSocket = INVALID_SOCKET;

if (nullptr == result)

{

exit(1);

}



struct addrinfo *rp = nullptr;

for (rp = result; rp != NULL; rp = rp->ai_next)

{

SOCKET sock = socket(rp->ai_family,

rp->ai_socktype,

rp->ai_protocol);



if (INVALID_SOCKET == sock)

{

continue;

}

else

{

if (AF_INET6 == rp->ai_family)

{

DWORD const ipv6Only = 0; // 0 - false

int const errorCode = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char const *)(&ipv6Only), sizeof(ipv6Only));

if (NO_ERROR != errorCode)

{

exit(1);

}

}

if (bind(sock, rp->ai_addr, rp->ai_addrlen) == NO_ERROR)

{



// connect

struct addrinfo *result2;

int const s2 = getUdpAddrInfo_(ipRemote, portRemote, &result2); // (1)

if (s2 != 0)

{

exit(1);

}



struct addrinfo *rp2 = nullptr;

bool connected = false;

if (result2)

{

for (rp2 = result2; rp2 != NULL; rp2 = rp2->ai_next)

{

if (connect(sock, rp2->ai_addr, rp2->ai_addrlen) == NO_ERROR)

{

connected = true;

break;

}

}

}

freeaddrinfo(result2);





if (connected)

{

connectedSocket = sock;

break;

}

}

else

{

closesocket(sock);

}

}

}



freeaddrinfo(result); /* No longer needed */



std::cout << "socket: " << connectedSocket << std::endl;



closesocket(connectedSocket);



WSACleanup();



exit(0);

}


The getUdpAddrInfo_ at (1) however only returns an IPv4 and no IPv6-mapped IPv4 address.


If I instead set


hints.ai_family = AF_INET6;



then the IPv4-mapped IPv6 address is returned as desired. Do I have to explicitely check what kind of socket I want to connect and ask for an appropriate address? Why does it not return the IPv6-mapped IPv4 address?


Best regards,


Johannes

Continue reading...
 

Similar threads

Π
Replies
0
Views
8
Παναγιώτης Φακίτσας
Π
Π
Replies
0
Views
13
Παναγιώτης Φακίτσας
Π
K
Replies
3
Views
200
Peter Foldes
P
Back
Top