Exemple #1
0
static void
test_routerlist_router_is_already_dir_fetching(void *arg)
{
  (void)arg;
  tor_addr_port_t test_ap, null_addr_ap, zero_port_ap;

  /* Setup */
  tor_addr_parse(&test_ap.addr, TEST_ADDR_STR);
  test_ap.port = TEST_DIR_PORT;
  tor_addr_make_null(&null_addr_ap.addr, AF_INET6);
  null_addr_ap.port = TEST_DIR_PORT;
  tor_addr_parse(&zero_port_ap.addr, TEST_ADDR_STR);
  zero_port_ap.port = 0;
  MOCK(connection_get_by_type_addr_port_purpose,
       mock_connection_get_by_type_addr_port_purpose);

  /* Test that we never get 1 from a NULL connection */
  mocked_connection = NULL;
  tt_assert(router_is_already_dir_fetching(&test_ap, 1, 1) == 0);
  tt_assert(router_is_already_dir_fetching(&test_ap, 1, 0) == 0);
  tt_assert(router_is_already_dir_fetching(&test_ap, 0, 1) == 0);
  /* We always expect 0 in these cases */
  tt_assert(router_is_already_dir_fetching(&test_ap, 0, 0) == 0);
  tt_assert(router_is_already_dir_fetching(NULL, 1, 1) == 0);
  tt_assert(router_is_already_dir_fetching(&null_addr_ap, 1, 1) == 0);
  tt_assert(router_is_already_dir_fetching(&zero_port_ap, 1, 1) == 0);

  /* Test that we get 1 with a connection in the appropriate circumstances */
  mocked_connection = connection_new(CONN_TYPE_DIR, AF_INET);
  tt_assert(router_is_already_dir_fetching(&test_ap, 1, 1) == 1);
  tt_assert(router_is_already_dir_fetching(&test_ap, 1, 0) == 1);
  tt_assert(router_is_already_dir_fetching(&test_ap, 0, 1) == 1);

  /* Test that we get 0 even with a connection in the appropriate
   * circumstances */
  tt_assert(router_is_already_dir_fetching(&test_ap, 0, 0) == 0);
  tt_assert(router_is_already_dir_fetching(NULL, 1, 1) == 0);
  tt_assert(router_is_already_dir_fetching(&null_addr_ap, 1, 1) == 0);
  tt_assert(router_is_already_dir_fetching(&zero_port_ap, 1, 1) == 0);

 done:
  /* If a connection is never set up, connection_free chokes on it. */
  if (mocked_connection) {
    buf_free(mocked_connection->inbuf);
    buf_free(mocked_connection->outbuf);
  }
  tor_free(mocked_connection);
  UNMOCK(connection_get_by_type_addr_port_purpose);
}
Exemple #2
0
/**
 * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
 * we do have, and an addr:port pair we do have, should return the bridge.
 */
static void
test_bridges_get_configured_bridge_by_exact_addr_port_digest_both(void *arg)
{
  char digest[DIGEST_LEN];
  bridge_info_t *bridge;
  const char fingerprint[HEX_DIGEST_LEN] =
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
  uint16_t port = 4444;
  char ret_addr[16];
  int ret;

  helper_add_bridges_to_bridgelist(arg);

  base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
  ret = tor_addr_parse(addr, "4.4.4.4");
  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success

  bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
  tt_ptr_op(bridge, OP_NE, NULL);

  tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
  tt_str_op("4.4.4.4", OP_EQ, ret_addr);

 done:
  tor_free(addr);

  mark_bridge_list();
  sweep_bridge_list();
}
Exemple #3
0
/**
 * Calling get_configured_bridge_by_exact_addr_port_digest() with no digest,
 * and an addr:port pair we do have, should return the bridge.
 */
static void
test_bridges_get_configured_bridge_by_exact_addr_port_digest_aonly(void *arg)
{
  bridge_info_t *bridge;
  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
  uint16_t port = 4444;
  char ret_addr[16];
  int ret;

  helper_add_bridges_to_bridgelist(arg);

  ret = tor_addr_parse(addr, "4.4.4.4");
  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success

  bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, NULL);
  tt_ptr_op(bridge, OP_NE, NULL);

  tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
  tt_str_op("4.4.4.4", OP_EQ, ret_addr);

 done:
  tor_free(addr);

  mark_bridge_list();
  sweep_bridge_list();
}
Exemple #4
0
/**
 * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
 * we do have, and an addr:port pair we don't have, should return NULL.
 */
static void
test_bridges_get_configured_bridge_by_exact_addr_port_digest_donly(void *arg)
{
  char digest[DIGEST_LEN];
  bridge_info_t *bridge;
  const char fingerprint[HEX_DIGEST_LEN] =
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
  uint16_t port = 11111;
  int ret;

  helper_add_bridges_to_bridgelist(arg);

  // We don't actually have a bridge with this addr:port pair
  base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
  ret = tor_addr_parse(addr, "111.111.111.111");
  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success

  bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
  tt_ptr_op(bridge, OP_EQ, NULL);

 done:
  tor_free(addr);

  mark_bridge_list();
  sweep_bridge_list();
}
Exemple #5
0
/**
 * Calling bridge_resolve_conflicts() with an identical bridge to one we've
 * already configure should mark the pre-configured bridge for removal.
 */
static void
test_bridges_bridge_resolve_conflicts(void *arg)
{
  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
  uint16_t port = 4444;
  const char *digest = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
  const char *transport = "apple";
  int ret;

  helper_add_bridges_to_bridgelist(arg);

  ret = tor_addr_parse(addr, "4.4.4.4");
  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success

  bridge_resolve_conflicts((const tor_addr_t*)addr, port, digest, transport);

  /* The bridge should now be marked for removal, and removed when we sweep the
   * bridge_list */
  sweep_bridge_list();
  ret = addr_is_a_configured_bridge((const tor_addr_t*)addr, port, digest);
  tt_int_op(ret, OP_EQ, 0);

 done:
  tor_free(addr);

  mark_bridge_list();
  sweep_bridge_list();
}
Exemple #6
0
/**
 * Calling get_transport_by_bridge_addrport() with the address and port of a
 * configured bridge which uses a pluggable transport when there is no global
 * transport_list should return -1 and the transport_t should be NULL.
 */
static void
test_bridges_get_transport_by_bridge_addrport_no_ptlist(void *arg)
{
  transport_t *transport = NULL;
  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
  uint16_t port = 1234;
  int ret;

  helper_add_bridges_to_bridgelist(arg);

  ret = tor_addr_parse(addr, "1.2.3.4");
  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?

  /* This will fail because the global transport_list has nothing in it, and so
   * transport_get_by_name() has nothing to return, even the the bridge *did*
   * say it had an obfs4 transport.
   */
  ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
                                         (const transport_t**)&transport);
  tt_int_op(ret, OP_EQ, -1); // returns -1 on failure
  tt_ptr_op(transport, OP_EQ, NULL);

 done:
  tor_free(addr);

  mark_bridge_list();
  sweep_bridge_list();
}
Exemple #7
0
static void
NS(test_main)(void *arg)
{
  int retval;
  int made_pending;
  const tor_addr_t *resolved_addr;
  tor_addr_t addr_to_compare;

  (void)arg;

  tor_addr_parse(&addr_to_compare, "8.8.8.8");

  or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));

  edge_connection_t *exitconn = create_valid_exitconn();

  TO_CONN(exitconn)->address = tor_strdup("8.8.8.8");

  retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
                            NULL);

  resolved_addr = &(exitconn->base_.addr);

  tt_int_op(retval,OP_EQ,1);
  tt_assert(tor_addr_eq(resolved_addr, (const tor_addr_t *)&addr_to_compare));
  tt_int_op(exitconn->address_ttl,OP_EQ,DEFAULT_DNS_TTL);

  done:
  tor_free(on_circ);
  tor_free(TO_CONN(exitconn)->address);
  tor_free(exitconn);
  return;
}
Exemple #8
0
/**
 * Calling get_transport_by_bridge_addrport() with the address and port of a
 * configured bridge which uses a pluggable transport should return 0 and set
 * appropriate transport_t.
 */
static void
test_bridges_get_transport_by_bridge_addrport(void *arg)
{
  transport_t *transport = NULL;
  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
  uint16_t port = 1234;
  int ret;

  helper_add_bridges_to_bridgelist(arg);
  mark_transport_list(); // Also initialise our transport_list

  ret = tor_addr_parse(addr, "1.2.3.4");
  tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?

  /* After we mock transport_get_by_name() to return a bogus transport_t with
   * the name it was asked for, the call should succeed.
   */
  MOCK(transport_get_by_name, mock_transport_get_by_name);
  ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
                                         (const transport_t**)&transport);
  tt_int_op(ret, OP_EQ, 0); // returns 0 on success
  tt_ptr_op(transport, OP_NE, NULL);
  tt_str_op(transport->name, OP_EQ, "obfs4");

 done:
  UNMOCK(transport_get_by_name);

  tor_free(addr);
  transport_free(transport);

  mark_bridge_list();
  sweep_bridge_list();
}
Exemple #9
0
static void
test_addr_is_loopback(void *data)
{
  static const struct loopback_item {
    const char *name;
    int is_loopback;
  } loopback_items[] = {
    { "::1", 1 },
    { "127.0.0.1", 1 },
    { "127.99.100.101", 1 },
    { "128.99.100.101", 0 },
    { "8.8.8.8", 0 },
    { "0.0.0.0", 0 },
    { "::2", 0 },
    { "::", 0 },
    { "::1.0.0.0", 0 },
    { NULL, 0 }
  };

  int i;
  tor_addr_t addr;
  (void)data;

  for (i=0; loopback_items[i].name; ++i) {
    tt_int_op(tor_addr_parse(&addr, loopback_items[i].name), OP_GE, 0);
    tt_int_op(tor_addr_is_loopback(&addr), OP_EQ,
              loopback_items[i].is_loopback);
  }

  tor_addr_make_unspec(&addr);
  tt_int_op(tor_addr_is_loopback(&addr), OP_EQ, 0);

 done:
  ;
}
Exemple #10
0
static void
test_virtaddrmap(void *data)
{
  /* Let's start with a bunch of random addresses. */
  int ipv6, bits, iter, b;
  virtual_addr_conf_t cfg[2];
  uint8_t bytes[16];

  (void)data;

  tor_addr_parse(&cfg[0].addr, "64.65.0.0");
  tor_addr_parse(&cfg[1].addr, "3491:c0c0::");

  for (ipv6 = 0; ipv6 <= 1; ++ipv6) {
    for (bits = 0; bits < 18; ++bits) {
      tor_addr_t last_a;
      cfg[ipv6].bits = bits;
      memset(bytes, 0, sizeof(bytes));
      tor_addr_copy(&last_a, &cfg[ipv6].addr);
      /* Generate 128 addresses with each addr/bits combination. */
      for (iter = 0; iter < 128; ++iter) {
        tor_addr_t a;

        get_random_virtual_addr(&cfg[ipv6], &a);
        //printf("%s\n", fmt_addr(&a));
        /* Make sure that the first b bits match the configured network */
        tt_int_op(0, OP_EQ, tor_addr_compare_masked(&a, &cfg[ipv6].addr,
                                                 bits, CMP_EXACT));

        /* And track which bits have been different between pairs of
         * addresses */
        update_difference(ipv6, bytes, &last_a, &a);
      }

      /* Now make sure all but the first 'bits' bits of bytes are true */
      for (b = bits+1; b < (ipv6?128:32); ++b) {
        tt_assert(1 & (bytes[b/8] >> (7-(b&7))));
      }
    }
  }

 done:
  ;
}
Exemple #11
0
/** Set *<b>out</b> to a newly allocated SOCKS4a resolve request with
 * <b>username</b> and <b>hostname</b> as provided.  Return the number
 * of bytes in the request. */
