Example #1
0
static void
test_util_format_unaligned_accessors(void *ignored)
{
  (void)ignored;
  char buf[9] = "onionsoup"; // 6f6e696f6e736f7570

  tt_u64_op(get_uint64(buf+1), OP_EQ, htonll(U64_LITERAL(0x6e696f6e736f7570)));
  tt_uint_op(get_uint32(buf+1), OP_EQ, htonl(0x6e696f6e));
  tt_uint_op(get_uint16(buf+1), OP_EQ, htons(0x6e69));
  tt_uint_op(get_uint8(buf+1), OP_EQ, 0x6e);

  set_uint8(buf+7, 0x61);
  tt_mem_op(buf, OP_EQ, "onionsoap", 9);

  set_uint16(buf+6, htons(0x746f));
  tt_mem_op(buf, OP_EQ, "onionstop", 9);

  set_uint32(buf+1, htonl(0x78696465));
  tt_mem_op(buf, OP_EQ, "oxidestop", 9);

  set_uint64(buf+1, htonll(U64_LITERAL(0x6266757363617465)));
  tt_mem_op(buf, OP_EQ, "obfuscate", 9);
 done:
  ;
}
Example #2
0
static void
test_buffers_zlib_fin_at_chunk_end(void *arg)
{
  char *msg = NULL;
  char *contents = NULL;
  char *expanded = NULL;
  buf_t *buf = NULL;
  tor_zlib_state_t *zlib_state = NULL;
  size_t out_len, in_len;
  size_t sz, headerjunk;
  (void) arg;

  buf = buf_new_with_capacity(128); /* will round up */
  sz = buf_get_default_chunk_size(buf);
  msg = tor_malloc_zero(sz);

  write_to_buf(msg, 1, buf);
  tt_assert(buf->head);

  /* Fill up the chunk so the zlib stuff won't fit in one chunk. */
  tt_uint_op(buf->head->memlen, OP_LT, sz);
  headerjunk = buf->head->memlen - 7;
  write_to_buf(msg, headerjunk-1, buf);
  tt_uint_op(buf->head->datalen, OP_EQ, headerjunk);
  tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk);
  /* Write an empty string, with finalization on. */
  zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
  tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0);

  in_len = buf_datalen(buf);
  contents = tor_malloc(in_len);

  tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0);

  tt_uint_op(in_len, OP_GT, headerjunk);

  tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len,
                                  contents + headerjunk, in_len - headerjunk,
                                  ZLIB_METHOD, 1,
                                  LOG_WARN));

  tt_int_op(out_len, OP_EQ, 0);
  tt_assert(expanded);

 done:
  buf_free(buf);
  tor_zlib_free(zlib_state);
  tor_free(contents);
  tor_free(expanded);
  tor_free(msg);
}
Example #3
0
static void
test_crypto_pwbox(void *arg)
{
  uint8_t *boxed=NULL, *decoded=NULL;
  size_t len, dlen;
  unsigned i;
  const char msg[] = "This bunny reminds you that you still have a "
    "salamander in your sylladex. She is holding the bunny Dave got you. "
    "It’s sort of uncanny how similar they are, aside from the knitted "
    "enhancements. Seriously, what are the odds?? So weird.";
  const char pw[] = "I'm a night owl and a wise bird too";

  const unsigned flags[] = { 0,
                             S2K_FLAG_NO_SCRYPT,
                             S2K_FLAG_LOW_MEM,
                             S2K_FLAG_NO_SCRYPT|S2K_FLAG_LOW_MEM,
                             S2K_FLAG_USE_PBKDF2 };
  (void)arg;

  for (i = 0; i < ARRAY_LENGTH(flags); ++i) {
    tt_int_op(0, OP_EQ, crypto_pwbox(&boxed, &len,
                                  (const uint8_t*)msg, strlen(msg),
                                  pw, strlen(pw), flags[i]));
    tt_assert(boxed);
    tt_assert(len > 128+32);

    tt_int_op(0, OP_EQ, crypto_unpwbox(&decoded, &dlen, boxed, len,
                                    pw, strlen(pw)));

    tt_assert(decoded);
    tt_uint_op(dlen, OP_EQ, strlen(msg));
    tt_mem_op(decoded, OP_EQ, msg, dlen);

    tor_free(decoded);

    tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
                                                     boxed, len,
                                                     pw, strlen(pw)-1));
    boxed[len-1] ^= 1;
    tt_int_op(UNPWBOX_BAD_SECRET, OP_EQ, crypto_unpwbox(&decoded, &dlen,
                                                     boxed, len,
                                                     pw, strlen(pw)));
    boxed[0] = 255;
    tt_int_op(UNPWBOX_CORRUPTED, OP_EQ, crypto_unpwbox(&decoded, &dlen,
                                                    boxed, len,
                                                    pw, strlen(pw)));

    tor_free(boxed);
  }

 done:
  tor_free(boxed);
  tor_free(decoded);
}
Example #4
0
static void
test_buffers_chunk_size(void *arg)
{
    (void)arg;
    const int min = 256;
    const int max = 65536;
    tt_uint_op(preferred_chunk_size(3), OP_EQ, min);
    tt_uint_op(preferred_chunk_size(25), OP_EQ, min);
    tt_uint_op(preferred_chunk_size(0), OP_EQ, min);
    tt_uint_op(preferred_chunk_size(256), OP_EQ, 512);
    tt_uint_op(preferred_chunk_size(65400), OP_EQ, max);
    /* Here, we're implicitly saying that the chunk header overhead is
     * between 1 and 100 bytes. 24..48 would probably be more accurate. */
    tt_uint_op(preferred_chunk_size(65536), OP_GT, 65536);
    tt_uint_op(preferred_chunk_size(65536), OP_LT, 65536+100);
    tt_uint_op(preferred_chunk_size(165536), OP_GT, 165536);
    tt_uint_op(preferred_chunk_size(165536), OP_LT, 165536+100);
done:
    ;
}
Example #5
0
static void
test_ext_or_cookie_auth_testvec(void *arg)
{
  char *reply=NULL, *client_hash=NULL;
  size_t reply_len;
  char *mem_op_hex_tmp=NULL;

  const char client_nonce[] = "But when I look ahead up the whi";
  (void)arg;

  ext_or_auth_cookie = tor_malloc_zero(32);
  memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
  ext_or_auth_cookie_is_set = 1;

  MOCK(crypto_rand, crypto_rand_return_tse_str);

  tt_int_op(0, OP_EQ,
            handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
                                     &reply_len));
  tt_ptr_op(reply, OP_NE, NULL );
  tt_uint_op(reply_len, OP_EQ, 64);
  tt_mem_op(reply+32,OP_EQ, "te road There is always another ", 32);
  /* HMACSHA256("Gliding wrapt in a brown mantle,"
   *     "ExtORPort authentication server-to-client hash"
   *     "But when I look ahead up the write road There is always another ");
   */
  test_memeq_hex(reply,
                 "ec80ed6e546d3b36fdfc22fe1315416b"
                 "029f1ade7610d910878b62eeb7403821");
  /* HMACSHA256("Gliding wrapt in a brown mantle,"
   *     "ExtORPort authentication client-to-server hash"
   *     "But when I look ahead up the write road There is always another ");
   * (Both values computed using Python CLI.)
   */
  test_memeq_hex(client_hash,
                 "ab391732dd2ed968cd40c087d1b1f25b"
                 "33b3cd77ff79bd80c2074bbf438119a2");

 done:
  UNMOCK(crypto_rand);
  tor_free(reply);
  tor_free(client_hash);
  tor_free(mem_op_hex_tmp);
}
Example #6
0
static void
test_pick_circid(void *arg)
{
  bitarray_t *ba = NULL;
  channel_t *chan1, *chan2;
  circid_t circid;
  int i;
  (void) arg;

  chan1 = tor_malloc_zero(sizeof(channel_t));
  chan2 = tor_malloc_zero(sizeof(channel_t));
  chan2->wide_circ_ids = 1;

  chan1->circ_id_type = CIRC_ID_TYPE_NEITHER;
  tt_int_op(0, OP_EQ, get_unique_circ_id_by_chan(chan1));

  /* Basic tests, with no collisions */
  chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
  for (i = 0; i < 50; ++i) {
    circid = get_unique_circ_id_by_chan(chan1);
    tt_uint_op(0, OP_LT, circid);
    tt_uint_op(circid, OP_LT, (1<<15));
  }
  chan1->circ_id_type = CIRC_ID_TYPE_HIGHER;
  for (i = 0; i < 50; ++i) {
    circid = get_unique_circ_id_by_chan(chan1);
    tt_uint_op((1<<15), OP_LT, circid);
    tt_uint_op(circid, OP_LT, (1<<16));
  }

  chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
  for (i = 0; i < 50; ++i) {
    circid = get_unique_circ_id_by_chan(chan2);
    tt_uint_op(0, OP_LT, circid);
    tt_uint_op(circid, OP_LT, (1u<<31));
  }
  chan2->circ_id_type = CIRC_ID_TYPE_HIGHER;
  for (i = 0; i < 50; ++i) {
    circid = get_unique_circ_id_by_chan(chan2);
    tt_uint_op((1u<<31), OP_LT, circid);
  }

  /* Now make sure that we can behave well when we are full up on circuits */
  chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
  chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
  chan1->wide_circ_ids = chan2->wide_circ_ids = 0;
  ba = bitarray_init_zero((1<<15));
  for (i = 0; i < (1<<15); ++i) {
    circid = get_unique_circ_id_by_chan(chan1);
    if (circid == 0) {
      tt_int_op(i, OP_GT, (1<<14));
      break;
    }
    tt_uint_op(circid, OP_LT, (1<<15));
    tt_assert(! bitarray_is_set(ba, circid));
    bitarray_set(ba, circid);
    channel_mark_circid_unusable(chan1, circid);
  }
  tt_int_op(i, OP_LT, (1<<15));
  /* Make sure that being full on chan1 does not interfere with chan2 */
  for (i = 0; i < 100; ++i) {
    circid = get_unique_circ_id_by_chan(chan2);
    tt_uint_op(circid, OP_GT, 0);
    tt_uint_op(circid, OP_LT, (1<<15));
    channel_mark_circid_unusable(chan2, circid);
  }

 done:
  tor_free(chan1);
  tor_free(chan2);
  bitarray_free(ba);
  circuit_free_all();
}
Example #7
0
static void
test_buffer_pullup(void *arg)
{
  buf_t *buf;
  char *stuff, *tmp;
  const char *cp;
  size_t sz;
  (void)arg;
  stuff = tor_malloc(16384);
  tmp = tor_malloc(16384);

  buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */

  tt_assert(buf);
  tt_int_op(buf_get_default_chunk_size(buf), OP_EQ, 4096);

  tt_int_op(buf_get_total_allocation(), OP_EQ, 0);

  /* There are a bunch of cases for pullup.  One is the trivial case. Let's
     mess around with an empty buffer. */
  buf_pullup(buf, 16);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_EQ, NULL);
  tt_uint_op(sz, OP_EQ, 0);

  /* Let's make sure nothing got allocated */
  tt_int_op(buf_get_total_allocation(), OP_EQ, 0);

  /* Case 1: everything puts into the first chunk with some moving. */

  /* Let's add some data. */
  crypto_rand(stuff, 16384);
  write_to_buf(stuff, 3000, buf);
  write_to_buf(stuff+3000, 3000, buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_LE, 4096);

  /* Make room for 3000 bytes in the first chunk, so that the pullup-move code
   * can get tested. */
  tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 3000);
  tt_mem_op(tmp,OP_EQ, stuff, 3000);
  buf_pullup(buf, 2048);
  assert_buf_ok(buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_GE, 2048);
  tt_mem_op(cp,OP_EQ, stuff+3000, 2048);
  tt_int_op(3000, OP_EQ, buf_datalen(buf));
  tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 0);
  tt_mem_op(tmp,OP_EQ, stuff+3000, 2048);

  buf_free(buf);

  /* Now try the large-chunk case. */
  buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  write_to_buf(stuff, 4000, buf);
  write_to_buf(stuff+4000, 4000, buf);
  write_to_buf(stuff+8000, 4000, buf);
  write_to_buf(stuff+12000, 4000, buf);
  tt_int_op(buf_datalen(buf), OP_EQ, 16000);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_LE, 4096);

  buf_pullup(buf, 12500);
  assert_buf_ok(buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_GE, 12500);
  tt_mem_op(cp,OP_EQ, stuff, 12500);
  tt_int_op(buf_datalen(buf), OP_EQ, 16000);

  fetch_from_buf(tmp, 12400, buf);
  tt_mem_op(tmp,OP_EQ, stuff, 12400);
  tt_int_op(buf_datalen(buf), OP_EQ, 3600);
  fetch_from_buf(tmp, 3500, buf);
  tt_mem_op(tmp,OP_EQ, stuff+12400, 3500);
  fetch_from_buf(tmp, 100, buf);
  tt_mem_op(tmp,OP_EQ, stuff+15900, 10);

  buf_free(buf);

  /* Make sure that the pull-up-whole-buffer case works */
  buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  write_to_buf(stuff, 4000, buf);
  write_to_buf(stuff+4000, 4000, buf);
  fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */
  buf_pullup(buf, 16000); /* Way too much. */
  assert_buf_ok(buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_EQ, 7900);
  tt_mem_op(cp,OP_EQ, stuff+100, 7900);

  buf_free(buf);
  buf = NULL;

  tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
 done:
  buf_free(buf);
  tor_free(stuff);
  tor_free(tmp);
}
Example #8
0
/** More tests for parsing different kinds of microdescriptors, and getting
 * invalid digests trackd from them. */
