aboutsummaryrefslogtreecommitdiffstats
path: root/epan/geoip_db.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2008-12-19 23:49:03 +0000
committerGerald Combs <gerald@wireshark.org>2008-12-19 23:49:03 +0000
commit7d22c0fb7f065d45c744fd97fee785f4b9ed8556 (patch)
treea7873b88f53d9a7db8509a12e299a82b3ef9001b /epan/geoip_db.c
parent6d04f793f019b456f8d8c81f231152fbba24da8b (diff)
Rename geoip.[ch] to geoip_db.[ch] so we don't collide with GeoIP.h. Rename
some functions to match. Add GeoIP lookups to the IP dissector. Add a preference for GeoIP lookups, which is disabled by default. svn path=/trunk/; revision=27063
Diffstat (limited to 'epan/geoip_db.c')
-rw-r--r--epan/geoip_db.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/epan/geoip_db.c b/epan/geoip_db.c
new file mode 100644
index 0000000000..3408bdb4a9
--- /dev/null
+++ b/epan/geoip_db.c
@@ -0,0 +1,303 @@
+/* geoip_db.c
+ * GeoIP database support
+ *
+ * Copyright 2008, Gerald Combs <gerald@wireshark.org>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* To do:
+ * We currently return a single string for each database. Some databases,
+ * e.g. GeoIPCity, can return other info such as area codes.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#ifdef HAVE_GEOIP
+#include "GeoIP.h"
+#include "GeoIPCity.h"
+
+#include "geoip_db.h"
+#include "uat.h"
+#include "prefs.h"
+#include "report_err.h"
+#include "value_string.h"
+#include <wsutil/file_util.h>
+
+/* This needs to match NUM_GEOIP_COLS in hostlist_table.h */
+#define MAX_GEOIP_DBS 8
+
+/* Column names for each database type */
+value_string geoip_type_name_vals[] = {
+ { GEOIP_COUNTRY_EDITION, "Country" },
+ { GEOIP_REGION_EDITION_REV0, "Region" },
+ { GEOIP_CITY_EDITION_REV0, "City"},
+ { GEOIP_ORG_EDITION, "Organization" },
+ { GEOIP_ISP_EDITION, "ISP" },
+ { GEOIP_CITY_EDITION_REV1, "City" },
+ { GEOIP_REGION_EDITION_REV1, "Region" },
+ { GEOIP_PROXY_EDITION, "Proxy" },
+ { GEOIP_ASNUM_EDITION, "AS Number" },
+ { GEOIP_NETSPEED_EDITION, "Speed" },
+ { GEOIP_DOMAIN_EDITION, "Domain" },
+ { 0, NULL }
+};
+
+static GArray *geoip_dat_arr = NULL;
+
+/* UAT definitions. Copied from oids.c */
+typedef struct _geoip_db_path_t {
+ char* path;
+} geoip_db_path_t;
+
+static geoip_db_path_t *geoip_db_paths = NULL;
+static guint num_geoip_db_paths = 0;
+static uat_t *geoip_db_paths_uat = NULL;
+UAT_CSTRING_CB_DEF(geoip_mod, path, geoip_db_path_t)
+
+
+/**
+ * Scan a directory for GeoIP databases and load them
+ */
+static void
+geoip_dat_scan_dir(const char *dirname) {
+ WS_DIR *dir;
+ WS_DIRENT *file;
+ const char *name;
+ char *datname;
+ GeoIP *gi;
+
+ if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) {
+ while ((file = ws_dir_read_name(dir)) != NULL) {
+ name = ws_dir_get_name(file);
+ if (g_str_has_prefix(file, "Geo") && g_str_has_suffix(file, ".dat")) {
+ datname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
+ gi = GeoIP_open(datname, GEOIP_MEMORY_CACHE);
+ if (gi) {
+ g_array_append_val(geoip_dat_arr, gi);
+ }
+ g_free(datname);
+ }
+ }
+ }
+}
+
+/* UAT callbacks */
+static void* geoip_db_path_copy_cb(void* dest, const void* orig, unsigned len _U_) {
+ const geoip_db_path_t *m = orig;
+ geoip_db_path_t *d = dest;
+
+ d->path = g_strdup(m->path);
+
+ return d;
+}
+
+static void geoip_db_path_free_cb(void* p) {
+ geoip_db_path_t *m = p;
+ if (m->path) g_free(m->path);
+}
+
+/**
+ * Initialize GeoIP lookups
+ */
+void
+geoip_db_init(void) {
+ guint i;
+ static uat_field_t geoip_db_paths_fields[] = {
+ UAT_FLD_CSTRING(geoip_mod, path, "The database path"),
+ UAT_END_FIELDS
+ };
+ char* geoip_load_error = NULL;
+
+ geoip_dat_arr = g_array_new(FALSE, FALSE, sizeof(GeoIP *));
+
+ geoip_db_paths_uat = uat_new("GeoIP Database Paths",
+ sizeof(geoip_db_path_t),
+ "geoip_db_paths",
+ FALSE,
+ (void*)&geoip_db_paths,
+ &num_geoip_db_paths,
+ UAT_CAT_GENERAL,
+ "ChGeoIPDbPaths",
+ geoip_db_path_copy_cb,
+ NULL,
+ geoip_db_path_free_cb,
+ geoip_db_paths_fields);
+
+ uat_load(geoip_db_paths_uat, &geoip_load_error);
+
+ if (geoip_load_error) {
+ report_failure("Error loading GeoIP database path table: %s", geoip_load_error);
+ return;
+ }
+
+ for (i = 0; i < num_geoip_db_paths; i++) {
+ if (geoip_db_paths[i].path) {
+ geoip_dat_scan_dir(geoip_db_paths[i].path);
+ }
+ }
+
+}
+
+guint
+geoip_num_dbs(void) {
+ return geoip_dat_arr->len;
+}
+
+const gchar *
+geoip_db_name(guint dbnum) {
+ GeoIP *gi;
+
+ gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
+ if (gi) {
+ return (val_to_str(gi->databaseType, geoip_type_name_vals, "Unknown database"));
+ }
+ return "Invalid database";
+}
+
+int
+geoip_db_type(guint dbnum) {
+ GeoIP *gi;
+
+ gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
+ if (gi) {
+ return (gi->databaseType);
+ }
+ return -1;
+}
+
+#define VAL_STR_LEN 100
+const char *
+geoip_db_lookup_ipv4(guint dbnum, guint32 addr, char *not_found) {
+ GeoIP *gi;
+ GeoIPRecord *gir;
+ const char *ret = not_found;
+ static char val[VAL_STR_LEN];
+
+ gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
+ if (gi) {
+ switch (gi->databaseType) {
+ case GEOIP_COUNTRY_EDITION:
+ ret = GeoIP_country_name_by_ipnum(gi, addr);
+ break;
+
+ case GEOIP_CITY_EDITION_REV0:
+ case GEOIP_CITY_EDITION_REV1:
+ gir = GeoIP_record_by_ipnum(gi, addr);
+ if (gir && gir->city && gir->region) {
+ g_snprintf(val, VAL_STR_LEN, "%s, %s", gir->city, gir->region);
+ ret = val;
+ } else if (gir && gir->city) {
+ g_snprintf(val, VAL_STR_LEN, "%s", gir->city);
+ ret = val;
+ }
+ break;
+
+ case GEOIP_ORG_EDITION:
+ case GEOIP_ISP_EDITION:
+ case GEOIP_ASNUM_EDITION:
+ ret = GeoIP_name_by_ipnum(gi, addr);
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (ret) {
+ return ret;
+ }
+ return not_found;
+}
+
+gchar *
+geoip_db_get_paths(void) {
+ GString* path_str = NULL;
+ gchar *path_ret;
+ char path_separator;
+ guint i;
+
+ path_str = g_string_new("");
+#ifdef _WIN32
+ path_separator = ';';
+#else
+ path_separator = ':';
+#endif
+
+ for (i = 0; i < num_geoip_db_paths; i++) {
+ if (geoip_db_paths[i].path) {
+ g_string_append_printf(path_str, "%s%c", geoip_db_paths[i].path, path_separator);
+ }
+ }
+
+ g_string_truncate(path_str, path_str->len-1);
+ path_ret = path_str->str;
+ g_string_free(path_str, FALSE);
+
+ return path_ret;
+}
+
+#else /* HAVE_GEOIP */
+void
+geoip_db_init(void) {}
+
+guint
+geoip_num_dbs(void) {
+ return 0;
+}
+
+const gchar *
+geoip_db_name(guint dbnum _U_) {
+ return "Unsupported";
+}
+
+int
+geoip_db_type(guint dbnum _U_) {
+ return -1;
+}
+
+const char *
+geoip_db_lookup_ipv4(guint dbnum _U_, guint32 addr _U_, char *not_found) {
+ return not_found;
+}
+
+gchar *
+geoip_db_get_paths(void) {
+ return "";
+}
+
+#endif /* HAVE_GEOIP */
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=4 noexpandtab
+ * :indentSize=4:tabSize=4:noTabs=false:
+ */ \ No newline at end of file