mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Add "IPVersions" to control command "status/clients-seen".
This commit is contained in:
parent
af175fa7e4
commit
cb51807236
109
src/or/geoip.c
109
src/or/geoip.c
@ -994,20 +994,25 @@ geoip_get_dirreq_history(geoip_client_action_t action,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return a newly allocated comma-separated string containing entries for
|
/** Store a newly allocated comma-separated string in
|
||||||
* all the countries from which we've seen enough clients connect as a
|
* *<a>country_str</a> containing entries for all the countries from
|
||||||
* bridge, directory server, or entry guard. The entry format is cc=num
|
* which we've seen enough clients connect as a bridge, directory
|
||||||
* where num is the number of IPs we've seen connecting from that country,
|
* server, or entry guard. The entry format is cc=num where num is the
|
||||||
* and cc is a lowercased country code. Returns NULL if we don't want
|
* number of IPs we've seen connecting from that country, and cc is a
|
||||||
* to export geoip data yet. This counts both IPv4 and IPv6 clients
|
* lowercased country code. *<a>country_str</a> is set to NULL if
|
||||||
* since they're in the same clientmap list. */
|
* we're not ready to export per country data yet.
|
||||||
char *
|
*
|
||||||
geoip_get_client_history(geoip_client_action_t action, int *total_ipv4,
|
* Store a newly allocated comma-separated string in <a>ipver_str</a>
|
||||||
int *total_ipv6)
|
* containing entries for clients connecting over IPv4 and IPv6. The
|
||||||
|
* format is family=num where num is the nubmer of IPs we've seen
|
||||||
|
* connecting over that protocol family, and family is 'v4' or 'v6'.
|
||||||
|
*
|
||||||
|
* Return 0 on success and -1 if we're missing geoip data. */
|
||||||
|
int
|
||||||
|
geoip_get_client_history(geoip_client_action_t action,
|
||||||
|
char **country_str, char **ipver_str)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
|
||||||
unsigned granularity = IP_GRANULARITY;
|
unsigned granularity = IP_GRANULARITY;
|
||||||
smartlist_t *chunks = NULL;
|
|
||||||
smartlist_t *entries = NULL;
|
smartlist_t *entries = NULL;
|
||||||
int n_countries = geoip_get_n_countries();
|
int n_countries = geoip_get_n_countries();
|
||||||
int i;
|
int i;
|
||||||
@ -1017,7 +1022,7 @@ geoip_get_client_history(geoip_client_action_t action, int *total_ipv4,
|
|||||||
unsigned ipv4_count = 0, ipv6_count = 0;
|
unsigned ipv4_count = 0, ipv6_count = 0;
|
||||||
|
|
||||||
if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6))
|
if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6))
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
counts = tor_malloc_zero(sizeof(unsigned)*n_countries);
|
counts = tor_malloc_zero(sizeof(unsigned)*n_countries);
|
||||||
HT_FOREACH(ent, clientmap, &client_history) {
|
HT_FOREACH(ent, clientmap, &client_history) {
|
||||||
@ -1039,13 +1044,25 @@ geoip_get_client_history(geoip_client_action_t action, int *total_ipv4,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (total_ipv4)
|
if (ipver_str) {
|
||||||
(*total_ipv4) = round_to_next_multiple_of(ipv4_count, granularity);
|
smartlist_t *chunks = smartlist_new();
|
||||||
if (total_ipv6)
|
smartlist_add_asprintf(chunks, "v4=%u",
|
||||||
(*total_ipv6) = round_to_next_multiple_of(ipv6_count, granularity);
|
round_to_next_multiple_of(ipv4_count, granularity));
|
||||||
/* Don't record anything if we haven't seen enough IPs. */
|
smartlist_add_asprintf(chunks, "v6=%u",
|
||||||
if (total < MIN_IPS_TO_NOTE_ANYTHING)
|
round_to_next_multiple_of(ipv6_count, granularity));
|
||||||
goto done;
|
*ipver_str = smartlist_join_strings(chunks, ",", 0, NULL);
|
||||||
|
SMARTLIST_FOREACH(chunks, char *, c, tor_free(c));
|
||||||
|
smartlist_free(chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't record per country data if we haven't seen enough IPs. */
|
||||||
|
if (total < MIN_IPS_TO_NOTE_ANYTHING) {
|
||||||
|
tor_free(counts);
|
||||||
|
if (country_str)
|
||||||
|
*country_str = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make a list of c_hist_t */
|
/* Make a list of c_hist_t */
|
||||||
entries = smartlist_new();
|
entries = smartlist_new();
|
||||||
for (i = 0; i < n_countries; ++i) {
|
for (i = 0; i < n_countries; ++i) {
|
||||||
@ -1066,23 +1083,21 @@ geoip_get_client_history(geoip_client_action_t action, int *total_ipv4,
|
|||||||
* the sort order could leak info. */
|
* the sort order could leak info. */
|
||||||
smartlist_sort(entries, _c_hist_compare);
|
smartlist_sort(entries, _c_hist_compare);
|
||||||
|
|
||||||
/* Build the result. */
|
if (country_str) {
|
||||||
chunks = smartlist_new();
|
smartlist_t *chunks = smartlist_new();
|
||||||
SMARTLIST_FOREACH(entries, c_hist_t *, ch, {
|
SMARTLIST_FOREACH(entries, c_hist_t *, ch, {
|
||||||
smartlist_add_asprintf(chunks, "%s=%u", ch->country, ch->total);
|
smartlist_add_asprintf(chunks, "%s=%u", ch->country, ch->total);
|
||||||
});
|
});
|
||||||
result = smartlist_join_strings(chunks, ",", 0, NULL);
|
*country_str = smartlist_join_strings(chunks, ",", 0, NULL);
|
||||||
done:
|
|
||||||
tor_free(counts);
|
|
||||||
if (chunks) {
|
|
||||||
SMARTLIST_FOREACH(chunks, char *, c, tor_free(c));
|
SMARTLIST_FOREACH(chunks, char *, c, tor_free(c));
|
||||||
smartlist_free(chunks);
|
smartlist_free(chunks);
|
||||||
}
|
}
|
||||||
if (entries) {
|
|
||||||
SMARTLIST_FOREACH(entries, c_hist_t *, c, tor_free(c));
|
SMARTLIST_FOREACH(entries, c_hist_t *, c, tor_free(c));
|
||||||
smartlist_free(entries);
|
smartlist_free(entries);
|
||||||
}
|
tor_free(counts);
|
||||||
return result;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return a newly allocated string holding the per-country request history
|
/** Return a newly allocated string holding the per-country request history
|
||||||
@ -1205,10 +1220,9 @@ geoip_format_dirreq_stats(time_t now)
|
|||||||
tor_assert(now >= start_of_dirreq_stats_interval);
|
tor_assert(now >= start_of_dirreq_stats_interval);
|
||||||
|
|
||||||
format_iso_time(t, now);
|
format_iso_time(t, now);
|
||||||
v2_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2,
|
geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2, &v2_ips_string,
|
||||||
NULL, NULL);
|
NULL);
|
||||||
v3_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS,
|
geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS, &v3_ips_string, NULL);
|
||||||
NULL, NULL);
|
|
||||||
v2_reqs_string = geoip_get_request_history(
|
v2_reqs_string = geoip_get_request_history(
|
||||||
GEOIP_CLIENT_NETWORKSTATUS_V2);
|
GEOIP_CLIENT_NETWORKSTATUS_V2);
|
||||||
v3_reqs_string = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS);
|
v3_reqs_string = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS);
|
||||||
@ -1414,10 +1428,9 @@ static char *bridge_stats_extrainfo = NULL;
|
|||||||
char *
|
char *
|
||||||
geoip_format_bridge_stats(time_t now)
|
geoip_format_bridge_stats(time_t now)
|
||||||
{
|
{
|
||||||
char *out = NULL, *data = NULL;
|
char *out = NULL, *data = NULL, *ipver = NULL;
|
||||||
long duration = now - start_of_bridge_stats_interval;
|
long duration = now - start_of_bridge_stats_interval;
|
||||||
char written[ISO_TIME_LEN+1];
|
char written[ISO_TIME_LEN+1];
|
||||||
int total_ipv4 = 0, total_ipv6 = 0;
|
|
||||||
|
|
||||||
if (duration < 0)
|
if (duration < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1425,18 +1438,17 @@ geoip_format_bridge_stats(time_t now)
|
|||||||
return NULL; /* Not initialized. */
|
return NULL; /* Not initialized. */
|
||||||
|
|
||||||
format_iso_time(written, now);
|
format_iso_time(written, now);
|
||||||
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4,
|
geoip_get_client_history(GEOIP_CLIENT_CONNECT, &data, &ipver);
|
||||||
&total_ipv6);
|
|
||||||
|
|
||||||
tor_asprintf(&out,
|
tor_asprintf(&out,
|
||||||
"bridge-stats-end %s (%ld s)\n"
|
"bridge-stats-end %s (%ld s)\n"
|
||||||
"bridge-ips %s\n"
|
"bridge-ips %s\n"
|
||||||
"bridge-ip-versions v4=%d,v6=%d\n",
|
"bridge-ip-versions %s\n",
|
||||||
written, duration,
|
written, duration,
|
||||||
data ? data : "",
|
data ? data : "",
|
||||||
total_ipv4,
|
ipver ? ipver : "");
|
||||||
total_ipv6);
|
|
||||||
tor_free(data);
|
tor_free(data);
|
||||||
|
tor_free(ipver);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -1447,17 +1459,20 @@ geoip_format_bridge_stats(time_t now)
|
|||||||
static char *
|
static char *
|
||||||
format_bridge_stats_controller(time_t now)
|
format_bridge_stats_controller(time_t now)
|
||||||
{
|
{
|
||||||
char *out = NULL, *data = NULL;
|
char *out = NULL, *country_data = NULL, *ipver_data = NULL;
|
||||||
char started[ISO_TIME_LEN+1];
|
char started[ISO_TIME_LEN+1];
|
||||||
(void) now;
|
(void) now;
|
||||||
|
|
||||||
format_iso_time(started, start_of_bridge_stats_interval);
|
format_iso_time(started, start_of_bridge_stats_interval);
|
||||||
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT, NULL, NULL);
|
geoip_get_client_history(GEOIP_CLIENT_CONNECT, &country_data, &ipver_data);
|
||||||
|
|
||||||
tor_asprintf(&out,
|
tor_asprintf(&out,
|
||||||
"TimeStarted=\"%s\" CountrySummary=%s",
|
"TimeStarted=\"%s\" CountrySummary=%s IPVersions=%s",
|
||||||
started, data ? data : "");
|
started,
|
||||||
tor_free(data);
|
country_data ? country_data : "",
|
||||||
|
ipver_data ? ipver_data : "");
|
||||||
|
tor_free(country_data);
|
||||||
|
tor_free(ipver_data);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1578,15 +1593,13 @@ geoip_format_entry_stats(time_t now)
|
|||||||
char t[ISO_TIME_LEN+1];
|
char t[ISO_TIME_LEN+1];
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
char *result;
|
char *result;
|
||||||
int total_ipv4, total_ipv6;
|
|
||||||
|
|
||||||
if (!start_of_entry_stats_interval)
|
if (!start_of_entry_stats_interval)
|
||||||
return NULL; /* Not initialized. */
|
return NULL; /* Not initialized. */
|
||||||
|
|
||||||
tor_assert(now >= start_of_entry_stats_interval);
|
tor_assert(now >= start_of_entry_stats_interval);
|
||||||
|
|
||||||
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4,
|
geoip_get_client_history(GEOIP_CLIENT_CONNECT, &data, NULL);
|
||||||
&total_ipv6);
|
|
||||||
format_iso_time(t, now);
|
format_iso_time(t, now);
|
||||||
tor_asprintf(&result,
|
tor_asprintf(&result,
|
||||||
"entry-stats-end %s (%u s)\n"
|
"entry-stats-end %s (%u s)\n"
|
||||||
|
@ -33,8 +33,8 @@ void geoip_remove_old_clients(time_t cutoff);
|
|||||||
|
|
||||||
void geoip_note_ns_response(geoip_client_action_t action,
|
void geoip_note_ns_response(geoip_client_action_t action,
|
||||||
geoip_ns_response_t response);
|
geoip_ns_response_t response);
|
||||||
char *geoip_get_client_history(geoip_client_action_t action, int *total_ipv4,
|
int geoip_get_client_history(geoip_client_action_t action,
|
||||||
int *total_ipv6);
|
char **country_str, char **ipver_str);
|
||||||
char *geoip_get_request_history(geoip_client_action_t action);
|
char *geoip_get_request_history(geoip_client_action_t action);
|
||||||
int getinfo_helper_geoip(control_connection_t *control_conn,
|
int getinfo_helper_geoip(control_connection_t *control_conn,
|
||||||
const char *question, char **answer,
|
const char *question, char **answer,
|
||||||
|
@ -1388,7 +1388,7 @@ test_geoip(void)
|
|||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
|
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
|
||||||
char *s = NULL;
|
char *s = NULL, *v = NULL;
|
||||||
const char *bridge_stats_1 =
|
const char *bridge_stats_1 =
|
||||||
"bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
|
"bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
|
||||||
"bridge-ips zz=24,xy=8\n"
|
"bridge-ips zz=24,xy=8\n"
|
||||||
@ -1457,7 +1457,6 @@ test_geoip(void)
|
|||||||
"entry-ips \n";
|
"entry-ips \n";
|
||||||
tor_addr_t addr;
|
tor_addr_t addr;
|
||||||
struct in6_addr in6;
|
struct in6_addr in6;
|
||||||
int total_ipv4, total_ipv6;
|
|
||||||
|
|
||||||
/* Populate the DB a bit. Add these in order, since we can't do the final
|
/* Populate the DB a bit. Add these in order, since we can't do the final
|
||||||
* 'sort' step. These aren't very good IP addresses, but they're perfectly
|
* 'sort' step. These aren't very good IP addresses, but they're perfectly
|
||||||
@ -1542,20 +1541,23 @@ test_geoip(void)
|
|||||||
SET_TEST_ADDRESS(i);
|
SET_TEST_ADDRESS(i);
|
||||||
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now);
|
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, now);
|
||||||
}
|
}
|
||||||
s = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4, &total_ipv6);
|
geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
|
||||||
test_assert(s);
|
test_assert(s);
|
||||||
|
test_assert(v);
|
||||||
test_streq("zz=24,ab=16,xy=8", s);
|
test_streq("zz=24,ab=16,xy=8", s);
|
||||||
test_eq(total_ipv4, 16);
|
test_streq("v4=16,v6=16", v);
|
||||||
test_eq(total_ipv6, 16);
|
|
||||||
tor_free(s);
|
tor_free(s);
|
||||||
|
tor_free(v);
|
||||||
|
|
||||||
/* Now clear out all the AB observations. */
|
/* Now clear out all the AB observations. */
|
||||||
geoip_remove_old_clients(now-6000);
|
geoip_remove_old_clients(now-6000);
|
||||||
s = geoip_get_client_history(GEOIP_CLIENT_CONNECT, &total_ipv4, &total_ipv6);
|
geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
|
||||||
test_assert(s);
|
test_assert(s);
|
||||||
|
test_assert(v);
|
||||||
test_streq("zz=24,xy=8", s);
|
test_streq("zz=24,xy=8", s);
|
||||||
test_eq(total_ipv4, 16);
|
test_streq("v4=16,v6=16", v);
|
||||||
test_eq(total_ipv6, 16);
|
tor_free(s);
|
||||||
|
tor_free(v);
|
||||||
|
|
||||||
/* Start testing bridge statistics by making sure that we don't output
|
/* Start testing bridge statistics by making sure that we don't output
|
||||||
* bridge stats without initializing them. */
|
* bridge stats without initializing them. */
|
||||||
|
Loading…
Reference in New Issue
Block a user