aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Palfrader <peter@palfrader.org>2008-08-13 12:45:23 +0000
committerPeter Palfrader <peter@palfrader.org>2008-08-13 12:45:23 +0000
commit49a616e0fadb9a7c8cf041693f431f221297cf9c (patch)
tree8be26e654df52d1d0c1caea7ee50d940f1004308 /src
parent7eaf5bd848791601be14873f8809a55cfa7f1c7d (diff)
downloadtor-49a616e0fadb9a7c8cf041693f431f221297cf9c.tar
tor-49a616e0fadb9a7c8cf041693f431f221297cf9c.tar.gz
Create string representation of exit summaries
svn:r16521
Diffstat (limited to 'src')
-rw-r--r--src/or/policies.c92
1 files changed, 88 insertions, 4 deletions
diff --git a/src/or/policies.c b/src/or/policies.c
index 918e94193..a51d01b74 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -924,13 +924,14 @@ smartlist_t *policy_summary_create(void);
void policy_summary_accept(smartlist_t *summary, uint16_t prt_min, uint16_t prt_max);
void policy_summary_reject(smartlist_t *summary, maskbits_t maskbits, uint16_t prt_min, uint16_t prt_max);
void policy_summary_add_item(smartlist_t *summary, addr_policy_t *p);
-void policy_summarize(smartlist_t *policy);
+char * policy_summarize(smartlist_t *policy);
int policy_summary_split(smartlist_t *summary, uint16_t prt_min, uint16_t prt_max);
policy_summary_item_t* policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts);
/** Create a new exit policy summary, initially only with a single
* port 1-64k item */
-/* XXXX This entire thing is O(N^2). Use an RB-tree if that turns out to matter. */
+/* XXXX This entire thing will do most stuff in O(N^2), or worse. Use an
+ * RB-tree if that turns out to matter. */
smartlist_t *
policy_summary_create(void)
{
@@ -1040,7 +1041,13 @@ policy_summary_reject(smartlist_t *summary,
}
}
-/** Add a single exit policy item to our summary */
+/** Add a single exit policy item to our summary:
+ * If it is an accept ignore it unless it is for all IP addresses
+ * ("*"), i.e. it's prefixlen/maskbits is 0, else call
+ * policy_summary_accept().
+ * If it's a reject ignore it if it is about one of the private
+ * networks, else call policy_summary_reject().
+ */
void
policy_summary_add_item(smartlist_t *summary, addr_policy_t *p)
{
@@ -1073,16 +1080,93 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p)
tor_assert(0);
}
-void
+/** Create a string representing a summary for an exit policy.
+ * The summary will either be an "accept" plus a comma-seperated list of port
+ * ranges or a "reject" plus portranges, depending on which is shorter.
+ */
+char *
policy_summarize(smartlist_t *policy)
{
smartlist_t *summary = policy_summary_create();
+ smartlist_t *accepts, *rejects;
+ int i, last, start_prt;
+ size_t accepts_len, rejects_len, shorter_len, final_size;
+ char *accepts_str, *rejects_str, *shorter_str, *result;
+ const char *prefix;
+
tor_assert(policy);
+ /* Create the summary list */
SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
policy_summary_add_item(summary, p);
});
+ /* Now create two lists of strings, one for accepted and one
+ * for rejected ports. We take care to merge ranges so that
+ * we avoid getting stuff like "1-4,5-9,10", instead we want
+ * "1-10"
+ */
+ i = 0;
+ start_prt = 1;
+ accepts = smartlist_create();
+ rejects = smartlist_create();
+ while (1) {
+ last = i == smartlist_len(summary)-1;
+ if (last ||
+ AT(i)->accepted != AT(i+1)->accepted) {
+ char buf[POLICY_BUF_LEN];
+
+ if (start_prt == AT(i)->prt_max)
+ tor_snprintf(buf, sizeof(buf), "%d", start_prt);
+ else
+ tor_snprintf(buf, sizeof(buf), "%d-%d", start_prt, AT(i)->prt_max);
+
+ if (AT(i)->accepted)
+ smartlist_add(accepts, tor_strdup(buf));
+ else
+ smartlist_add(rejects, tor_strdup(buf));
+
+ if (last)
+ break;
+
+ start_prt = AT(i+1)->prt_min;
+ };
+ i++;
+ };
+
+ /* Figure out which of the two stringlists will be shorter and use
+ * that to build the result
+ */
+ accepts_str = smartlist_join_strings(accepts, ",", 0, &accepts_len);
+ rejects_str = smartlist_join_strings(rejects, ",", 0, &rejects_len);
+
+ if (rejects_len < accepts_len) {
+ shorter_str = rejects_str;
+ shorter_len = rejects_len;
+ prefix = "reject";
+ } else {
+ shorter_str = accepts_str;
+ shorter_len = accepts_len;
+ prefix = "accept";
+ }
+
+ final_size = strlen(prefix)+1+shorter_len+1;
+ result = malloc(final_size);
+ tor_snprintf(result, final_size, "%s %s", prefix, shorter_str);
+
+ /* cleanup */
+ SMARTLIST_FOREACH(summary, policy_summary_item_t *, s, tor_free(s));
+ smartlist_clear(summary);
+
+ tor_free(accepts_str);
+ SMARTLIST_FOREACH(accepts, char *, s, tor_free(s));
+ smartlist_clear(accepts);
+
+ tor_free(rejects_str);
+ SMARTLIST_FOREACH(rejects, char *, s, tor_free(s));
+ smartlist_clear(rejects);
+
+ return result;
}