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_ipv4[ip[0]];
74 else if (ip_size == 16)
75 first_level = s_root_ipv6[ip[0]];
76 else
77 return NULL;
78
79 if (!first_level) return NULL;
80
81 return ip_to_geo_rec(ip, 1, first_level);
82}
83
84const uint8_t* get_country_code(const uint8_t* idx)
85{
86 if (!idx || *idx >= sizeof(country_codes)/sizeof(country_codes[0]))
87 return NULL;
88
89 return country_codes[*idx];
90}
91
92int interactive(struct gengetopt_args_info* params)
93{
94 uint8_t ip[16];
95 const uint8_t* cc;
96 int ret, ip_size=4;
97
98 ret = inet_pton(AF_INET, params->ip_arg, ip);
99 if (ret != 1)
100 {
101 ip_size = 16;
102 ret = inet_pton(AF_INET6, params->ip_arg, ip);
103 if (ret != 1)
104 {
105 if (!params->quiet_flag)
106 fprintf(stderr, "Invalid IP %s\n", params->ip_arg);
107 return -1;
108 }
109 }
110
111 cc = ip_to_geo(ip, ip_size);
112
113 if (params->quiet_flag)
114 printf("%s\n", (cc)?(char*)get_country_code(cc):"<none>");
115 else
116 printf("IP %s : %s\n", params->ip_arg, (cc)?(char*)get_country_code(cc):"<none>");
117
118 return 0;
119}
120
121int main(int argc, char** argv)
122{
123 int ret;
124 struct gengetopt_args_info params;
125
126 ret = cmdline_parser (argc, argv, &params);
127
128 if (ret) return ret;
129
130 /* self_test(); */
131
132 if (params.ip_given)
133 return interactive(&params);
134 else if (params.daemon_flag)
135 return daemonize(&params);
136 else
137 cmdline_parser_print_help();
138
139 return 0;
140}

Archive Download this file

Branches

Tags