IP to Geo

IP to Geo Git Source Tree

Root/src/ip_to_geo.c

1#include <sys/socket.h>
2#include <netinet/in.h>
3#include <arpa/inet.h>
4#include <stdint.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "ip_to_geo.h"
10
11#include "ip_data.c"
12
13static const uint8_t* ip_to_geo_rec(uint8_t* ip, unsigned level, const ip_level* root)
14{
15 unsigned cur_average;
16 const ip_level* cur_ip;
17 unsigned cur_addr;
18
19 while (1)
20 {
21 cur_ip = root;
22 cur_addr = ip[level];
23
24 // Optimistic search
25 if (cur_addr && level != 1)
26 {
27 cur_average = cur_addr >> root->average;
28
29 while (cur_average-- && cur_ip->next)
30 cur_ip = cur_ip->next;
31 }
32
33#define IP_TEST \
34 { \
35 if (cur_addr >= cur_ip->start && cur_addr <= cur_ip->end) \
36 { \
37 if (cur_ip->childs) \
38 { \
39 level++; \
40 root = cur_ip->childs; \
41 continue; \
42 } \
43 else \
44 return &cur_ip->code; \
45 } \
46 }
47
48 if (cur_addr < cur_ip->start)
49 {
50 for (cur_ip = cur_ip->prev; cur_ip; cur_ip = cur_ip->prev)
51 IP_TEST;
52 }
53 else if (cur_addr > cur_ip->end)
54 {
55 for (cur_ip = cur_ip->next; cur_ip; cur_ip = cur_ip->next)
56 IP_TEST;
57 }
58 else
59 IP_TEST;
60
61 break;
62 }
63 return NULL;
64}
65
66
67const uint8_t* ip_to_geo(uint8_t* ip, unsigned ip_size)
68{
69 const ip_level* first_level;
70
71 if (ip_size == 4)
72 first_level = s_root_ip[ip[0]];
73 else
74 return NULL;
75
76 if (!first_level) return NULL;
77
78 return ip_to_geo_rec(ip, 1, first_level);
79}
80
81const uint8_t* get_country_code(const uint8_t* idx)
82{
83 if (!idx || *idx >= sizeof(country_codes)/sizeof(country_codes[0]))
84 return NULL;
85
86 return country_codes[*idx];
87}
88
89int interactive(struct gengetopt_args_info* params)
90{
91 uint8_t ip[16];
92 const uint8_t* cc;
93 int ret, ip_size=4;
94
95 ret = inet_pton(AF_INET, params->ip_arg, ip);
96 if (ret != 1)
97 {
98 ip_size = 16;
99 ret = inet_pton(AF_INET6, params->ip_arg, ip);
100 if (ret != 1)
101 {
102 if (!params->quiet_flag)
103 fprintf(stderr, "Invalid IP %s\n", params->ip_arg);
104 return -1;
105 }
106 }
107
108 cc = ip_to_geo((uint8_t*)&ret, ip_size);
109
110 if (params->quiet_flag)
111 printf("%s\n", (cc)?(char*)get_country_code(cc):"<none>");
112 else
113 printf("IP %s : %s\n", params->ip_arg, (cc)?(char*)get_country_code(cc):"<none>");
114
115 return 0;
116}
117
118int main(int argc, char** argv)
119{
120 int ret;
121 struct gengetopt_args_info params;
122
123 ret = cmdline_parser (argc, argv, &params);
124
125 if (ret) return ret;
126
127 /* self_test(); */
128
129 if (params.ip_given)
130 return interactive(&params);
131 else if (params.daemon_flag)
132 return daemonize(&params);
133 else
134 cmdline_parser_print_help();
135
136 return 0;
137}

Archive Download this file

Branches

Tags