I have a list of IP addresses, stored like this:
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 */
...
};
I get the IP address from the sniffed packet (casting it to struct iphdr *iph = (struct iphdr *)(packet + sizeof(struct ether_header));
I convert it in a character string using inet_ntop
; finally, I compare the IP address from the packet with the ones in the list with the following code:
/*
* 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;
}
I'd like to make this more fast, without using strtok
, strcmp
, malloc
or free
.
In /usr/include/netinet/ip.h
I see that addresses are
u_int32_t saddr;
u_int32_t daddr;
is it possible to compare without even using inet_ntop
first, maybe just comparing the two addresses while they still are u_int32_t
?
EDIT: here's a solution example for whoever will read this question.
#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;
}
Thanks to iharob too for the bsearch
hint.