2012-06-28 66 views
1

我正在编写一个Java内插器(使用LD_PRELOAD方法),它修改网络通信系统调用(connect/sendto)中的收件人信息。将IPv6转换为IPv4只给出0.0.0.1

每当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地址。结果总是一样的。

两件事情我想提一提,我认为可能涉及:

  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

我在做什么错?

更新:在Java中,插座连接是通过通常的方法来完成:

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

夹着该连接()系统调用是如下所述的代码:

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

如果您没有向我们展示您迄今为止编写的代码,没有人可以帮助您。 – selbie

+0

@selbie:添加的代码。 :) –

+0

您是否检查过IPv6地址的单个字节?确保你得到正确的字节(字节顺序等)。 –

回答

0

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