将IPv6转换为IPv4仅提供0.0.0.1

时间:2012-06-28 06:20:14

标签: c++ c linux sockets ip

我正在编写一个Java内插器(使用LD_PRELOAD方法)来修改网络通信系统调用中的收件人信息(connect / sendto)。

每当Java尝试连接到另一个套接字时,我都会修改预期的收件人IP和端口。 Java使用IPv4映射的IPv6地址。所以,我需要提取它的IPv4部分。我使用Nicolas Bachschmidt在{{​​3}}规定的方法实现了这一目标。

我面临的问题是,对于每个IPv4映射的IPv6地址,我获得的结果字符串(IPv4部分)始终是0.0.0.1。相反,它应该是10.0.0.1(对于::ffff:10.0.0.1)。我尝试过不同的IP地址。结果总是一样的。

我想提及的两件事我认为可能有关:

  1. 当我在一个月前在我的本地网络(具有192.168.1.XXX IP地址)上测试相同的程序时,该程序正常工作。点(我不认为)代码存在任何问题。为了验证这一点,我问了一个关于stackoverflow的问题,将IPv4映射的IPv6地址转换为IPv4,其链接在前面提到过。

  2. 我正在尝试在我的大学网络(具有10.XXX.XXX.XXX IP地址)和VirtualBox(也提供10.XXX.XXX.XXX地址的NAT模式)上测试此程序。但是,在这些情况下,我尝试连接到10.0.0.112.0.0.1。两者都给0.0.0.1

  3. 我做错了什么?

    更新:在Java中,套接字连接通过常用方法完成:

    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);
    }
    

1 个答案:

答案 0 :(得分:0)

感谢@ugoren十六进制转储技术(在评论中),我能够发现IPv6结构本身包含一个0.0.0.1地址。我意识到问题可能是由于不同的JDK。 Java项目是使用OpenJDK 7构建的,而我使用的PC有OpenJDK 6.当我将JDK更新到版本7时,错误消失了。但是,它让我遇到了另一个错误,这个错误记录在一个新的stackoverflow question,我仍然无法解决。