C 快速比较IP地址的最智能方法?

C 快速比较IP地址的最智能方法?,c,linux,networking,ip,libpcap,C,Linux,Networking,Ip,Libpcap,我有一个IP地址列表,存储方式如下: char IP_addresses_list[] = { "157.55.130", /* 157.55.130.0/24 */ "157.56.52", /* 157.56.52.0/24 */ "157.12.53", /* 157.12.53.0/24 */ ... }; 我从嗅探的数据包中获取IP地址(将其转换为struct iphdr*iph=(struct iphdr*)(数据包+sizeof(struct

我有一个IP地址列表,存储方式如下:

char IP_addresses_list[] = {
    "157.55.130", /* 157.55.130.0/24 */
    "157.56.52",  /* 157.56.52.0/24 */
    "157.12.53",  /* 157.12.53.0/24 */
    ...
};
我从嗅探的数据包中获取IP地址(将其转换为
struct iphdr*iph=(struct iphdr*)(数据包+sizeof(struct ether_header));
我使用
inet_ntop
将其转换为字符串;最后,我将数据包中的IP地址与列表中的IP地址进行比较,并使用以下代码:

/* 
* input: IP address to search in the list
* output: 1 if IP address is found in the list, 0 otherwise
*/
int find_IP_addr(char *server) {
    int ret = 0;
    int i, string_size1, string_size2;
    char *copied_server, *copied_const_char;
    char *save_ptr1, *save_ptr2;
    char dot[2] = ".";
    /* Here I store the IP address from the packet */
    char first_IPaddr_pkt[4], second_IPaddr_pkt[4], third_IPaddr_pkt[4];
    /* Here I store the IP address from the list */
    char first_IPaddr_list[4], second_IPaddr_list[4], third_IPaddr_list[4];

    string_size1 = strlen(server)+1;
    copied_server = (char *)malloc(string_size1 * sizeof(char));
    strcpy(copied_server, server);

    /* I store and compare the first three bits of the IP address */
    strcpy(first_IPaddr_pkt, strtok_r(copied_server, dot, &save_ptr1));
    strcpy(second_IPaddr_pkt, strtok_r(NULL, dot, &save_ptr1));
    strcpy(third_IPaddr_pkt, strtok_r(NULL, dot, &save_ptr1));  
    printf("tokenized %s, %s and %s\n", first_IPaddr_pkt, second_IPaddr_pkt, third_IPaddr_pkt);

    /* Now I scan the list */
    for (i=0; i<LIST_LENGTH; i++) {
        /* I copy an address from the list */
        string_size2 = strlen(IP_addresses_list[i])+1; // +1 for null character
        copied_const_char = (char *)malloc(string_size2 * sizeof(char));
        strcpy(copied_const_char, IP_addresses_list[i]);
        /* Let's split the address from the list */
        strcpy(first_IPaddr_list, strtok_r(copied_const_char, dot, &save_ptr2));
        strcpy(second_IPaddr_list, strtok_r(NULL, dot, &save_ptr2));
        strcpy(third_IPaddr_list, strtok_r(NULL, dot, &save_ptr2)); 
        printf("tokenized %s, %s and %s\n", first_IPaddr_list, second_IPaddr_list, third_IPaddr_list);
        /* I compare the first byte of the address from the packet I got and 
        the first byte of the address from the list:
        if they are different, there's no reason to continue comparing 
        the other bytes of the addresses */
        if (strcmp(first_IPaddr_pkt, first_IPaddr_list) != 0) {
            continue;
        }
        else  {
            if (strcmp(second_IPaddr_pkt, second_IPaddr_list) != 0) {
                continue;
        }
        else {
            if (strcmp(third_IPaddr_pkt, third_IPaddr_list) != 0) {
                continue;
            }
            else
                /* All the bytes are the same! */
                ret = 1;
            }
        }
        free(copied_const_char);
    }
    free(copied_server);
    return ret;
}

是否可以在不使用
inet\u ntop
的情况下进行比较,可能只是在两个地址仍然是
u\u int32\t
时进行比较

编辑:下面是一个解决方案示例,供阅读此问题的人参考

#include <stdio.h>
#include <sys/types.h>

int main() {

    // In the list I have: 104.40.0.0./13
    int cidr = 13;
    u_int32_t ipaddr_from_pkt = 1747488105;     // pkt coming from 104.40.141.105
    u_int32_t ipaddr_from_list = 1747451904;    // 104.40.0.0
    int mask = (-1) << (32 - cidr);

    if ((ipaddr_from_pkt & mask) == ipaddr_from_list)
        printf("IP address belongs to the given range!!!\n");
    else printf ("failure\n");

    return 0;
}
#包括
#包括
int main(){
//在列表中我有:104.40.0.0./13
int-cidr=13;
u_int32_t ipaddr_from_pkt=1747488105;//pkt from 104.40.141.105
u_int32_t ipaddr_from_list=1747451904;//104.40.0.0

int mask=(-1)性能问题与strcmp()无关,
malloc()
,但是没有必要

如果只使用IPv4地址,则只需16个字符即可存储该地址,这样就可以删除
malloc()
,并将临时存储声明为数组

但是,如果列表中有许多ip地址,则有一个重要的改进


首先,您需要对IP地址列表进行排序,然后使用
bsearch()
搜索正确的IP。这样,代码将在O(log(2n))时间内运行,比O(N)快得多,特别是对于大的
N

最快的方法是在字典中存储地址,请参见我的方法是:

  • 只需将
    strncat
    “.0”
    一起使用,即可构建有效的IPv4地址
  • 使用带有套接字类型等常量值的
    getaddrinfo
    来构建
    addrinfo
    结构
  • 比较
    addrinfo
    的相关字段

  • 基本上,

    中的示例可以避免将二进制数据转换为字符串。如果将它们保持为二进制,则比较起来非常容易:

    match = (ip & listed_mask) == listed_ip;
    
    “/24”是一个掩码。表示只有24个最高位是相关的。您可以将其转换为二进制掩码,如下所示:

    listed_mask = (-1) << (32 - 24);
    

    listed\u mask=(-1)这些地址都不是有效的IPv4地址,所以我先将它们转换成类似的地址,然后使用标准网络库。这有很多代码只用于ip地址比较。是的,不要使用
    malloc()
    /
    free()
    ,也没有合理的理由需要
    strtok()
    。“是否可以在不使用
    inet\u ntop
    的情况下进行比较,可能只是在两个地址仍然是
    u\u int32\t
    时进行比较?”?“为什么与32位无符号的
    int
    值相比无效?当新程序员开始关心可读性时,你让我认为你的代码是错误的,因此给出了错误的答案。
    strlen(服务器)+1
    我没有看到
    +1
    ,因为它与其他字符太接近,因此看起来像一个单独的对象。中没有字典。不建议使用仅链接的答案。呃,但是链接描述了如何实现字典?您不会将链接保留为答案。这就是我的答案。我写了“157.55.130”因为我的意思是“157.55.130.0/24”:我不想写从157.55.130.0到157.55.130.255的整个地址范围。如果我得到一个来自157.55.130.45的数据包,我只比较地址的前三个字节(157.55.130)你不必听从我的建议,但是让一个标准的库函数来完成你的工作,形成一个格式良好的地址绝对是我喜欢你的长手比较解决方案。我考虑使用为工作而设计的工具,在这种情况下,使用一个标准的库函数来设计。理解表示IP地址的字符串比编写自己的、可能存在错误的版本要聪明得多。假设你不必每秒解析数百万个地址,那么在我能想到的任何机器上,开销都可以忽略不计。我不擅长使用掩码和逻辑运算符:你能解释一下你的代码吗?/24是一个mask。您使用它来计算“列出的\u掩码”-见上文。然后您使用掩码用&操作屏蔽掉ip中不相关的8位。这将用零替换不相关的位。您将结果压缩到列表中列出的\u ip(已屏蔽)如果相等的话,你已经找到了匹配项。我的列表确实会很长,超过150个IP地址。
    b搜索
    可能是一个不错的策略!
    listed_mask = (-1) << (32 - 24);