Commit 1e49c908 authored by Sebastian Hahn's avatar Sebastian Hahn
Browse files

Speed up the execution of exit_policy_is_general_exit_helper()

It isn't necessary to walk through all possible subnets when the policy
we're looking at doesn't touch that subnet.
parent 01030a4d
Loading
Loading
Loading
Loading
+21 −15
Original line number Diff line number Diff line
@@ -870,7 +870,7 @@ policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
static int
exit_policy_is_general_exit_helper(smartlist_t *policy, int port)
{
  uint32_t j;
  uint32_t mask, ip, i;
  /* Is this /8 rejected (1), or undecided (0)? */
  char subnet_status[256];

@@ -878,15 +878,22 @@ exit_policy_is_general_exit_helper(smartlist_t *policy, int port)
  SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
    if (p->prt_min > port || p->prt_max < port)
      continue; /* Doesn't cover our port. */
    for (j = 0; j < 256; ++j) {
    mask = 0;
    tor_assert(p->maskbits <= 32);

    if (p->maskbits)
      mask = UINT32_MAX<<(32-p->maskbits);
    ip = tor_addr_to_ipv4h(&p->addr);

    /* Calculate the first and last subnet that this exit policy touches
     * and set it as loop boundaries. */
    for (i = ((mask & ip)>>24); i <= (~((mask & ip) ^ mask)>>24); ++i) {
      tor_addr_t addr;
      if (subnet_status[j] != 0)
      if (subnet_status[i] != 0)
        continue; /* We already reject some part of this /8 */
      tor_addr_from_ipv4h(&addr, j<<24);
      tor_addr_from_ipv4h(&addr, i<<24);
      if (tor_addr_is_internal(&addr, 0))
        continue; /* Local or non-routable addresses */
      if (tor_addr_compare_masked(&addr, &p->addr, p->maskbits,
                                  CMP_EXACT) == 0) {
      if (p->policy_type == ADDR_POLICY_ACCEPT) {
        if (p->maskbits > 8)
          continue; /* Narrower than a /8. */
@@ -894,8 +901,7 @@ exit_policy_is_general_exit_helper(smartlist_t *policy, int port)
         * for this port! */
        return 1;
      } else if (p->policy_type == ADDR_POLICY_REJECT) {
          subnet_status[j] = 1;
        }
        subnet_status[i] = 1;
      }
    }
  });