diff options
author | Nick Mathewson <nickm@torproject.org> | 2014-04-02 11:49:18 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2014-04-02 15:38:00 -0400 |
commit | 4215c801ffc11f19949be3da2d46158664f0bf97 (patch) | |
tree | c58005130f4b2c763efa1b23192623d243e958f6 | |
parent | c230ff4ca97ae6bf8ddbf2d19a1a7d33371cde3a (diff) | |
download | tor-4215c801ffc11f19949be3da2d46158664f0bf97.tar tor-4215c801ffc11f19949be3da2d46158664f0bf97.tar.gz |
Tests for resolved_cell_parse
-rw-r--r-- | src/test/test_cell_formats.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index 55d8d0f00..b0eb2fca2 100644 --- a/src/test/test_cell_formats.c +++ b/src/test/test_cell_formats.c @@ -872,6 +872,346 @@ test_cfmt_extended_cells(void *arg) tor_free(mem_op_hex_tmp); } +static void +test_cfmt_resolved_cells(void *arg) +{ + smartlist_t *addrs = smartlist_new(); + relay_header_t rh; + cell_t cell; + int r, errcode; + address_ttl_t *a; + + (void)arg; +#define CLEAR_CELL() do { \ + memset(&cell, 0, sizeof(cell)); \ + memset(&rh, 0, sizeof(rh)); \ + } while (0) +#define CLEAR_ADDRS() do { \ + SMARTLIST_FOREACH(addrs, address_ttl_t *, a, \ + address_ttl_free(a); ); \ + smartlist_clear(addrs); \ + } while (0) +#define SET_CELL(s) do { \ + CLEAR_CELL(); \ + memcpy(cell.payload + RELAY_HEADER_SIZE, (s), sizeof((s))-1); \ + rh.length = sizeof((s))-1; \ + rh.command = RELAY_COMMAND_RESOLVED; \ + errcode = -1; \ + } while (0) + + /* The cell format is one or more answers; each of the form + * type [1 byte---0:hostname, 4:ipv4, 6:ipv6, f0:err-transient, f1:err] + * length [1 byte] + * body [length bytes] + * ttl [4 bytes] + */ + + /* Let's try an empty cell */ + SET_CELL(""); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 0); + CLEAR_ADDRS(); /* redundant but let's be consistent */ + + /* Cell with one ipv4 addr */ + SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00"); + tt_int_op(rh.length, ==, 10); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 1); + a = smartlist_get(addrs, 0); + tt_str_op(fmt_addr(&a->addr), ==, "127.0.2.10"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 256); + CLEAR_ADDRS(); + + /* Cell with one ipv6 addr */ + SET_CELL("\x06\x10" + "\x20\x02\x90\x90\x00\x00\x00\x00" + "\x00\x00\x00\x00\xf0\xf0\xab\xcd" + "\x02\00\x00\x01"); + tt_int_op(rh.length, ==, 22); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 1); + a = smartlist_get(addrs, 0); + tt_str_op(fmt_addr(&a->addr), ==, "2002:9090::f0f0:abcd"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 0x2000001); + CLEAR_ADDRS(); + + /* Cell with one hostname */ + SET_CELL("\x00\x11" + "motherbrain.zebes" + "\x00\00\x00\x00"); + tt_int_op(rh.length, ==, 23); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 1); + a = smartlist_get(addrs, 0); + tt_assert(tor_addr_is_null(&a->addr)); + tt_str_op(a->hostname, ==, "motherbrain.zebes"); + tt_int_op(a->ttl, ==, 0); + CLEAR_ADDRS(); + +#define LONG_NAME \ + "this-hostname-has-255-characters.in-order-to-test-whether-very-long.ho" \ + "stnames-are-accepted.i-am-putting-it-in-a-macro-because-although.this-" \ + "function-is-already-very-full.of-copy-and-pasted-stuff.having-this-app" \ + "ear-more-than-once-would-bother-me-somehow.is" + + tt_int_op(strlen(LONG_NAME), ==, 255); + SET_CELL("\x00\xff" + LONG_NAME + "\x00\01\x00\x00"); + tt_int_op(rh.length, ==, 261); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 1); + a = smartlist_get(addrs, 0); + tt_assert(tor_addr_is_null(&a->addr)); + tt_str_op(a->hostname, ==, LONG_NAME); + tt_int_op(a->ttl, ==, 65536); + CLEAR_ADDRS(); + + /* Cells with an error */ + SET_CELL("\xf0\x2b" + "I'm sorry, Dave. I'm afraid I can't do that" + "\x00\x11\x22\x33"); + tt_int_op(rh.length, ==, 49); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, RESOLVED_TYPE_ERROR_TRANSIENT); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 0); + CLEAR_ADDRS(); + + SET_CELL("\xf1\x40" + "This hostname is too important for me to allow you to resolve it" + "\x00\x00\x00\x00"); + tt_int_op(rh.length, ==, 70); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, RESOLVED_TYPE_ERROR); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 0); + CLEAR_ADDRS(); + + /* Cell with an unrecognized type */ + SET_CELL("\xee\x16" + "fault in the AE35 unit" + "\x09\x09\x01\x01"); + tt_int_op(rh.length, ==, 28); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 0); + CLEAR_ADDRS(); + + /* Cell with one of each */ + SET_CELL(/* unrecognized: */ + "\xee\x16" + "fault in the AE35 unit" + "\x09\x09\x01\x01" + /* error: */ + "\xf0\x2b" + "I'm sorry, Dave. I'm afraid I can't do that" + "\x00\x11\x22\x33" + /* IPv6: */ + "\x06\x10" + "\x20\x02\x90\x90\x00\x00\x00\x00" + "\x00\x00\x00\x00\xf0\xf0\xab\xcd" + "\x02\00\x00\x01" + /* IPv4: */ + "\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" + /* Hostname: */ + "\x00\x11" + "motherbrain.zebes" + "\x00\00\x00\x00" + ); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); /* no error reported; we got answers */ + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 3); + a = smartlist_get(addrs, 0); + tt_str_op(fmt_addr(&a->addr), ==, "2002:9090::f0f0:abcd"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 0x2000001); + a = smartlist_get(addrs, 1); + tt_str_op(fmt_addr(&a->addr), ==, "127.0.2.10"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 256); + a = smartlist_get(addrs, 2); + tt_assert(tor_addr_is_null(&a->addr)); + tt_str_op(a->hostname, ==, "motherbrain.zebes"); + tt_int_op(a->ttl, ==, 0); + CLEAR_ADDRS(); + + /* Cell with several of similar type */ + SET_CELL(/* IPv4 */ + "\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" + "\x04\x04" "\x08\x08\x08\x08" "\x00\00\x01\x05" + "\x04\x04" "\x7f\xb0\x02\xb0" "\x00\01\xff\xff" + /* IPv6 */ + "\x06\x10" + "\x20\x02\x90\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\xca\xfe\xf0\x0d" + "\x00\00\x00\x01" + "\x06\x10" + "\x20\x02\x90\x01\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\xfa\xca\xde" + "\x00\00\x00\x03"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 5); + a = smartlist_get(addrs, 0); + tt_str_op(fmt_addr(&a->addr), ==, "127.0.2.10"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 256); + a = smartlist_get(addrs, 1); + tt_str_op(fmt_addr(&a->addr), ==, "8.8.8.8"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 261); + a = smartlist_get(addrs, 2); + tt_str_op(fmt_addr(&a->addr), ==, "127.176.2.176"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 131071); + a = smartlist_get(addrs, 3); + tt_str_op(fmt_addr(&a->addr), ==, "2002:9000::cafe:f00d"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 1); + a = smartlist_get(addrs, 4); + tt_str_op(fmt_addr(&a->addr), ==, "2002:9001::fa:cade"); + tt_ptr_op(a->hostname, ==, NULL); + tt_int_op(a->ttl, ==, 3); + CLEAR_ADDRS(); + + /* Full cell */ +#define LONG_NAME2 \ + "this-name-has-231-characters.so-that-it-plus-LONG_NAME-can-completely-" \ + "fill-up-the-payload-of-a-cell.its-important-to-check-for-the-full-thin" \ + "g-case.to-avoid-off-by-one-errors.where-full-things-are-misreported-as" \ + ".overflowing-by-one.z" + + tt_int_op(strlen(LONG_NAME2), ==, 231); + SET_CELL("\x00\xff" + LONG_NAME + "\x00\01\x00\x00" + "\x00\xe7" + LONG_NAME2 + "\x00\01\x00\x00"); + tt_int_op(rh.length, ==, RELAY_PAYLOAD_SIZE); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, 0); + tt_int_op(smartlist_len(addrs), ==, 2); + a = smartlist_get(addrs, 0); + tt_str_op(a->hostname, ==, LONG_NAME); + a = smartlist_get(addrs, 1); + tt_str_op(a->hostname, ==, LONG_NAME2); + CLEAR_ADDRS(); + + /* BAD CELLS */ + + /* Invalid length on an IPv4 */ + SET_CELL("\x04\x03zzz1234"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" + "\x04\x05zzzzz1234"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + /* Invalid length on an IPv6 */ + SET_CELL("\x06\x03zzz1234"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" + "\x06\x17wwwwwwwwwwwwwwwww1234"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" + "\x06\x10xxxx"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + /* Empty hostname */ + SET_CELL("\x00\x00xxxx"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + /* rh.length out of range */ + CLEAR_CELL(); + rh.length = 499; + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(errcode, ==, 0); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + /* Item length extends beyond rh.length */ + CLEAR_CELL(); + SET_CELL("\x00\xff" + LONG_NAME + "\x00\01\x00\x00"); + rh.length -= 1; + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + rh.length -= 5; + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00"); + rh.length -= 1; + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + SET_CELL("\xee\x10" + "\x20\x02\x90\x01\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\xfa\xca\xde" + "\x00\00\x00\x03"); + rh.length -= 1; + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + /* Truncated item after first character */ + SET_CELL("\x04"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + SET_CELL("\xee"); + r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(r, ==, -1); + tt_int_op(smartlist_len(addrs), ==, 0); + + done: + CLEAR_ADDRS(); + CLEAR_CELL(); + smartlist_free(addrs); +#undef CLEAR_ADDRS +#undef CLEAR_CELL +} + #define TEST(name, flags) \ { #name, test_cfmt_ ## name, flags, 0, NULL } @@ -883,6 +1223,7 @@ struct testcase_t cell_format_tests[] = { TEST(created_cells, 0), TEST(extend_cells, 0), TEST(extended_cells, 0), + TEST(resolved_cells, 0), END_OF_TESTCASES }; |