2014-04-13 55 views
0

我有两个字符串格式的IPv6地址。我需要比较这些地址的前48位。IPV6地址的按位比较

inet_pton()给我in6_addr。

如何从这些地址提取前n位?

+0

可寻址内存的最小单位是一个字节。所以除非n是字节大小的倍数,否则不能提取n'位。 – ajay

回答

1
struct in6_addr { 
unsigned char s6_addr[16]; /* IPv6 address */ 
}; 

char str[INET6_ADDRSTRLEN] //I assumed this has been filled up// 
struct in6_addr addr1; 

inet_pton(AF_INET6,&str, &addr1) 

inet_pton将为我们填充上述结构。如果你只想要第6字节(48位),

unsigned char array[6]; 
for(int i=0;i<6;i++) 
array[i] = addr1.s6_addr[i]; 

现在你可以绕过array您的subnet.this的比较是如何提取的第6字节,我会做最好的功能,比较第一这个地址不需要每次都这样做,它会让你的工作更轻松。

这是来自unix网络编程的richard stevens。这是一个简单的函数来比较两个IP address.you可以直接通过sockaddr_xx结构和功能将竭尽全力为您

#ifdef HAVE_SOCKADDR_DL_STRUCT 
#include <net/if_dl.h> 
#endif 

int 
sock_cmp_addr(const struct sockaddr *sa1, const struct sockaddr *sa2, 
     socklen_t salen) 
{ 
if (sa1->sa_family != sa2->sa_family) 
    return(-1); 

switch (sa1->sa_family) { 
case AF_INET: { 
    return(memcmp(&((struct sockaddr_in *) sa1)->sin_addr, 
        &((struct sockaddr_in *) sa2)->sin_addr, 
        sizeof(struct in_addr))); 
} 

#ifdef IPV6 
     case AF_INET6: { 
    return(memcmp(&((struct sockaddr_in6 *) sa1)->sin6_addr, 
        &((struct sockaddr_in6 *) sa2)->sin6_addr, 
        sizeof(struct in6_addr))); 
} 
#endif 

#ifdef AF_UNIX 
     case AF_UNIX: { 
    return(strcmp(((struct sockaddr_un *) sa1)->sun_path, 
        ((struct sockaddr_un *) sa2)->sun_path)); 
} 
#endif 

#ifdef HAVE_SOCKADDR_DL_STRUCT 
     case AF_LINK: { 
    return(-1);  /* no idea what to compare here ? */ 
} 
#endif 
} 
return (-1); 
} 

,你可以修改这个方案对第一n字节的子网工作,也它不是以字符串格式,但一些简单的修改会给你想要的结果。

1

正如@deviantfan建议的那样,您需要使用结构中存在的s6_addr结构。

unsigned char r=0; 
    int i; 
    //assuming your addresses are in add1 and addr2 after `inet_pton`. 
    for(i=0; i<6;i++) 
     r = (addr1.sin6_addr.s6_addr[i]^addr2.sin6_addr.s6_addr[i]) | r ; 


    if(!r){ 
     //Same first 48 bits 
    } 
    else{ 
     //Not same 
    } 

在这里,我关注下进行异或运算的6个字节的每个字节和所有的异或或运算在一起。只有当所有48位都相同时,最终结果才会变成zero