IP to Geo

IP to Geo Commit Details

Date:2016-02-04 20:39:50 (4 years 8 months ago)
Author:Grégory Soutadé
Branch:master
Commit:57fce2afe292b86d208afa393aa02b59d3e88315
Parents: 36d5b0f43beb730b8c9eda2995079de0a122c5a2
Message:Move from recursive algorithm to linear one Update REQ_IPV4 and REQ_IPV6 defines

Changes:
Msrc/ip_to_geo.c (3 diffs)
Msrc/ip_to_geo.h (1 diff)
Msrc/protocol.h (1 diff)
Msrc/server.c (1 diff)
Msrc/test.c (1 diff)
Mtests/iptogeo.py (3 diffs)

File differences

src/ip_to_geo.c
1010
1111
1212
13
13
1414
1515
16
17
16
17
1818
19
20
19
2120
22
21
22
2323
24
25
26
24
25
26
27
28
29
30
31
2732
2833
29
30
3134
32
33
34
35
36
37
35
36
37
38
39
40
41
42
43
44
45
46
3847
39
40
41
42
43
44
45
46
48
49
50
51
52
53
54
55
56
57
58
4759
48
49
50
5160
61
62
5263
5364
5465
5566
56
67
5768
58
69
70
71
72
73
74
5975
6076
6177
62
78
6379
6480
6581
......
106122
107123
108124
109
125
110126
111127
112128
......
125141
126142
127143
128
144
129145
130146
131147
#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;
const ip_level* cur_ip = root;
unsigned cur_addr = (ipv4 >> (level*8)) & 0xFF;
const ip_level* cur_ip;
unsigned cur_addr;
// Optimistic search
if (cur_addr && level != 2)
while (1)
{
cur_average = cur_addr >> root->average;
cur_ip = root;
cur_addr = ip[level];
while (cur_average-- && cur_ip->next)
cur_ip = cur_ip->next;
}
// Optimistic search
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 \
do { \
if (cur_addr >= cur_ip->start && cur_addr <= cur_ip->end) \
{ \
if (cur_ip->childs) \
return ip_to_geo_rec(ipv4, level-1, cur_ip->childs); \
else \
return &cur_ip->code; \
} \
} while (0)
if (cur_addr >= cur_ip->start && cur_addr <= cur_ip->end) \
{ \
if (cur_ip->childs) \
{ \
level++; \
root = cur_ip->childs; \
continue; \
} \
else \
return &cur_ip->code; \
} \
}
if (cur_addr < cur_ip->start)
{
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)
if (cur_addr < cur_ip->start)
{
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;
}
else
IP_TEST;
break;
}
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;
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)
return -1;
}
cc = ip_to_geo((uint32_t)ret);
cc = ip_to_geo((uint8_t*)&ret, 4);
if (params->quiet_flag)
printf("%s\n", (cc)?(char*)get_country_code(cc):"<none>");
if (ret) return ret;
//self_test();
/* self_test(); */
if (params.ip_given)
return interactive(&params);
src/ip_to_geo.h
1212
1313
1414
15
15
1616
1717
1818
uint8_t code;
} 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);
int strip_to_int(char* strip_, uint32_t* ip);
src/protocol.h
99
1010
1111
12
13
12
13
1414
1515
1616
17
18
19
20
21
22
23
24
25
17
2618
2719
2820
#define REQ_REQ 1
#define REQ_RESP 0
uint8_t req;
#define REQ_IPV4 32
#define REQ_IPV6 128
#define REQ_IPV4 4
#define REQ_IPV6 16
uint8_t err;
uint8_t ip_type; // 4 or 6
uint32_t flags;
union {
uint32_t ipv4;
struct {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
}ipv6;
};
uint8_t ip[16]; // ipv4 or ipv6
uint8_t country_code[4];
} request_t;
src/server.c
117117
118118
119119
120
121
120
121
122
123
124
125
126
122127
123128
124129
else
{
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)
{
req.err = REQ_IP_NOT_FOUND;
src/test.c
66
77
88
9
910
10
11
1112
1213
1314
static void do_test(int a, int b, int c, int d)
{
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>");
}
tests/iptogeo.py
1313
1414
1515
16
17
16
17
1818
1919
2020
......
4040
4141
4242
43
43
4444
4545
4646
4747
4848
49
49
5050
5151
5252
......
6868
6969
7070
71
72
73
74
7571
76
72
7773
7874
7975
VERSION = 1
REQ = 1
RESP = 0
IPV4 = 32
IPV6 = 128
IPV4 = 4
IPV6 = 16
IP_NOT_FOUND = 6
self._socket.settimeout(self._timeout)
self._socket.connect((self._remote_addr, self._remote_port))
def _create_request(self, int_ip):
def _create_request(self, ip):
packet = ''
packet += struct.pack('<IBBBBI', IPToGeo.MAGIC, IPToGeo.VERSION, IPToGeo.REQ,
0, #err
IPToGeo.IPV4, # ip type
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('<I', 0) # country code
def ip_to_geo(self, ip):
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:
self._socket.send(packet)
except IOError, e:

Archive Download the corresponding diff file

Branches

Tags