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

Archive Download this file

Branches

Tags