aboutsummaryrefslogtreecommitdiff
path: root/src/feature/nodelist/nodefamily.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-11-24 10:53:38 -0500
committerNick Mathewson <nickm@torproject.org>2018-11-24 10:53:38 -0500
commitd29e3a02d57aef402a1aaf9747ef44393b043d98 (patch)
tree167123ebf54d20cc8ed7cb938c30b77977a7c17d /src/feature/nodelist/nodefamily.c
parent0e9a963b6b87282011fe204e81b5c2530153a935 (diff)
downloadtor-d29e3a02d57aef402a1aaf9747ef44393b043d98.tar.gz
tor-d29e3a02d57aef402a1aaf9747ef44393b043d98.zip
Add a function to canonicalize nodefamilies per prop298
This is the same as the regular canonical nodefamily format, except that unrecognized elements are preserved.
Diffstat (limited to 'src/feature/nodelist/nodefamily.c')
-rw-r--r--src/feature/nodelist/nodefamily.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/src/feature/nodelist/nodefamily.c b/src/feature/nodelist/nodefamily.c
index 29659ed93d..944ad54755 100644
--- a/src/feature/nodelist/nodefamily.c
+++ b/src/feature/nodelist/nodefamily.c
@@ -93,13 +93,47 @@ nodefamily_parse(const char *s, const uint8_t *rsa_id_self,
{
smartlist_t *sl = smartlist_new();
smartlist_split_string(sl, s, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- nodefamily_t *result = nodefamily_from_members(sl, rsa_id_self, flags);
+ nodefamily_t *result = nodefamily_from_members(sl, rsa_id_self, flags, NULL);
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_free(sl);
return result;
}
/**
+ * Canonicalize the family list <b>s</b>, returning a newly allocated string.
+ *
+ * The canonicalization rules are fully specified in dir-spec.txt, but,
+ * briefly: $hexid entries are put in caps, $hexid[=~]foo entries are
+ * truncated, nicknames are put into lowercase, unrecognized entries are left
+ * alone, and everything is sorted.
+ **/
+char *
+nodefamily_canonicalize(const char *s, const uint8_t *rsa_id_self,
+ unsigned flags)
+{
+ smartlist_t *sl = smartlist_new();
+ smartlist_t *result_members = smartlist_new();
+ smartlist_split_string(sl, s, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ nodefamily_t *nf = nodefamily_from_members(sl, rsa_id_self, flags,
+ result_members);
+
+ char *formatted = nodefamily_format(nf);
+ smartlist_split_string(result_members, formatted, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ smartlist_sort_strings(result_members);
+ char *combined = smartlist_join_strings(result_members, " ", 0, NULL);
+
+ nodefamily_free(nf);
+ SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
+ smartlist_free(sl);
+ SMARTLIST_FOREACH(result_members, char *, cp, tor_free(cp));
+ smartlist_free(result_members);
+ tor_free(formatted);
+
+ return combined;
+}
+
+/**
* qsort helper for encoded nodefamily elements.
**/
static int
@@ -117,11 +151,15 @@ compare_members(const void *a, const void *b)
* family declaration if it is not there already.
*
* The <b>flags</b> element is interpreted as in nodefamily_parse().
+ *
+ * If <b>unrecognized</b> is provided, fill it copies of any unrecognized
+ * members. (Note that malformed $hexids are not considered unrecognized.)
**/
nodefamily_t *
nodefamily_from_members(const smartlist_t *members,
const uint8_t *rsa_id_self,
- unsigned flags)
+ unsigned flags,
+ smartlist_t *unrecognized_out)
{
const int n_self = rsa_id_self ? 1 : 0;
int n_bad_elements = 0;
@@ -146,6 +184,9 @@ nodefamily_from_members(const smartlist_t *members,
ptr[0] = NODEFAMILY_BY_RSA_ID;
memcpy(ptr+1, digest_buf, DIGEST_LEN);
}
+ } else {
+ if (unrecognized_out)
+ smartlist_add_strdup(unrecognized_out, cp);
}
if (bad_element) {