static ssize_t
build_socks_resolve_request(char **out,
                            const char *username,
                            const char *hostname,
                            int reverse,
                            int version)
{
  size_t len = 0;
  tor_assert(out);
  tor_assert(username);
  tor_assert(hostname);

  if (version == 4) {
    len = 8 + strlen(username) + 1 + strlen(hostname) + 1;
    *out = tor_malloc(len);
    (*out)[0] = 4;      /* SOCKS version 4 */
    (*out)[1] = '\xF0'; /* Command: resolve. */
    set_uint16((*out)+2, htons(0)); /* port: 0. */
    set_uint32((*out)+4, htonl(0x00000001u)); /* addr: 0.0.0.1 */
    memcpy((*out)+8, username, strlen(username)+1);
    memcpy((*out)+8+strlen(username)+1, hostname, strlen(hostname)+1);
  } else if (version == 5) {
    int is_ip_address;
    tor_addr_t addr;
    size_t addrlen;
    int ipv6;
    is_ip_address = tor_addr_parse(&addr, hostname) != -1;
    if (!is_ip_address && reverse) {
      log_err(LD_GENERAL, "Tried to do a reverse lookup on a non-IP!");
      return -1;
    }
    ipv6 = reverse && tor_addr_family(&addr) == AF_INET6;
    addrlen = reverse ? (ipv6 ? 16 : 4) : 1 + strlen(hostname);
    len = 6 + addrlen;
    *out = tor_malloc(len);
    (*out)[0] = 5; /* SOCKS version 5 */
    (*out)[1] = reverse ? '\xF1' : '\xF0'; /* RESOLVE_PTR or RESOLVE */
    (*out)[2] = 0; /* reserved. */
    if (reverse) {
      (*out)[3] = ipv6 ? 4 : 1;
      if (ipv6)
        memcpy((*out)+4, tor_addr_to_in6_addr8(&addr), 16);
      else
        set_uint32((*out)+4, tor_addr_to_ipv4n(&addr));
    } else {
      (*out)[3] = 3;
      (*out)[4] = (char)(uint8_t)(addrlen - 1);
      memcpy((*out)+5, hostname, addrlen - 1);
    }
    set_uint16((*out)+4+addrlen, 0); /* port */
  } else {
    tor_assert(0);
  }

  return len;
}
Exemple #12
0
/**
 * Mock transport_get_by_name() to simply return a transport_t for the
 * transport name that was input to it.
 */
