Move from recursive algorithm to linear one Update REQ_IPV4 and REQ_IPV6 defines
This commit is contained in:
parent
36d5b0f43b
commit
57fce2afe2
|
@ -10,56 +10,72 @@
|
||||||
|
|
||||||
#include "ip_data.c"
|
#include "ip_data.c"
|
||||||
|
|
||||||
static const uint8_t* ip_to_geo_rec(uint32_t ipv4, unsigned level, const ip_level* root)
|
static const uint8_t* ip_to_geo_rec(uint8_t* ip, unsigned level, const ip_level* root)
|
||||||
{
|
{
|
||||||
unsigned cur_average;
|
unsigned cur_average;
|
||||||
const ip_level* cur_ip = root;
|
const ip_level* cur_ip;
|
||||||
unsigned cur_addr = (ipv4 >> (level*8)) & 0xFF;
|
unsigned cur_addr;
|
||||||
|
|
||||||
// Optimistic search
|
while (1)
|
||||||
if (cur_addr && level != 2)
|
|
||||||
{
|
{
|
||||||
cur_average = cur_addr >> root->average;
|
cur_ip = root;
|
||||||
|
cur_addr = ip[level];
|
||||||
|
|
||||||
while (cur_average-- && cur_ip->next)
|
// Optimistic search
|
||||||
cur_ip = cur_ip->next;
|
if (cur_addr && level != 1)
|
||||||
}
|
{
|
||||||
|
cur_average = cur_addr >> root->average;
|
||||||
|
|
||||||
|
while (cur_average-- && cur_ip->next)
|
||||||
|
cur_ip = cur_ip->next;
|
||||||
|
}
|
||||||
|
|
||||||
#define IP_TEST \
|
#define IP_TEST \
|
||||||
do { \
|
|
||||||
if (cur_addr >= cur_ip->start && cur_addr <= cur_ip->end) \
|
|
||||||
{ \
|
{ \
|
||||||
if (cur_ip->childs) \
|
if (cur_addr >= cur_ip->start && cur_addr <= cur_ip->end) \
|
||||||
return ip_to_geo_rec(ipv4, level-1, cur_ip->childs); \
|
{ \
|
||||||
else \
|
if (cur_ip->childs) \
|
||||||
return &cur_ip->code; \
|
{ \
|
||||||
} \
|
level++; \
|
||||||
} while (0)
|
root = cur_ip->childs; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
return &cur_ip->code; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
if (cur_addr < cur_ip->start)
|
if (cur_addr < cur_ip->start)
|
||||||
{
|
{
|
||||||
for (cur_ip = cur_ip->prev; cur_ip; cur_ip = cur_ip->prev)
|
for (cur_ip = cur_ip->prev; cur_ip; cur_ip = cur_ip->prev)
|
||||||
|
IP_TEST;
|
||||||
|
}
|
||||||
|
else if (cur_addr > cur_ip->end)
|
||||||
|
{
|
||||||
|
for (cur_ip = cur_ip->next; cur_ip; cur_ip = cur_ip->next)
|
||||||
|
IP_TEST;
|
||||||
|
}
|
||||||
|
else
|
||||||
IP_TEST;
|
IP_TEST;
|
||||||
}
|
|
||||||
else if (cur_addr > cur_ip->end)
|
|
||||||
{
|
|
||||||
for (cur_ip = cur_ip->next; cur_ip; cur_ip = cur_ip->next)
|
|
||||||
IP_TEST;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
IP_TEST;
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const uint8_t* ip_to_geo(uint32_t ipv4)
|
const uint8_t* ip_to_geo(uint8_t* ip, unsigned ip_size)
|
||||||
{
|
{
|
||||||
const ip_level* first_level = s_root_ip[ipv4 >> 24];
|
const ip_level* first_level;
|
||||||
|
|
||||||
|
if (ip_size == 4)
|
||||||
|
first_level = s_root_ip[ip[0]];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (!first_level) return NULL;
|
if (!first_level) return NULL;
|
||||||
|
|
||||||
return ip_to_geo_rec(ipv4, 2, first_level);
|
return ip_to_geo_rec(ip, 1, first_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* get_country_code(const uint8_t* idx)
|
const uint8_t* get_country_code(const uint8_t* idx)
|
||||||
|
@ -106,7 +122,7 @@ int interactive(struct gengetopt_args_info* params)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cc = ip_to_geo((uint32_t)ret);
|
cc = ip_to_geo((uint8_t*)&ret, 4);
|
||||||
|
|
||||||
if (params->quiet_flag)
|
if (params->quiet_flag)
|
||||||
printf("%s\n", (cc)?(char*)get_country_code(cc):"<none>");
|
printf("%s\n", (cc)?(char*)get_country_code(cc):"<none>");
|
||||||
|
@ -125,7 +141,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
if (ret) return ret;
|
if (ret) return ret;
|
||||||
|
|
||||||
//self_test();
|
/* self_test(); */
|
||||||
|
|
||||||
if (params.ip_given)
|
if (params.ip_given)
|
||||||
return interactive(¶ms);
|
return interactive(¶ms);
|
||||||
|
|
|
@ -12,7 +12,7 @@ typedef struct ip_level_t {
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
} ip_level;
|
} ip_level;
|
||||||
|
|
||||||
const uint8_t* ip_to_geo(uint32_t ipv4);
|
const uint8_t* ip_to_geo(uint8_t* ip, unsigned ip_size);
|
||||||
const uint8_t* get_country_code(const uint8_t* idx);
|
const uint8_t* get_country_code(const uint8_t* idx);
|
||||||
int strip_to_int(char* strip_, uint32_t* ip);
|
int strip_to_int(char* strip_, uint32_t* ip);
|
||||||
|
|
||||||
|
|
|
@ -9,20 +9,12 @@ typedef struct {
|
||||||
#define REQ_REQ 1
|
#define REQ_REQ 1
|
||||||
#define REQ_RESP 0
|
#define REQ_RESP 0
|
||||||
uint8_t req;
|
uint8_t req;
|
||||||
#define REQ_IPV4 32
|
#define REQ_IPV4 4
|
||||||
#define REQ_IPV6 128
|
#define REQ_IPV6 16
|
||||||
uint8_t err;
|
uint8_t err;
|
||||||
uint8_t ip_type; // 4 or 6
|
uint8_t ip_type; // 4 or 6
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
union {
|
uint8_t ip[16]; // ipv4 or ipv6
|
||||||
uint32_t ipv4;
|
|
||||||
struct {
|
|
||||||
uint32_t a;
|
|
||||||
uint32_t b;
|
|
||||||
uint32_t c;
|
|
||||||
uint32_t d;
|
|
||||||
}ipv6;
|
|
||||||
};
|
|
||||||
uint8_t country_code[4];
|
uint8_t country_code[4];
|
||||||
} request_t;
|
} request_t;
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,13 @@ static int handle_request(thread_ctx_t* thread_ctx, int socket)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (thread_ctx->quiet < 0)
|
if (thread_ctx->quiet < 0)
|
||||||
syslog(LOG_DEBUG, "Request for %08x from socket %d", req.ipv4, socket);
|
{
|
||||||
geo = ip_to_geo(req.ipv4);
|
char dst[64];
|
||||||
|
inet_ntop((req.ip_type == REQ_IPV4)?AF_INET:AF_INET6, req.ip, dst, sizeof(dst));
|
||||||
|
syslog(LOG_DEBUG, "Request for %s from socket %d", dst, socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
geo = ip_to_geo(req.ip, req.ip_type);
|
||||||
if (!geo)
|
if (!geo)
|
||||||
{
|
{
|
||||||
req.err = REQ_IP_NOT_FOUND;
|
req.err = REQ_IP_NOT_FOUND;
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
static void do_test(int a, int b, int c, int d)
|
static void do_test(int a, int b, int c, int d)
|
||||||
{
|
{
|
||||||
const uint8_t* cc;
|
const uint8_t* cc;
|
||||||
|
uint8_t ip[4] = {a, b, c, d};
|
||||||
|
|
||||||
cc = ip_to_geo(IP(a,b,c,d));
|
cc = ip_to_geo(ip, 4);
|
||||||
printf("IP %d.%d.%d.%d : %s\n", a, b, c, d, (cc)?(char*)get_country_code(cc):"<none>");
|
printf("IP %d.%d.%d.%d : %s\n", a, b, c, d, (cc)?(char*)get_country_code(cc):"<none>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ class IPToGeo(object):
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
REQ = 1
|
REQ = 1
|
||||||
RESP = 0
|
RESP = 0
|
||||||
IPV4 = 32
|
IPV4 = 4
|
||||||
IPV6 = 128
|
IPV6 = 16
|
||||||
|
|
||||||
IP_NOT_FOUND = 6
|
IP_NOT_FOUND = 6
|
||||||
|
|
||||||
|
@ -40,13 +40,13 @@ class IPToGeo(object):
|
||||||
self._socket.settimeout(self._timeout)
|
self._socket.settimeout(self._timeout)
|
||||||
self._socket.connect((self._remote_addr, self._remote_port))
|
self._socket.connect((self._remote_addr, self._remote_port))
|
||||||
|
|
||||||
def _create_request(self, int_ip):
|
def _create_request(self, ip):
|
||||||
packet = ''
|
packet = ''
|
||||||
packet += struct.pack('<IBBBBI', IPToGeo.MAGIC, IPToGeo.VERSION, IPToGeo.REQ,
|
packet += struct.pack('<IBBBBI', IPToGeo.MAGIC, IPToGeo.VERSION, IPToGeo.REQ,
|
||||||
0, #err
|
0, #err
|
||||||
IPToGeo.IPV4, # ip type
|
IPToGeo.IPV4, # ip type
|
||||||
0) # flags
|
0) # flags
|
||||||
packet += struct.pack('<I', int_ip) # ipv4
|
packet += struct.pack('<BBBB', ip[0], ip[1], ip[2], ip[3]) # ipv4
|
||||||
packet += struct.pack('<III', 0, 0, 0) # ipv6
|
packet += struct.pack('<III', 0, 0, 0) # ipv6
|
||||||
packet += struct.pack('<I', 0) # country code
|
packet += struct.pack('<I', 0) # country code
|
||||||
|
|
||||||
|
@ -68,12 +68,8 @@ class IPToGeo(object):
|
||||||
|
|
||||||
def ip_to_geo(self, ip):
|
def ip_to_geo(self, ip):
|
||||||
splitted_ip = [int(a) for a in ip.split('.')]
|
splitted_ip = [int(a) for a in ip.split('.')]
|
||||||
int_ip = splitted_ip[0] << 24
|
|
||||||
int_ip |= splitted_ip[1] << 16
|
|
||||||
int_ip |= splitted_ip[2] << 8
|
|
||||||
int_ip |= splitted_ip[3] << 0
|
|
||||||
|
|
||||||
packet = self._create_request(int_ip)
|
packet = self._create_request(splitted_ip)
|
||||||
try:
|
try:
|
||||||
self._socket.send(packet)
|
self._socket.send(packet)
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user