static void
test_md_parse(void *arg)
{
  (void) arg;
  char *mem_op_hex_tmp = NULL;
  smartlist_t *invalid = smartlist_new();

  smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA,
                                                  NULL, 1, SAVED_NOWHERE,
                                                  invalid);
  tt_int_op(smartlist_len(mds), OP_EQ, 11);
  tt_int_op(smartlist_len(invalid), OP_EQ, 4);

  test_memeq_hex(smartlist_get(invalid,0),
                 "5d76bf1c6614e885614a1e0ad074e1ab"
                 "4ea14655ebeefb1736a71b5ed8a15a51");
  test_memeq_hex(smartlist_get(invalid,1),
                 "2fde0ee3343669c2444cd9d53cbd39c6"
                 "a7d1fc0513513e840ca7f6e68864b36c");
  test_memeq_hex(smartlist_get(invalid,2),
                 "20d1576c5ab11bbcff0dedb1db4a3cfc"
                 "c8bc8dd839d8cbfef92d00a1a7d7b294");
  test_memeq_hex(smartlist_get(invalid,3),
                 "074770f394c73dbde7b44412e9692add"
                 "691a478d4727f9804b77646c95420a96");

  /* Spot-check the valid ones. */
  const microdesc_t *md = smartlist_get(mds, 5);
  test_memeq_hex(md->digest,
                 "54bb6d733ddeb375d2456c79ae103961"
                 "da0cae29620375ac4cf13d54da4d92b3");
  tt_int_op(md->last_listed, OP_EQ, 0);
  tt_int_op(md->saved_location, OP_EQ, SAVED_NOWHERE);
  tt_int_op(md->no_save, OP_EQ, 0);
  tt_uint_op(md->held_in_map, OP_EQ, 0);
  tt_uint_op(md->held_by_nodes, OP_EQ, 0);
  tt_assert(md->onion_curve25519_pkey);

  md = smartlist_get(mds, 6);
  test_memeq_hex(md->digest,
                 "53f740bd222ab37f19f604b1d3759aa6"
                 "5eff1fbce9ac254bd0fa50d4af9b1bae");
  tt_assert(! md->exit_policy);

  md = smartlist_get(mds, 8);
  test_memeq_hex(md->digest,
                 "a0a155562d8093d8fd0feb7b93b7226e"
                 "17f056c2142aab7a4ea8c5867a0376d5");
  tt_assert(md->onion_curve25519_pkey);

  md = smartlist_get(mds, 10);
  test_memeq_hex(md->digest,
                 "409ebd87d23925a2732bd467a92813c9"
                 "21ca378fcb9ca193d354c51550b6d5e9");
  tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
  tt_int_op(md->ipv6_orport, OP_EQ, 9090);

 done:
  SMARTLIST_FOREACH(mds, microdesc_t *, mdsc, microdesc_free(mdsc));
  smartlist_free(mds);
  SMARTLIST_FOREACH(invalid, char *, cp, tor_free(cp));
  smartlist_free(invalid);
  tor_free(mem_op_hex_tmp);
}
Example #9
0
static void
test_crypto_ed25519_fuzz_donna(void *arg)
{
  const unsigned iters = 1024;
  uint8_t msg[1024];
  unsigned i;
  (void)arg;

  tt_uint_op(iters, OP_EQ, sizeof(msg));
  crypto_rand((char*) msg, sizeof(msg));

  /* Fuzz Ed25519-donna vs ref10, alternating the implementation used to
   * generate keys/sign per iteration.
   */
  for (i = 0; i < iters; ++i) {
    const int use_donna = i & 1;
    uint8_t blinding[32];
    curve25519_keypair_t ckp;
    ed25519_keypair_t kp, kp_blind, kp_curve25519;
    ed25519_public_key_t pk, pk_blind, pk_curve25519;
    ed25519_signature_t sig, sig_blind;
    int bit = 0;

    crypto_rand((char*) blinding, sizeof(blinding));

    /* Impl. A:
     *  1. Generate a keypair.
     *  2. Blinded the keypair.
     *  3. Sign a message (unblinded).
     *  4. Sign a message (blinded).
     *  5. Generate a curve25519 keypair, and convert it to Ed25519.
     */
    ed25519_set_impl_params(use_donna);
    tt_int_op(0, OP_EQ, ed25519_keypair_generate(&kp, i&1));
    tt_int_op(0, OP_EQ, ed25519_keypair_blind(&kp_blind, &kp, blinding));
    tt_int_op(0, OP_EQ, ed25519_sign(&sig, msg, i, &kp));
    tt_int_op(0, OP_EQ, ed25519_sign(&sig_blind, msg, i, &kp_blind));

    tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ckp, i&1));
    tt_int_op(0, OP_EQ, ed25519_keypair_from_curve25519_keypair(
            &kp_curve25519, &bit, &ckp));

    /* Impl. B:
     *  1. Validate the public key by rederiving it.
     *  2. Validate the blinded public key by rederiving it.
     *  3. Validate the unblinded signature (and test a invalid signature).
     *  4. Validate the blinded signature.
     *  5. Validate the public key (from Curve25519) by rederiving it.
     */
    ed25519_set_impl_params(!use_donna);
    tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pk, &kp.seckey));
    tt_mem_op(pk.pubkey, OP_EQ, kp.pubkey.pubkey, 32);

    tt_int_op(0, OP_EQ, ed25519_public_blind(&pk_blind, &kp.pubkey, blinding));
    tt_mem_op(pk_blind.pubkey, OP_EQ, kp_blind.pubkey.pubkey, 32);

    tt_int_op(0, OP_EQ, ed25519_checksig(&sig, msg, i, &pk));
    sig.sig[0] ^= 15;
    tt_int_op(-1, OP_EQ, ed25519_checksig(&sig, msg, sizeof(msg), &pk));

    tt_int_op(0, OP_EQ, ed25519_checksig(&sig_blind, msg, i, &pk_blind));

    tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key(
            &pk_curve25519, &ckp.pubkey, bit));
    tt_mem_op(pk_curve25519.pubkey, OP_EQ, kp_curve25519.pubkey.pubkey, 32);
  }

 done:
  ;
}
Example #10
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);
}
Example #11
0
void
hs_helper_desc_equal(const hs_descriptor_t *desc1,
                     const hs_descriptor_t *desc2)
{
  /* Plaintext data section. */
  tt_int_op(desc1->plaintext_data.version, OP_EQ,
            desc2->plaintext_data.version);
  tt_uint_op(desc1->plaintext_data.lifetime_sec, OP_EQ,
             desc2->plaintext_data.lifetime_sec);
  tt_assert(tor_cert_eq(desc1->plaintext_data.signing_key_cert,
                        desc2->plaintext_data.signing_key_cert));
  tt_mem_op(desc1->plaintext_data.signing_pubkey.pubkey, OP_EQ,
            desc2->plaintext_data.signing_pubkey.pubkey,
            ED25519_PUBKEY_LEN);
  tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ,
            desc2->plaintext_data.blinded_pubkey.pubkey,
            ED25519_PUBKEY_LEN);
  tt_u64_op(desc1->plaintext_data.revision_counter, ==,
            desc2->plaintext_data.revision_counter);

  /* NOTE: We can't compare the encrypted blob because when encoding the
   * descriptor, the object is immutable thus we don't update it with the
   * encrypted blob. As contrast to the decoding process where we populate a
   * descriptor object. */

  /* Superencrypted data section. */
  tt_mem_op(desc1->superencrypted_data.auth_ephemeral_pubkey.public_key, OP_EQ,
            desc2->superencrypted_data.auth_ephemeral_pubkey.public_key,
            CURVE25519_PUBKEY_LEN);

  /* Auth clients. */
  {
    tt_assert(desc1->superencrypted_data.clients);
    tt_assert(desc2->superencrypted_data.clients);
    tt_int_op(smartlist_len(desc1->superencrypted_data.clients), ==,
              smartlist_len(desc2->superencrypted_data.clients));
    for (int i=0;
         i < smartlist_len(desc1->superencrypted_data.clients);
         i++) {
      hs_desc_authorized_client_t
        *client1 = smartlist_get(desc1->superencrypted_data.clients, i),
        *client2 = smartlist_get(desc2->superencrypted_data.clients, i);
      tt_mem_op(client1->client_id, OP_EQ, client2->client_id,
                sizeof(client1->client_id));
      tt_mem_op(client1->iv, OP_EQ, client2->iv,
                sizeof(client1->iv));
      tt_mem_op(client1->encrypted_cookie, OP_EQ, client2->encrypted_cookie,
                sizeof(client1->encrypted_cookie));
    }
  }

  /* Encrypted data section. */
  tt_uint_op(desc1->encrypted_data.create2_ntor, ==,
             desc2->encrypted_data.create2_ntor);

  /* Authentication type. */
  tt_int_op(!!desc1->encrypted_data.intro_auth_types, ==,
            !!desc2->encrypted_data.intro_auth_types);
  if (desc1->encrypted_data.intro_auth_types &&
      desc2->encrypted_data.intro_auth_types) {
    tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), ==,
              smartlist_len(desc2->encrypted_data.intro_auth_types));
    for (int i = 0;
         i < smartlist_len(desc1->encrypted_data.intro_auth_types);
         i++) {
      tt_str_op(smartlist_get(desc1->encrypted_data.intro_auth_types, i),OP_EQ,
                smartlist_get(desc2->encrypted_data.intro_auth_types, i));
    }
  }
