Skip to content
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

Closed
wants to merge 12 commits into from

Conversation

rl1987
Copy link
Contributor

@rl1987 rl1987 commented Sep 22, 2018

@coveralls
Copy link

coveralls commented Sep 22, 2018

Pull Request Test Coverage Report for Build 2610

  • 0 of 65 (0.0%) changed or added relevant lines in 2 files are covered.
  • 11953 unchanged lines in 53 files lost coverage.
  • Overall coverage increased (+0.08%) to 62.009%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/core/or/connection_or.c 0 30 0.0%
src/core/or/channeltls.c 0 35 0.0%
Files with Coverage Reduction New Missed Lines %
src/core/or/or.h 1 88.89%
src/core/or/channelpadding.c 5 97.27%
src/app/config/confparse.c 5 80.36%
src/lib/tls/tortls.c 6 96.55%
src/lib/container/order.h 6 0.0%
src/lib/evloop/procmon.c 7 76.74%
src/core/or/status.c 7 86.87%
src/feature/nodelist/torcert.c 14 95.22%
src/core/proto/proto_socks.c 14 92.74%
src/feature/control/fmt_serverstatus.c 18 0.0%
Totals Coverage Status
Change from base Build 2312: 0.08%
Covered Lines: 44089
Relevant Lines: 71101

💛 - Coveralls

const NETINFO_ADDR_TYPE_IPV6 = 6;

struct netinfo_addr {
u8 addr_type IN [NETINFO_ADDR_TYPE_IPV4, NETINFO_ADDR_TYPE_IPV6];
Copy link
Contributor

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

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.


netinfo_addr_t *my_addr = netinfo_cell_get_other_addr(netinfo_cell);
Copy link
Contributor

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?

Copy link
Contributor Author

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.

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);
Copy link
Contributor

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

Copy link
Contributor

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 ?

Copy link
Contributor Author

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.

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++) {
Copy link
Contributor

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

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.

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?
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the comments in 216880f and used the the helper function in 6867bea.

/* 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);
Copy link
Contributor

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.

Copy link
Contributor Author

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;

Copy link
Contributor

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;
}
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

@@ -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;
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did so in e9b6b8a.

@ghost ghost closed this May 25, 2021
@ghost ghost deleted the branch torproject:master May 25, 2021 12:55
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants