diff options
author | Gerald Combs <gerald@wireshark.org> | 2018-02-08 17:20:26 -0800 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2018-03-06 18:02:21 +0000 |
commit | a1da75c554881667dd92e11f098630f2d604872b (patch) | |
tree | b1d6a60a663bf93f1eede809a0c383544508d6e2 /mmdbresolve.c | |
parent | b2d3680558d19998c55b48e9807a26e145756eba (diff) |
Transition from GeoIP Legacy to MaxMindDB.
MaxMind is discontinuing its legacy databases in April in favor of
GeoIP2, which use a newer database format (MaxMind DB). The reference C
library (libmaxminddb) is available under the Apache 2.0 license which
isn't quite compatible with ours.
Add mmdbresolve, a utility that reads IPv4 and IPv6 addresses on stdin
and prints resolved information on stdout. Place it under a liberal
license (MIT) so that we can keep libmaxminddb at arm's length. Add
epan/maxmind_db.[ch], which spawns mmdbresolve and communicates with it
via stdio.
Migrate the preferences and documentation to MaxMindDB.
Change the IPv4 and IPv6 asnum fields to FT_UINT32s. Change the
geographic coordinate fields to FT_DOUBLEs.
Bug: 10658
Change-Id: I24aeed637bea1b41d173270bda413af230f4425f
Reviewed-on: https://code.wireshark.org/review/26214
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'mmdbresolve.c')
-rw-r--r-- | mmdbresolve.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/mmdbresolve.c b/mmdbresolve.c new file mode 100644 index 0000000000..3568a0b4b9 --- /dev/null +++ b/mmdbresolve.c @@ -0,0 +1,169 @@ +/* Read IPv4 and IPv6 addresses on stdin and print their MMDB entries on stdout. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This progam uses the MaxMind DB library (libmaxminddb) and MUST be + * compatible with its license (Apache 2.0). + * + * SPDX-License-Identifier: MIT + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> + +#include <string.h> + +#include <maxminddb.h> + +#define MAX_ADDR_LEN 46 +#define MMDBR_STRINGIFY(x) MMDBR_STRINGIFY_S(x) +#define MMDBR_STRINGIFY_S(s) #s +#define OUT_BUF_SIZE 65536 + +static const char *co_iso_key[] = {"country", "iso_code", NULL}; +static const char *co_name_key[] = {"country", "names", "en", NULL}; +static const char *ci_name_key[] = {"city", "names", "en", NULL}; +static const char *asn_o_key[] = {"autonomous_system_organization", NULL}; +static const char *asn_key[] = {"autonomous_system_number", NULL}; +static const char *l_lat_key[] = {"location", "latitude", NULL}; +static const char *l_lon_key[] = {"location", "longitude", NULL}; +static const char *empty_key[] = {NULL}; + +static const char **lookup_keys[] = { + co_iso_key, + co_name_key, + ci_name_key, + asn_o_key, + asn_key, + l_lat_key, + l_lon_key, + empty_key +}; + +static void print_usage(void) { + fprintf(stderr, "Usage: mmdbresolve -f db_file [-f db_file ...]\n"); +} + +int +main(int argc, char *argv[]) +{ + char addr_str[MAX_ADDR_LEN+1]; + size_t mmdb_count = 0; + MMDB_s *mmdbs = NULL; + int mmdb_err; + int opt; + const char *optstring = "f:"; + + char *out_buf = (char *) malloc(OUT_BUF_SIZE); + setvbuf(stdout, out_buf, _IOFBF, OUT_BUF_SIZE); + + fprintf(stdout, "[init]\n"); + + while ((opt = getopt(argc, argv, optstring)) != -1) { + if (opt == 'f') { + MMDB_s try_mmdb; + mmdb_err = MMDB_open(optarg, 0, &try_mmdb); + fprintf(stdout, "db.%zd.path: %s\n", mmdb_count, optarg); + fprintf(stdout, "db.%zd.status: ", mmdb_count); + if (mmdb_err == MMDB_SUCCESS) { + mmdb_count++; + mmdbs = (MMDB_s *) realloc(mmdbs, mmdb_count * sizeof(MMDB_s)); + mmdbs[mmdb_count - 1] = try_mmdb; + fprintf(stdout, "OK\n"); + fprintf(stdout, "db.%zd.type: %s\n", mmdb_count, mmdbs[mmdb_count - 1].metadata.database_type); + } else { + fprintf(stdout, "ERROR %s\n", MMDB_strerror(mmdb_err)); + } + }; + } + + fprintf(stdout, "mmdbresolve.status: %s\n", mmdb_count > 0 ? "true": "false"); + fprintf(stdout, "# End init\n"); + fflush(stdout); + + if (mmdb_count < 1) { + print_usage(); + exit(1); + } + + while (!feof(stdin)) { + int gai_err; + + if (fscanf(stdin, "%" MMDBR_STRINGIFY(MAX_ADDR_LEN) "s", addr_str) < 1) { + continue; + } + fprintf(stdout, "[%s]\n", addr_str); + + for (size_t mmdb_idx = 0; mmdb_idx < mmdb_count; mmdb_idx++) { + fprintf(stdout, "# %s\n", mmdbs[mmdb_idx].metadata.database_type); + MMDB_lookup_result_s result = MMDB_lookup_string(&mmdbs[mmdb_idx], addr_str, &gai_err, &mmdb_err); + + if (result.found_entry && gai_err == 0 && mmdb_err == MMDB_SUCCESS) { + for (size_t key_idx = 0; lookup_keys[key_idx][0]; key_idx++) { + MMDB_entry_data_s entry_data; + int status = MMDB_aget_value(&result.entry, &entry_data, lookup_keys[key_idx]); + if (status == MMDB_SUCCESS && entry_data.has_data) { + char *sep = ""; + for (int idx = 0; lookup_keys[key_idx][idx] != 0; idx++) { + fprintf(stdout, "%s%s", sep, lookup_keys[key_idx][idx]); + sep = "."; + } + switch (entry_data.type) { + case MMDB_DATA_TYPE_UTF8_STRING: + { + char len_fmt[12]; // : %.xxxxxs\n\0 + snprintf(len_fmt, 11, ": %%.%us\n", entry_data.data_size); + fprintf(stdout, len_fmt, entry_data.utf8_string); + } + break; + case MMDB_DATA_TYPE_UINT16: + fprintf(stdout, ": %u\n", entry_data.uint16); + break; + case MMDB_DATA_TYPE_UINT32: + fprintf(stdout, ": %u\n", entry_data.uint32); + break; + case MMDB_DATA_TYPE_INT32: + fprintf(stdout, ": %d\n", entry_data.int32); + break; + case MMDB_DATA_TYPE_BOOLEAN: + fprintf(stdout, ": %s\n", entry_data.boolean ? "True" : "False"); + break; + case MMDB_DATA_TYPE_DOUBLE: + fprintf(stdout, ": %f\n", entry_data.double_value); + break; + case MMDB_DATA_TYPE_FLOAT: + fprintf(stdout, ": %f\n", entry_data.float_value); + break; + default: + fprintf(stdout, ": UNKNOWN (%d)\n", entry_data.type); + } + } + } + } else { + // dump error info. + } + } + fprintf(stdout, "# End %s\n", addr_str); + fflush(stdout); + } + + return 0; +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |