我正在编写一个Java中介程序(使用ld_preload方法),用于修改网络通信系统调用(connect/sendto)中的收件人信息。
每当Java尝试连接到另一个套接字时,我都会修改预期的收件人IP和端口。Java使用IPv4映射的IPv6地址。所以,我需要提取它的ipv4部分。我使用nicolas bachschmidt在link中指定的方法来实现这一点。
我面临的问题是,对于每个ipv4映射的ipv6地址,我获得的结果字符串(ipv4部分)总是0.0.0.1。相反,它应该是10.0.0.1(对于::ffff:10.0.0.1)。我用不同的IP地址试过了。结果总是一样的。
我想说的两件事可能与此有关:
一个月前,当我在我的本地网络上测试同一个程序时(它有192.168.1.XXXip地址),该程序工作正常。重点是(我不认为)代码有任何问题。为了验证这一点,我在stackoverflow上提出了一个问题,要将ipv4-mapped-ipv6地址转换为ipv4,前面提到了ipv4的链接)。
我正试图在我的大学网络(有10.XXX.XXX.XXXIP地址)和VirtualBox(也有10.XXX.XXX.XXX地址的NAT模式)上测试这个程序。但是,在这些情况下,我尝试连接到10.0.0.112.0.0.1。两者都给出0.0.0.1
我做错什么了?
更新:在java中,socket连接是通过通常的方法完成的:

Socket conn = new Socket("10.0.0.1", 50021);

插入此connect()系统调用的代码如下:
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);
}

最佳答案

多亏了@ugoren hex dump技术(在注释中),我才发现ipv6结构本身包含一个0.0.0.1地址。我意识到问题可能是由于不同的jdk造成的。java项目是使用openjdk 7构建的,而我使用的pc有openjdk 6。当我将JDK更新到版本7时,错误消失了。然而,它让我陷入了另一个错误,这个错误被记录在一个新的stackoverflow question中,我仍然无法解决。

10-05 22:49
查看更多