static transport_t *
mock_transport_get_by_name(const char *name)
{
  tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
  uint16_t port = 9999;
  int socksv = 9;
  char *args = tor_strdup("foo=bar");

  if (!mock_transport) {
    tor_addr_parse(addr, "99.99.99.99");
    mock_transport = transport_new(addr, port, name, socksv, args);
  }

  tor_free(addr);
  tor_free(args);

  return mock_transport;
}
Exemple #13
0
/** Test tor_addr_parse() and tor_addr_port_parse(). */
static void
test_addr_parse(void *arg)
{
  int r;
  tor_addr_t addr;
  char buf[TOR_ADDR_BUF_LEN];
  uint16_t port = 0;

  /* Correct call. */
  (void)arg;
  r= tor_addr_parse(&addr, "192.0.2.1");
  tt_int_op(r,OP_EQ, AF_INET);
  tor_addr_to_str(buf, &addr, sizeof(buf), 0);
  tt_str_op(buf,OP_EQ, "192.0.2.1");

  r= tor_addr_parse(&addr, "11:22::33:44");
  tt_int_op(r,OP_EQ, AF_INET6);
  tor_addr_to_str(buf, &addr, sizeof(buf), 0);
  tt_str_op(buf,OP_EQ, "11:22::33:44");

  r= tor_addr_parse(&addr, "[11:22::33:44]");
  tt_int_op(r,OP_EQ, AF_INET6);
  tor_addr_to_str(buf, &addr, sizeof(buf), 0);
  tt_str_op(buf,OP_EQ, "11:22::33:44");

  r= tor_addr_parse(&addr, "11:22:33:44:55:66:1.2.3.4");
  tt_int_op(r,OP_EQ, AF_INET6);
  tor_addr_to_str(buf, &addr, sizeof(buf), 0);
  tt_str_op(buf,OP_EQ, "11:22:33:44:55:66:102:304");

  r= tor_addr_parse(&addr, "11:22::33:44:1.2.3.4");
  tt_int_op(r,OP_EQ, AF_INET6);
  tor_addr_to_str(buf, &addr, sizeof(buf), 0);
  tt_str_op(buf,OP_EQ, "11:22::33:44:102:304");

  /* Empty string. */
  r= tor_addr_parse(&addr, "");
  tt_int_op(r,OP_EQ, -1);

  /* Square brackets around IPv4 address. */
  r= tor_addr_parse(&addr, "[192.0.2.1]");
  tt_int_op(r,OP_EQ, -1);

  /* Only left square bracket. */
  r= tor_addr_parse(&addr, "[11:22::33:44");
  tt_int_op(r,OP_EQ, -1);

  /* Only right square bracket. */
  r= tor_addr_parse(&addr, "11:22::33:44]");
  tt_int_op(r,OP_EQ, -1);

  /* Leading colon. */
  r= tor_addr_parse(&addr, ":11:22::33:44");
  tt_int_op(r,OP_EQ, -1);

  /* Trailing colon. */
  r= tor_addr_parse(&addr, "11:22::33:44:");
  tt_int_op(r,OP_EQ, -1);

  /* Too many hex words in IPv4-mapped IPv6 address. */
  r= tor_addr_parse(&addr, "11:22:33:44:55:66:77:88:1.2.3.4");
  tt_int_op(r,OP_EQ, -1);

  /* Correct call. */
  r= tor_addr_port_parse(LOG_DEBUG,
                         "192.0.2.1:1234",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, 0);
  tor_addr_to_str(buf, &addr, sizeof(buf), 0);
  tt_str_op(buf,OP_EQ, "192.0.2.1");
  tt_int_op(port,OP_EQ, 1234);

  r= tor_addr_port_parse(LOG_DEBUG,
                         "[::1]:1234",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, 0);
  tor_addr_to_str(buf, &addr, sizeof(buf), 0);
  tt_str_op(buf,OP_EQ, "::1");
  tt_int_op(port,OP_EQ, 1234);

  /* Domain name. */
  r= tor_addr_port_parse(LOG_DEBUG,
                         "torproject.org:1234",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, -1);

  /* Only IP. */
  r= tor_addr_port_parse(LOG_DEBUG,
                         "192.0.2.2",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, -1);

  r= tor_addr_port_parse(LOG_DEBUG,
                         "192.0.2.2",
                         &addr, &port, 200);
  tt_int_op(r, OP_EQ, 0);
  tt_int_op(port,OP_EQ,200);

  r= tor_addr_port_parse(LOG_DEBUG,
                         "[::1]",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, -1);

  r= tor_addr_port_parse(LOG_DEBUG,
                         "[::1]",
                         &addr, &port, 400);
  tt_int_op(r, OP_EQ, 0);
  tt_int_op(port,OP_EQ,400);

  /* Bad port. */
  r= tor_addr_port_parse(LOG_DEBUG,
                         "192.0.2.2:66666",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, -1);
  r= tor_addr_port_parse(LOG_DEBUG,
                         "192.0.2.2:66666",
                         &addr, &port, 200);
  tt_int_op(r, OP_EQ, -1);

  /* Only domain name */
  r= tor_addr_port_parse(LOG_DEBUG,
                         "torproject.org",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, -1);
  r= tor_addr_port_parse(LOG_DEBUG,
                         "torproject.org",
                         &addr, &port, 200);
  tt_int_op(r, OP_EQ, -1);

  /* Bad IP address */
  r= tor_addr_port_parse(LOG_DEBUG,
                         "192.0.2:1234",
                         &addr, &port, -1);
  tt_int_op(r, OP_EQ, -1);

  /* Make sure that the default port has lower priority than the real
     one */
  r= tor_addr_port_parse(LOG_DEBUG,
                         "192.0.2.2:1337",
                         &addr, &port, 200);
  tt_int_op(r, OP_EQ, 0);
  tt_int_op(port,OP_EQ,1337);

  r= tor_addr_port_parse(LOG_DEBUG,
                         "[::1]:1369",
                         &addr, &port, 200);
  tt_int_op(r, OP_EQ, 0);
  tt_int_op(port,OP_EQ,1369);

 done:
  ;
}
Exemple #14
0
static void
test_circbw_relay(void *arg)
{
  cell_t cell;
  relay_header_t rh;
  tor_addr_t addr;
  edge_connection_t *edgeconn;
  entry_connection_t *entryconn1=NULL;
  origin_circuit_t *circ;
  int delivered = 0;
  int overhead = 0;

  (void)arg;

  MOCK(connection_mark_unattached_ap_, mock_connection_mark_unattached_ap_);
  MOCK(connection_start_reading, mock_start_reading);
  MOCK(connection_mark_for_close_internal_, mock_mark_for_close);
  MOCK(relay_send_command_from_edge_, mock_send_command);
  MOCK(circuit_mark_for_close_, mock_mark_circ_for_close);

  circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
  circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
  circ->cpath->deliver_window = CIRCWINDOW_START;

  entryconn1 = fake_entry_conn(circ, 1);
  edgeconn = ENTRY_TO_EDGE_CONN(entryconn1);

  /* Stream id 0: Not counted */
  PACK_CELL(0, RELAY_COMMAND_END, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Stream id 1: Counted */
  PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  /* Properly formatted connect cell: counted */
  PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
  tor_addr_parse(&addr, "30.40.50.60");
  rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
                                            &addr, 1024);
  relay_header_pack((uint8_t*)&cell.payload, &rh);                    \
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  /* Properly formatted resolved cell in correct state: counted */
  edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
  entryconn1->socks_request->command = SOCKS_COMMAND_RESOLVE;
  edgeconn->on_circuit = TO_CIRCUIT(circ);
  PACK_CELL(1, RELAY_COMMAND_RESOLVED,
            "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  edgeconn->base_.state = AP_CONN_STATE_OPEN;
  entryconn1->socks_request->has_finished = 1;

  /* Connected cell after open: not counted */
  PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Resolved cell after open: not counted */
  PACK_CELL(1, RELAY_COMMAND_RESOLVED, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Drop cell: not counted */
  PACK_CELL(1, RELAY_COMMAND_DROP, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Data cell on stream 0: not counted */
  PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Data cell on open connection: counted */
  ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
  PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  /* Empty Data cell on open connection: not counted */
  ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
  PACK_CELL(1, RELAY_COMMAND_DATA, "");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Sendme on valid stream: counted */
  edgeconn->package_window -= STREAMWINDOW_INCREMENT;
  ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
  PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  /* Sendme on valid stream with full window: not counted */
  ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
  PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
  edgeconn->package_window = STREAMWINDOW_START;
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Sendme on unknown stream: not counted */
  ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0;
  PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Sendme on circuit with full window: not counted */
  PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Sendme on circuit with non-full window: counted */
  PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234");
  circ->cpath->package_window = 900;
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  /* Invalid extended cell: not counted */
  PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Invalid extended cell: not counted */
  PACK_CELL(1, RELAY_COMMAND_EXTENDED, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Invalid HS cell: not counted */
  PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* "Valid" HS cell in expected state: counted */
  TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
  PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  /* End cell on non-closed connection: counted */
  PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
                                     circ->cpath);
  ASSERT_COUNTED_BW();

  /* End cell on connection that already got one: not counted */
  PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
  connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
                                     circ->cpath);
  ASSERT_UNCOUNTED_BW();

  /* Simulate closed stream on entryconn, then test: */
  if (!subtest_circbw_halfclosed(circ, 2))
    goto done;

  circ->base_.purpose = CIRCUIT_PURPOSE_PATH_BIAS_TESTING;
  if (!subtest_circbw_halfclosed(circ, 6))
    goto done;

  /* Path bias: truncated */
  tt_int_op(circ->base_.marked_for_close, OP_EQ, 0);
  PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234");
  pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
  tt_int_op(circ->base_.marked_for_close, OP_EQ, 1);

 done:
  UNMOCK(connection_start_reading);
  UNMOCK(connection_mark_unattached_ap_);
  UNMOCK(connection_mark_for_close_internal_);
  UNMOCK(relay_send_command_from_edge_);
  UNMOCK(circuit_mark_for_close_);
  circuit_free_(TO_CIRCUIT(circ));
  connection_free_minimal(ENTRY_TO_CONN(entryconn1));
}
Exemple #15
0
/** Run unit tests for IPv6 encoding/decoding/manipulation functions. */
static void
test_addr_ip6_helpers(void)
{
  char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN];
  char rbuf[REVERSE_LOOKUP_NAME_BUF_LEN];
  struct in6_addr a1, a2;
  tor_addr_t t1, t2;
  int r, i;
  uint16_t port1, port2;
  maskbits_t mask;
  const char *p1;
  struct sockaddr_storage sa_storage;
  struct sockaddr_in *sin;
  struct sockaddr_in6 *sin6;

  /* Test tor_inet_ntop and tor_inet_pton: IPv6 */
  {
    const char *ip = "2001::1234";
    const char *ip_ffff = "::ffff:192.168.1.2";

    /* good round trip */
    test_eq(tor_inet_pton(AF_INET6, ip, &a1), 1);
    test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), &buf);
    test_streq(buf, ip);

    /* good round trip - ::ffff:0:0 style */
    test_eq(tor_inet_pton(AF_INET6, ip_ffff, &a2), 1);
    test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)), &buf);
    test_streq(buf, ip_ffff);

    /* just long enough buffer (remember \0) */
    test_streq(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1), ip);
    test_streq(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1),
               ip_ffff);

    /* too short buffer (remember \0) */
    test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)), NULL);
    test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)), NULL);
  }

  /* ==== Converting to and from sockaddr_t. */
  sin = (struct sockaddr_in *)&sa_storage;
  sin->sin_family = AF_INET;
  sin->sin_port = 9090;
  sin->sin_addr.s_addr = htonl(0x7f7f0102); /*127.127.1.2*/
  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL);
  test_eq(tor_addr_family(&t1), AF_INET);
  test_eq(tor_addr_to_ipv4h(&t1), 0x7f7f0102);

  memset(&sa_storage, 0, sizeof(sa_storage));
  test_eq(sizeof(struct sockaddr_in),
          tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage,
                               sizeof(sa_storage)));
  test_eq(1234, ntohs(sin->sin_port));
  test_eq(0x7f7f0102, ntohl(sin->sin_addr.s_addr));

  memset(&sa_storage, 0, sizeof(sa_storage));
  sin6 = (struct sockaddr_in6 *)&sa_storage;
  sin6->sin6_family = AF_INET6;
  sin6->sin6_port = htons(7070);
  sin6->sin6_addr.s6_addr[0] = 128;
  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL);
  test_eq(tor_addr_family(&t1), AF_INET6);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
  test_streq(p1, "8000::");

  memset(&sa_storage, 0, sizeof(sa_storage));
  test_eq(sizeof(struct sockaddr_in6),
          tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage,
                               sizeof(sa_storage)));
  test_eq(AF_INET6, sin6->sin6_family);
  test_eq(9999, ntohs(sin6->sin6_port));
  test_eq(0x80000000, ntohl(S6_ADDR32(sin6->sin6_addr)[0]));

  /* ==== tor_addr_lookup: static cases.  (Can't test dns without knowing we
   * have a good resolver. */
  test_eq(0, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1));
  test_eq(AF_INET, tor_addr_family(&t1));
  test_eq(tor_addr_to_ipv4h(&t1), 0x7f808182);

  test_eq(0, tor_addr_lookup("9000::5", AF_UNSPEC, &t1));
  test_eq(AF_INET6, tor_addr_family(&t1));
  test_eq(0x90, tor_addr_to_in6_addr8(&t1)[0]);
  test_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14));
  test_eq(0x05, tor_addr_to_in6_addr8(&t1)[15]);

  /* === Test pton: valid af_inet6 */
  /* Simple, valid parsing. */
  r = tor_inet_pton(AF_INET6,
                    "0102:0304:0506:0708:090A:0B0C:0D0E:0F10", &a1);
  test_assert(r==1);
  for (i=0;i<16;++i) { test_eq(i+1, (int)a1.s6_addr[i]); }
  /* ipv4 ending. */
  test_pton6_same("0102:0304:0506:0708:090A:0B0C:0D0E:0F10",
                  "0102:0304:0506:0708:090A:0B0C:13.14.15.16");
  /* shortened words. */
  test_pton6_same("0001:0099:BEEF:0000:0123:FFFF:0001:0001",
                  "1:99:BEEF:0:0123:FFFF:1:1");
  /* zeros at the beginning */
  test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001",
                  "::9:c0a8:1:1");
  test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001",
                  "::9:c0a8:0.1.0.1");
  /* zeros in the middle. */
  test_pton6_same("fe80:0000:0000:0000:0202:1111:0001:0001",
                  "fe80::202:1111:1:1");
  /* zeros at the end. */
  test_pton6_same("1000:0001:0000:0007:0000:0000:0000:0000",
                  "1000:1:0:7::");

  /* === Test ntop: af_inet6 */
  test_ntop6_reduces("0:0:0:0:0:0:0:0", "::");

  test_ntop6_reduces("0001:0099:BEEF:0006:0123:FFFF:0001:0001",
                     "1:99:beef:6:123:ffff:1:1");

  //test_ntop6_reduces("0:0:0:0:0:0:c0a8:0101", "::192.168.1.1");
  test_ntop6_reduces("0:0:0:0:0:ffff:c0a8:0101", "::ffff:192.168.1.1");
  test_ntop6_reduces("002:0:0000:0:3::4", "2::3:0:0:4");
  test_ntop6_reduces("0:0::1:0:3", "::1:0:3");
  test_ntop6_reduces("008:0::0", "8::");
  test_ntop6_reduces("0:0:0:0:0:ffff::1", "::ffff:0.0.0.1");
  test_ntop6_reduces("abcd:0:0:0:0:0:7f00::", "abcd::7f00:0");
  test_ntop6_reduces("0000:0000:0000:0000:0009:C0A8:0001:0001",
                     "::9:c0a8:1:1");
  test_ntop6_reduces("fe80:0000:0000:0000:0202:1111:0001:0001",
                     "fe80::202:1111:1:1");
  test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000",
                     "1000:1:0:7::");

  /* Bad af param */
  test_eq(tor_inet_pton(AF_UNSPEC, 0, 0), -1);

  /* === Test pton: invalid in6. */
  test_pton6_bad("foobar.");
  test_pton6_bad("-1::");
  test_pton6_bad("00001::");
  test_pton6_bad("10000::");
  test_pton6_bad("::10000");
  test_pton6_bad("55555::");
  test_pton6_bad("9:-60::");
  test_pton6_bad("9:+60::");
  test_pton6_bad("9|60::");
  test_pton6_bad("0x60::");
  test_pton6_bad("::0x60");
  test_pton6_bad("9:0x60::");
  test_pton6_bad("1:2:33333:4:0002:3::");
  test_pton6_bad("1:2:3333:4:fish:3::");
  test_pton6_bad("1:2:3:4:5:6:7:8:9");
  test_pton6_bad("1:2:3:4:5:6:7");
  test_pton6_bad("1:2:3:4:5:6:1.2.3.4.5");
  test_pton6_bad("1:2:3:4:5:6:1.2.3");
  test_pton6_bad("::1.2.3");
  test_pton6_bad("::1.2.3.4.5");
  test_pton6_bad("::ffff:0xff.0.0.0");
  test_pton6_bad("::ffff:ff.0.0.0");
  test_pton6_bad("::ffff:256.0.0.0");
  test_pton6_bad("::ffff:-1.0.0.0");
  test_pton6_bad("99");
  test_pton6_bad("");
  test_pton6_bad(".");
  test_pton6_bad(":");
  test_pton6_bad("1::2::3:4");
  test_pton6_bad("a:::b:c");
  test_pton6_bad(":::a:b:c");
  test_pton6_bad("a:b:c:::");

  /* test internal checking */
  test_external_ip("fbff:ffff::2:7", 0);
  test_internal_ip("fc01::2:7", 0);
  test_internal_ip("fc01::02:7", 0);
  test_internal_ip("fc01::002:7", 0);
  test_internal_ip("fc01::0002:7", 0);
  test_internal_ip("fdff:ffff::f:f", 0);
  test_external_ip("fe00::3:f", 0);

  test_external_ip("fe7f:ffff::2:7", 0);
  test_internal_ip("fe80::2:7", 0);
  test_internal_ip("febf:ffff::f:f", 0);

  test_internal_ip("fec0::2:7:7", 0);
  test_internal_ip("feff:ffff::e:7:7", 0);
  test_external_ip("ff00::e:7:7", 0);

  test_internal_ip("::", 0);
  test_internal_ip("::1", 0);
  test_internal_ip("::1", 1);
  test_internal_ip("::", 0);
  test_external_ip("::", 1);
  test_external_ip("::2", 0);
  test_external_ip("2001::", 0);
  test_external_ip("ffff::", 0);

  test_external_ip("::ffff:0.0.0.0", 1);
  test_internal_ip("::ffff:0.0.0.0", 0);
  test_internal_ip("::ffff:0.255.255.255", 0);
  test_external_ip("::ffff:1.0.0.0", 0);

  test_external_ip("::ffff:9.255.255.255", 0);
  test_internal_ip("::ffff:10.0.0.0", 0);
  test_internal_ip("::ffff:10.255.255.255", 0);
  test_external_ip("::ffff:11.0.0.0", 0);

  test_external_ip("::ffff:126.255.255.255", 0);
  test_internal_ip("::ffff:127.0.0.0", 0);
  test_internal_ip("::ffff:127.255.255.255", 0);
  test_external_ip("::ffff:128.0.0.0", 0);

  test_external_ip("::ffff:172.15.255.255", 0);
  test_internal_ip("::ffff:172.16.0.0", 0);
  test_internal_ip("::ffff:172.31.255.255", 0);
  test_external_ip("::ffff:172.32.0.0", 0);

  test_external_ip("::ffff:192.167.255.255", 0);
  test_internal_ip("::ffff:192.168.0.0", 0);
  test_internal_ip("::ffff:192.168.255.255", 0);
  test_external_ip("::ffff:192.169.0.0", 0);

  test_external_ip("::ffff:169.253.255.255", 0);
  test_internal_ip("::ffff:169.254.0.0", 0);
  test_internal_ip("::ffff:169.254.255.255", 0);
  test_external_ip("::ffff:169.255.0.0", 0);
  test_assert(is_internal_IP(0x7f000001, 0));

  /* tor_addr_compare(tor_addr_t x2) */
  test_addr_compare("ffff::", ==, "ffff::0");
  test_addr_compare("0::3:2:1", <, "0::ffff:0.3.2.1");
  test_addr_compare("0::2:2:1", <, "0::ffff:0.3.2.1");
  test_addr_compare("0::ffff:0.3.2.1", >, "0::0:0:0");
  test_addr_compare("0::ffff:5.2.2.1", <, "::ffff:6.0.0.0"); /* XXXX wrong. */
  tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", &t1, NULL, NULL, NULL);
  tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL);
  test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0);
  tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", &t1, NULL, NULL, NULL);
  tor_addr_parse_mask_ports("2.3.4.5", &t2, NULL, NULL, NULL);
  test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0);

  /* test compare_masked */
  test_addr_compare_masked("ffff::", ==, "ffff::0", 128);
  test_addr_compare_masked("ffff::", ==, "ffff::0", 64);
  test_addr_compare_masked("0::2:2:1", <, "0::8000:2:1", 81);
  test_addr_compare_masked("0::2:2:1", ==, "0::8000:2:1", 80);

  /* Test undecorated tor_addr_to_str */
  test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
  test_streq(p1, "123:45:6789::5005:11");
  test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
  test_streq(p1, "18.0.0.1");

  /* Test decorated tor_addr_to_str */
  test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  test_streq(p1, "[123:45:6789::5005:11]");
  test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  test_streq(p1, "18.0.0.1");

  /* Test buffer bounds checking of tor_addr_to_str */
  test_eq(AF_INET6, tor_addr_parse(&t1, "::")); /* 2 + \0 */
  test_eq_ptr(tor_addr_to_str(buf, &t1, 2, 0), NULL); /* too short buf */
  test_streq(tor_addr_to_str(buf, &t1, 3, 0), "::");
  test_eq_ptr(tor_addr_to_str(buf, &t1, 4, 1), NULL); /* too short buf */
  test_streq(tor_addr_to_str(buf, &t1, 5, 1), "[::]");

  test_eq(AF_INET6, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */
  test_eq_ptr(tor_addr_to_str(buf, &t1, 10, 0), NULL); /* too short buf */
  test_streq(tor_addr_to_str(buf, &t1, 11, 0), "2000::1337");
  test_eq_ptr(tor_addr_to_str(buf, &t1, 12, 1), NULL); /* too short buf */
  test_streq(tor_addr_to_str(buf, &t1, 13, 1), "[2000::1337]");

  test_eq(AF_INET, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */
  test_eq_ptr(tor_addr_to_str(buf, &t1, 7, 0), NULL); /* too short buf */
  test_streq(tor_addr_to_str(buf, &t1, 8, 0), "1.2.3.4");

  test_eq(AF_INET, tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */
  test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 0), NULL); /* too short buf */
  test_streq(tor_addr_to_str(buf, &t1, 16, 0), "255.255.255.255");
  test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 1), NULL); /* too short buf */
  test_streq(tor_addr_to_str(buf, &t1, 16, 1), "255.255.255.255");

  t1.family = AF_UNSPEC;
  test_eq_ptr(tor_addr_to_str(buf, &t1, sizeof(buf), 0), NULL);

  /* Test tor_addr_parse_PTR_name */
  i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 0);
  test_eq(0, i);
  i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 1);
  test_eq(0, i);
  i = tor_addr_parse_PTR_name(&t1, "1.0.168.192.in-addr.arpa",
                                         AF_UNSPEC, 1);
  test_eq(1, i);
  test_eq(tor_addr_family(&t1), AF_INET);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  test_streq(p1, "192.168.0.1");
  i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 0);
  test_eq(0, i);
  i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 1);
  test_eq(1, i);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  test_streq(p1, "192.168.0.99");
  memset(&t1, 0, sizeof(t1));
  i = tor_addr_parse_PTR_name(&t1,
                                         "0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  test_eq(1, i);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  test_streq(p1, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]");
  /* Failing cases. */
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  test_eq(i, -1);
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.f.0."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  test_eq(i, -1);
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f.X.0.0.0.0.9."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  test_eq(i, -1);
  i = tor_addr_parse_PTR_name(&t1, "32.1.1.in-addr.arpa",
                                         AF_UNSPEC, 0);
  test_eq(i, -1);
  i = tor_addr_parse_PTR_name(&t1, ".in-addr.arpa",
                                         AF_UNSPEC, 0);
  test_eq(i, -1);
  i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
                                         AF_UNSPEC, 0);
  test_eq(i, -1);
  i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
                                         AF_INET6, 0);
  test_eq(i, -1);
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.0."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_INET, 0);
  test_eq(i, -1);

  /* === Test tor_addr_to_PTR_name */

  /* Stage IPv4 addr */
  memset(&sa_storage, 0, sizeof(sa_storage));
  sin = (struct sockaddr_in *)&sa_storage;
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = htonl(0x7f010203); /* 127.1.2.3 */
  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL);

  /* Check IPv4 PTR - too short buffer */
  test_eq(tor_addr_to_PTR_name(rbuf, 1, &t1), -1);
  test_eq(tor_addr_to_PTR_name(rbuf,
                               strlen("3.2.1.127.in-addr.arpa") - 1,
                               &t1), -1);

  /* Check IPv4 PTR - valid addr */
  test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),
          strlen("3.2.1.127.in-addr.arpa"));
  test_streq(rbuf, "3.2.1.127.in-addr.arpa");

  /* Invalid addr family */
  t1.family = AF_UNSPEC;
  test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), -1);

  /* Stage IPv6 addr */
  memset(&sa_storage, 0, sizeof(sa_storage));
  sin6 = (struct sockaddr_in6 *)&sa_storage;
  sin6->sin6_family = AF_INET6;
  sin6->sin6_addr.s6_addr[0] = 0x80; /* 8000::abcd */
  sin6->sin6_addr.s6_addr[14] = 0xab;
  sin6->sin6_addr.s6_addr[15] = 0xcd;

  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL);

  {
    const char* addr_PTR = "d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0."
      "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.ip6.arpa";

    /* Check IPv6 PTR - too short buffer */
    test_eq(tor_addr_to_PTR_name(rbuf, 0, &t1), -1);
    test_eq(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1), -1);

    /* Check IPv6 PTR - valid addr */
    test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),
            strlen(addr_PTR));
    test_streq(rbuf, addr_PTR);
  }

  /* test tor_addr_parse_mask_ports */
  test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6,
                             0, 0, 0, 0x0000000f, 17, 47, 95);
  test_streq(p1, "::f");
  //test_addr_parse("[::fefe:4.1.1.7/120]:999-1000");
  //test_addr_parse_check("::fefe:401:107", 120, 999, 1000);
  test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6,
                             0, 0, 0x0000ffff, 0x04010107, 120, 443, 443);
  test_streq(p1, "::ffff:4.1.1.7");
  test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6,
                             0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000);

  test_streq(p1, "abcd:2::44a:0");
  r=tor_addr_parse_mask_ports("[fefef::]/112", &t1, NULL, NULL, NULL);
  test_assert(r == -1);
  r=tor_addr_parse_mask_ports("efef::/112", &t1, NULL, NULL, NULL);
  test_assert(r == -1);
  r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]", &t1, NULL, NULL, NULL);
  test_assert(r == -1);
  r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL);
  test_assert(r == -1);
  r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]", &t1, NULL, NULL, NULL);
  test_assert(r == -1);
  /* Test for V4-mapped address with mask < 96.  (arguably not valid) */
  r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]", &t1, &mask, NULL, NULL);
  test_assert(r == -1);
  r=tor_addr_parse_mask_ports("1.1.2.2/33", &t1, &mask, NULL, NULL);
  test_assert(r == -1);
  r=tor_addr_parse_mask_ports("1.1.2.2/31", &t1, &mask, NULL, NULL);
  test_assert(r == AF_INET);
  r=tor_addr_parse_mask_ports("[efef::]/112", &t1, &mask, &port1, &port2);
  test_assert(r == AF_INET6);
  test_assert(port1 == 1);
  test_assert(port2 == 65535);

  /* make sure inet address lengths >= max */
  test_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255"));
  test_assert(TOR_ADDR_BUF_LEN >=
              sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"));

  test_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr));

  /* get interface addresses */
  r = get_interface_address6(LOG_DEBUG, AF_INET, &t1);
  i = get_interface_address6(LOG_DEBUG, AF_INET6, &t2);

  TT_BLATHER(("v4 address: %s (family=%d)", fmt_addr(&t1),
              tor_addr_family(&t1)));
  TT_BLATHER(("v6 address: %s (family=%d)", fmt_addr(&t2),
              tor_addr_family(&t2)));

 done:
  ;
}
Exemple #16
0
static void
test_pt_parsing(void *arg)
{
  char line[200];
  transport_t *transport = NULL;
  tor_addr_t test_addr;

  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
  (void)arg;
  mp->conf_state = PT_PROTO_INFANT;
  mp->transports = smartlist_new();

  /* incomplete cmethod */
  strlcpy(line,"CMETHOD trebuchet",sizeof(line));
  tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);

  reset_mp(mp);

  /* wrong proxy type */
  strlcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999",sizeof(line));
  tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);

  reset_mp(mp);

  /* wrong addrport */
  strlcpy(line,"CMETHOD trebuchet socks4 abcd",sizeof(line));
  tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);

  reset_mp(mp);

  /* correct line */
  strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
  tt_int_op(parse_cmethod_line(line, mp), OP_EQ, 0);
  tt_int_op(smartlist_len(mp->transports), OP_EQ, 1);
  transport = smartlist_get(mp->transports, 0);
  /* test registered address of transport */
  tor_addr_parse(&test_addr, "127.0.0.1");
  tt_assert(tor_addr_eq(&test_addr, &transport->addr));
  /* test registered port of transport */
  tt_uint_op(transport->port, OP_EQ, 1999);
  /* test registered SOCKS version of transport */
  tt_int_op(transport->socks_version, OP_EQ, PROXY_SOCKS5);
  /* test registered name of transport */
  tt_str_op(transport->name,OP_EQ, "trebuchet");

  reset_mp(mp);

  /* incomplete smethod */
  strlcpy(line,"SMETHOD trebuchet",sizeof(line));
  tt_int_op(parse_smethod_line(line, mp), OP_LT, 0);

  reset_mp(mp);

  /* wrong addr type */
  strlcpy(line,"SMETHOD trebuchet abcd",sizeof(line));
  tt_int_op(parse_smethod_line(line, mp), OP_LT, 0);

  reset_mp(mp);

  /* cowwect */
  strlcpy(line,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line));
  tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0);
  tt_int_op(smartlist_len(mp->transports), OP_EQ, 1);
  transport = smartlist_get(mp->transports, 0);
  /* test registered address of transport */
  tor_addr_parse(&test_addr, "127.0.0.2");
  tt_assert(tor_addr_eq(&test_addr, &transport->addr));
  /* test registered port of transport */
  tt_uint_op(transport->port, OP_EQ, 2999);
  /* test registered name of transport */
  tt_str_op(transport->name,OP_EQ, "trebuchy");

  reset_mp(mp);

  /* Include some arguments. Good ones. */
  strlcpy(line,"SMETHOD trebuchet 127.0.0.1:9999 "
          "ARGS:counterweight=3,sling=snappy",
          sizeof(line));
  tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0);
  tt_int_op(1, OP_EQ, smartlist_len(mp->transports));
  {
    const transport_t *transport_ = smartlist_get(mp->transports, 0);
    tt_assert(transport_);
    tt_str_op(transport_->name, OP_EQ, "trebuchet");
    tt_int_op(transport_->port, OP_EQ, 9999);
    tt_str_op(fmt_addr(&transport_->addr), OP_EQ, "127.0.0.1");
    tt_str_op(transport_->extra_info_args, OP_EQ,
              "counterweight=3,sling=snappy");
  }
  reset_mp(mp);

  /* unsupported version */
  strlcpy(line,"VERSION 666",sizeof(line));
  tt_int_op(parse_version(line, mp), OP_LT, 0);

  /* incomplete VERSION */
  strlcpy(line,"VERSION ",sizeof(line));
  tt_int_op(parse_version(line, mp), OP_LT, 0);

  /* correct VERSION */
  strlcpy(line,"VERSION 1",sizeof(line));
  tt_int_op(parse_version(line, mp), OP_EQ, 0);

 done:
  reset_mp(mp);
  smartlist_free(mp->transports);
  tor_free(mp);
}
Exemple #17
0
hs_desc_intro_point_t *
hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
                            const char *addr, int legacy)
{
  int ret;
  ed25519_keypair_t auth_kp;
  hs_desc_intro_point_t *intro_point = NULL;
  hs_desc_intro_point_t *ip = hs_desc_intro_point_new();

  /* For a usable intro point we need at least two link specifiers: One legacy
   * keyid and one ipv4 */
  {
    tor_addr_t a;
    tor_addr_make_unspec(&a);
    link_specifier_t *ls_legacy = link_specifier_new();
    link_specifier_t *ls_ip = link_specifier_new();
    link_specifier_set_ls_type(ls_legacy, LS_LEGACY_ID);
    memset(link_specifier_getarray_un_legacy_id(ls_legacy), 'C',
           link_specifier_getlen_un_legacy_id(ls_legacy));
    int family = tor_addr_parse(&a, addr);
    switch (family) {
    case AF_INET:
          link_specifier_set_ls_type(ls_ip, LS_IPV4);
          link_specifier_set_un_ipv4_addr(ls_ip, tor_addr_to_ipv4h(&a));
          link_specifier_set_un_ipv4_port(ls_ip, 9001);
          break;
        case AF_INET6:
          link_specifier_set_ls_type(ls_ip, LS_IPV6);
          memcpy(link_specifier_getarray_un_ipv6_addr(ls_ip),
                 tor_addr_to_in6_addr8(&a),
                 link_specifier_getlen_un_ipv6_addr(ls_ip));
          link_specifier_set_un_ipv6_port(ls_ip, 9001);
          break;
        default:
          /* Stop the test, not supposed to have an error.
           * Compare with -1 to show the actual family.
           */
          tt_int_op(family, OP_EQ, -1);
    }
    smartlist_add(ip->link_specifiers, ls_legacy);
    smartlist_add(ip->link_specifiers, ls_ip);
  }

  ret = ed25519_keypair_generate(&auth_kp, 0);
  tt_int_op(ret, ==, 0);
  ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
                                      &auth_kp.pubkey, now,
                                      HS_DESC_CERT_LIFETIME,
                                      CERT_FLAG_INCLUDE_SIGNING_KEY);
  tt_assert(ip->auth_key_cert);

  if (legacy) {
    ip->legacy.key = crypto_pk_new();
    tt_assert(ip->legacy.key);
    ret = crypto_pk_generate_key(ip->legacy.key);
    tt_int_op(ret, ==, 0);
    ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
                                    &signing_kp->pubkey, ip->legacy.key,
                                    now + HS_DESC_CERT_LIFETIME,
                                    &ip->legacy.cert.encoded);
    tt_assert(ip->legacy.cert.encoded);
    tt_u64_op(cert_len, OP_GT, 0);
    ip->legacy.cert.len = cert_len;
  }

  /* Encryption key. */
  {
    int signbit;
    curve25519_keypair_t curve25519_kp;
    ed25519_keypair_t ed25519_kp;
    tor_cert_t *cross_cert;

    ret = curve25519_keypair_generate(&curve25519_kp, 0);
    tt_int_op(ret, ==, 0);
    ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
                                            &curve25519_kp);
    cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
                                 &ed25519_kp.pubkey, time(NULL),
                                 HS_DESC_CERT_LIFETIME,
                                 CERT_FLAG_INCLUDE_SIGNING_KEY);
    tt_assert(cross_cert);
    ip->enc_key_cert = cross_cert;
  }

  intro_point = ip;
 done:
  if (intro_point == NULL)
    tor_free(ip);

  return intro_point;
}
Exemple #18
0
static void
test_virtaddrmap_persist(void *data)
{
  (void)data;
  const char *a, *b, *c;
  tor_addr_t addr;
  char *ones = NULL;

  addressmap_init();

  // Try a hostname.
  a = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME,
                                          tor_strdup("foobar.baz"));
  tt_assert(a);
  tt_assert(!strcmpend(a, ".virtual"));

  // mock crypto_rand to repeat the same result twice; make sure we get
  // different outcomes.  (Because even though the odds for receiving the
  // same 80-bit address twice is only 1/2^40, it could still happen for
  // some user -- but running our test through 2^40 iterations isn't
  // reasonable.)
  canned_data = "1234567890" // the first call returns this.
                "1234567890" // the second call returns this.
                "abcdefghij"; // the third call returns this.
  canned_data_len = 30;
  MOCK(crypto_rand, crypto_canned);

  a = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME,
                                          tor_strdup("quuxit.baz"));
  b = addressmap_register_virtual_address(RESOLVED_TYPE_HOSTNAME,
                                          tor_strdup("nescio.baz"));
  tt_assert(a);
  tt_assert(b);
  tt_str_op(a, OP_EQ, "gezdgnbvgy3tqojq.virtual");
  tt_str_op(b, OP_EQ, "mfrggzdfmztwq2lk.virtual");

  // Now try something to get us an ipv4 address
  UNMOCK(crypto_rand);
  tt_int_op(0,OP_EQ, parse_virtual_addr_network("192.168.0.0/16",
                                                AF_INET, 0, NULL));
  a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
                                          tor_strdup("foobar.baz"));
  tt_assert(a);
  tt_assert(!strcmpstart(a, "192.168."));
  tor_addr_parse(&addr, a);
  tt_int_op(AF_INET, OP_EQ, tor_addr_family(&addr));

  b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
                                          tor_strdup("quuxit.baz"));
  tt_str_op(b, OP_NE, a);
  tt_assert(!strcmpstart(b, "192.168."));

  // Try some canned entropy and verify all the we discard duplicates,
  // addresses that end with 0, and addresses that end with 255.
  MOCK(crypto_rand, crypto_canned);
  canned_data = "\x01\x02\x03\x04" // okay
                "\x01\x02\x03\x04" // duplicate
                "\x03\x04\x00\x00" // bad ending 1
                "\x05\x05\x00\xff" // bad ending 2
                "\x05\x06\x07\xf0"; // okay
  canned_data_len = 20;
  a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
                                          tor_strdup("wumble.onion"));
  b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
                                          tor_strdup("wumpus.onion"));
  tt_str_op(a, OP_EQ, "192.168.3.4");
  tt_str_op(b, OP_EQ, "192.168.7.240");

  // Now try IPv6!
  UNMOCK(crypto_rand);
  tt_int_op(0,OP_EQ, parse_virtual_addr_network("1010:F000::/20",
                                                AF_INET6, 0, NULL));
  a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
                                          tor_strdup("foobar.baz"));
  tt_assert(a);
  tt_assert(!strcmpstart(a, "[1010:f"));
  tor_addr_parse(&addr, a);
  tt_int_op(AF_INET6, OP_EQ, tor_addr_family(&addr));

  b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
                                          tor_strdup("quuxit.baz"));
  tt_str_op(b, OP_NE, a);
  tt_assert(!strcmpstart(b, "[1010:f"));

  // Try IPv6 with canned entropy, to make sure we detect duplicates.
  MOCK(crypto_rand, crypto_canned);
  canned_data = "acanthopterygian" // okay
                "cinematographist" // okay
                "acanthopterygian" // duplicate
                "acanthopterygian" // duplicate
                "acanthopterygian" // duplicate
                "cinematographist" // duplicate
                "coadministration"; // okay
  canned_data_len = 16 * 7;
  a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
                                          tor_strdup("wuffle.baz"));
  b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
                                          tor_strdup("gribble.baz"));
  c = addressmap_register_virtual_address(RESOLVED_TYPE_IPV6,
                                      tor_strdup("surprisingly-legible.baz"));
  tt_str_op(a, OP_EQ, "[1010:f16e:7468:6f70:7465:7279:6769:616e]");
  tt_str_op(b, OP_EQ, "[1010:fe65:6d61:746f:6772:6170:6869:7374]");
  tt_str_op(c, OP_EQ, "[1010:f164:6d69:6e69:7374:7261:7469:6f6e]");

  // Try address exhaustion: make sure we can actually fail if we
  // get too many already-existing addresses.
  canned_data_len = 128*1024;
  canned_data = ones = tor_malloc(canned_data_len);
  memset(ones, 1, canned_data_len);
  // There is some chance this one will fail if a previous random
  // allocation gave out the address already.
  a = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
                                          tor_strdup("might-work.onion"));
  if (a) {
    tt_str_op(a, OP_EQ, "192.168.1.1");
  }
  setup_capture_of_logs(LOG_WARN);
  // This one will definitely fail, since we've set up the RNG to hand
  // out "1" forever.
  b = addressmap_register_virtual_address(RESOLVED_TYPE_IPV4,
                                          tor_strdup("wont-work.onion"));
  tt_assert(b == NULL);
  expect_single_log_msg_containing("Ran out of virtual addresses!");

 done:
  UNMOCK(crypto_rand);
  tor_free(ones);
  addressmap_free_all();
  teardown_capture_of_logs();
}
Exemple #19
0
/** Parse the encoded introduction points in <b>intro_points_encoded</b> of
 * length <b>intro_points_encoded_size</b> and write the result to the
 * descriptor in <b>parsed</b>; return the number of successfully parsed
 * introduction points or -1 in case of a failure. */
