mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Lay down some infrastructure for bridges in the New Guard Order.
This includes: * making bridge_info_t exposed but opaque * allowing guards where we don't know an identity * making it possible to learn the identity of a guard * creating a guard that lacks a node_t * remembering a guard's address and port. * Looking up a guard by address and port. * Only enforcing the rule that we need a live consensus to update the "listed" status for guards when we are not using bridges.
This commit is contained in:
parent
89f5f149df
commit
1d52ac4d3f
@ -2121,3 +2121,11 @@ tor_addr_port_new(const tor_addr_t *addr, uint16_t port)
|
||||
return ap;
|
||||
}
|
||||
|
||||
/** Return true iff <a>a</b> and <b>b</b> are the same address and port */
|
||||
int
|
||||
tor_addr_port_eq(const tor_addr_port_t *a,
|
||||
const tor_addr_port_t *b)
|
||||
{
|
||||
return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port;
|
||||
}
|
||||
|
||||
|
@ -342,6 +342,8 @@ get_interface_address_list(int severity, int include_internal)
|
||||
}
|
||||
|
||||
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
|
||||
int tor_addr_port_eq(const tor_addr_port_t *a,
|
||||
const tor_addr_port_t *b);
|
||||
|
||||
#ifdef ADDRESS_PRIVATE
|
||||
MOCK_DECL(smartlist_t *,get_interface_addresses_raw,(int severity,
|
||||
|
@ -28,7 +28,9 @@
|
||||
/** Information about a configured bridge. Currently this just matches the
|
||||
* ones in the torrc file, but one day we may be able to learn about new
|
||||
* bridges on our own, and remember them in the state file. */
|
||||
typedef struct {
|
||||
struct bridge_info_t {
|
||||
/** Address and port of the bridge, as configured by the user.*/
|
||||
tor_addr_port_t addrport_configured;
|
||||
/** Address of the bridge. */
|
||||
tor_addr_t addr;
|
||||
/** TLS port for the bridge. */
|
||||
@ -49,7 +51,7 @@ typedef struct {
|
||||
/** A smartlist of k=v values to be passed to the SOCKS proxy, if
|
||||
transports are used for this bridge. */
|
||||
smartlist_t *socks_args;
|
||||
} bridge_info_t;
|
||||
};
|
||||
|
||||
static void bridge_free(bridge_info_t *bridge);
|
||||
|
||||
@ -111,6 +113,40 @@ bridge_free(bridge_info_t *bridge)
|
||||
tor_free(bridge);
|
||||
}
|
||||
|
||||
/** Return a list of all the configured bridges, as bridge_info_t pointers. */
|
||||
const smartlist_t *
|
||||
bridge_list_get(void)
|
||||
{
|
||||
if (!bridge_list)
|
||||
bridge_list = smartlist_new();
|
||||
return bridge_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a <b>bridge</b>, return a pointer to its RSA identity digest, or
|
||||
* NULL if we don't know one for it.
|
||||
*/
|
||||
const uint8_t *
|
||||
bridge_get_rsa_id_digest(const bridge_info_t *bridge)
|
||||
{
|
||||
tor_assert(bridge);
|
||||
if (tor_digest_is_zero(bridge->identity))
|
||||
return NULL;
|
||||
else
|
||||
return (const uint8_t *) bridge->identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a <b>bridge</b>, return a pointer to its configured addr:port
|
||||
* combination.
|
||||
*/
|
||||
const tor_addr_port_t *
|
||||
bridge_get_addr_port(const bridge_info_t *bridge)
|
||||
{
|
||||
tor_assert(bridge);
|
||||
return &bridge->addrport_configured;
|
||||
}
|
||||
|
||||
/** If we have a bridge configured whose digest matches <b>digest</b>, or a
|
||||
* bridge with no known digest whose address matches any of the
|
||||
* tor_addr_port_t's in <b>orports</b>, return that bridge. Else return
|
||||
@ -243,6 +279,7 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port,
|
||||
hex_str(digest, DIGEST_LEN), fmt_addrport(addr, port),
|
||||
transport_info ? transport_info : "");
|
||||
tor_free(transport_info);
|
||||
// XXXX prop271 here. we will need to update the guard info too.
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,6 +398,8 @@ bridge_add_from_config(bridge_line_t *bridge_line)
|
||||
bridge_line->transport_name);
|
||||
|
||||
b = tor_malloc_zero(sizeof(bridge_info_t));
|
||||
tor_addr_copy(&b->addrport_configured.addr, &bridge_line->addr);
|
||||
b->addrport_configured.port = bridge_line->port;
|
||||
tor_addr_copy(&b->addr, &bridge_line->addr);
|
||||
b->port = bridge_line->port;
|
||||
memcpy(b->identity, bridge_line->digest, DIGEST_LEN);
|
||||
@ -718,6 +757,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
|
||||
fmt_and_decorate_addr(&bridge->addr),
|
||||
(int) bridge->port);
|
||||
}
|
||||
// XXXX prop271 here we will need to update the guard info too.
|
||||
add_bridge_as_entry_guard(get_guard_selection_info(), node);
|
||||
|
||||
log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
|
||||
|
@ -14,8 +14,14 @@
|
||||
|
||||
struct bridge_line_t;
|
||||
|
||||
/* Opaque handle to a configured bridge */
|
||||
typedef struct bridge_info_t bridge_info_t;
|
||||
|
||||
void mark_bridge_list(void);
|
||||
void sweep_bridge_list(void);
|
||||
const smartlist_t *bridge_list_get(void);
|
||||
const uint8_t *bridge_get_rsa_id_digest(const bridge_info_t *bridge);
|
||||
const tor_addr_port_t * bridge_get_addr_port(const bridge_info_t *bridge);
|
||||
|
||||
int addr_is_a_configured_bridge(const tor_addr_t *addr, uint16_t port,
|
||||
const char *digest);
|
||||
|
@ -163,6 +163,10 @@ static int node_is_possible_guard(guard_selection_t *gs, const node_t *node);
|
||||
static int node_passes_guard_filter(const or_options_t *options,
|
||||
guard_selection_t *gs,
|
||||
const node_t *node);
|
||||
static entry_guard_t *entry_guard_add_to_sample_impl(guard_selection_t *gs,
|
||||
const uint8_t *rsa_id_digest,
|
||||
const char *nickname,
|
||||
const tor_addr_port_t *bridge_addrport);
|
||||
|
||||
/** Return 0 if we should apply guardfraction information found in the
|
||||
* consensus. A specific consensus can be specified with the
|
||||
@ -693,25 +697,47 @@ STATIC entry_guard_t *
|
||||
entry_guard_add_to_sample(guard_selection_t *gs,
|
||||
const node_t *node)
|
||||
{
|
||||
const int GUARD_LIFETIME = get_guard_lifetime_days() * 86400;
|
||||
tor_assert(gs);
|
||||
tor_assert(node);
|
||||
|
||||
log_info(LD_GUARD, "Adding %s as to the entry guard sample set.",
|
||||
node_describe(node));
|
||||
|
||||
return entry_guard_add_to_sample_impl(gs,
|
||||
(const uint8_t*)node->identity,
|
||||
node_get_nickname(node),
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backend: adds a new sampled guard to <b>gs</b>, with given identity,
|
||||
* nickname, and ORPort. rsa_id_digest and bridge_addrport are
|
||||
* optional, but we need one of them. nickname is optional.
|
||||
*/
|
||||
static entry_guard_t *
|
||||
entry_guard_add_to_sample_impl(guard_selection_t *gs,
|
||||
const uint8_t *rsa_id_digest,
|
||||
const char *nickname,
|
||||
const tor_addr_port_t *bridge_addrport)
|
||||
{
|
||||
const int GUARD_LIFETIME = get_guard_lifetime_days() * 86400;
|
||||
tor_assert(gs);
|
||||
|
||||
// XXXX prop271 take ed25519 identity here too.
|
||||
|
||||
/* make sure that the guard is not already sampled. */
|
||||
if (BUG(have_sampled_guard_with_id(gs, (uint8_t*)node->identity)))
|
||||
if (rsa_id_digest && BUG(have_sampled_guard_with_id(gs, rsa_id_digest)))
|
||||
return NULL; // LCOV_EXCL_LINE
|
||||
/* Make sure we can actually identify the guard. */
|
||||
if (BUG(!rsa_id_digest && !bridge_addrport))
|
||||
return NULL; // LCOV_EXCL_LINE
|
||||
|
||||
entry_guard_t *guard = tor_malloc_zero(sizeof(entry_guard_t));
|
||||
|
||||
/* persistent fields */
|
||||
guard->is_persistent = (rsa_id_digest != NULL);
|
||||
guard->selection_name = tor_strdup(gs->name);
|
||||
memcpy(guard->identity, node->identity, DIGEST_LEN);
|
||||
strlcpy(guard->nickname, node_get_nickname(node), sizeof(guard->nickname));
|
||||
if (rsa_id_digest)
|
||||
memcpy(guard->identity, rsa_id_digest, DIGEST_LEN);
|
||||
if (nickname)
|
||||
strlcpy(guard->nickname, nickname, sizeof(guard->nickname));
|
||||
guard->sampled_on_date = randomize_time(approx_time(), GUARD_LIFETIME/10);
|
||||
tor_free(guard->sampled_by_version);
|
||||
guard->sampled_by_version = tor_strdup(VERSION);
|
||||
@ -720,6 +746,8 @@ entry_guard_add_to_sample(guard_selection_t *gs,
|
||||
|
||||
/* non-persistent fields */
|
||||
guard->is_reachable = GUARD_REACHABLE_MAYBE;
|
||||
if (bridge_addrport)
|
||||
guard->bridge_addr = tor_memdup(bridge_addrport, sizeof(*bridge_addrport));
|
||||
|
||||
smartlist_add(gs->sampled_entry_guards, guard);
|
||||
guard->in_selection = gs;
|
||||
@ -728,6 +756,87 @@ entry_guard_add_to_sample(guard_selection_t *gs,
|
||||
return guard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry guard to the "bridges" guard selection sample, with
|
||||
* information taken from <b>bridge</b>. Return that entry guard.
|
||||
*/
|
||||
entry_guard_t *
|
||||
entry_guard_add_bridge_to_sample(const bridge_info_t *bridge)
|
||||
{
|
||||
guard_selection_t *gs = get_guard_selection_by_name("bridges",
|
||||
GS_TYPE_BRIDGE,
|
||||
1);
|
||||
const uint8_t *id_digest = bridge_get_rsa_id_digest(bridge);
|
||||
const tor_addr_port_t *addrport = bridge_get_addr_port(bridge);
|
||||
|
||||
tor_assert(addrport);
|
||||
|
||||
return entry_guard_add_to_sample_impl(gs, id_digest, NULL, addrport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the entry_guard_t in <b>gs</b> whose address is <b>addrport</b>,
|
||||
* or NULL if none exists.
|
||||
*/
|
||||
static entry_guard_t *
|
||||
entry_guard_get_by_bridge_addr(guard_selection_t *gs,
|
||||
const tor_addr_port_t *addrport)
|
||||
{
|
||||
if (! gs)
|
||||
return NULL;
|
||||
if (BUG(!addrport))
|
||||
return NULL;
|
||||
SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, g) {
|
||||
if (g->bridge_addr && tor_addr_port_eq(addrport, g->bridge_addr))
|
||||
return g;
|
||||
} SMARTLIST_FOREACH_END(g);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Update the guard subsystem's knowledge of the identity of the bridge
|
||||
* at <b>addrport</b>. Idempotent.
|
||||
*/
|
||||
void
|
||||
entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport,
|
||||
const uint8_t *rsa_id_digest)
|
||||
{
|
||||
guard_selection_t *gs = get_guard_selection_by_name("bridges",
|
||||
GS_TYPE_BRIDGE,
|
||||
0);
|
||||
if (!gs)
|
||||
return;
|
||||
|
||||
entry_guard_t *g = entry_guard_get_by_bridge_addr(gs, addrport);
|
||||
if (!g)
|
||||
return;
|
||||
|
||||
int make_persistent = 0;
|
||||
|
||||
if (tor_digest_is_zero(g->identity)) {
|
||||
memcpy(g->identity, rsa_id_digest, DIGEST_LEN);
|
||||
make_persistent = 1;
|
||||
} else if (tor_memeq(g->identity, rsa_id_digest, DIGEST_LEN)) {
|
||||
/* Nothing to see here; we learned something we already knew. */
|
||||
if (BUG(! g->is_persistent))
|
||||
make_persistent = 1;
|
||||
} else {
|
||||
char old_id[HEX_DIGEST_LEN+1];
|
||||
base16_encode(old_id, sizeof(old_id), g->identity, sizeof(g->identity));
|
||||
log_warn(LD_BUG, "We 'learned' an identity %s for a bridge at %s:%d, but "
|
||||
"we already knew a different one (%s). Ignoring the new info as "
|
||||
"possibly bogus.",
|
||||
hex_str((const char *)rsa_id_digest, DIGEST_LEN),
|
||||
fmt_and_decorate_addr(&addrport->addr), addrport->port,
|
||||
old_id);
|
||||
return; // redundant, but let's be clear: we're not making this persistent.
|
||||
}
|
||||
|
||||
if (make_persistent) {
|
||||
g->is_persistent = 1;
|
||||
entry_guards_changed_for_guard_selection(gs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of sampled guards in <b>gs</b> that are "filtered"
|
||||
* (that is, we're willing to connect to them) and that are "usable"
|
||||
@ -892,14 +1001,16 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
|
||||
|
||||
// It's important to use only a live consensus here; we don't want to
|
||||
// make changes based on anything expired or old.
|
||||
networkstatus_t *ns = networkstatus_get_live_consensus(approx_time());
|
||||
if (gs->type != GS_TYPE_BRIDGE) {
|
||||
networkstatus_t *ns = networkstatus_get_live_consensus(approx_time());
|
||||
|
||||
log_info(LD_GUARD, "Updating sampled guard status based on received "
|
||||
"consensus.");
|
||||
log_info(LD_GUARD, "Updating sampled guard status based on received "
|
||||
"consensus.");
|
||||
|
||||
if (! ns || ns->valid_until < approx_time()) {
|
||||
log_info(LD_GUARD, "Hey, that consensus isn't still valid. Ignoring.");
|
||||
return;
|
||||
if (! ns || ns->valid_until < approx_time()) {
|
||||
log_info(LD_GUARD, "Hey, there wasn't a valid consensus. Ignoring");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int n_changes = 0;
|
||||
@ -2070,6 +2181,11 @@ entry_guard_encode_for_state(entry_guard_t *guard)
|
||||
smartlist_add_asprintf(result, "in=%s", guard->selection_name);
|
||||
smartlist_add_asprintf(result, "rsa_id=%s",
|
||||
hex_str(guard->identity, DIGEST_LEN));
|
||||
if (guard->bridge_addr) {
|
||||
smartlist_add_asprintf(result, "bridge_addr=%s:%d",
|
||||
fmt_and_decorate_addr(&guard->bridge_addr->addr),
|
||||
guard->bridge_addr->port);
|
||||
}
|
||||
if (strlen(guard->nickname)) {
|
||||
smartlist_add_asprintf(result, "nickname=%s", guard->nickname);
|
||||
}
|
||||
@ -2152,6 +2268,7 @@ entry_guard_parse_from_state(const char *s)
|
||||
char *listed = NULL;
|
||||
char *confirmed_on = NULL;
|
||||
char *confirmed_idx = NULL;
|
||||
char *bridge_addr = NULL;
|
||||
|
||||
// pathbias
|
||||
char *pb_use_attempts = NULL;
|
||||
@ -2180,6 +2297,7 @@ entry_guard_parse_from_state(const char *s)
|
||||
FIELD(listed);
|
||||
FIELD(confirmed_on);
|
||||
FIELD(confirmed_idx);
|
||||
FIELD(bridge_addr);
|
||||
FIELD(pb_use_attempts);
|
||||
FIELD(pb_use_successes);
|
||||
FIELD(pb_circ_attempts);
|
||||
@ -2218,6 +2336,7 @@ entry_guard_parse_from_state(const char *s)
|
||||
}
|
||||
|
||||
entry_guard_t *guard = tor_malloc_zero(sizeof(entry_guard_t));
|
||||
guard->is_persistent = 1;
|
||||
|
||||
if (in == NULL) {
|
||||
log_warn(LD_CIRC, "Guard missing 'in' field");
|
||||
@ -2247,6 +2366,16 @@ entry_guard_parse_from_state(const char *s)
|
||||
guard->identity, DIGEST_LEN);
|
||||
}
|
||||
|
||||
if (bridge_addr) {
|
||||
tor_addr_port_t res;
|
||||
memset(&res, 0, sizeof(res));
|
||||
int r = tor_addr_port_parse(LOG_WARN, bridge_addr,
|
||||
&res.addr, &res.port, -1);
|
||||
if (r == 0)
|
||||
guard->bridge_addr = tor_memdup(&res, sizeof(res));
|
||||
/* On error, we already warned. */
|
||||
}
|
||||
|
||||
/* Process the various time fields. */
|
||||
|
||||
#define HANDLE_TIME(field) do { \
|
||||
@ -2357,6 +2486,7 @@ entry_guard_parse_from_state(const char *s)
|
||||
tor_free(listed);
|
||||
tor_free(confirmed_on);
|
||||
tor_free(confirmed_idx);
|
||||
tor_free(bridge_addr);
|
||||
tor_free(pb_use_attempts);
|
||||
tor_free(pb_use_successes);
|
||||
tor_free(pb_circ_attempts);
|
||||
@ -2388,6 +2518,8 @@ entry_guards_update_guards_in_state(or_state_t *state)
|
||||
if (!strcmp(gs->name, "legacy"))
|
||||
continue; /* This is encoded differently. */
|
||||
SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
|
||||
if (guard->is_persistent == 0)
|
||||
continue;
|
||||
*nextline = tor_malloc_zero(sizeof(config_line_t));
|
||||
(*nextline)->key = tor_strdup("Guard");
|
||||
(*nextline)->value = entry_guard_encode_for_state(guard);
|
||||
@ -2908,6 +3040,7 @@ add_an_entry_guard(guard_selection_t *gs,
|
||||
return NULL;
|
||||
}
|
||||
entry = tor_malloc_zero(sizeof(entry_guard_t));
|
||||
entry->is_persistent = 1;
|
||||
log_info(LD_CIRC, "Chose %s as new entry guard.",
|
||||
node_describe(node));
|
||||
strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname));
|
||||
@ -3020,6 +3153,7 @@ entry_guard_free(entry_guard_t *e)
|
||||
tor_free(e->sampled_by_version);
|
||||
tor_free(e->extra_state_fields);
|
||||
tor_free(e->selection_name);
|
||||
tor_free(e->bridge_addr);
|
||||
tor_free(e);
|
||||
}
|
||||
|
||||
@ -3840,6 +3974,7 @@ entry_guards_parse_state_for_guard_selection(
|
||||
node = tor_malloc_zero(sizeof(entry_guard_t));
|
||||
/* all entry guards on disk have been contacted */
|
||||
node->made_contact = 1;
|
||||
node->is_persistent = 1;
|
||||
smartlist_add(new_entry_guards, node);
|
||||
smartlist_split_string(args, line->value, " ",
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
|
@ -125,7 +125,9 @@ struct entry_guard_t {
|
||||
* Which selection does this guard belong to?
|
||||
*/
|
||||
char *selection_name;
|
||||
guard_selection_t *in_selection;
|
||||
|
||||
/** Bridges only: address of the bridge. */
|
||||
tor_addr_port_t *bridge_addr;
|
||||
|
||||
/* ==== Non-persistent fields. */
|
||||
/* == These are used by sampled guards */
|
||||
@ -140,6 +142,9 @@ struct entry_guard_t {
|
||||
* to try again until it either succeeds or fails. Primary guards can
|
||||
* never be pending. */
|
||||
unsigned is_pending : 1;
|
||||
/** If true, don't write this guard to disk. (Used for bridges with unknown
|
||||
* identities) */
|
||||
unsigned is_persistent : 1;
|
||||
/** When did we get the earliest connection failure for this guard?
|
||||
* We clear this field on a successful connect. We do _not_ clear it
|
||||
* when we mark the guard as "MAYBE" reachable.
|
||||
@ -160,6 +165,9 @@ struct entry_guard_t {
|
||||
/** This string holds any fields that we are maintaining because
|
||||
* we saw them in the state, even if we don't understand them. */
|
||||
char *extra_state_fields;
|
||||
|
||||
/** Backpointer to the guard selection that this guard belongs to. */
|
||||
guard_selection_t *in_selection;
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
@ -554,6 +562,14 @@ STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now);
|
||||
void remove_all_entry_guards_for_guard_selection(guard_selection_t *gs);
|
||||
void remove_all_entry_guards(void);
|
||||
|
||||
struct bridge_info_t;
|
||||
// XXXX prop271 should this be a public API?
|
||||
entry_guard_t *entry_guard_add_bridge_to_sample(
|
||||
const struct bridge_info_t *bridge);
|
||||
|
||||
void entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport,
|
||||
const uint8_t *rsa_id_digest);
|
||||
|
||||
void entry_guards_compute_status_for_guard_selection(
|
||||
guard_selection_t *gs, const or_options_t *options, time_t now);
|
||||
void entry_guards_compute_status(const or_options_t *options, time_t now);
|
||||
|
@ -1055,6 +1055,9 @@ test_entry_guard_encode_for_state_maximal(void *arg)
|
||||
strlcpy(eg->nickname, "Fred", sizeof(eg->nickname));
|
||||
eg->selection_name = tor_strdup("default");
|
||||
memcpy(eg->identity, "plurpyflurpyslurpydo", DIGEST_LEN);
|
||||
eg->bridge_addr = tor_malloc_zero(sizeof(tor_addr_port_t));
|
||||
tor_addr_from_ipv4h(&eg->bridge_addr->addr, 0x08080404);
|
||||
eg->bridge_addr->port = 9999;
|
||||
eg->sampled_on_date = 1479081600;
|
||||
eg->sampled_by_version = tor_strdup("1.2.3");
|
||||
eg->unlisted_since_date = 1479081645;
|
||||
@ -1069,6 +1072,7 @@ test_entry_guard_encode_for_state_maximal(void *arg)
|
||||
tt_str_op(s, OP_EQ,
|
||||
"in=default "
|
||||
"rsa_id=706C75727079666C75727079736C75727079646F "
|
||||
"bridge_addr=8.8.4.4:9999 "
|
||||
"nickname=Fred "
|
||||
"sampled_on=2016-11-14T00:00:00 "
|
||||
"sampled_by=1.2.3 "
|
||||
@ -1100,6 +1104,7 @@ test_entry_guard_parse_from_state_minimal(void *arg)
|
||||
test_mem_op_hex(eg->identity, OP_EQ,
|
||||
"596f75206d6179206e656564206120686f626279");
|
||||
tt_str_op(eg->nickname, OP_EQ, "$596F75206D6179206E656564206120686F626279");
|
||||
tt_ptr_op(eg->bridge_addr, OP_EQ, NULL);
|
||||
tt_i64_op(eg->sampled_on_date, OP_GE, t);
|
||||
tt_i64_op(eg->sampled_on_date, OP_LE, t+86400);
|
||||
tt_i64_op(eg->unlisted_since_date, OP_EQ, 0);
|
||||
@ -1126,6 +1131,7 @@ test_entry_guard_parse_from_state_maximal(void *arg)
|
||||
eg = entry_guard_parse_from_state(
|
||||
"in=fred "
|
||||
"rsa_id=706C75727079666C75727079736C75727079646F "
|
||||
"bridge_addr=[1::3]:9999 "
|
||||
"nickname=Fred "
|
||||
"sampled_on=2016-11-14T00:00:00 "
|
||||
"sampled_by=1.2.3 "
|
||||
@ -1139,6 +1145,8 @@ test_entry_guard_parse_from_state_maximal(void *arg)
|
||||
|
||||
test_mem_op_hex(eg->identity, OP_EQ,
|
||||
"706C75727079666C75727079736C75727079646F");
|
||||
tt_str_op(fmt_addr(&eg->bridge_addr->addr), OP_EQ, "1::3");
|
||||
tt_int_op(eg->bridge_addr->port, OP_EQ, 9999);
|
||||
tt_str_op(eg->nickname, OP_EQ, "Fred");
|
||||
tt_i64_op(eg->sampled_on_date, OP_EQ, 1479081600);
|
||||
tt_i64_op(eg->unlisted_since_date, OP_EQ, 1479081645);
|
||||
@ -1205,6 +1213,7 @@ test_entry_guard_parse_from_state_partial_failure(void *arg)
|
||||
eg = entry_guard_parse_from_state(
|
||||
"in=default "
|
||||
"rsa_id=706C75727079666C75727079736C75727079646F "
|
||||
"bridge_addr=1.2.3.3.4:5 "
|
||||
"nickname=FredIsANodeWithAStrangeNicknameThatIsTooLong "
|
||||
"sampled_on=2016-11-14T00:00:99 "
|
||||
"sampled_by=1.2.3 stuff in the middle "
|
||||
@ -1219,6 +1228,7 @@ test_entry_guard_parse_from_state_partial_failure(void *arg)
|
||||
test_mem_op_hex(eg->identity, OP_EQ,
|
||||
"706C75727079666C75727079736C75727079646F");
|
||||
tt_str_op(eg->nickname, OP_EQ, "FredIsANodeWithAStrangeNicknameThatIsTooL");
|
||||
tt_ptr_op(eg->bridge_addr, OP_EQ, NULL);
|
||||
tt_i64_op(eg->sampled_on_date, OP_EQ, t);
|
||||
tt_i64_op(eg->unlisted_since_date, OP_EQ, 0);
|
||||
tt_str_op(eg->sampled_by_version, OP_EQ, "1.2.3");
|
||||
|
Loading…
Reference in New Issue
Block a user