1

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:

  1. 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).

  2. 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 gives 10.XXX.XXX.XXX addresses). However, I have tried to connect to 10.0.0.1 and 12.0.0.1 in these cases. Both give 0.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);
}
Community
  • 1
  • 1
Muhammad Waqar
  • 849
  • 2
  • 13
  • 29
  • 1
    No one can help you if you don't show us the code that you've written thus far. – selbie Jun 28 '12 at 06:31
  • Have you checked the individual bytes of the IPv6 address? To make sure you get the correct bytes (byte ordering and such). – Some programmer dude Jun 28 '12 at 06:55
  • Print a hex dump (a simple `printf("%x %x %x...")`) of `lsk_in6->sin6_addr.s6_addr` before `memcpy` and `addr4.sin_addr.s_addr` after it. You'll see if the problem is before this (`sin6_addr` already bad), after this (`addr4` is fine), or during `memcpy` (unlikely). – ugoren Jun 28 '12 at 06:56
  • Also, it's only for addresses in the `10.x.x.x` range? Never for any other addresses? – Some programmer dude Jun 28 '12 at 06:56
  • @ugoren: You are right. By printing hex dump, I got the output `0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1`. What would cause this? :-/ – Muhammad Waqar Jun 28 '12 at 07:08
  • @JoachimPileborg: No, it's for every IP address that I try to connect to using Java. I have tried 10.0.0.XXX, 12.0.0.XXX and 192.168.1.XXX series uptil now. – Muhammad Waqar Jun 28 '12 at 07:09
  • @WaqarHameed, I think the question is how you got into the `AF_INET6` case. If you connect to an IPv4 address, you should be in `AF_INET`. I suggest that you print the various fields of the `sk` parameter (and `sl` too) and see if you can make sense of it. – ugoren Jun 28 '12 at 07:15
  • Calling this `connect` function, how is the socket address filled in in the `AF_INET6` case? – Some programmer dude Jun 28 '12 at 07:19
  • @ugoren: I posted an answer to this question myself, thanks to you. Java itself uses IPv4-mapped-IPv6 addresses for all connections that it makes, this is what I have observed. Hence `AF_INET6`. – Muhammad Waqar Jun 28 '12 at 07:21
  • That is an ipv6 address of ::1 which is the loopback address (similar to 127.0.0.1 in ipv4). Are you testing this by connecting back to the same machine? If so it's probably connecting over ipv6 using the loopback address, not the mapped ipv4 address... – jcoder Jun 28 '12 at 07:50

1 Answers1

0

Thanks to @ugoren hex dump technique (in comments), I was able to figure out that the IPv6 structure itself contained a 0.0.0.1 address. I realized that the problem may be due to different JDKs. The Java project was built using OpenJDK 7 while the PC I was using had OpenJDK 6. When I updated the JDK to version 7, the error disappeared. However, it has landed me to another error which is documented at a new stackoverflow question which I am still unable to resolve.

Community
  • 1
  • 1
Muhammad Waqar
  • 849
  • 2
  • 13
  • 29