int
rend_parse_introduction_points(rend_service_descriptor_t *parsed,
                               const char *intro_points_encoded,
                               size_t intro_points_encoded_size)
{
  const char *current_ipo, *end_of_intro_points;
  smartlist_t *tokens = NULL;
  directory_token_t *tok;
  rend_intro_point_t *intro;
  extend_info_t *info;
  int result, num_ok=1;
  memarea_t *area = NULL;
  tor_assert(parsed);
  /** Function may only be invoked once. */
  tor_assert(!parsed->intro_nodes);
  if (!intro_points_encoded || intro_points_encoded_size == 0) {
    log_warn(LD_REND, "Empty or zero size introduction point list");
    goto err;
  }
  /* Consider one intro point after the other. */
  current_ipo = intro_points_encoded;
  end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
  tokens = smartlist_new();
  parsed->intro_nodes = smartlist_new();
  area = memarea_new();

  while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo,
                      "introduction-point ")) {
    /* Determine end of string. */
    const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
                                 "\nintroduction-point ");
    if (!eos)
      eos = end_of_intro_points;
    else
      eos = eos+1;
    tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
    /* Free tokens and clear token list. */
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_clear(tokens);
    memarea_clear(area);
    /* Tokenize string. */
    if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
      log_warn(LD_REND, "Error tokenizing introduction point");
      goto err;
    }
    /* Advance to next introduction point, if available. */
    current_ipo = eos;
    /* Check minimum allowed length of introduction point. */
    if (smartlist_len(tokens) < 5) {
      log_warn(LD_REND, "Impossibly short introduction point.");
      goto err;
    }
    /* Allocate new intro point and extend info. */
    intro = tor_malloc_zero(sizeof(rend_intro_point_t));
    info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
    /* Parse identifier. */
    tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
    if (base32_decode(info->identity_digest, DIGEST_LEN,
                      tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
      log_warn(LD_REND, "Identity digest contains illegal characters: %s",
               tok->args[0]);
      rend_intro_point_free(intro);
      goto err;
    }
    /* Write identifier to nickname. */
    info->nickname[0] = '$';
    base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
                  info->identity_digest, DIGEST_LEN);
    /* Parse IP address. */
    tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
    if (tor_addr_parse(&info->addr, tok->args[0])<0) {
      log_warn(LD_REND, "Could not parse introduction point address.");
      rend_intro_point_free(intro);
      goto err;
    }
    if (tor_addr_family(&info->addr) != AF_INET) {
      log_warn(LD_REND, "Introduction point address was not ipv4.");
      rend_intro_point_free(intro);
      goto err;
    }

    /* Parse onion port. */
    tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
    info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
                                           &num_ok,NULL);
    if (!info->port || !num_ok) {
      log_warn(LD_REND, "Introduction point onion port %s is invalid",
               escaped(tok->args[0]));
      rend_intro_point_free(intro);
      goto err;
    }
    /* Parse onion key. */
    tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
    if (!crypto_pk_public_exponent_ok(tok->key)) {
      log_warn(LD_REND,
               "Introduction point's onion key had invalid exponent.");
      rend_intro_point_free(intro);
      goto err;
    }
    info->onion_key = tok->key;
    tok->key = NULL; /* Prevent free */
    /* Parse service key. */
    tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
    if (!crypto_pk_public_exponent_ok(tok->key)) {
      log_warn(LD_REND,
               "Introduction point key had invalid exponent.");
      rend_intro_point_free(intro);
      goto err;
    }
    intro->intro_key = tok->key;
    tok->key = NULL; /* Prevent free */
    /* Add extend info to list of introduction points. */
    smartlist_add(parsed->intro_nodes, intro);
  }
  result = smartlist_len(parsed->intro_nodes);
  goto done;

 err:
  result = -1;

 done:
  /* Free tokens and clear token list. */
  if (tokens) {
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_free(tokens);
  }
  if (area)
    memarea_drop_all(area);

  return result;
}
Exemple #20
0
/** Run unit tests for IPv6 encoding/decoding/manipulation functions. */
static void
test_addr_ip6_helpers(void *arg)
{
  char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN];
  char rbuf[REVERSE_LOOKUP_NAME_BUF_LEN];
  struct in6_addr a1, a2;
  tor_addr_t t1, t2;
  int r, i;
  uint16_t port1, port2;
  maskbits_t mask;
  const char *p1;
  struct sockaddr_storage sa_storage;
  struct sockaddr_in *sin;
  struct sockaddr_in6 *sin6;

  /* Test tor_inet_ntop and tor_inet_pton: IPv6 */
  (void)arg;
  {
    const char *ip = "2001::1234";
    const char *ip_ffff = "::ffff:192.168.1.2";

    /* good round trip */
    tt_int_op(tor_inet_pton(AF_INET6, ip, &a1),OP_EQ, 1);
    tt_ptr_op(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)),OP_EQ, &buf);
    tt_str_op(buf,OP_EQ, ip);

    /* good round trip - ::ffff:0:0 style */
    tt_int_op(tor_inet_pton(AF_INET6, ip_ffff, &a2),OP_EQ, 1);
    tt_ptr_op(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)),OP_EQ, &buf);
    tt_str_op(buf,OP_EQ, ip_ffff);

    /* just long enough buffer (remember \0) */
    tt_str_op(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1),OP_EQ, ip);
    tt_str_op(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1),OP_EQ,
               ip_ffff);

    /* too short buffer (remember \0) */
    tt_ptr_op(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)),OP_EQ, NULL);
    tt_ptr_op(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)),OP_EQ, NULL);
  }

  /* ==== Converting to and from sockaddr_t. */
  sin = (struct sockaddr_in *)&sa_storage;
  sin->sin_family = AF_INET;
  sin->sin_port = htons(9090);
  sin->sin_addr.s_addr = htonl(0x7f7f0102); /*127.127.1.2*/
  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, &port1);
  tt_int_op(tor_addr_family(&t1),OP_EQ, AF_INET);
  tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ, 0x7f7f0102);
  tt_int_op(port1, OP_EQ, 9090);

  memset(&sa_storage, 0, sizeof(sa_storage));
  tt_int_op(sizeof(struct sockaddr_in),OP_EQ,
          tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage,
                               sizeof(sa_storage)));
  tt_int_op(1234,OP_EQ, ntohs(sin->sin_port));
  tt_int_op(0x7f7f0102,OP_EQ, ntohl(sin->sin_addr.s_addr));

  memset(&sa_storage, 0, sizeof(sa_storage));
  sin6 = (struct sockaddr_in6 *)&sa_storage;
  sin6->sin6_family = AF_INET6;
  sin6->sin6_port = htons(7070);
  sin6->sin6_addr.s6_addr[0] = 128;
  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, &port1);
  tt_int_op(tor_addr_family(&t1),OP_EQ, AF_INET6);
  tt_int_op(port1, OP_EQ, 7070);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
  tt_str_op(p1,OP_EQ, "8000::");

  memset(&sa_storage, 0, sizeof(sa_storage));
  tt_int_op(sizeof(struct sockaddr_in6),OP_EQ,
          tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage,
                               sizeof(sa_storage)));
  tt_int_op(AF_INET6,OP_EQ, sin6->sin6_family);
  tt_int_op(9999,OP_EQ, ntohs(sin6->sin6_port));
  tt_int_op(0x80000000,OP_EQ, ntohl(S6_ADDR32(sin6->sin6_addr)[0]));

  /* ==== tor_addr_lookup: static cases.  (Can't test dns without knowing we
   * have a good resolver. */
  tt_int_op(0,OP_EQ, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1));
  tt_int_op(AF_INET,OP_EQ, tor_addr_family(&t1));
  tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ, 0x7f808182);

  tt_int_op(0,OP_EQ, tor_addr_lookup("9000::5", AF_UNSPEC, &t1));
  tt_int_op(AF_INET6,OP_EQ, tor_addr_family(&t1));
  tt_int_op(0x90,OP_EQ, tor_addr_to_in6_addr8(&t1)[0]);
  tt_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14));
  tt_int_op(0x05,OP_EQ, tor_addr_to_in6_addr8(&t1)[15]);

  /* === Test pton: valid af_inet6 */
  /* Simple, valid parsing. */
  r = tor_inet_pton(AF_INET6,
                    "0102:0304:0506:0708:090A:0B0C:0D0E:0F10", &a1);
  tt_int_op(r, OP_EQ, 1);
  for (i=0;i<16;++i) { tt_int_op(i+1,OP_EQ, (int)a1.s6_addr[i]); }
  /* ipv4 ending. */
  test_pton6_same("0102:0304:0506:0708:090A:0B0C:0D0E:0F10",
                  "0102:0304:0506:0708:090A:0B0C:13.14.15.16");
  /* shortened words. */
  test_pton6_same("0001:0099:BEEF:0000:0123:FFFF:0001:0001",
                  "1:99:BEEF:0:0123:FFFF:1:1");
  /* zeros at the beginning */
  test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001",
                  "::9:c0a8:1:1");
  test_pton6_same("0000:0000:0000:0000:0009:C0A8:0001:0001",
                  "::9:c0a8:0.1.0.1");
  /* zeros in the middle. */
  test_pton6_same("fe80:0000:0000:0000:0202:1111:0001:0001",
                  "fe80::202:1111:1:1");
  /* zeros at the end. */
  test_pton6_same("1000:0001:0000:0007:0000:0000:0000:0000",
                  "1000:1:0:7::");

  /* === Test ntop: af_inet6 */
  test_ntop6_reduces("0:0:0:0:0:0:0:0", "::");

  test_ntop6_reduces("0001:0099:BEEF:0006:0123:FFFF:0001:0001",
                     "1:99:beef:6:123:ffff:1:1");

  //test_ntop6_reduces("0:0:0:0:0:0:c0a8:0101", "::192.168.1.1");
  test_ntop6_reduces("0:0:0:0:0:ffff:c0a8:0101", "::ffff:192.168.1.1");
  test_ntop6_reduces("0:0:0:0:0:0:c0a8:0101", "::192.168.1.1");
  test_ntop6_reduces("002:0:0000:0:3::4", "2::3:0:0:4");
  test_ntop6_reduces("0:0::1:0:3", "::1:0:3");
  test_ntop6_reduces("008:0::0", "8::");
  test_ntop6_reduces("0:0:0:0:0:ffff::1", "::ffff:0.0.0.1");
  test_ntop6_reduces("abcd:0:0:0:0:0:7f00::", "abcd::7f00:0");
  test_ntop6_reduces("0000:0000:0000:0000:0009:C0A8:0001:0001",
                     "::9:c0a8:1:1");
  test_ntop6_reduces("fe80:0000:0000:0000:0202:1111:0001:0001",
                     "fe80::202:1111:1:1");
  test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000",
                     "1000:1:0:7::");

  /* Bad af param */
  tt_int_op(tor_inet_pton(AF_UNSPEC, 0, 0),OP_EQ, -1);

  /* === Test pton: invalid in6. */
  test_pton6_bad("foobar.");
  test_pton6_bad("-1::");
  test_pton6_bad("00001::");
  test_pton6_bad("10000::");
  test_pton6_bad("::10000");
  test_pton6_bad("55555::");
  test_pton6_bad("9:-60::");
  test_pton6_bad("9:+60::");
  test_pton6_bad("9|60::");
  test_pton6_bad("0x60::");
  test_pton6_bad("::0x60");
  test_pton6_bad("9:0x60::");
  test_pton6_bad("1:2:33333:4:0002:3::");
  test_pton6_bad("1:2:3333:4:fish:3::");
  test_pton6_bad("1:2:3:4:5:6:7:8:9");
  test_pton6_bad("1:2:3:4:5:6:7");
  test_pton6_bad("1:2:3:4:5:6:1.2.3.4.5");
  test_pton6_bad("1:2:3:4:5:6:1.2.3");
  test_pton6_bad("::1.2.3");
  test_pton6_bad("::1.2.3.4.5");
  test_pton6_bad("::ffff:0xff.0.0.0");
  test_pton6_bad("::ffff:ff.0.0.0");
  test_pton6_bad("::ffff:256.0.0.0");
  test_pton6_bad("::ffff:-1.0.0.0");
  test_pton6_bad("99");
  test_pton6_bad("");
  test_pton6_bad(".");
  test_pton6_bad(":");
  test_pton6_bad("1::2::3:4");
  test_pton6_bad("a:::b:c");
  test_pton6_bad(":::a:b:c");
  test_pton6_bad("a:b:c:::");
  test_pton6_bad("1.2.3.4");
  test_pton6_bad(":1.2.3.4");
  test_pton6_bad(".2.3.4");
  /* Regression tests for 22789. */
  test_pton6_bad("0xfoo");
  test_pton6_bad("0x88");
  test_pton6_bad("0xyxxy");
  test_pton6_bad("0XFOO");
  test_pton6_bad("0X88");
  test_pton6_bad("0XYXXY");
  test_pton6_bad("0x");
  test_pton6_bad("0X");

  /* test internal checking */
  test_external_ip("fbff:ffff::2:7", 0);
  test_internal_ip("fc01::2:7", 0);
  test_internal_ip("fc01::02:7", 0);
  test_internal_ip("fc01::002:7", 0);
  test_internal_ip("fc01::0002:7", 0);
  test_internal_ip("fdff:ffff::f:f", 0);
  test_external_ip("fe00::3:f", 0);

  test_external_ip("fe7f:ffff::2:7", 0);
  test_internal_ip("fe80::2:7", 0);
  test_internal_ip("febf:ffff::f:f", 0);

  test_internal_ip("fec0::2:7:7", 0);
  test_internal_ip("feff:ffff::e:7:7", 0);
  test_external_ip("ff00::e:7:7", 0);

  test_internal_ip("::", 0);
  test_internal_ip("::1", 0);
  test_internal_ip("::1", 1);
  test_internal_ip("::", 0);
  test_external_ip("::", 1);
  test_external_ip("::2", 0);
  test_external_ip("2001::", 0);
  test_external_ip("ffff::", 0);

  test_external_ip("::ffff:0.0.0.0", 1);
  test_internal_ip("::ffff:0.0.0.0", 0);
  test_internal_ip("::ffff:0.255.255.255", 0);
  test_external_ip("::ffff:1.0.0.0", 0);

  test_external_ip("::ffff:9.255.255.255", 0);
  test_internal_ip("::ffff:10.0.0.0", 0);
  test_internal_ip("::ffff:10.255.255.255", 0);
  test_external_ip("::ffff:11.0.0.0", 0);

  test_external_ip("::ffff:126.255.255.255", 0);
  test_internal_ip("::ffff:127.0.0.0", 0);
  test_internal_ip("::ffff:127.255.255.255", 0);
  test_external_ip("::ffff:128.0.0.0", 0);

  test_external_ip("::ffff:172.15.255.255", 0);
  test_internal_ip("::ffff:172.16.0.0", 0);
  test_internal_ip("::ffff:172.31.255.255", 0);
  test_external_ip("::ffff:172.32.0.0", 0);

  test_external_ip("::ffff:192.167.255.255", 0);
  test_internal_ip("::ffff:192.168.0.0", 0);
  test_internal_ip("::ffff:192.168.255.255", 0);
  test_external_ip("::ffff:192.169.0.0", 0);

  test_external_ip("::ffff:169.253.255.255", 0);
  test_internal_ip("::ffff:169.254.0.0", 0);
  test_internal_ip("::ffff:169.254.255.255", 0);
  test_external_ip("::ffff:169.255.0.0", 0);

  /* tor_addr_compare(tor_addr_t x2) */
  test_addr_compare("ffff::", OP_EQ, "ffff::0");
  test_addr_compare("0::3:2:1", OP_LT, "0::ffff:0.3.2.1");
  test_addr_compare("0::2:2:1", OP_LT, "0::ffff:0.3.2.1");
  test_addr_compare("0::ffff:0.3.2.1", OP_GT, "0::0:0:0");
  test_addr_compare("0::ffff:5.2.2.1", OP_LT,
                    "::ffff:6.0.0.0"); /* XXXX wrong. */
  tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", 0, &t1, NULL, NULL, NULL);
  tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL);
  tt_int_op(tor_addr_compare(&t1, &t2, CMP_SEMANTIC), OP_EQ, 0);
  tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", 0, &t1, NULL, NULL, NULL);
  tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL);
  tt_int_op(tor_addr_compare(&t1, &t2, CMP_SEMANTIC), OP_LT, 0);

  /* test compare_masked */
  test_addr_compare_masked("ffff::", OP_EQ, "ffff::0", 128);
  test_addr_compare_masked("ffff::", OP_EQ, "ffff::0", 64);
  test_addr_compare_masked("0::2:2:1", OP_LT, "0::8000:2:1", 81);
  test_addr_compare_masked("0::2:2:1", OP_EQ, "0::8000:2:1", 80);

  /* Test undecorated tor_addr_to_str */
  tt_int_op(AF_INET6,OP_EQ, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
  tt_str_op(p1,OP_EQ, "123:45:6789::5005:11");
  tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&t1, "18.0.0.1"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
  tt_str_op(p1,OP_EQ, "18.0.0.1");

  /* Test decorated tor_addr_to_str */
  tt_int_op(AF_INET6,OP_EQ, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  tt_str_op(p1,OP_EQ, "[123:45:6789::5005:11]");
  tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&t1, "18.0.0.1"));
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  tt_str_op(p1,OP_EQ, "18.0.0.1");

  /* Test buffer bounds checking of tor_addr_to_str */
  tt_int_op(AF_INET6,OP_EQ, tor_addr_parse(&t1, "::")); /* 2 + \0 */
  tt_ptr_op(tor_addr_to_str(buf, &t1, 2, 0),OP_EQ, NULL); /* too short buf */
  tt_str_op(tor_addr_to_str(buf, &t1, 3, 0),OP_EQ, "::");
  tt_ptr_op(tor_addr_to_str(buf, &t1, 4, 1),OP_EQ, NULL); /* too short buf */
  tt_str_op(tor_addr_to_str(buf, &t1, 5, 1),OP_EQ, "[::]");

  tt_int_op(AF_INET6,OP_EQ, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */
  tt_ptr_op(tor_addr_to_str(buf, &t1, 10, 0),OP_EQ, NULL); /* too short buf */
  tt_str_op(tor_addr_to_str(buf, &t1, 11, 0),OP_EQ, "2000::1337");
  tt_ptr_op(tor_addr_to_str(buf, &t1, 12, 1),OP_EQ, NULL); /* too short buf */
  tt_str_op(tor_addr_to_str(buf, &t1, 13, 1),OP_EQ, "[2000::1337]");

  tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */
  tt_ptr_op(tor_addr_to_str(buf, &t1, 7, 0),OP_EQ, NULL); /* too short buf */
  tt_str_op(tor_addr_to_str(buf, &t1, 8, 0),OP_EQ, "1.2.3.4");

  tt_int_op(AF_INET, OP_EQ,
            tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */
  tt_ptr_op(tor_addr_to_str(buf, &t1, 15, 0),OP_EQ, NULL); /* too short buf */
  tt_str_op(tor_addr_to_str(buf, &t1, 16, 0),OP_EQ, "255.255.255.255");
  tt_ptr_op(tor_addr_to_str(buf, &t1, 15, 1),OP_EQ, NULL); /* too short buf */
  tt_str_op(tor_addr_to_str(buf, &t1, 16, 1),OP_EQ, "255.255.255.255");

  t1.family = AF_UNSPEC;
  tt_ptr_op(tor_addr_to_str(buf, &t1, sizeof(buf), 0),OP_EQ, NULL);

  /* Test tor_addr_parse_PTR_name */
  i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 0);
  tt_int_op(0,OP_EQ, i);
  i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 1);
  tt_int_op(0,OP_EQ, i);
  i = tor_addr_parse_PTR_name(&t1, "9999999999999999999999999999.in-addr.arpa",
                              AF_UNSPEC, 1);
  tt_int_op(-1,OP_EQ, i);
  i = tor_addr_parse_PTR_name(&t1, "1.0.168.192.in-addr.arpa",
                                         AF_UNSPEC, 1);
  tt_int_op(1,OP_EQ, i);
  tt_int_op(tor_addr_family(&t1),OP_EQ, AF_INET);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  tt_str_op(p1,OP_EQ, "192.168.0.1");
  i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 0);
  tt_int_op(0,OP_EQ, i);
  i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 1);
  tt_int_op(1,OP_EQ, i);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  tt_str_op(p1,OP_EQ, "192.168.0.99");
  memset(&t1, 0, sizeof(t1));
  i = tor_addr_parse_PTR_name(&t1,
                                         "0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  tt_int_op(1,OP_EQ, i);
  p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
  tt_str_op(p1,OP_EQ, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]");
  /* Failing cases. */
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  tt_int_op(i,OP_EQ, -1);
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.f.0."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  tt_int_op(i,OP_EQ, -1);
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f.X.0.0.0.0.9."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_UNSPEC, 0);
  tt_int_op(i,OP_EQ, -1);
  i = tor_addr_parse_PTR_name(&t1, "32.1.1.in-addr.arpa",
                                         AF_UNSPEC, 0);
  tt_int_op(i,OP_EQ, -1);
  i = tor_addr_parse_PTR_name(&t1, ".in-addr.arpa",
                                         AF_UNSPEC, 0);
  tt_int_op(i,OP_EQ, -1);
  i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
                                         AF_UNSPEC, 0);
  tt_int_op(i,OP_EQ, -1);
  i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
                                         AF_INET6, 0);
  tt_int_op(i,OP_EQ, -1);
  i = tor_addr_parse_PTR_name(&t1,
                                         "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.0."
                                         "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
                                         "ip6.ARPA",
                                         AF_INET, 0);
  tt_int_op(i,OP_EQ, -1);

  /* === Test tor_addr_to_PTR_name */

  /* Stage IPv4 addr */
  memset(&sa_storage, 0, sizeof(sa_storage));
  sin = (struct sockaddr_in *)&sa_storage;
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = htonl(0x7f010203); /* 127.1.2.3 */
  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL);

  /* Check IPv4 PTR - too short buffer */
  tt_int_op(tor_addr_to_PTR_name(rbuf, 1, &t1),OP_EQ, -1);
  tt_int_op(tor_addr_to_PTR_name(rbuf,
                               strlen("3.2.1.127.in-addr.arpa") - 1,
                               &t1),OP_EQ, -1);

  /* Check IPv4 PTR - valid addr */
  tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),OP_EQ,
          strlen("3.2.1.127.in-addr.arpa"));
  tt_str_op(rbuf,OP_EQ, "3.2.1.127.in-addr.arpa");

  /* Invalid addr family */
  t1.family = AF_UNSPEC;
  tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),OP_EQ, -1);

  /* Stage IPv6 addr */
  memset(&sa_storage, 0, sizeof(sa_storage));
  sin6 = (struct sockaddr_in6 *)&sa_storage;
  sin6->sin6_family = AF_INET6;
  sin6->sin6_addr.s6_addr[0] = 0x80; /* 8000::abcd */
  sin6->sin6_addr.s6_addr[14] = 0xab;
  sin6->sin6_addr.s6_addr[15] = 0xcd;

  tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL);

  {
    const char* addr_PTR = "d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0."
      "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.ip6.arpa";

    /* Check IPv6 PTR - too short buffer */
    tt_int_op(tor_addr_to_PTR_name(rbuf, 0, &t1),OP_EQ, -1);
    tt_int_op(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1),OP_EQ, -1);

    /* Check IPv6 PTR - valid addr */
    tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),OP_EQ,
            strlen(addr_PTR));
    tt_str_op(rbuf,OP_EQ, addr_PTR);
  }

  /* XXXX turn this into a separate function; it's not all IPv6. */
  /* test tor_addr_parse_mask_ports */
  test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6,
                             0, 0, 0, 0x0000000f, 17, 47, 95);
  tt_str_op(p1,OP_EQ, "::f");
  //test_addr_parse("[::fefe:4.1.1.7/120]:999-1000");
  //test_addr_parse_check("::fefe:401:107", 120, 999, 1000);
  test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6,
                             0, 0, 0x0000ffff, 0x04010107, 120, 443, 443);
  tt_str_op(p1,OP_EQ, "::ffff:4.1.1.7");
  test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6,
                             0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000);

  tt_str_op(p1,OP_EQ, "abcd:2::44a:0");
  /* Try some long addresses. */
  r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111]",
                              0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, AF_INET6);
  r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:11111]",
                              0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111:1]",
                              0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports(
         "[ffff:1111:1111:1111:1111:1111:1111:ffff:"
         "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:"
         "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:"
         "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
         0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  /* Try some failing cases. */
  r=tor_addr_parse_mask_ports("[fefef::]/112", 0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[fefe::/112", 0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[fefe::", 0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[fefe::X]", 0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("efef::/112", 0, &t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]",0,&t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/fred",0,&t1,&mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/255.255.0.0",
                              0,&t1, NULL, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  /* This one will get rejected because it isn't a pure prefix. */
  r=tor_addr_parse_mask_ports("1.1.2.3/255.255.64.0",0,&t1, &mask,NULL,NULL);
  tt_int_op(r, OP_EQ, -1);
  /* Test for V4-mapped address with mask < 96.  (arguably not valid) */
  r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]",0,&t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("1.1.2.2/33",0,&t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  /* Try extended wildcard addresses with out TAPMP_EXTENDED_STAR*/
  r=tor_addr_parse_mask_ports("*4",0,&t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("*6",0,&t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  tt_int_op(r, OP_EQ, -1);
  /* Try a mask with a wildcard. */
  r=tor_addr_parse_mask_ports("*/16",0,&t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("*4/16",TAPMP_EXTENDED_STAR,
                              &t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  r=tor_addr_parse_mask_ports("*6/30",TAPMP_EXTENDED_STAR,
                              &t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, -1);
  /* Basic mask tests*/
  r=tor_addr_parse_mask_ports("1.1.2.2/31",0,&t1, &mask, NULL, NULL);
  tt_int_op(r, OP_EQ, AF_INET);
  tt_int_op(mask,OP_EQ,31);
  tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET);
  tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0x01010202);
  r=tor_addr_parse_mask_ports("3.4.16.032:1-2",0,&t1, &mask, &port1, &port2);
  tt_int_op(r, OP_EQ, AF_INET);
  tt_int_op(mask,OP_EQ,32);
  tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET);
  tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0x03041020);
  tt_uint_op(port1, OP_EQ, 1);
  tt_uint_op(port2, OP_EQ, 2);
  r=tor_addr_parse_mask_ports("1.1.2.3/255.255.128.0",0,&t1, &mask,NULL,NULL);
  tt_int_op(r, OP_EQ, AF_INET);
  tt_int_op(mask,OP_EQ,17);
  tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET);
  tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0x01010203);
  r=tor_addr_parse_mask_ports("[efef::]/112",0,&t1, &mask, &port1, &port2);
  tt_int_op(r, OP_EQ, AF_INET6);
  tt_uint_op(port1, OP_EQ, 1);
  tt_uint_op(port2, OP_EQ, 65535);
  /* Try regular wildcard behavior without TAPMP_EXTENDED_STAR */
  r=tor_addr_parse_mask_ports("*:80-443",0,&t1,&mask,&port1,&port2);
  tt_int_op(r,OP_EQ,AF_INET); /* Old users of this always get inet */
  tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET);
  tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0);
  tt_int_op(mask,OP_EQ,0);
  tt_int_op(port1,OP_EQ,80);
  tt_int_op(port2,OP_EQ,443);
  /* Now try wildcards *with* TAPMP_EXTENDED_STAR */
  r=tor_addr_parse_mask_ports("*:8000-9000",TAPMP_EXTENDED_STAR,
                              &t1,&mask,&port1,&port2);
  tt_int_op(r,OP_EQ,AF_UNSPEC);
  tt_int_op(tor_addr_family(&t1),OP_EQ,AF_UNSPEC);
  tt_int_op(mask,OP_EQ,0);
  tt_int_op(port1,OP_EQ,8000);
  tt_int_op(port2,OP_EQ,9000);
  r=tor_addr_parse_mask_ports("*4:6667",TAPMP_EXTENDED_STAR,
                              &t1,&mask,&port1,&port2);
  tt_int_op(r,OP_EQ,AF_INET);
  tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET);
  tt_int_op(tor_addr_to_ipv4h(&t1),OP_EQ,0);
  tt_int_op(mask,OP_EQ,0);
  tt_int_op(port1,OP_EQ,6667);
  tt_int_op(port2,OP_EQ,6667);
  r=tor_addr_parse_mask_ports("*6",TAPMP_EXTENDED_STAR,
                              &t1,&mask,&port1,&port2);
  tt_int_op(r,OP_EQ,AF_INET6);
  tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET6);
  tt_assert(tor_mem_is_zero((const char*)tor_addr_to_in6_addr32(&t1), 16));
  tt_int_op(mask,OP_EQ,0);
  tt_int_op(port1,OP_EQ,1);
  tt_int_op(port2,OP_EQ,65535);

  /* make sure inet address lengths >= max */
  tt_int_op(INET_NTOA_BUF_LEN, OP_GE, sizeof("255.255.255.255"));
  tt_int_op(TOR_ADDR_BUF_LEN, OP_GE,
            sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"));

  tt_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr));

  /* get interface addresses */
  r = get_interface_address6(LOG_DEBUG, AF_INET, &t1);
  tt_int_op(r, OP_LE, 0); // "it worked or it didn't"
  i = get_interface_address6(LOG_DEBUG, AF_INET6, &t2);
  tt_int_op(i, OP_LE, 0); // "it worked or it didn't"

  TT_BLATHER(("v4 address: %s (family=%d)", fmt_addr(&t1),
              tor_addr_family(&t1)));
  TT_BLATHER(("v6 address: %s (family=%d)", fmt_addr(&t2),
              tor_addr_family(&t2)));

 done:
  ;
}
Exemple #21
0
/**
 * Generate a routerstatus for v3_networkstatus test.
 */
