I am writing a Java interposer (using LD_PRELOAD method) that modifies the recipient information in network communication system calls (connect/sendto).
Whenever Java tries to connect to another socket, I modify the intended recipient IP and port. Java uses IPv4-mapped-IPv6 addresses. So, I need to extract the IPv4 part of it. I achieve this using the method prescribed by Nicolas Bachschmidt at link.
The problem I am facing is that for every IPv4-mapped-IPv6 address, the result string (IPv4 part) I obtain is always 0.0.0.1
. Instead it should be 10.0.0.1
(for ::ffff:10.0.0.1
). I have tried this with different IP addresses. The result is always the same.
Two things I would like to mention that I think may be related:
When I tested the same program a month ago on my local network (that has
192.168.1.XXX
IP addresses), the program worked correctly. Point being (I don't think) there is any problem with code. To verify this, I asked a question on stackoverflow to convert IPv4-mapped-IPv6 addresses to IPv4, the link of which is mentioned earlier).I am trying to test this program now on my university network (that has
10.XXX.XXX.XXX
IP addresses) and VirtualBox (NAT mode that also gives10.XXX.XXX.XXX
addresses). However, I have tried to connect to10.0.0.1
and12.0.0.1
in these cases. Both give0.0.0.1
.
What am I doing wrong?
UPDATE: In Java, socket connection is done by the usual method:
Socket conn = new Socket("10.0.0.1", 50021);
The code to interpose this connect() system call is as follows:
int connect(int fd, const struct sockaddr *sk, socklen_t sl)
{
struct sockaddr_in *lsk_in = (struct sockaddr_in *) sk;
struct sockaddr_in6 *lsk_in6 = (struct sockaddr_in6 *) sk;
struct sockaddr_in addr4;
unsigned int len;
int nbytes, oport, tport, ret, i;
char ip_address[30];
char buffer[1024];
char tempBuffer[1024];
if((lsk_in->sin_family == AF_INET) || (lsk_in->sin_family == AF_INET6))
{
if(lsk_in->sin_family == AF_INET)
{
oport = ntohs(lsk_in->sin_port);
memcpy(&addr4.sin_addr.s_addr, &lsk_in->sin_addr.s_addr, sizeof(addr4.sin_addr.s_addr));
}
else if(lsk_in->sin_family == AF_INET6)
{
oport = ntohs(lsk_in6->sin6_port);
//This is where the problem is. I always get 0.0.0.1
memcpy(&addr4.sin_addr.s_addr, lsk_in6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
}
memset(buffer, '\0', sizeof(buffer));
sprintf(buffer, "%s%c%s%c%i", NAT_VM_CONNECT_RULE, NAT_VM_DELIMITER, (char *)inet_ntoa(addr4.sin_addr), NAT_VM_DELIMITER, oport);
nbytes = send(sock, buffer, strlen(buffer), 0);
if(DEBUG_MODE)
fprintf(stdout, "[LD_INTERPOSER] Sent[%s]\n", buffer);
memset(buffer, '\0', sizeof(buffer));
nbytes = recv(sock, buffer, sizeof(buffer), 0);
fprintf(stderr, "[LD_INTERPOSER] Received CONNECT [%s]\n", buffer);
memset(ip_address, '\0', sizeof(ip_address));
int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer;
strncpy(ip_address, buffer, pos);
ip_address[pos] = '\0';
tport = atoi(buffer + pos + 1);
if(lsk_in->sin_family == AF_INET)
{
lsk_in->sin_addr.s_addr = inet_addr(ip_address + 7);
lsk_in->sin_port = htons(tport);
}
else if(lsk_in->sin_family == AF_INET6)
{
inet_pton(AF_INET6, ip_address, &(lsk_in6->sin6_addr));
lsk_in6->sin6_port = htons(tport);
}
fprintf(stderr, "[LD_INTERPOSER] IP[%s], Port[%d] for VM[%s]\n", ip_address, tport, vm_ip);
}
return real_connect(fd, sk, sl);
}