The routerstatus_has_changed() function is used by controllers to to tell which rs entries are new. But it only looks at a fraction of the fields which might change in a routerstatus. Also, it only checks for semantic changes that tor cares about (though this is not documented).
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related.
Learn more.
So the issue is with that router_has_changed() is not properly documented. The fact that it only checks for semantic changes that tor cares about, is not documented?
The other part of the code just wants descriptors that are different enough to matter.
This means adding an argument to the function that makes it check for different kinds of changes. Or making two functions. But we try not to copy and paste code, we get functions to call other functions instead.
routerstatus_has_changed() checks for some differences in descriptors. This is the right thing to do when the function is called from some code. But it hides some changed descriptors from controllers.
When called from control port code, the function should check if the timestamp has changed. That will give the controller all the changed descriptors.
The definition of the routerstatus_t structure, as in or.h has only time_t published_on. Is that the required timestamp to check.
A check like, (a->published_on != b->published_on) would do the task?
Then this check would be the right one, I suppose:
/* Function to check for new descriptors. Returns 0 if changed, else 1 */static int check_timestamp(const routerstatus_t *a){ if(a->published_on == a->now) return 1; else return 0;}
Have added a patch file. Do let me know, if the changes are correct, although I doubt as 'now' is not a structure member.
But if I need to check for change in timestamp, and published_on is my parameter, then I need to compare it with something.
Oh, I'm sorry, I've been giving you bad advice. I must have searched for the wrong function name.
We don't need a new function. We need to change the existing function to look at more fields.
Here's what we need to do:
The routerstatus_t struct has a lot of fields. routerstatus_has_changed() checks a few of them. But it needs to check every field that is output by networkstatus_getinfo_helper_single().
These missing fields can be compared using !=:
published
ipv6_orport
is_v2_dir
bandwidth_kb
This missing field must be compared using tor_addr_compare(..., ..., CMP_EXACT):
ipv6_addr
We don't need to worry about the summarised IPv4 exit policy output by networkstatus_getinfo_helper_single(). The descriptor_digest check will find changes in this field.
Then we need to add comments to routerstatus_has_changed() saying that it checks for changes that are output by the control port. And we need to add a comment to routerstatus_format_entry() saying that any extra control port fields need to be added to routerstatus_has_changed() as well.
Trac: Keywords: N/Adeleted, ipv6 added Status: new to needs_revision Milestone: Tor: unspecified to Tor: 0.3.4.x-final
teor, I think you have tor_addr_compare backwards. Its documentation says:
* Given two addresses <b>addr1</b> and <b>addr2</b>, return 0 if the two * addresses are equivalent under the mask mbits, less than 0 if addr1 * precedes addr2, and greater than 0 otherwise.
So the original use of tor_addr_compare (without "!") is correct.
(Unit tests would have caught this bug; that's one reason why unit tests are so great. ;) Any chance of writing those?)
As a smaller issue, it seems that this patch says the same line twice:
Another question: how did you decide on the list of fields to check? It seems that some but not all of the fields in routerstatus_t are now checked for equality, but I don't understand the rationale about why the remaining ones (pv, exitsummary) are not. Is that intentional?
Teor asks:
How can we make sure we update functions when we add new members to a struct?
In some cases, using a constructor for a struct instance will work, since we have turned on the options that let us know about any uninitialized members. But in cases like this, I don't see an easy way to use a constructor.
One option here would be to stop assuming that we list all relevant the members here. We could instead change the code that we only list the irrelevant members, by:
Making sure that when we construct routerstatus_t, we initialize the whole object to 0.
In a function like this, using memcpy() to make a temporary copy of the routerstatus_t.
Instead of listing all the relevant members in a comparison, we could just use fast_memeq() to compare. If there are some members we don't want to compare, we would set them to 0 before calling fast_memeq().
I'm not sure if this is actually a good idea, though.
teor, I think you have tor_addr_compare backwards. Its documentation says:
* Given two addresses <b>addr1</b> and <b>addr2</b>, return 0 if the two * addresses are equivalent under the mask mbits, less than 0 if addr1 * precedes addr2, and greater than 0 otherwise.}}}So the original use of tor_addr_compare (without "!") is correct.
You're right. Oops!
(Unit tests would have caught this bug; that's one reason why unit tests are so great. ;) Any chance of writing those?)
I think we should have unit tests.
As a smaller issue, it seems that this patch says the same line twice:
{{{
a->is_hs_dir != b->is_hs_dir ||
a->is_hs_dir != b->is_hs_dir ||
}}}
Another question: how did you decide on the list of fields to check? It seems that some but not all of the fields in routerstatus_t are now checked for equality, but I don't understand the rationale about why the remaining ones (pv, exitsummary) are not. Is that intentional?
We only check the fields that are output via the control port.
We should revise this like to say "only" not "also":
{{{
/* Given two router status entries for the same router identity, return 1 if
if the contents have changed between them. Otherwise, return 0.
It also checks for changes for that are output by control port. */
https://github.com/ArunaMaurya221B/tor/commit/e29292dda5ef68e441f267864357a7568b29588e#diff-fcb162b79906521706b54d280b939d57R1540> --- > > Teor asks:> > How can we make sure we update functions when we add new members to a struct?> > In some cases, using a constructor for a struct instance will work, since we have turned on the options that let us know about any uninitialized members. But in cases like this, I don't see an easy way to use a constructor.> > One option here would be to stop assuming that we list all relevant the members here. We could instead change the code that we only list the _irrelevant_ members, by:> 1. Making sure that when we construct routerstatus_t, we initialize the whole object to 0.> 2. In a function like this, using memcpy() to make a temporary copy of the routerstatus_t.> 3. Instead of listing all the relevant members in a comparison, we could just use fast_memeq() to compare. If there are some members we don't want to compare, we would set them to 0 before calling fast_memeq().> I'm not sure if this is actually a good idea, though.I think it is enough to comment the control port printing function, and this function, and say that they must be kept in sync.
These needs_revision, tickets, tagged with 034-removed-*, are no longer in-scope for 0.3.4. We can reconsider any of them, if somebody does the necessary revision.
Trac: Milestone: Tor: 0.3.4.x-final to Tor: unspecified
I would actually love some help !
I am a complete beginner in C, so I don't know how to go around with writing the makefile for my test (just to see if my tests work). I have follwed tutorials on how to write makefiles, but I don't see how to handle the multiple depth of dependencies.
What steps should I take to write my test makefile ? Since I don't want to go through "making" the whole Tor project everytime I want to see if my test file works.
Also, is this the right place to ask for help ? It feels weird posting questions on an issue.
Thanks !
The implementation of routerstatus_has_changed() is correct, it's only designed to detect changes in the control port routerstatus format. Let's rename routerstatus_has_changed() to a name that contains "control"?
If you'd like to remove the named and unnamed code, let's do it in another ticket, and try to remove as much as we can.
Okay -- I've changed the comments, updated the tests to verify that routerstatus_format_entry() actually changed (or hasn't), and renamed the identifier. I went with "visibly" instead of "control", but I'm open to suggestions for other identifiers that aren't even longer.
There's a conflict with #32695 (moved), which removed networkstatus_consensus_has_ipv6() above routerstatus_has_visibly_clanged(). The conflict is stopping CI from running,