1 /*
2 * Project : ipv6calc
3 * File : databases/lib/libipv6calc_db_wrapper_GeoIP2.c
4 * Version : $Id: c3531f8e3bbf483d49332a0c7b6e391497268f77 $
5 * Copyright : 2019-2021 by Peter Bieringer <pb (at) bieringer.de>
6 *
7 * Information:
8 * ipv6calc DB-IP.com database wrapper for MaxMindDB databases
9 */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <dlfcn.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <stdlib.h>
17 #include <time.h>
18
19 #include "config.h"
20
21 #include "libipv6calcdebug.h"
22 #include "libipv6calc.h"
23
24 #include "libipv6calc_db_wrapper.h"
25
26
27 #ifdef SUPPORT_GEOIP2
28
29 #include "libipv6calc_db_wrapper_GeoIP2.h"
30
31 char geoip2_db_dir[PATH_MAX] = GEOIP2_DB;
32
33 static const char* wrapper_geoip2_info = "GeoIP2";
34
35
36 // DB used for resolution after automatic election, which is currently done by checking for DB files and the sequence in the header file
37 static int geoip2_db_country_v4 = 0;
38 static int geoip2_db_country_v6 = 0;
39 static int geoip2_db_region_city_v4 = 0;
40 static int geoip2_db_region_city_v6 = 0;
41 static int geoip2_db_asn_v4 = 0;
42 static int geoip2_db_asn_v6 = 0;
43
44 typedef struct {
45 unsigned int num;
46 int dbtype;
47 int dbym;
48 } s_ipv6calc_geoip2_db;
49
50 #define GeoIP2_FREE 0
51 #define GeoIP2_COMM 1
52 #define GeoIP2_MAX 2
53
54 static s_ipv6calc_geoip2_db geoip2_db_country_v4_best[GeoIP2_MAX];
55 static s_ipv6calc_geoip2_db geoip2_db_country_v6_best[GeoIP2_MAX];
56 static s_ipv6calc_geoip2_db geoip2_db_region_city_v4_best[GeoIP2_MAX];
57 static s_ipv6calc_geoip2_db geoip2_db_region_city_v6_best[GeoIP2_MAX];
58 static s_ipv6calc_geoip2_db geoip2_db_asn_v4_best[GeoIP2_MAX];
59 static s_ipv6calc_geoip2_db geoip2_db_asn_v6_best[GeoIP2_MAX];
60
61 static int type2index[GeoIP2_DB_MAX+1];
62
63 // select FREE database if COMM is older than given months
64 int geoip2_db_comm_to_free_switch_min_delta_months = 12;
65
66 // select better database of same product (COMM/FREE) only if not older than given months
67 int geoip2_db_better_max_delta_months = 1;
68
69 // select only a specific GeoIP2 db type
70 int geoip2_db_only_type = 0;
71
72
73 #define GeoIP2_UNPACK_YM(dbym) ((dbym > 0) ? ((dbym % 12) + ((dbym / 12)) * 100) : 0)
74
75
76 /* database usage map */
77 #define GeoIP2_DB_MAX_BLOCKS_32 2 // 0-63
78 static uint32_t geoip2_db_usage_map[GeoIP2_DB_MAX_BLOCKS_32];
79
80 #define GeoIP2_DB_USAGE_MAP_TAG(db) if (db < (32 * GeoIP2_DB_MAX_BLOCKS_32)) { \
81 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Tag usage for db: %d", db); \
82 geoip2_db_usage_map[db / 32] |= 1 << (db % 32); \
83 } else { \
84 fprintf(stderr, "FIXME: unsupported db value (exceed limit): %d (%d)\n", db, 32 * GeoIP2_DB_MAX_BLOCKS_32 - 1); \
85 exit(1); \
86 };
87
88 char geoip2_db_usage_string[IPV6CALC_STRING_MAX] = "";
89
90 // local cache
91 static MMDB_s mmdb_cache[GeoIP2_DB_MAX+1];
92
93 // local prototyping
94 static char *libipv6calc_db_wrapper_GeoIP2_dbfilename(const unsigned int type);
95 static void libipv6calc_db_wrapper_GeoIP2_close(const int type);
96
97
98 /*
99 * function initialise the GeoIP2 wrapper
100 *
101 * in : (nothing)
102 * out: 0=ok, 1=error
103 */
libipv6calc_db_wrapper_GeoIP2_wrapper_init(void)104 int libipv6calc_db_wrapper_GeoIP2_wrapper_init(void) {
105 int i, dbym, dbtype, ret, product;
106
107 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called");
108
109 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Check for standard GeoIP2 databases");
110
111 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "custom directory: %s", geoip2_db_dir);
112
113 /* check available databases for resolution */
114 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
115 // add entry to mapping
116 type2index[libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number] = i;
117
118 // clean local cache
119 mmdb_cache[libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number].file_size = 0;
120 mmdb_cache[libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number].flags = 0;
121
122 // add features to implemented
123 wrapper_features_by_source_implemented[IPV6CALC_DB_SOURCE_GEOIP2] |= libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features;
124
125 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "GeoIP2 database test for availability: %s", libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].filename);
126 if (libipv6calc_db_wrapper_GeoIP2_db_avail(libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number) == 1) {
127 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "GeoIP2 database available: %s", libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].description);
128 wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] |= libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features;
129 } else {
130 // db not available
131 continue;
132 };
133
134 ret = libipv6calc_db_wrapper_GeoIP2_open_type(libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number);
135 if (ret != MMDB_SUCCESS) {
136 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Error opening GeoIP2 by type");
137 continue;
138 };
139
140 dbtype = libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number;
141
142 if ((geoip2_db_only_type > 0) && (geoip2_db_only_type != dbtype)) {
143 // not selected
144 continue;
145 };
146
147 if ((libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].internal & IPV6CALC_DB_GEOIP2_INTERNAL_FREE) != 0) {
148 product = GeoIP2_FREE;
149 } else {
150 product = GeoIP2_COMM;
151 };
152
153 time_t db_time = mmdb_cache[dbtype].metadata.build_epoch;
154 struct tm *db_gmtime = gmtime(&db_time);
155
156 dbym = (db_gmtime->tm_year + 1900) * 12 + (db_gmtime->tm_mon + 1);
157 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "GEOIP2 type=%d dbym=%d Year/Month=%d unixtime=%llu", dbtype, dbym, GeoIP2_UNPACK_YM(dbym), (long long unsigned int) mmdb_cache[dbtype].metadata.build_epoch);
158
159 #define GeoIP2_DB_SELECT_BETTER(best) \
160 if ( \
161 (best.num == 0) \
162 || ( \
163 (best.dbym > 0) \
164 && ((best.dbym - dbym) <= geoip2_db_better_max_delta_months) \
165 ) \
166 ) { \
167 best.num = libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number; \
168 best.dbym = dbym; \
169 best.dbtype = dbtype; \
170 };
171
172
173 // note: databases are listed in sequence "less data" before "more data"
174 if ((libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features & IPV6CALC_DB_IPV4_TO_CC) != 0) {
175 GeoIP2_DB_SELECT_BETTER(geoip2_db_country_v4_best[product])
176 };
177
178 if ((libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features & IPV6CALC_DB_IPV6_TO_CC) != 0) {
179 GeoIP2_DB_SELECT_BETTER(geoip2_db_country_v6_best[product])
180 };
181
182 if ((libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features & (IPV6CALC_DB_IPV4_TO_REGION | IPV6CALC_DB_IPV4_TO_CITY)) != 0) {
183 GeoIP2_DB_SELECT_BETTER(geoip2_db_region_city_v4_best[product])
184 };
185
186 if ((libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features & (IPV6CALC_DB_IPV6_TO_REGION | IPV6CALC_DB_IPV6_TO_CITY)) != 0) {
187 GeoIP2_DB_SELECT_BETTER(geoip2_db_region_city_v6_best[product])
188 };
189
190 if ((libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features & IPV6CALC_DB_IPV4_TO_AS) != 0) {
191 GeoIP2_DB_SELECT_BETTER(geoip2_db_asn_v4_best[product])
192 };
193
194 if ((libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features & IPV6CALC_DB_IPV6_TO_AS) != 0) {
195 GeoIP2_DB_SELECT_BETTER(geoip2_db_asn_v6_best[product])
196 };
197
198 wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] |= libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].features;
199 };
200
201 // select free instead of comm, if comm is outdated and free available
202 if (geoip2_db_comm_to_free_switch_min_delta_months > 0) {
203 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "GeoIP2 database priority check (comm->free) after months: %d", geoip2_db_comm_to_free_switch_min_delta_months);
204 #define SELECT_FREE_INSTEAD_OF_COMM(free, comm, final) \
205 if ((free.num > 0) && (comm.num > 0)) { \
206 if (free.dbym - comm.dbym > geoip2_db_comm_to_free_switch_min_delta_months) { \
207 final = free.num; \
208 }; \
209 };
210 SELECT_FREE_INSTEAD_OF_COMM(geoip2_db_country_v4_best[GeoIP2_FREE], geoip2_db_country_v4_best[GeoIP2_COMM], geoip2_db_country_v4)
211 SELECT_FREE_INSTEAD_OF_COMM(geoip2_db_country_v6_best[GeoIP2_FREE], geoip2_db_country_v6_best[GeoIP2_COMM], geoip2_db_country_v6)
212 SELECT_FREE_INSTEAD_OF_COMM(geoip2_db_region_city_v4_best[GeoIP2_FREE], geoip2_db_region_city_v4_best[GeoIP2_COMM], geoip2_db_region_city_v4)
213 SELECT_FREE_INSTEAD_OF_COMM(geoip2_db_region_city_v6_best[GeoIP2_FREE], geoip2_db_region_city_v6_best[GeoIP2_COMM], geoip2_db_region_city_v6)
214 SELECT_FREE_INSTEAD_OF_COMM(geoip2_db_asn_v4_best[GeoIP2_FREE], geoip2_db_asn_v4_best[GeoIP2_COMM], geoip2_db_asn_v4)
215 SELECT_FREE_INSTEAD_OF_COMM(geoip2_db_asn_v6_best[GeoIP2_FREE], geoip2_db_asn_v6_best[GeoIP2_COMM], geoip2_db_asn_v6)
216 };
217
218 #define FILL_EMPTY(product, final) \
219 if ((product.num > 0) && (final == 0)) { \
220 final = product.num; \
221 };
222
223 // fill empty ones with comm
224 FILL_EMPTY(geoip2_db_country_v4_best[GeoIP2_COMM], geoip2_db_country_v4)
225 FILL_EMPTY(geoip2_db_country_v6_best[GeoIP2_COMM], geoip2_db_country_v6)
226 FILL_EMPTY(geoip2_db_region_city_v4_best[GeoIP2_COMM], geoip2_db_region_city_v4)
227 FILL_EMPTY(geoip2_db_region_city_v6_best[GeoIP2_COMM], geoip2_db_region_city_v6)
228 FILL_EMPTY(geoip2_db_asn_v4_best[GeoIP2_COMM], geoip2_db_asn_v4)
229 FILL_EMPTY(geoip2_db_asn_v6_best[GeoIP2_COMM], geoip2_db_asn_v6)
230
231 // fill empty ones with free
232 FILL_EMPTY(geoip2_db_country_v4_best[GeoIP2_FREE], geoip2_db_country_v4)
233 FILL_EMPTY(geoip2_db_country_v6_best[GeoIP2_FREE], geoip2_db_country_v6)
234 FILL_EMPTY(geoip2_db_region_city_v4_best[GeoIP2_FREE], geoip2_db_region_city_v4)
235 FILL_EMPTY(geoip2_db_region_city_v6_best[GeoIP2_FREE], geoip2_db_region_city_v6)
236 FILL_EMPTY(geoip2_db_asn_v4_best[GeoIP2_FREE], geoip2_db_asn_v4)
237 FILL_EMPTY(geoip2_db_asn_v6_best[GeoIP2_FREE], geoip2_db_asn_v6)
238
239 /* close handles which are not necessary further on */
240 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
241 if (mmdb_cache[libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number].file_size > 0) {
242 if (
243 (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == geoip2_db_country_v4_best[GeoIP2_FREE].num)
244 || (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == geoip2_db_country_v4_best[GeoIP2_COMM].num)
245 || (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == geoip2_db_country_v6_best[GeoIP2_FREE].num)
246 || (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == geoip2_db_country_v6_best[GeoIP2_COMM].num)
247 ) {
248 // database is in use
249 continue;
250 };
251
252 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Close further unused GeoIP2: type=%d desc='%s'", libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number, libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].description);
253 libipv6calc_db_wrapper_GeoIP2_close(libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number);
254 };
255 };
256
257 wrapper_features |= wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2];
258
259 return 0;
260 };
261
262
263 /*
264 * wrapper: GeoIP2_close
265 */
libipv6calc_db_wrapper_GeoIP2_close(const int type)266 static void libipv6calc_db_wrapper_GeoIP2_close(const int type) {
267 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called type=%u", type);
268
269 if (mmdb_cache[type].file_size > 0) {
270 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Close GeoIP2: type=%d desc='%s'", type, libipv6calc_db_wrapper_GeoIP2_db_file_desc[type2index[type]].description);
271 libipv6calc_db_wrapper_MMDB_close(&mmdb_cache[type]);
272 /* cleanup cache entry */
273 mmdb_cache[type].file_size = 0;
274 } else if (mmdb_cache[type].flags > 0) {
275 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Already closed GeoIP2: type=%d desc='%s'", type, libipv6calc_db_wrapper_GeoIP2_db_file_desc[type2index[type]].description);
276 };
277 };
278
279
280 /*
281 * function cleanup the GeoIP2 wrapper
282 *
283 * in : (nothing)
284 * out: 0=ok, 1=error
285 */
libipv6calc_db_wrapper_GeoIP2_wrapper_cleanup(void)286 int libipv6calc_db_wrapper_GeoIP2_wrapper_cleanup(void) {
287 int i;
288
289 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called");
290
291 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
292 libipv6calc_db_wrapper_GeoIP2_close(i);
293 };
294
295 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Finished");
296 return 0;
297 };
298
299
300 /*
301 * function info of GeoIP2 wrapper
302 *
303 * in : ptr and size of string to be filled
304 * out: modified string;
305 */
libipv6calc_db_wrapper_GeoIP2_wrapper_info(char * string,const size_t size)306 void libipv6calc_db_wrapper_GeoIP2_wrapper_info(char* string, const size_t size) {
307 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called");
308
309 snprintf(string, size, "GeoIP2 available databases: Country4=%d Country6=%d ASN4=%d ASN6=%d City4=%d City6=%d", \
310 (wrapper_features & IPV6CALC_DB_IPV4_TO_CC) ? 1 : 0, \
311 (wrapper_features & IPV6CALC_DB_IPV6_TO_CC) ? 1 : 0, \
312 (wrapper_features & IPV6CALC_DB_IPV4_TO_AS) ? 1 : 0, \
313 (wrapper_features & IPV6CALC_DB_IPV6_TO_AS) ? 1 : 0, \
314 (wrapper_features & IPV6CALC_DB_IPV4_TO_CITY) ? 1 : 0, \
315 (wrapper_features & IPV6CALC_DB_IPV6_TO_CITY) ? 1 : 0 \
316 );
317
318 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Finished");
319 return;
320 };
321
322 /*
323 * function print database info of GeoIP2 wrapper
324 *
325 * in : (void)
326 * out: (void)
327 */
libipv6calc_db_wrapper_GeoIP2_wrapper_print_db_info(const int level_verbose,const char * prefix_string)328 void libipv6calc_db_wrapper_GeoIP2_wrapper_print_db_info(const int level_verbose, const char *prefix_string) {
329 int ret, i, type, count = 0;
330
331 const char *prefix = "\0";
332 if (prefix_string != NULL) {
333 prefix = prefix_string;
334 };
335
336 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called");
337
338 IPV6CALC_DB_FEATURE_INFO(prefix, IPV6CALC_DB_SOURCE_GEOIP2)
339
340 fprintf(stderr, "%sGeoIP2: info of available databases in directory: %s\n", prefix, geoip2_db_dir);
341
342 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
343 type = libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number;
344
345 if (libipv6calc_db_wrapper_GeoIP2_db_avail(type)) {
346 // GeoIP2 returned that database is available
347 ret = libipv6calc_db_wrapper_GeoIP2_open_type(type);
348 if (ret != MMDB_SUCCESS) {
349 fprintf(stderr, "%sGeoIP2: %-30s: [%1d] %-30s (CAN'T OPEN database information)\n", prefix, libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].description, type, libipv6calc_db_wrapper_GeoIP2_dbfilename(type));
350 } else {
351 fprintf(stderr, "%sGeoIP2: %-30s: [%1d] %-30s (%s)\n", prefix, libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].description, type, libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].filename, libipv6calc_db_wrapper_GeoIP2_database_info(type));
352 libipv6calc_db_wrapper_GeoIP2_close(type);
353 count++;
354 };
355 } else {
356 if (level_verbose == LEVEL_VERBOSE2) {
357 fprintf(stderr, "%sGeoIP2: %-30s: [%1d] %-30s (%s)\n", prefix, libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].description, type, libipv6calc_db_wrapper_GeoIP2_dbfilename(type), strerror(errno));
358 };
359 continue;
360 };
361 };
362
363 if (count == 0) {
364 fprintf(stderr, "%sGeoIP2: NO available databases found in directory: %s\n", prefix, geoip2_db_dir);
365 } else {
366 if (level_verbose >= LEVEL_VERBOSE2) {
367 fprintf(stderr, "%sGeoIP2: detected best databases FREE Country4=%-3d DB%-2d %6d Country6=%-3d DB%-2d %6d City4=%-3d DB%-2d %6d City6=%-3d DB%-2d %6d\n"
368 , prefix
369 , geoip2_db_country_v4_best[GeoIP2_FREE].num
370 , geoip2_db_country_v4_best[GeoIP2_FREE].dbtype
371 , GeoIP2_UNPACK_YM(geoip2_db_country_v4_best[GeoIP2_FREE].dbym)
372 , geoip2_db_country_v6_best[GeoIP2_FREE].num
373 , geoip2_db_country_v6_best[GeoIP2_FREE].dbtype
374 , GeoIP2_UNPACK_YM(geoip2_db_country_v6_best[GeoIP2_FREE].dbym)
375 , geoip2_db_region_city_v4_best[GeoIP2_FREE].num
376 , geoip2_db_region_city_v4_best[GeoIP2_FREE].dbtype
377 , GeoIP2_UNPACK_YM(geoip2_db_region_city_v4_best[GeoIP2_FREE].dbym)
378 , geoip2_db_region_city_v6_best[GeoIP2_FREE].num
379 , geoip2_db_region_city_v6_best[GeoIP2_FREE].dbtype
380 , GeoIP2_UNPACK_YM(geoip2_db_region_city_v6_best[GeoIP2_FREE].dbym)
381 );
382
383 fprintf(stderr, "%sGeoIP2: detected best databases COMM Country4=%-3d DB%-2d %6d Country6=%-3d DB%-2d %6d City4=%-3d DB%-2d %6d City6=%-3d DB%-2d %6d\n"
384 , prefix
385 , geoip2_db_country_v4_best[GeoIP2_COMM].num
386 , geoip2_db_country_v4_best[GeoIP2_COMM].dbtype
387 , GeoIP2_UNPACK_YM(geoip2_db_country_v4_best[GeoIP2_COMM].dbym)
388 , geoip2_db_country_v6_best[GeoIP2_COMM].num
389 , geoip2_db_country_v6_best[GeoIP2_COMM].dbtype
390 , GeoIP2_UNPACK_YM(geoip2_db_country_v6_best[GeoIP2_COMM].dbym)
391 , geoip2_db_region_city_v4_best[GeoIP2_COMM].num
392 , geoip2_db_region_city_v4_best[GeoIP2_COMM].dbtype
393 , GeoIP2_UNPACK_YM(geoip2_db_region_city_v4_best[GeoIP2_COMM].dbym)
394 , geoip2_db_region_city_v6_best[GeoIP2_COMM].num
395 , geoip2_db_region_city_v6_best[GeoIP2_COMM].dbtype
396 , GeoIP2_UNPACK_YM(geoip2_db_region_city_v6_best[GeoIP2_COMM].dbym)
397 );
398 } else if (level_verbose >= LEVEL_VERBOSE) {
399 fprintf(stderr, "%sGeoIP2: detected best databases FREE Country4=%-3d Country6=%-3d City4=%-3d City6=%-3d\n"
400 , prefix
401 , geoip2_db_country_v4_best[GeoIP2_FREE].num
402 , geoip2_db_country_v6_best[GeoIP2_FREE].num
403 , geoip2_db_region_city_v4_best[GeoIP2_FREE].num
404 , geoip2_db_region_city_v6_best[GeoIP2_FREE].num
405 );
406
407 fprintf(stderr, "%sGeoIP2: detected best databases COMM Country4=%-3d Country6=%-3d City4=%-3d City6=%-3d\n"
408 , prefix
409 , geoip2_db_country_v4_best[GeoIP2_COMM].num
410 , geoip2_db_country_v6_best[GeoIP2_COMM].num
411 , geoip2_db_region_city_v4_best[GeoIP2_COMM].num
412 , geoip2_db_region_city_v6_best[GeoIP2_COMM].num
413 );
414
415 };
416
417 if (level_verbose >= LEVEL_VERBOSE) {
418 fprintf(stderr, "%sGeoIP2: selected best databases normal Country4=%-3d%s Country6=%-3d%s City4=%-3d%s City6=%-3d\n"
419 , prefix
420 , geoip2_db_country_v4
421 , (level_verbose >= LEVEL_VERBOSE2) ? " " : ""
422 , geoip2_db_country_v6
423 , (level_verbose >= LEVEL_VERBOSE2) ? " " : ""
424 , geoip2_db_region_city_v4
425 , (level_verbose >= LEVEL_VERBOSE2) ? " " : ""
426 , geoip2_db_region_city_v6
427 );
428
429 if (geoip2_db_comm_to_free_switch_min_delta_months > 0) {
430 fprintf(stderr, "%sGeoIP2: selected best databases method: COMM older than %d months are deselected in case of FREE is available\n"
431 , prefix
432 , geoip2_db_comm_to_free_switch_min_delta_months
433 );
434 };
435
436 if (geoip2_db_better_max_delta_months > 0) {
437 fprintf(stderr, "%sGeoIP2: selected best databases method: COMM/FREE with more features are only selected in case not older than %d months of already found COMM/FREE\n"
438 , prefix
439 , geoip2_db_better_max_delta_months
440 );
441 };
442
443 if (geoip2_db_only_type > 0) {
444 fprintf(stderr, "%sGeoIP2: selected best databases method: by applying given DB type filter: %d\n"
445 , prefix
446 , geoip2_db_only_type
447 );
448 };
449 };
450 };
451
452 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Finished");
453 return;
454 };
455
456
457 /*
458 * wrapper: string regarding used database infos
459 */
libipv6calc_db_wrapper_GeoIP2_wrapper_db_info_used(void)460 char *libipv6calc_db_wrapper_GeoIP2_wrapper_db_info_used(void) {
461 int type, i;
462 char tempstring[IPV6CALC_STRING_MAX];
463 char *info;
464
465 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called");
466
467 for (i = 0; i < GeoIP2_DB_MAX_BLOCKS_32; i++) {
468 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "geoip2_db_usage_map[%d]=%08x", i, (unsigned int) geoip2_db_usage_map[i]);
469 };
470
471 for (type = 0; type < 32 * GeoIP2_DB_MAX_BLOCKS_32; type++) {
472 if ((geoip2_db_usage_map[type / 32] & (1 << (type % 32))) != 0) {
473 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "DB type used: %d", type);
474
475 info = libipv6calc_db_wrapper_GeoIP2_database_info(type);
476
477 if (info == NULL) { continue; }; // NULL pointer returned
478
479 if (strlen(info) == 0) { continue; }; // empty string returned
480
481 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "type=%d info=%s", type, info);
482
483 if (strlen(geoip2_db_usage_string) > 0) {
484 if (strstr(geoip2_db_usage_string, info) != NULL) {
485 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "type=%d info=%s (skip, already displayed)", type, info);
486 continue;
487 }; // string already included
488
489 snprintf(tempstring, sizeof(tempstring), "%s / %s", geoip2_db_usage_string, info);
490 } else {
491 snprintf(tempstring, sizeof(tempstring), "%s", info);
492 };
493
494 snprintf(geoip2_db_usage_string, sizeof(geoip2_db_usage_string), "%s", tempstring);
495 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "type=%d geoip2_db_usage_string=%s", type, geoip2_db_usage_string);
496 };
497 };
498
499 return(geoip2_db_usage_string);
500 };
501
502
503 /*******************************
504 * Wrapper extension functions for GeoIP2
505 *******************************/
506
507 /*
508 * wrapper extension: GeoIP2_dbfilename
509 */
libipv6calc_db_wrapper_GeoIP2_dbfilename(const unsigned int type)510 static char *libipv6calc_db_wrapper_GeoIP2_dbfilename(const unsigned int type) {
511 static char tempstring[IPV6CALC_STRING_MAX];
512 int entry = -1, i;
513
514 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called: %s type=%d", wrapper_geoip2_info, type);
515
516 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
517 if (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == type) {
518 entry = i;
519 break;
520 };
521 };
522
523 if (entry < 0) {
524 return(NULL);
525 };
526
527 snprintf(tempstring, sizeof(tempstring), "%s/%s", geoip2_db_dir, libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].filename);
528
529 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Finished: %s type=%d has filename=%s", wrapper_geoip2_info, type, tempstring);
530
531 return(tempstring);
532 };
533
534
535 /*
536 * wrapper extension: GeoIP2_dbdescription
537 */
libipv6calc_db_wrapper_GeoIP2_dbdescription(const unsigned int type)538 const char *libipv6calc_db_wrapper_GeoIP2_dbdescription(const unsigned int type) {
539 int entry = -1, i;
540
541 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called: %s type=%d", wrapper_geoip2_info, type);
542
543 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
544 if (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == type) {
545 entry = i;
546 break;
547 };
548 };
549
550 if (entry < 0) {
551 return("unknown");
552 };
553
554 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Finished: %s type=%d has description=%s", wrapper_geoip2_info, type, libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].description);
555
556 return(libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].description);
557 };
558
559
560 /*
561 * wrapper extension: GeoIP2_db_avail
562 * ret: 1=avail 0=not-avail
563 */
libipv6calc_db_wrapper_GeoIP2_db_avail(const unsigned int type)564 int libipv6calc_db_wrapper_GeoIP2_db_avail(const unsigned int type) {
565 char *filename;
566 int r = 0;
567
568 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called: %s type=%d", wrapper_geoip2_info, type);
569
570 filename = libipv6calc_db_wrapper_GeoIP2_dbfilename(type);
571
572 if (filename == NULL) {
573 goto END_libipv6calc_db_wrapper;
574 };
575
576 r = (access(filename, R_OK) == 0) ? 1:0;
577
578 if (r == 0) {
579 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Finished: %s type=%d (still unknown) (r=%d: %s)", wrapper_geoip2_info, type, r, strerror(errno));
580 } else {
581 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Finished: %s type=%d (%s) (r=%d)", wrapper_geoip2_info, type, filename, r);
582 };
583
584 END_libipv6calc_db_wrapper:
585 return(r);
586 };
587
588
589 /*
590 * wrapper extension: GeoIP2_open_type
591 * input:
592 * type (mandatory)
593 * modified:
594 * mmdb_cache
595 * output:
596 * result
597 */
libipv6calc_db_wrapper_GeoIP2_open_type(const unsigned int type)598 int libipv6calc_db_wrapper_GeoIP2_open_type(const unsigned int type) {
599 char *filename;
600 int entry = -1, i;
601 int ret;
602
603 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called: %s type=%d", wrapper_geoip2_info, type);
604
605 // check for valid type
606 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
607 if (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == type) {
608 entry = i;
609 break;
610 };
611 };
612
613 if (entry < 0) {
614 mmdb_cache[type].file_size = 0;
615 mmdb_cache[type].flags = 0;
616 ret = MMDB_FILE_OPEN_ERROR;
617 goto END_libipv6calc_db_wrapper;
618 };
619
620 if (mmdb_cache[type].file_size > 0) {
621 // already open
622 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Database already opened (cached) type=%d", type);
623 ret = MMDB_SUCCESS;
624 goto END_libipv6calc_db_wrapper;
625 };
626
627 // retrieve filename
628 filename = libipv6calc_db_wrapper_GeoIP2_dbfilename(type);
629
630 if (filename == NULL) {
631 mmdb_cache[type].file_size = 0;
632 mmdb_cache[type].flags = 0;
633 ret = MMDB_FILE_OPEN_ERROR;
634 goto END_libipv6calc_db_wrapper;
635 };
636
637 ret = libipv6calc_db_wrapper_MMDB_open(filename, MMDB_MODE_MMAP, &mmdb_cache[type]);
638
639 if (ret != MMDB_SUCCESS) {
640 if (ipv6calc_quiet == 0) {
641 fprintf(stderr, "MMDB_open failed: %s (%s)\n", libipv6calc_db_wrapper_MMDB_strerror(ret), filename);
642 if (ret == MMDB_IO_ERROR) {
643 fprintf(stderr, "MMDB_open IO error: %s (%s)\n", strerror(errno), filename);
644 };
645 };
646 mmdb_cache[type].file_size = 0;
647 mmdb_cache[type].flags = 0;
648 ret = MMDB_FILE_OPEN_ERROR;
649 goto END_libipv6calc_db_wrapper;
650 };
651
652 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Database successfully opened (fill-cache), type=%d", type);
653
654 END_libipv6calc_db_wrapper:
655 return(ret);
656 };
657
658
659 /*******************************
660 * Wrapper functions for GeoIP2
661 *******************************/
662
663
664 /*
665 * wrapper: GeoIP2_database_info
666 */
libipv6calc_db_wrapper_GeoIP2_database_info(const unsigned int type)667 char *libipv6calc_db_wrapper_GeoIP2_database_info(const unsigned int type) {
668 static char resultstring[IPV6CALC_STRING_MAX];
669 char datastring[IPV6CALC_STRING_MAX];
670 char tempstring[IPV6CALC_STRING_MAX];
671
672 MMDB_s mmdb;
673 int ret, i, entry = -1;
674
675
676 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called: %s", wrapper_geoip2_info);
677
678 // check for valid type
679 for (i = 0; i < MAXENTRIES_ARRAY(libipv6calc_db_wrapper_GeoIP2_db_file_desc); i++) {
680 if (libipv6calc_db_wrapper_GeoIP2_db_file_desc[i].number == (type & 0xffff)) {
681 entry = i;
682 break;
683 };
684 };
685
686 if (entry < 0) {
687 ERRORPRINT_WA("Invalid type (FIX CODE): %d", type);
688 goto END_libipv6calc_db_wrapper;
689 };
690
691
692 ret = libipv6calc_db_wrapper_GeoIP2_open_type(type);
693
694 if (ret != MMDB_SUCCESS) {
695 snprintf(resultstring, sizeof(resultstring), "%s", "(CAN'T OPEN database information)");
696 goto END_libipv6calc_db_wrapper;
697 };
698
699 // get metadata
700 //
701 /*
702 const char *meta_dump = "\n"
703 " Database metadata\n"
704 " Node count: %i\n"
705 " Record size: %i bits\n"
706 " IP version: IPv%i\n"
707 " Binary format: %i.%i\n"
708 " Build epoch: %llu (%s)\n"
709 " Type: %s\n"
710 " Languages: ";
711
712 fprintf(stdout, meta_dump,
713 */
714
715 mmdb = mmdb_cache[type];
716
717 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "meta: NodeCount=%i RecordSize=%i IpVersion=%i BinaryFormat=%i.%i BuildTime=%llu Type=%s", \
718 mmdb.metadata.node_count,
719 mmdb.metadata.record_size,
720 mmdb.metadata.ip_version,
721 mmdb.metadata.binary_format_major_version,
722 mmdb.metadata.binary_format_minor_version,
723 (long long unsigned int) mmdb.metadata.build_epoch,
724 mmdb.metadata.database_type);
725
726 const time_t epoch = (const time_t)mmdb.metadata.build_epoch;
727
728 char year[5];
729 strftime(year, sizeof(year), "%Y", gmtime(&epoch));
730 snprintf(resultstring, sizeof(resultstring), "%s Copyright (c) %s MaxMind All Rights Reserved"
731 , mmdb.metadata.database_type
732 , year
733 );
734
735 strftime(datastring, sizeof(datastring), "%Y%m%d-%H%M%S UTC", gmtime(&epoch));
736 snprintf(tempstring, sizeof(tempstring), "%s, created: %s", resultstring, datastring);
737 snprintf(resultstring, sizeof(resultstring), "%s", tempstring);
738
739 END_libipv6calc_db_wrapper:
740 return(resultstring);
741 };
742
743
744 /*********************************************
745 * Abstract functions
746 * *******************************************/
747
748 /* function query for feature set
749 * ret=-1: unknown
750 * 0 : not matching
751 * 1 : ok
752 */
libipv6calc_db_wrapper_GeoIP2_has_features(uint32_t features)753 int libipv6calc_db_wrapper_GeoIP2_has_features(uint32_t features) {
754 int result = -1;
755
756 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Called with feature value to test: 0x%08x", features);
757
758 if ((wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] & features) == features) {
759 result = 1;
760 } else {
761 result = 0;
762 };
763
764 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Return with result: %d", result);
765 return(result);
766 };
767
768
769 /* country code */
libipv6calc_db_wrapper_GeoIP2_wrapper_country_code_by_addr(const ipv6calc_ipaddr * ipaddrp,char * country,const size_t country_len)770 int libipv6calc_db_wrapper_GeoIP2_wrapper_country_code_by_addr(const ipv6calc_ipaddr *ipaddrp, char *country, const size_t country_len) {
771 int result = MMDB_INVALID_DATA_ERROR;
772
773 int GeoIP2_type = 0;
774
775 if (ipaddrp->proto == IPV6CALC_PROTO_IPV4) {
776 GeoIP2_type = geoip2_db_country_v4;
777
778 if ((wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] & IPV6CALC_DB_IPV4_TO_CC) == 0) {
779 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "No GeoIP2 database supporting IPv4 country available");
780 goto END_libipv6calc_db_wrapper;
781 };
782 } else if (ipaddrp->proto == IPV6CALC_PROTO_IPV6) {
783 GeoIP2_type = geoip2_db_country_v6;
784
785 if ((wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] & IPV6CALC_DB_IPV6_TO_CC) == 0) {
786 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "No GeoIP2 database supporting IPv6 country available");
787 goto END_libipv6calc_db_wrapper;
788 };
789 } else {
790 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Unsupported proto: %d", ipaddrp->proto);
791 goto END_libipv6calc_db_wrapper;
792 };
793
794 result = libipv6calc_db_wrapper_GeoIP2_open_type(GeoIP2_type);
795
796 if (result != MMDB_SUCCESS) {
797 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Error opening GeoIP2 by type");
798 goto END_libipv6calc_db_wrapper;
799 };
800
801 result = libipv6calc_db_wrapper_MMDB_country_code_by_addr(ipaddrp, country, country_len, &mmdb_cache[GeoIP2_type]);
802
803 if (result != MMDB_SUCCESS) {
804 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "no match found");
805 goto END_libipv6calc_db_wrapper;
806 };
807
808 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "result country=%s", country);
809
810 GeoIP2_DB_USAGE_MAP_TAG(GeoIP2_type);
811
812 goto END_libipv6calc_db_wrapper; // keep db open
813
814 END_libipv6calc_db_wrapper:
815 return(result);
816 };
817
818
819 /* ASN */
libipv6calc_db_wrapper_GeoIP2_wrapper_asn_by_addr(const ipv6calc_ipaddr * ipaddrp)820 uint32_t libipv6calc_db_wrapper_GeoIP2_wrapper_asn_by_addr(const ipv6calc_ipaddr *ipaddrp) {
821 uint32_t result = ASNUM_AS_UNKNOWN;
822
823 int GEOIP2_type = 0;
824
825 if (ipaddrp->proto == IPV6CALC_PROTO_IPV4) {
826 GEOIP2_type = geoip2_db_asn_v4;
827
828 if ((wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] & IPV6CALC_DB_IPV4_TO_AS) == 0) {
829 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "No GeoIP2 database supporting IPv4 ASN");
830 goto END_libipv6calc_db_wrapper;
831 };
832 } else if (ipaddrp->proto == IPV6CALC_PROTO_IPV6) {
833 GEOIP2_type = geoip2_db_asn_v6;
834
835 if ((wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] & IPV6CALC_DB_IPV6_TO_AS) == 0) {
836 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "No GeoIP2 database supporting IPv6 ASN");
837 goto END_libipv6calc_db_wrapper;
838 };
839 } else {
840 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Unsupported proto: %d", ipaddrp->proto);
841 goto END_libipv6calc_db_wrapper;
842 };
843
844 result = libipv6calc_db_wrapper_GeoIP2_open_type(GEOIP2_type);
845
846 if (result != MMDB_SUCCESS) {
847 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Error opening GeoIP2 by type");
848 goto END_libipv6calc_db_wrapper;
849 };
850
851 result = libipv6calc_db_wrapper_MMDB_asn_by_addr(ipaddrp, &mmdb_cache[GEOIP2_type]);
852
853 if (result == ASNUM_AS_UNKNOWN) {
854 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "no match found");
855 goto END_libipv6calc_db_wrapper;
856 };
857
858 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "result ASN=%u", result);
859
860 GeoIP2_DB_USAGE_MAP_TAG(GEOIP2_type);
861
862 goto END_libipv6calc_db_wrapper;
863
864 END_libipv6calc_db_wrapper:
865 return(result);
866 };
867
868
869 /* GeonameID */
libipv6calc_db_wrapper_GeoIP2_wrapper_GeonameID_by_addr(const ipv6calc_ipaddr * ipaddrp,int * source_ptr)870 uint32_t libipv6calc_db_wrapper_GeoIP2_wrapper_GeonameID_by_addr(const ipv6calc_ipaddr *ipaddrp, int *source_ptr) {
871 uint32_t result = IPV6CALC_DB_GEO_GEONAMEID_UNKNOWN;
872
873 int GEOIP2_type = 0;
874
875 if (ipaddrp->proto == IPV6CALC_PROTO_IPV4) {
876 GEOIP2_type = geoip2_db_region_city_v4;
877
878 if ((wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] & IPV6CALC_DB_IPV4_TO_GEONAMEID) == 0) {
879 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "No GeoIP2 database supporting IPv4 GeonameID");
880 goto END_libipv6calc_db_wrapper;
881 };
882 } else if (ipaddrp->proto == IPV6CALC_PROTO_IPV6) {
883 GEOIP2_type = geoip2_db_region_city_v6;
884
885 if ((wrapper_features_by_source[IPV6CALC_DB_SOURCE_GEOIP2] & IPV6CALC_DB_IPV6_TO_GEONAMEID) == 0) {
886 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "No GeoIP2 database supporting IPv6 GeonameID");
887 goto END_libipv6calc_db_wrapper;
888 };
889 } else {
890 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Unsupported proto: %d", ipaddrp->proto);
891 goto END_libipv6calc_db_wrapper;
892 };
893
894 result = libipv6calc_db_wrapper_GeoIP2_open_type(GEOIP2_type);
895
896 if (result != MMDB_SUCCESS) {
897 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Error opening GeoIP2 by type");
898 goto END_libipv6calc_db_wrapper;
899 };
900
901 result = libipv6calc_db_wrapper_MMDB_GeonameID_by_addr(ipaddrp, &mmdb_cache[GEOIP2_type], source_ptr);
902
903 if (result == IPV6CALC_DB_GEO_GEONAMEID_UNKNOWN) {
904 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "no match found");
905 goto END_libipv6calc_db_wrapper;
906 };
907
908 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "result GeonameID=%u", result);
909
910 GeoIP2_DB_USAGE_MAP_TAG(GEOIP2_type);
911
912 goto END_libipv6calc_db_wrapper;
913
914 END_libipv6calc_db_wrapper:
915 return(result);
916 };
917
918
919 /* all information */
libipv6calc_db_wrapper_GeoIP2_all_by_addr(const ipv6calc_ipaddr * ipaddrp,libipv6calc_db_wrapper_geolocation_record * recordp)920 int libipv6calc_db_wrapper_GeoIP2_all_by_addr(const ipv6calc_ipaddr *ipaddrp, libipv6calc_db_wrapper_geolocation_record *recordp) {
921 int result = -1;
922
923 int GeoIP2_type = 0;
924 int GeoIP2_type_asn = 0;
925
926 libipv6calc_db_wrapper_geolocation_record record_asn;
927
928 if (ipaddrp->proto == IPV6CALC_PROTO_IPV4) {
929 GeoIP2_type = geoip2_db_region_city_v4;
930 GeoIP2_type_asn = geoip2_db_asn_v4;
931
932 if (GeoIP2_type == 0) {
933 // fallback
934 GeoIP2_type = geoip2_db_country_v4;
935 };
936 } else if (ipaddrp->proto == IPV6CALC_PROTO_IPV6) {
937 GeoIP2_type = geoip2_db_region_city_v6;
938 GeoIP2_type_asn = geoip2_db_asn_v6;
939
940 if (GeoIP2_type == 0) {
941 // fallback
942 GeoIP2_type = geoip2_db_country_v6;
943 };
944 } else {
945 DEBUGPRINT_WA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Unsupported proto: %d", ipaddrp->proto);
946 goto END_libipv6calc_db_wrapper;
947 };
948
949 result = libipv6calc_db_wrapper_GeoIP2_open_type(GeoIP2_type);
950
951 if (result != MMDB_SUCCESS) {
952 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Error opening GeoIP2 by type");
953 goto END_libipv6calc_db_wrapper;
954 };
955
956 result = libipv6calc_db_wrapper_MMDB_all_by_addr(ipaddrp, recordp, &mmdb_cache[GeoIP2_type]);
957
958 if (result != MMDB_SUCCESS) {
959 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "no match found");
960 goto END_libipv6calc_db_wrapper;
961 };
962
963 // ASN is stored in a different database
964 if (GeoIP2_type_asn > 0) {
965 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "fetch ASN information from dedicated database");
966 result = libipv6calc_db_wrapper_GeoIP2_open_type(GeoIP2_type_asn);
967
968 if (result != MMDB_SUCCESS) {
969 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "Error opening GeoIP2 by type");
970 goto END_libipv6calc_db_wrapper;
971 };
972
973 result = libipv6calc_db_wrapper_MMDB_all_by_addr(ipaddrp, &record_asn, &mmdb_cache[GeoIP2_type_asn]);
974
975 if (result != MMDB_SUCCESS) {
976 DEBUGPRINT_NA(DEBUG_libipv6calc_db_wrapper_GeoIP2, "no match found");
977 goto END_libipv6calc_db_wrapper;
978 };
979
980 // copy information
981 recordp->asn = record_asn.asn;
982 snprintf(recordp->organization_name, IPV6CALC_DB_SIZE_ORG_NAME, "%s", record_asn.organization_name);
983 };
984
985 END_libipv6calc_db_wrapper:
986 return(result);
987 };
988
989 #endif
990