vote_routerstatus_t *
dir_common_gen_routerstatus_for_v3ns(int idx, time_t now)
{
  vote_routerstatus_t *vrs=NULL;
  routerstatus_t *rs = NULL;
  tor_addr_t addr_ipv6;
  char *method_list = NULL;

  switch (idx) {
    case 0:
      /* Generate the first routerstatus. */
      vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
      rs = &vrs->status;
      vrs->version = tor_strdup("0.1.2.14");
      rs->published_on = now-1500;
      strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
      memset(rs->identity_digest, TEST_DIR_ROUTER_ID_1, DIGEST_LEN);
      memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_1, DIGEST_LEN);
      rs->addr = 0x99008801;
      rs->or_port = 443;
      rs->dir_port = 8000;
      /* all flags but running and v2dir cleared */
      rs->is_flagged_running = 1;
      rs->is_v2_dir = 1;
      break;
    case 1:
      /* Generate the second routerstatus. */
      vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
      rs = &vrs->status;
      vrs->version = tor_strdup("0.2.0.5");
      rs->published_on = now-1000;
      strlcpy(rs->nickname, "router1", sizeof(rs->nickname));
      memset(rs->identity_digest, TEST_DIR_ROUTER_ID_2, DIGEST_LEN);
      memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_2, DIGEST_LEN);
      rs->addr = 0x99009901;
      rs->or_port = 443;
      rs->dir_port = 0;
      tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
      tor_addr_copy(&rs->ipv6_addr, &addr_ipv6);
      rs->ipv6_orport = 4711;
      rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
        rs->is_valid = rs->is_possible_guard = rs->is_v2_dir = 1;
      break;
    case 2:
      /* Generate the third routerstatus. */
      vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
      rs = &vrs->status;
      vrs->version = tor_strdup("0.1.0.3");
      rs->published_on = now-1000;
      strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
      memset(rs->identity_digest, TEST_DIR_ROUTER_ID_3, DIGEST_LEN);
      memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_3, DIGEST_LEN);
      rs->addr = 0xAA009901;
      rs->or_port = 400;
      rs->dir_port = 9999;
      rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
        rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
        rs->is_possible_guard = 1;
      break;
    case 3:
      /* Generate a fourth routerstatus that is not running. */
      vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
      rs = &vrs->status;
      vrs->version = tor_strdup("0.1.6.3");
      rs->published_on = now-1000;
      strlcpy(rs->nickname, "router4", sizeof(rs->nickname));
      memset(rs->identity_digest, TEST_DIR_ROUTER_ID_4, DIGEST_LEN);
      memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_4, DIGEST_LEN);
      rs->addr = 0xC0000203;
      rs->or_port = 500;
      rs->dir_port = 1999;
      rs->is_v2_dir = 1;
      /* Running flag (and others) cleared */
      break;
    case 4:
      /* No more for this test; return NULL */
      vrs = NULL;
      break;
    default:
      /* Shouldn't happen */
      tt_assert(0);
  }
  if (vrs) {
    vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
    method_list = make_consensus_method_list(MIN_SUPPORTED_CONSENSUS_METHOD,
                                             MAX_SUPPORTED_CONSENSUS_METHOD,
                                             ",");
    tor_asprintf(&vrs->microdesc->microdesc_hash_line,
                 "m %s "
                 "sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n",
                 method_list, idx);
  }

 done:
  tor_free(method_list);
  return vrs;
}
Exemple #22
0
static void
test_cfmt_connected_cells(void *arg)
{
  relay_header_t rh;
  cell_t cell;
  tor_addr_t addr;
  int ttl, r;
  char *mem_op_hex_tmp = NULL;
  (void)arg;

  /* Let's try an oldschool one with nothing in it. */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "", 0);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_UNSPEC);
  tt_int_op(ttl, ==, -1);

  /* A slightly less oldschool one: only an IPv4 address */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x20\x30\x40\x50", 4);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  tt_str_op(fmt_addr(&addr), ==, "32.48.64.80");
  tt_int_op(ttl, ==, -1);

  /* Bogus but understandable: truncated TTL */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x11\x12\x13\x14\x15", 5);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  tt_str_op(fmt_addr(&addr), ==, "17.18.19.20");
  tt_int_op(ttl, ==, -1);

  /* Regular IPv4 one: address and TTL */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
                  "\x02\x03\x04\x05\x00\x00\x0e\x10", 8);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  tt_str_op(fmt_addr(&addr), ==, "2.3.4.5");
  tt_int_op(ttl, ==, 3600);

  /* IPv4 with too-big TTL */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
                  "\x02\x03\x04\x05\xf0\x00\x00\x00", 8);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  tt_str_op(fmt_addr(&addr), ==, "2.3.4.5");
  tt_int_op(ttl, ==, -1);

  /* IPv6 (ttl is mandatory) */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
                  "\x00\x00\x00\x00\x06"
                  "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
                  "\x00\x00\x00\x00\x00\x00\x00\x68"
                  "\x00\x00\x02\x58", 25);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET6);
  tt_str_op(fmt_addr(&addr), ==, "2607:f8b0:400c:c02::68");
  tt_int_op(ttl, ==, 600);

  /* IPv6 (ttl too big) */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
                  "\x00\x00\x00\x00\x06"
                  "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
                  "\x00\x00\x00\x00\x00\x00\x00\x68"
                  "\x90\x00\x02\x58", 25);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET6);
  tt_str_op(fmt_addr(&addr), ==, "2607:f8b0:400c:c02::68");
  tt_int_op(ttl, ==, -1);

  /* Bogus size: 3. */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
                  "\x00\x01\x02", 3);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, -1);

  /* Bogus family: 7. */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
                  "\x00\x00\x00\x00\x07"
                  "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
                  "\x00\x00\x00\x00\x00\x00\x00\x68"
                  "\x90\x00\x02\x58", 25);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, -1);

  /* Truncated IPv6. */
  make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
                  "\x00\x00\x00\x00\x06"
                  "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
                  "\x00\x00\x00\x00\x00\x00\x00\x68"
                  "\x00\x00\x02", 24);
  relay_header_unpack(&rh, cell.payload);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, -1);

  /* Now make sure we can generate connected cells correctly. */
  /* Try an IPv4 address */
  memset(&rh, 0, sizeof(rh));
  memset(&cell, 0, sizeof(cell));
  tor_addr_parse(&addr, "30.40.50.60");
  rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
                                            &addr, 128);
  tt_int_op(rh.length, ==, 8);
  test_memeq_hex(cell.payload+RELAY_HEADER_SIZE, "1e28323c" "00000080");

  /* Try parsing it. */
  tor_addr_make_unspec(&addr);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  tt_str_op(fmt_addr(&addr), ==, "30.40.50.60");
  tt_int_op(ttl, ==, 128);

  /* Try an IPv6 address */
  memset(&rh, 0, sizeof(rh));
  memset(&cell, 0, sizeof(cell));
  tor_addr_parse(&addr, "2620::6b0:b:1a1a:0:26e5:480e");
  rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
                                            &addr, 3600);
  tt_int_op(rh.length, ==, 25);
  test_memeq_hex(cell.payload + RELAY_HEADER_SIZE,
                 "00000000" "06"
                 "2620000006b0000b1a1a000026e5480e" "00000e10");

  /* Try parsing it. */
  tor_addr_make_unspec(&addr);
  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  tt_int_op(r, ==, 0);
  tt_int_op(tor_addr_family(&addr), ==, AF_INET6);
  tt_str_op(fmt_addr(&addr), ==, "2620:0:6b0:b:1a1a:0:26e5:480e");
  tt_int_op(ttl, ==, 3600);

 done:
  tor_free(mem_op_hex_tmp);
}