maxmind: add optional synchronous lookups

When tshark enables synchronous resolution of IP addresses to names,
forces calls to maxmind_db_lookup_ipv4()/_ipv6() to block-wait for the
maxmind response.

Proposed fix for #14691.

(backported from commit c0abaa06f7)
This commit is contained in:
David Perry 2021-01-07 16:21:42 -05:00 committed by Guy Harris
parent 3e35fecccb
commit f1677bd31c
4 changed files with 90 additions and 30 deletions

View File

@ -943,6 +943,7 @@ libwireshark.so.14 libwireshark14 #MINVER#
maxmind_db_get_paths@Base 2.5.1
maxmind_db_lookup_ipv4@Base 2.5.1
maxmind_db_lookup_ipv6@Base 2.5.1
maxmind_db_set_synchrony@Base 3.4.5
mbim_register_uuid_ext@Base 1.12.0~rc1
memory_usage_component_register@Base 1.12.0~rc1
memory_usage_gc@Base 1.12.0~rc1

View File

@ -533,6 +533,7 @@ void
set_resolution_synchrony(gboolean synchronous)
{
resolve_synchronously = synchronous;
maxmind_db_set_synchrony(synchronous);
}
static void

View File

@ -98,6 +98,8 @@ UAT_DIRECTORYNAME_CB_DEF(maxmind_mod, path, maxmind_db_path_t)
static GPtrArray *mmdb_file_arr; // .mmdb files
static gboolean resolve_synchronously = FALSE;
#if 0
#define MMDB_DEBUG(...) { \
char *MMDB_DEBUG_MSG = g_strdup_printf(__VA_ARGS__); \
@ -345,7 +347,15 @@ read_mmdbr_stdout_worker(gpointer data _U_) {
g_async_queue_push(mmdbr_response_q, response); // Will be freed by maxmind_db_lookup_process.
response = g_new0(mmdb_response_t, 1);
} else if (strcmp(cur_addr, "init") != 0) {
MMDB_DEBUG("Discarded previous values due to bad address");
if (resolve_synchronously) {
// Synchronous lookups expect a 1-in 1-out resolution.
MMDB_DEBUG("Pushing not-found result due to bad address");
g_async_queue_push(mmdbr_response_q, response); // Will be freed by maxmind_db_lookup_process.
response = g_new0(mmdb_response_t, 1);
}
else {
MMDB_DEBUG("Discarded previous values due to bad address");
}
}
cur_addr[0] = '\0';
init_lookup(&response->mmdb_val);
@ -606,6 +616,51 @@ void maxmind_db_pref_cleanup(void)
mmdb_resolve_stop();
}
static void maxmind_db_pop_response(mmdb_response_t *response)
{
mmdb_lookup_t *mmdb_val = (mmdb_lookup_t *) g_memdup(&response->mmdb_val, sizeof(mmdb_lookup_t));
if (response->mmdb_val.country_iso) {
char *country_iso = (char *) response->mmdb_val.country_iso;
mmdb_val->country_iso = chunkify_string(country_iso);
g_free(country_iso);
}
if (response->mmdb_val.country) {
char *country = (char *) response->mmdb_val.country;
mmdb_val->country = chunkify_string(country);
g_free(country);
}
if (response->mmdb_val.city) {
char *city = (char *) response->mmdb_val.city;
mmdb_val->city = chunkify_string(city);
g_free(city);
}
if (response->mmdb_val.as_org) {
char *as_org = (char *) response->mmdb_val.as_org;
mmdb_val->as_org = chunkify_string(as_org);
g_free(as_org);
}
MMDB_DEBUG("popped response %s city %s country %s", response->is_ipv4 ? "v4" : "v6", mmdb_val->city, mmdb_val->country);
if (response->is_ipv4) {
wmem_map_insert(mmdb_ipv4_map, GUINT_TO_POINTER(response->ipv4_addr), mmdb_val);
} else {
wmem_map_insert(mmdb_ipv6_map, chunkify_v6_addr(&response->ipv6_addr), mmdb_val);
}
g_free(response);
}
static void maxmind_db_await_response(void)
{
mmdb_response_t *response;
if (mmdbr_response_q != NULL) {
MMDB_DEBUG("entering blocking wait for response");
response = (mmdb_response_t *) g_async_queue_pop(mmdbr_response_q);
MMDB_DEBUG("exiting blocking wait for response");
maxmind_db_pop_response(response);
}
}
/**
* Public API
*/
@ -616,36 +671,8 @@ gboolean maxmind_db_lookup_process(void)
mmdb_response_t *response;
while (mmdbr_response_q && (response = (mmdb_response_t *) g_async_queue_try_pop(mmdbr_response_q)) != NULL) {
mmdb_lookup_t *mmdb_val = (mmdb_lookup_t *) g_memdup(&response->mmdb_val, sizeof(mmdb_lookup_t));
if (response->mmdb_val.country_iso) {
char *country_iso = (char *) response->mmdb_val.country_iso;
mmdb_val->country_iso = chunkify_string(country_iso);
g_free(country_iso);
}
if (response->mmdb_val.country) {
char *country = (char *) response->mmdb_val.country;
mmdb_val->country = chunkify_string(country);
g_free(country);
}
if (response->mmdb_val.city) {
char *city = (char *) response->mmdb_val.city;
mmdb_val->city = chunkify_string(city);
g_free(city);
}
if (response->mmdb_val.as_org) {
char *as_org = (char *) response->mmdb_val.as_org;
mmdb_val->as_org = chunkify_string(as_org);
g_free(as_org);
}
MMDB_DEBUG("popped response %s city %s country %s", response->is_ipv4 ? "v4" : "v6", mmdb_val->city, mmdb_val->country);
if (response->is_ipv4) {
wmem_map_insert(mmdb_ipv4_map, GUINT_TO_POINTER(response->ipv4_addr), mmdb_val);
} else {
wmem_map_insert(mmdb_ipv6_map, chunkify_v6_addr(&response->ipv6_addr), mmdb_val);
}
new_entries = TRUE;
g_free(response);
maxmind_db_pop_response(response);
}
return new_entries;
@ -664,6 +691,10 @@ maxmind_db_lookup_ipv4(const ws_in4_addr *addr) {
ws_inet_ntop4(addr, addr_str, WS_INET_ADDRSTRLEN);
MMDB_DEBUG("looking up %s", addr_str);
g_async_queue_push(mmdbr_request_q, g_strdup_printf("%s\n", addr_str));
if (resolve_synchronously) {
maxmind_db_await_response();
result = (mmdb_lookup_t *) wmem_map_lookup(mmdb_ipv4_map, GUINT_TO_POINTER(*addr));
}
}
}
@ -683,6 +714,10 @@ maxmind_db_lookup_ipv6(const ws_in6_addr *addr) {
ws_inet_ntop6(addr, addr_str, WS_INET6_ADDRSTRLEN);
MMDB_DEBUG("looking up %s", addr_str);
g_async_queue_push(mmdbr_request_q, g_strdup_printf("%s\n", addr_str));
if (resolve_synchronously) {
maxmind_db_await_response();
result = (mmdb_lookup_t *) wmem_map_lookup(mmdb_ipv6_map, addr->bytes);
}
}
}
@ -713,6 +748,11 @@ maxmind_db_get_paths(void) {
return g_string_free(path_str, FALSE);
}
void
maxmind_db_set_synchrony(gboolean synchronous) {
resolve_synchronously = synchronous;
}
#else // HAVE_MAXMINDDB
void
@ -742,6 +782,12 @@ gchar *
maxmind_db_get_paths(void) {
return g_strdup("");
}
void
maxmind_db_set_synchrony(gboolean synchronous _U_) {
/* Nothing to set. */
}
#endif // HAVE_MAXMINDDB

View File

@ -85,6 +85,18 @@ static inline gboolean maxmind_db_has_coords(const mmdb_lookup_t *result)
result->longitude != DBL_MAX && result->latitude != DBL_MAX;
}
/**
* Select whether lookups should be performed synchronously.
* Default is asynchronous lookups.
*
* @param synchronous Whether maxmind lookups should be synchronous.
*
* XXX - if we ever have per-session host name etc. information, we
* should probably have the "resolve synchronously or asynchronously"
* flag be per-session, set with an epan API.
*/
WS_DLL_PUBLIC void maxmind_db_set_synchrony(gboolean synchronous);
#ifdef __cplusplus
}
#endif /* __cplusplus */