-
Notifications
You must be signed in to change notification settings - Fork 933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#27325: Rework NETINFO wire format handling to rely on trunnel #370
Conversation
Pull Request Test Coverage Report for Build 2610
💛 - Coveralls |
const NETINFO_ADDR_TYPE_IPV6 = 6; | ||
|
||
struct netinfo_addr { | ||
u8 addr_type IN [NETINFO_ADDR_TYPE_IPV4, NETINFO_ADDR_TYPE_IPV6]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm is it possible this is missing 3 values by any chance (looking at tor-spec.txt):
"Type" is one of:
0x00 -- Hostname
0x04 -- IPv4 address
0x06 -- IPv6 address
0xF0 -- Error, transient
0xF1 -- Error, nontransient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems also that the are mapped from RESOLVED_TYPE_*
values. We should put a strong comment to keep them insync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old code did not use any address type values other 4 and 6. I suppose they cannot realistically appear in a valid NETINFO cell during handshake?
Added a comment in 9cd116b.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code doesn't use it but doesn't mean the protocol doesn't allow it.
This specific "netinfo addr" structure actually should be generalized (and probably put outside the netinfo context) because it is also a structure that is used in the RELAY_RESOLVED
cell so all type need to be there.
It just happens that the NETINFO cell will only care about two of those values.
src/core/or/channeltls.c
Outdated
|
||
netinfo_addr_t *my_addr = netinfo_cell_get_other_addr(netinfo_cell); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use the const
getter here you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Did so in b0a8cf0.
src/core/or/channeltls.c
Outdated
if (my_addr_type == RESOLVED_TYPE_IPV4 && my_addr_len == 4) { | ||
tor_addr_from_ipv4n(&my_apparent_addr, get_uint32(my_addr_ptr)); | ||
uint32_t ipv4 = netinfo_addr_get_addr_ipv4(my_addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the ipv4
will be network order here so I would try to reflect that in the name of the variable because we'll get confused really fast :S
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, why do we need to do that if we have the address already in my_apparent_addr
? Can't we simply compare that with me->addr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trunnel does change between endianness automatically - see netinfo_addr_encode()
and netinfo_addr_parse_into()
.
Simplified the code to rely on my_apparent_addr
in 92ada4d.
src/core/or/channeltls.c
Outdated
n_other_addrs = (uint8_t) *cp++; | ||
while (n_other_addrs && cp < end-2) { | ||
n_other_addrs = netinfo_cell_get_n_my_addrs(netinfo_cell); | ||
for (size_t i = 0; i < n_other_addrs; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
size_t i
--> uint8_t i
. I say we match the type with our top limit n_other_addrs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 1ae0ab8.
netinfo_addr_t *netinfo_addr = netinfo_addr_new(); | ||
|
||
if (addr_family == AF_INET) { | ||
netinfo_addr_set_addr_type(netinfo_addr, NETINFO_ADDR_TYPE_IPV4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When decoding, we used RESOLVED_TYPE_...
, here the NETINFO_...
are used. Whichever we use, we should simply be consistent and stick to use one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In b195438, I fixed parsing code to use macros from netinfo.trunnel.
src/core/or/connection_or.c
Outdated
uint8_t *ipv6_buf = netinfo_addr_getarray_addr_ipv6(netinfo_addr); | ||
// XXX: this looks sketchy | ||
memcpy(ipv6_buf, tor_addr->addr.in6_addr.s6_addr, 16); | ||
// XXX: can we avoid memcpy here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The HS subsystem does it like this:
const uint8_t *in6_addr = tor_addr_to_in6_addr8(&ap.addr);
uint8_t *ipv6_array = link_specifier_getarray_un_ipv6_addr(ls);
memcpy(ipv6_array, in6_addr, addr_len);
You can probably ignore addr_len
and instead use 16.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* Timestamp, if we're a relay. */ | ||
if (public_server_mode(get_options()) || ! conn->is_outgoing) | ||
set_uint32(cell.payload, htonl((uint32_t)now)); | ||
netinfo_cell_set_timestamp(netinfo_cell, (uint32_t)now); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You sure you can remove the htonl()
? Trunnel won't magically switch it :S... Spec specifies:
The timestamp is a big-endian unsigned integer number of seconds since the Unix epoch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, as trunnel changes the endianness for us:
597 /* Encode u32 timestamp */
598 trunnel_assert(written <= avail);
599 if (avail - written < 4)
600 goto truncated;
601 trunnel_set_uint32(ptr, trunnel_htonl(obj->timestamp));
602 written += 4; ptr += 4;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
errmsg); | ||
r = -1; | ||
goto cleanup; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is OK to remove this check because the encoding function does call netinfo_cell_check()
and -1
is returned if the check fails. -2
is the allocation failed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But we do lose the error message if we rely on _encode()
calling _check()
.
While calling _check()
in here is not strictly necessary, it may prove useful in case struct gets populated incorrectly. I would say let's leave it here just to be safe and make debugging easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
src/core/or/connection_or.c
Outdated
@@ -2434,8 +2461,7 @@ connection_or_send_netinfo,(or_connection_t *conn)) | |||
cell_t cell; | |||
time_t now = time(NULL); | |||
const routerinfo_t *me; | |||
int len; | |||
uint8_t *out; | |||
int r = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A trick that I like is set this to -1
so then every goto
will have the right error value set. Then if you reach the cleanup:
label, just before you set r = 0
. This way, any code addition later, we avoid the error of someone forgetting to set r
within the error path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did so in e9b6b8a.
https://trac.torproject.org/projects/tor/ticket/27325