Witness: enum witness_interface_state
[metze/wireshark/wip.git] / epan / geoip_db.c
1 /* geoip_db.c
2  * GeoIP database support
3  *
4  * Copyright 2008, Gerald Combs <gerald@wireshark.org>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 /* To do:
28  * We currently return a single string for each database. Some databases,
29  * e.g. GeoIPCity, can return other info such as area codes.
30  */
31
32 #include "config.h"
33
34 #include <glib.h>
35
36 #ifdef HAVE_GEOIP
37 #include <GeoIP.h>
38 #include <GeoIPCity.h>
39
40 #include "geoip_db.h"
41 #include "uat.h"
42 #include "prefs.h"
43 #include "value_string.h"
44
45 #include <wsutil/report_err.h>
46 #include <wsutil/file_util.h>
47
48 /* This needs to match NUM_GEOIP_COLS in hostlist_table.h */
49 #define MAX_GEOIP_DBS 13
50
51 /* Column names for each database type */
52 value_string geoip_type_name_vals[] = {
53     { GEOIP_COUNTRY_EDITION,        "Country" },
54     { GEOIP_REGION_EDITION_REV0,    "Region" },
55     { GEOIP_CITY_EDITION_REV0,      "City"},
56     { GEOIP_ORG_EDITION,            "Organization" },
57     { GEOIP_ISP_EDITION,            "ISP" },
58     { GEOIP_CITY_EDITION_REV1,      "City" },
59     { GEOIP_REGION_EDITION_REV1,    "Region" },
60     { GEOIP_PROXY_EDITION,          "Proxy" },
61     { GEOIP_ASNUM_EDITION,          "AS Number" },
62     { GEOIP_NETSPEED_EDITION,       "Speed" },
63     { GEOIP_DOMAIN_EDITION,         "Domain" },
64 #ifdef HAVE_GEOIP_V6
65     { GEOIP_COUNTRY_EDITION_V6,     "Country" },
66 /* This is the closest thing to a version that GeoIP.h seems to provide. */
67 #if NUM_DB_TYPES > 31 /* 1.4.7 */
68     { GEOIP_CITY_EDITION_REV0_V6,   "City"},
69     { GEOIP_CITY_EDITION_REV1_V6,   "City"},
70     { GEOIP_ASNUM_EDITION_V6,       "AS Number" },
71     { GEOIP_ISP_EDITION_V6,         "ISP" },
72     { GEOIP_ORG_EDITION_V6,         "Organization" },
73     { GEOIP_DOMAIN_EDITION_V6,      "Domain" },
74 #endif /* NUM_DB_TYPES > 31 */
75 #if NUM_DB_TYPES > 32 /* 1.4.8 */
76     { GEOIP_NETSPEED_EDITION_REV1_V6, "Speed" },
77 #endif /* NUM_DB_TYPES > 32 */
78 #endif /* HAVE_GEOIP_V6 */
79     { WS_LAT_FAKE_EDITION,          "Latitude" },   /* fake database */
80     { WS_LON_FAKE_EDITION,          "Longitude" },  /* fake database */
81     { 0, NULL }
82 };
83
84 static GArray *geoip_dat_arr = NULL;
85
86 /* UAT definitions. Copied from oids.c */
87 typedef struct _geoip_db_path_t {
88     char* path;
89 } geoip_db_path_t;
90
91 static geoip_db_path_t *geoip_db_paths = NULL;
92 static guint num_geoip_db_paths = 0;
93 static uat_t *geoip_db_paths_uat = NULL;
94 UAT_DIRECTORYNAME_CB_DEF(geoip_mod, path, geoip_db_path_t)
95
96
97 /**
98  * Scan a directory for GeoIP databases and load them
99  */
100 static void
101 geoip_dat_scan_dir(const char *dirname) {
102     WS_DIR *dir;
103     WS_DIRENT *file;
104     const char *name;
105     char *datname;
106     GeoIP *gi;
107
108     if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) {
109         while ((file = ws_dir_read_name(dir)) != NULL) {
110             name = ws_dir_get_name(file);
111             if (g_str_has_prefix(file, "Geo") && g_str_has_suffix(file, ".dat")) {
112                 datname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
113                 gi = GeoIP_open(datname, GEOIP_MEMORY_CACHE);
114                 if (gi) {
115                     g_array_append_val(geoip_dat_arr, gi);
116                 }
117                 g_free(datname);
118             }
119         }
120         ws_dir_close (dir);
121     }
122 }
123
124 /* UAT callbacks */
125 static void* geoip_db_path_copy_cb(void* dest, const void* orig, size_t len _U_) {
126     const geoip_db_path_t *m = (const geoip_db_path_t *)orig;
127     geoip_db_path_t *d = (geoip_db_path_t *)dest;
128
129     d->path = g_strdup(m->path);
130
131     return d;
132 }
133
134 static void geoip_db_path_free_cb(void* p) {
135     geoip_db_path_t *m = (geoip_db_path_t *)p;
136     g_free(m->path);
137 }
138
139 /* called every time the user presses "Apply" or "OK in the list of
140  * GeoIP directories, and also once on startup */
141 static void geoip_db_post_update_cb(void) {
142     GeoIP *gi;
143     guint i;
144
145     /* If we have old data, clear out the whole thing
146      * and start again. TODO: Just update the ones that
147      * have changed for efficiency's sake. */
148     if (geoip_dat_arr) {
149         /* skip the last two, as they are fake */
150         for (i = 0; i < geoip_db_num_dbs() - 2; i++) {
151             gi = g_array_index(geoip_dat_arr, GeoIP *, i);
152             if (gi) {
153                 GeoIP_delete(gi);
154             }
155         }
156         /* don't use GeoIP_delete() on the two fake
157          * databases as they weren't created by GeoIP_new()
158          * or GeoIP_open() */
159         gi = g_array_index(geoip_dat_arr, GeoIP *, i);
160         if (gi) {
161             g_free(gi);
162         }
163         gi = g_array_index(geoip_dat_arr, GeoIP *, i+1);
164         if (gi) {
165             g_free(gi);
166         }
167         /* finally, free the array itself */
168         g_array_free(geoip_dat_arr, TRUE);
169     }
170
171     /* allocate the array */
172     geoip_dat_arr = g_array_new(FALSE, FALSE, sizeof(GeoIP *));
173
174     /* Walk all the directories */
175     for (i = 0; i < num_geoip_db_paths; i++) {
176         if (geoip_db_paths[i].path) {
177             geoip_dat_scan_dir(geoip_db_paths[i].path);
178         }
179     }
180
181     /* add fake databases for latitude and longitude
182      * (using "City" in reality) */
183
184     /* latitude */
185     gi = (GeoIP *)g_malloc(sizeof (GeoIP));
186     gi->databaseType = WS_LAT_FAKE_EDITION;
187     g_array_append_val(geoip_dat_arr, gi);
188
189     /* longitude */
190     gi = (GeoIP *)g_malloc(sizeof (GeoIP));
191     gi->databaseType = WS_LON_FAKE_EDITION;
192     g_array_append_val(geoip_dat_arr, gi);
193 }
194
195 /**
196  * Initialize GeoIP lookups
197  */
198 void
199 geoip_db_pref_init(module_t *nameres)
200 {
201     static uat_field_t geoip_db_paths_fields[] = {
202         UAT_FLD_DIRECTORYNAME(geoip_mod, path, "GeoIP Database Directory", "The GeoIP database directory path"),
203         UAT_END_FIELDS
204     };
205
206     geoip_db_paths_uat = uat_new("GeoIP Database Paths",
207             sizeof(geoip_db_path_t),
208             "geoip_db_paths",
209             FALSE,
210             (void**)&geoip_db_paths,
211             &num_geoip_db_paths,
212             /* affects dissection of packets (as the GeoIP database is
213                used when dissecting), but not set of named fields */
214             UAT_AFFECTS_DISSECTION,
215             "ChGeoIPDbPaths",
216             geoip_db_path_copy_cb,
217             NULL,
218             geoip_db_path_free_cb,
219             geoip_db_post_update_cb,
220             geoip_db_paths_fields);
221
222     prefs_register_uat_preference(nameres,
223             "geoip_db_paths",
224             "GeoIP database directories",
225                 "Search paths for GeoIP address mapping databases.\n"
226                 "Wireshark will look in each directory for files beginning\n"
227                 "with \"Geo\" and ending with \".dat\".",
228             geoip_db_paths_uat);
229 }
230
231 guint
232 geoip_db_num_dbs(void) {
233     return geoip_dat_arr->len;
234 }
235
236 const gchar *
237 geoip_db_name(guint dbnum) {
238     GeoIP *gi;
239
240     gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
241     if (gi) {
242         return (val_to_str_const(gi->databaseType, geoip_type_name_vals, "Unknown database"));
243     }
244     return "Invalid database";
245 }
246
247 int
248 geoip_db_type(guint dbnum) {
249     GeoIP *gi;
250
251     gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
252     if (gi) {
253         return (gi->databaseType);
254     }
255     return -1;
256 }
257
258 static int
259 geoip_db_lookup_latlon4(guint32 addr, float *lat, float *lon) {
260     GeoIP *gi;
261     GeoIPRecord *gir;
262     guint i;
263
264     for (i = 0; i < geoip_db_num_dbs(); i++) {
265         gi = g_array_index(geoip_dat_arr, GeoIP *, i);
266         if (gi) {
267             switch (gi->databaseType) {
268                 case GEOIP_CITY_EDITION_REV0:
269                 case GEOIP_CITY_EDITION_REV1:
270                     gir = GeoIP_record_by_ipnum(gi, addr);
271                     if(gir) {
272                         *lat = gir->latitude;
273                         *lon = gir->longitude;
274                         return 0;
275                     }
276                     return -1;
277                     /*break;*/
278
279                 default:
280                     break;
281             }
282         }
283     }
284     return -1;
285 }
286
287 #define VAL_STR_LEN 100
288
289 /*
290  * GeoIP 1.4.3 and later provide GeoIP_set_charset(), but in versions
291  * 1.4.3 to 1.4.6 that only applies to the City databases. I.e., it's
292  * possible to produce invalid UTF-8 sequences even if GeoIP_set_charset()
293  * is used.
294  */
295 static void
296 iso_8859_1_to_utf_8(char *val) {
297     char *utf8_val;
298
299     utf8_val = g_convert(val, VAL_STR_LEN, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
300     if (utf8_val) {
301         g_strlcpy(val, utf8_val, VAL_STR_LEN);
302         g_free(utf8_val);
303     }
304
305 }
306
307 const char *
308 geoip_db_lookup_ipv4(guint dbnum, guint32 addr, const char *not_found) {
309     GeoIP *gi;
310     GeoIPRecord *gir;
311     const char *raw_val, *ret = not_found;
312     static char val[VAL_STR_LEN];
313
314     gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
315     if (gi) {
316         switch (gi->databaseType) {
317             case GEOIP_COUNTRY_EDITION:
318                 raw_val = GeoIP_country_name_by_ipnum(gi, addr);
319                 if (raw_val) {
320                     g_snprintf(val, VAL_STR_LEN, "%s", raw_val);
321                     iso_8859_1_to_utf_8(val);
322                     ret = val;
323                 }
324                 break;
325
326             case GEOIP_CITY_EDITION_REV0:
327             case GEOIP_CITY_EDITION_REV1:
328                 gir = GeoIP_record_by_ipnum(gi, addr);
329                 if (gir && gir->city && gir->region) {
330                     g_snprintf(val, VAL_STR_LEN, "%s, %s", gir->city, gir->region);
331                     iso_8859_1_to_utf_8(val);
332                     ret = val;
333                 } else if (gir && gir->city) {
334                     g_snprintf(val, VAL_STR_LEN, "%s", gir->city);
335                     iso_8859_1_to_utf_8(val);
336                     ret = val;
337                 }
338                 break;
339
340             case GEOIP_ORG_EDITION:
341             case GEOIP_ISP_EDITION:
342             case GEOIP_ASNUM_EDITION:
343                 raw_val = GeoIP_name_by_ipnum(gi, addr);
344                 if (raw_val) {
345                     g_snprintf(val, VAL_STR_LEN, "%s", raw_val);
346                     iso_8859_1_to_utf_8(val);
347                     ret = val;
348                 }
349                 break;
350
351             case WS_LAT_FAKE_EDITION:
352             {
353                 float lat;
354                 float lon;
355                 char *c;
356                 if(geoip_db_lookup_latlon4(addr, &lat, &lon) == 0) {
357                     g_snprintf(val, VAL_STR_LEN, "%f", lat);
358                     c = strchr(val, ',');
359                     if (c != NULL) *c = '.';
360                     ret = val;
361                 }
362             }
363                 break;
364
365             case WS_LON_FAKE_EDITION:
366             {
367                 float lat;
368                 float lon;
369                 char *c;
370                 if(geoip_db_lookup_latlon4(addr, &lat, &lon) == 0) {
371                     g_snprintf(val, VAL_STR_LEN, "%f", lon);
372                     c = strchr(val, ',');
373                     if (c != NULL) *c = '.';
374                     ret = val;
375                 }
376             }
377                 break;
378
379             default:
380                 break;
381         }
382     }
383     return ret;
384 }
385
386 #ifdef HAVE_GEOIP_V6
387
388 static int
389 #if NUM_DB_TYPES > 31 /* 1.4.7 */
390 geoip_db_lookup_latlon6(geoipv6_t addr, float *lat, float *lon) {
391     GeoIP *gi;
392     GeoIPRecord *gir;
393     guint i;
394
395     for (i = 0; i < geoip_db_num_dbs(); i++) {
396         gi = g_array_index(geoip_dat_arr, GeoIP *, i);
397         if (gi) {
398             switch (gi->databaseType) {
399                 case GEOIP_CITY_EDITION_REV0_V6:
400                 case GEOIP_CITY_EDITION_REV1_V6:
401                     gir = GeoIP_record_by_ipnum_v6(gi, addr);
402                     if(gir) {
403                         *lat = gir->latitude;
404                         *lon = gir->longitude;
405                         return 0;
406                     }
407                     return -1;
408                     /*break;*/
409
410                 default:
411                     break;
412             }
413         }
414     }
415     return -1;
416 }
417 #else /* NUM_DB_TYPES */
418 geoip_db_lookup_latlon6(geoipv6_t addr _U_, float *lat _U_, float *lon _U_) {
419     return -1;
420 }
421 #endif /* NUM_DB_TYPES */
422
423 const char *
424 geoip_db_lookup_ipv6(guint dbnum, struct e_in6_addr addr, const char *not_found) {
425     GeoIP *gi;
426     geoipv6_t gaddr;
427     const char *raw_val, *ret = not_found;
428     static char val[VAL_STR_LEN];
429 #if NUM_DB_TYPES > 31
430     GeoIPRecord *gir;
431 #endif
432
433     memcpy(&gaddr, &addr, sizeof(addr));
434
435     gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
436     if (gi) {
437         switch (gi->databaseType) {
438             case GEOIP_COUNTRY_EDITION_V6:
439                 raw_val = GeoIP_country_name_by_ipnum_v6(gi, gaddr);
440                 if (raw_val) {
441                     g_snprintf(val, VAL_STR_LEN, "%s", raw_val);
442                     iso_8859_1_to_utf_8(val);
443                     ret = val;
444                 }
445                 break;
446
447 #if NUM_DB_TYPES > 31
448             case GEOIP_CITY_EDITION_REV0_V6:
449             case GEOIP_CITY_EDITION_REV1_V6:
450                 gir = GeoIP_record_by_ipnum_v6(gi, gaddr);
451                 if (gir && gir->city && gir->region) {
452                     g_snprintf(val, VAL_STR_LEN, "%s, %s", gir->city, gir->region);
453                     iso_8859_1_to_utf_8(val);
454                     ret = val;
455                 } else if (gir && gir->city) {
456                     g_snprintf(val, VAL_STR_LEN, "%s", gir->city);
457                     iso_8859_1_to_utf_8(val);
458                     ret = val;
459                 }
460                 break;
461
462             case GEOIP_ORG_EDITION_V6:
463             case GEOIP_ISP_EDITION_V6:
464             case GEOIP_ASNUM_EDITION_V6:
465                 raw_val = GeoIP_name_by_ipnum_v6(gi, gaddr);
466                 if (raw_val) {
467                     g_snprintf(val, VAL_STR_LEN, "%s", raw_val);
468                     iso_8859_1_to_utf_8(val);
469                     ret = val;
470                 }
471                 break;
472 #endif /* NUM_DB_TYPES */
473
474             case WS_LAT_FAKE_EDITION:
475             {
476                 float lat;
477                 float lon;
478                 char *c;
479                 if(geoip_db_lookup_latlon6(gaddr, &lat, &lon) == 0) {
480                     g_snprintf(val, VAL_STR_LEN, "%f", lat);
481                     c = strchr(val, ',');
482                     if (c != NULL) *c = '.';
483                     ret = val;
484                 }
485             }
486                 break;
487
488             case WS_LON_FAKE_EDITION:
489             {
490                 float lat;
491                 float lon;
492                 char *c;
493                 if(geoip_db_lookup_latlon6(gaddr, &lat, &lon) == 0) {
494                     g_snprintf(val, VAL_STR_LEN, "%f", lon);
495                     c = strchr(val, ',');
496                     if (c != NULL) *c = '.';
497                     ret = val;
498                 }
499             }
500                 break;
501
502             default:
503                 break;
504         }
505     }
506     return ret;
507 }
508
509 #else /* HAVE_GEOIP_V6 */
510
511 const char *
512 geoip_db_lookup_ipv6(guint dbnum _U_, struct e_in6_addr addr _U_, const char *not_found) {
513     return not_found;
514 }
515
516 #endif /* HAVE_GEOIP_V6 */
517
518 gchar *
519 geoip_db_get_paths(void) {
520     GString* path_str = NULL;
521     gchar *path_ret;
522     char path_separator;
523     guint i;
524
525     path_str = g_string_new("");
526 #ifdef _WIN32
527     path_separator = ';';
528 #else
529     path_separator = ':';
530 #endif
531
532     for (i = 0; i < num_geoip_db_paths; i++) {
533         if (geoip_db_paths[i].path) {
534             g_string_append_printf(path_str, "%s%c", geoip_db_paths[i].path, path_separator);
535         }
536     }
537
538     g_string_truncate(path_str, path_str->len-1);
539     path_ret = path_str->str;
540     g_string_free(path_str, FALSE);
541
542     return path_ret;
543 }
544
545 #else /* HAVE_GEOIP */
546 guint
547 geoip_db_num_dbs(void) {
548     return 0;
549 }
550
551 const gchar *
552 geoip_db_name(guint dbnum _U_) {
553     return "Unsupported";
554 }
555
556 int
557 geoip_db_type(guint dbnum _U_) {
558     return -1;
559 }
560
561 const char *
562 geoip_db_lookup_ipv4(guint dbnum _U_, guint32 addr _U_, const char *not_found) {
563     return not_found;
564 }
565
566 const char *
567 geoip_db_lookup_ipv6(guint dbnum _U_, guint32 addr _U_, const char *not_found) {
568     return not_found;
569 }
570
571 gchar *
572 geoip_db_get_paths(void) {
573     return g_strdup("");
574 }
575
576 #endif /* HAVE_GEOIP */
577
578 /*
579  * Editor modelines
580  *
581  * Local Variables:
582  * c-basic-offset: 4
583  * tab-width: 8
584  * indent-tabs-mode: nil
585  * End:
586  *
587  * ex: set shiftwidth=4 tabstop=8 expandtab:
588  * :indentSize=4:tabSize=8:noTabs=true:
589  */