Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing IPV4 socket(sockaddr_in) with IPV6 Socket(sockaddr_in6)

Tags:

c++

sockets

udp

I have a UDP Server which has to serve clients on both IPV4 and IPV6 address. I have created a single IPV6 socket to serve both the IPV4 and IPV6 clients.

The server stores IPAddress of the client on the very first communication. If it is a IPV4 client it stores as IPV4 Address and if it is a IPV6 client the server stores as IPV6 address. For all future communication it checks the storage whether this client is already known(stored) and then acts accordingly. For comparing the client address with the stored address I do a memcmp based on the family type (AF_INET and AF_INET6).

While communicating with IPV6 client the system is working normally but while communicating with IPV4 client the system behaves as if it never knew the client. While debugging I found that due to IPV6 the Socket Type the IPAddresss of the IPV4 client is received as IPV6 mapped IPV4 Address with family set to IPV6. To Solve this I need to compare between the IPV4 Stored address and the IPV6 mapped address. For this I am using sin_addr.s_addr of IPV4 structure and sin6_addr.in6_u.u6_addr32 of IPV6 structure. Please find the code snippet below.

ipv6_clientdata = (const struct sockaddr_in6 *)&sockStor;
ipv4_storeddata = (const struct sockaddr_in *)&(_stData[index].clientaddr);
if( (ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) && 
    (ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr) 
  )
{
    addrfound = true;
}

I would like to know whether this method is the proper solution for comparing IPV6 Mapped IPV4 address with IPV4 address or is there any other better way.

like image 801
Dinesh P.R. Avatar asked Nov 04 '22 19:11

Dinesh P.R.


1 Answers

As Joachim Pileborg reasoned, you don't need to care about this when the IPv4 address comes from an earlier packet received on the same socket because you will be comparing one mapped IPv4 address to another. It is only in the case that the IPv4 address was obtained from an external source that you have to care.

As João Augusto pointed out, you neglected to check that the IPv6 address indeed is an IPv4 mapped address before comparing the last 32 bits. There is a macro IN6_IS_ADDR_V4MAPPED that will help you do this:

if (
    IN6_IS_ADDR_V4MAPPED(&(ipv6_clientdata->sin6_addr)) &&
    (ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) &&
    (ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr)
) {
    addrfound = true;
}
like image 55
Celada Avatar answered Nov 12 '22 10:11

Celada