Commit 1adc1254 authored by Peter Palfrader's avatar Peter Palfrader
Browse files

implement policy_summary_accept and policy_summary_reject together with a set of helpers

svn:r16519
parent f5adde1a
Loading
Loading
Loading
Loading
+83 −12
Original line number Diff line number Diff line
@@ -917,13 +917,16 @@ typedef struct policy_summary_item_t {
    uint16_t prt_max; /**< Highest port number to accept/reject. */
    uint64_t reject_count; /**< Number of IP-Addresses that are rejected to
                                this portrange. */
    int accepted:1; /** Has this port already been accepted */
} policy_summary_item_t;

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, 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);
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 */
@@ -937,6 +940,7 @@ policy_summary_create(void)
  item->prt_min = 1;
  item->prt_max = 65535;
  item->reject_count = 0;
  item->accepted = 0;

  summary = smartlist_create();
  smartlist_add(summary, item);
@@ -944,24 +948,91 @@ policy_summary_create(void)
  return summary;
}

/** Split the summary item in <b>item</b> at the port <b>new_starts</b>.
 * The current item is changed to end at new-starts - 1, the new item
 * copies reject_count and accepted from the old item,
 * starts at new_starts and ends at the port where the original item
 * previously ended.
 */
policy_summary_item_t*
policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts) {
  policy_summary_item_t* new;

  new = tor_malloc_zero(sizeof(policy_summary_item_t));
  new->prt_min = new_starts;
  new->prt_max = old->prt_max;
  new->reject_count = old->reject_count;
  new->accepted = old->accepted;

  old->prt_max = new_starts-1;

  tor_assert(old->prt_min < old->prt_max);
  tor_assert(new->prt_min < new->prt_max);
  return new;
}

#define AT(x) ((policy_summary_item_t*)smartlist_get(summary, x))
#define REJECT_CUTOFF_COUNT (1<<25)
/* Split an exit policy summary so that prt_min and prt_max
 * fall at exactly the start and end of an item respectively.
 */
int
policy_summary_split(smartlist_t *summary,
                     uint16_t prt_min, uint16_t prt_max)
{
  int start_at_index;

  int i = 0;
  while (AT(i)->prt_max < prt_min)
    i++;
  if (AT(i)->prt_min != prt_min) {
    policy_summary_item_t* new_item;
    new_item = policy_summary_item_split(AT(i), prt_min);
    smartlist_insert(summary, i+1, new_item);
    i++;
  }
  start_at_index = i;

  while(AT(i)->prt_max < prt_max)
    i++;
  if (AT(i)->prt_max != prt_max) {
    policy_summary_item_t* new_item;
    new_item = policy_summary_item_split(AT(i), prt_max+1);
    smartlist_insert(summary, i+1, new_item);
  }

  return start_at_index;
}

/** Mark port ranges as accepted if they are below the reject_count */
void
policy_summary_accept(smartlist_t *summary,
                      uint16_t prt_min, uint16_t prt_max)
{
 /* XXX */
 (void) summary;
 (void) prt_min;
 (void) prt_max;
  int i = policy_summary_split(summary, prt_min, prt_max);
  while (AT(i)->prt_max <= prt_max) {
    if (AT(i)->accepted ||
        AT(i)->reject_count > REJECT_CUTOFF_COUNT)
      continue;
    AT(i)->accepted = 1;
    i++;
  }
}

/** Count the number of addresses in a network with prefixlen maskbits
 * against the given portrange. */
void
policy_summary_reject(smartlist_t *summary,
                      maskbits_t maskbits,
                      uint16_t prt_min, uint16_t prt_max)
{
 /* XXX */
 (void) summary;
 (void) prt_min;
 (void) prt_max;
  int i = policy_summary_split(summary, prt_min, prt_max);
  /* XXX: ipv4 specific */
  int count = (1 << (32-maskbits));
  while (AT(i)->prt_max <= prt_max) {
    AT(i)->reject_count += count;
    i++;
  }
}

/** Add a single exit policy item to our summary */
@@ -991,7 +1062,7 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p)
     }

     if (!is_private) {
       policy_summary_reject(summary, p->prt_min, p->prt_max);
       policy_summary_reject(summary, p->maskbits, p->prt_min, p->prt_max);
     }
  } else
    tor_assert(0);