Example #12
0
static void
test_proto_var_cell(void *arg)
{
  (void)arg;
  char *mem_op_hex_tmp = NULL;
  char tmp[1024];
  buf_t *buf = NULL;
  var_cell_t *cell = NULL;

  buf = buf_new();
  memset(tmp, 0xf0, sizeof(tmp));

  /* Short little commands will make us say "no cell yet." */
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  tt_ptr_op(cell, OP_EQ, NULL);
  buf_add(buf, "\x01\x02\x02\0x2", 4);
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  /* An incomplete fixed-length cell makes us say "no cell yet". */
  buf_add(buf, "\x03", 1);
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  /* A complete fixed length-cell makes us say "not a variable-length cell" */
  buf_add(buf, tmp, 509);
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  buf_clear(buf);

  /* An incomplete versions cell is a variable-length cell that isn't ready
   * yet. */
  buf_add(buf,
          "\x01\x02\x03\x04" /* circid */
          "\x07" /* VERSIONS */
          "\x00\x04" /* 4 bytes long */
          "\x00" /* incomplete */, 8);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  tt_ptr_op(cell, OP_EQ, NULL);
  /* Complete it, and it's a variable-length cell. Leave a byte on the end for
   * fun. */
  buf_add(buf, "\x09\x00\x25\ff", 4);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  tt_ptr_op(cell, OP_NE, NULL);
  tt_int_op(cell->command, OP_EQ, CELL_VERSIONS);
  tt_uint_op(cell->circ_id, OP_EQ, 0x01020304);
  tt_int_op(cell->payload_len, OP_EQ, 4);
  test_mem_op_hex(cell->payload, OP_EQ, "00090025");
  var_cell_free(cell);
  cell = NULL;
  tt_int_op(buf_datalen(buf), OP_EQ, 1);
  buf_clear(buf);

  /* In link protocol 3 and earlier, circid fields were two bytes long. Let's
   * ensure that gets handled correctly. */
  buf_add(buf,
          "\x23\x45\x81\x00\x06" /* command 81; 6 bytes long */
          "coraje", 11);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 3));
  tt_ptr_op(cell, OP_NE, NULL);
  tt_int_op(cell->command, OP_EQ, 129);
  tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
  tt_int_op(cell->payload_len, OP_EQ, 6);
  tt_mem_op(cell->payload, OP_EQ, "coraje", 6);
  var_cell_free(cell);
  cell = NULL;
  tt_int_op(buf_datalen(buf), OP_EQ, 0);

  /* In link protocol 2, only VERSIONS cells counted as variable-length */
  buf_add(buf,
          "\x23\x45\x81\x00\x06"
          "coraje", 11); /* As above */
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
  buf_clear(buf);
  buf_add(buf,
          "\x23\x45\x07\x00\x06"
          "futuro", 11);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
  tt_ptr_op(cell, OP_NE, NULL);
  tt_int_op(cell->command, OP_EQ, 7);
  tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
  tt_int_op(cell->payload_len, OP_EQ, 6);
  tt_mem_op(cell->payload, OP_EQ, "futuro", 6);
  var_cell_free(cell);
  cell = NULL;

 done:
  buf_free(buf);
  var_cell_free(cell);
  tor_free(mem_op_hex_tmp);
}
Example #13
0
static void
test_routerkeys_ed_certs(void *args)
{
  (void)args;
  ed25519_keypair_t kp1, kp2;
  tor_cert_t *cert[2] = {NULL, NULL}, *nocert = NULL;
  tor_cert_t *parsed_cert[2] = {NULL, NULL};
  time_t now = 1412094534;
  uint8_t *junk = NULL;
  char *base64 = NULL;

  tt_int_op(0,OP_EQ,ed25519_keypair_generate(&kp1, 0));
  tt_int_op(0,OP_EQ,ed25519_keypair_generate(&kp2, 0));

  for (int i = 0; i <= 1; ++i) {
    uint32_t flags = i ? CERT_FLAG_INCLUDE_SIGNING_KEY : 0;

    cert[i] = tor_cert_create(&kp1, 5, &kp2.pubkey, now, 10000, flags);
    tt_assert(cert[i]);

    tt_uint_op(cert[i]->sig_bad, OP_EQ, 0);
    tt_uint_op(cert[i]->sig_ok, OP_EQ, 1);
    tt_uint_op(cert[i]->cert_expired, OP_EQ, 0);
    tt_uint_op(cert[i]->cert_valid, OP_EQ, 1);
    tt_int_op(cert[i]->cert_type, OP_EQ, 5);
    tt_mem_op(cert[i]->signed_key.pubkey, OP_EQ, &kp2.pubkey.pubkey, 32);
    tt_mem_op(cert[i]->signing_key.pubkey, OP_EQ, &kp1.pubkey.pubkey, 32);
    tt_int_op(cert[i]->signing_key_included, OP_EQ, i);

    tt_assert(cert[i]->encoded);
    tt_int_op(cert[i]->encoded_len, OP_EQ, 104 + 36 * i);
    tt_int_op(cert[i]->encoded[0], OP_EQ, 1);
    tt_int_op(cert[i]->encoded[1], OP_EQ, 5);

    parsed_cert[i] = tor_cert_parse(cert[i]->encoded, cert[i]->encoded_len);
    tt_assert(parsed_cert[i]);
    tt_int_op(cert[i]->encoded_len, OP_EQ, parsed_cert[i]->encoded_len);
    tt_mem_op(cert[i]->encoded, OP_EQ, parsed_cert[i]->encoded,
              cert[i]->encoded_len);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->sig_ok, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->cert_valid, OP_EQ, 0);

    /* Expired */
    tt_int_op(tor_cert_checksig(parsed_cert[i], &kp1.pubkey, now + 30000),
              OP_LT, 0);
    tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 1);
    parsed_cert[i]->cert_expired = 0;

    /* Wrong key */
    tt_int_op(tor_cert_checksig(parsed_cert[i], &kp2.pubkey, now), OP_LT, 0);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 1);
    parsed_cert[i]->sig_bad = 0;

    /* Missing key */
    int ok = tor_cert_checksig(parsed_cert[i], NULL, now);
    tt_int_op(ok < 0, OP_EQ, i == 0);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0);
    tt_assert(parsed_cert[i]->sig_ok == (i != 0));
    tt_assert(parsed_cert[i]->cert_valid == (i != 0));
    parsed_cert[i]->sig_bad = 0;
    parsed_cert[i]->sig_ok = 0;
    parsed_cert[i]->cert_valid = 0;

    /* Right key */
    tt_int_op(tor_cert_checksig(parsed_cert[i], &kp1.pubkey, now), OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->sig_ok, OP_EQ, 1);
    tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->cert_valid, OP_EQ, 1);
  }

  /* Now try some junky certs. */
  /* - Truncated */
  nocert = tor_cert_parse(cert[0]->encoded, cert[0]->encoded_len-1);
  tt_ptr_op(NULL, OP_EQ, nocert);

  /* - First byte modified */
  cert[0]->encoded[0] = 99;
  nocert = tor_cert_parse(cert[0]->encoded, cert[0]->encoded_len);
  tt_ptr_op(NULL, OP_EQ, nocert);
  cert[0]->encoded[0] = 1;

  /* - Extra byte at the end*/
  junk = tor_malloc_zero(cert[0]->encoded_len + 1);
  memcpy(junk, cert[0]->encoded, cert[0]->encoded_len);
  nocert = tor_cert_parse(junk, cert[0]->encoded_len+1);
  tt_ptr_op(NULL, OP_EQ, nocert);

  /* - Multiple signing key instances */
  tor_free(junk);
  junk = tor_malloc_zero(104 + 36 * 2);
  junk[0] = 1; /* version */
  junk[1] = 5; /* cert type */
  junk[6] = 1; /* key type */
  junk[39] = 2; /* n_extensions */
  junk[41] = 32; /* extlen */
  junk[42] = 4; /* exttype */
  junk[77] = 32; /* extlen */
  junk[78] = 4; /* exttype */
  nocert = tor_cert_parse(junk, 104 + 36 * 2);
  tt_ptr_op(NULL, OP_EQ, nocert);

 done:
  tor_cert_free(cert[0]);
  tor_cert_free(cert[1]);
  tor_cert_free(parsed_cert[0]);
  tor_cert_free(parsed_cert[1]);
  tor_cert_free(nocert);
  tor_free(junk);
  tor_free(base64);
}
Example #14
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:
  ;
}