Reputation: 505
I am using TCP accept() function on a dualstack socket. Next I am trying to print IPV4 mapped Ipv6 client address using getnameinfo(). For the first connection to accept(), getnameinfo() is correctly returning IPv4-Ipv6 client source address. But for second clients on wards it is returning the same IPv4 mapped Ipv6 address as first. Can any one help me in this ?
Pseudo Code:
struct sockaddr_storage client_ip;
socklen_t sock_len = sizeof(client_ip);
char buffer[INET6_ADDRSTRLEN];
struct sockaddr_in sa4;
static char *pclient_ipv4_addr = NULL;
while(1)
{
fd = accept(master_fd, (struct sockaddr*)&client_ip, &sock_len);
if (!getnameinfo((struct sockaddr*)&client_ip, sock_len, buffer,
sizeof(buffer),0,0,NI_NUMERICHOST))
{
pclient_ipv4_addr = buffer;
if (client_ip.ss_family==AF_INET6)
{
struct sockaddr_in6 *sa6=(struct sockaddr_in6*)&client_ip;
if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
{
memset(&sa4,0,sizeof(sa4));
sa4.sin_family=AF_INET;
sa4.sin_port=sa6->sin6_port;
memcpy(&sa4.sin_addr.s_addr, sa6->sin6_addr.s6_addr+12, 4);
memcpy(&client_ip, &sa4,sizeof(sa4));
sock_len=sizeof(sa4);
pclient_ipv4_addr = inet_ntoa(sa4.sin_addr);
printf("IPV4 add is %s\n", pclient_ipv4_addr );
}
}
}
memset(buffer, 0 , INET6_ADDRSTRLEN);
}
For eg: For First client pclient_ipv4_addr is "192.168.208.13", then for next client also
pclient_ipv4_addr is printing the same address. Is non reentrant of getnameinfo(0 any issue? How
can solve this?
Upvotes: 0
Views: 1576
Reputation: 596582
Try something more like this:
struct sockaddr_storage client_ip;
socklen_t sock_len;
while(1)
{
sock_len = sizeof(client_ip);
fd = accept(master_fd, (struct sockaddr*)&client_ip, &sock_len);
if (fd == -1)
break;
if (client_ip.ss_family==AF_INET)
{
struct sockaddr_in *sa4 = (struct sockaddr_in*) &client_ip;
printf("IPv4 add is %s\n", inet_ntoa(sa4->sin_addr) );
}
else if (client_ip.ss_family==AF_INET6)
{
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*) &client_ip;
if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
{
struct in_addr a4;
memcpy(&a4, sa6->sin6_addr.s6_addr+12, 4);
printf("IPv4 add is %s\n", inet_ntoa(a4) );
}
else
{
char buffer[INET6_ADDRSTRLEN];
if (getnameinfo((struct sockaddr*)&client_ip, sock_len, buffer, sizeof(buffer), 0, 0, NI_NUMERICHOST) == 0)
printf("IPv6 add is %s\n", buffer );
}
}
}
Upvotes: 1