mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-11 05:03:34 +01:00
Get the client side of receiving an IPv6 address to work
This makes it so we can handle getting an IPv6 in the 3 different formats we specified it for in RESOLVED cells, END_STREAM_REASON_EXITPOLICY cells, and CONNECTED cells. We don't cache IPv6 addresses yet, since proposal 205 isn't implemented. There's a refactored function for parsing connected cells; it has unit tests.
This commit is contained in:
parent
93dc7dcf41
commit
cac5335195
@ -576,10 +576,7 @@ client_dns_set_addressmap_impl(origin_circuit_t *on_circ,
|
|||||||
const char *exitname,
|
const char *exitname,
|
||||||
int ttl)
|
int ttl)
|
||||||
{
|
{
|
||||||
/* <address>.<hex or nickname>.exit\0 or just <address>\0 */
|
char *extendedaddress=NULL, *extendedval=NULL;
|
||||||
char extendedaddress[MAX_SOCKS_ADDR_LEN+MAX_VERBOSE_NICKNAME_LEN+10];
|
|
||||||
/* 123.123.123.123.<hex or nickname>.exit\0 or just 123.123.123.123\0 */
|
|
||||||
char extendedval[INET_NTOA_BUF_LEN+MAX_VERBOSE_NICKNAME_LEN+10];
|
|
||||||
(void)on_circ;
|
(void)on_circ;
|
||||||
|
|
||||||
tor_assert(address);
|
tor_assert(address);
|
||||||
@ -594,18 +591,19 @@ client_dns_set_addressmap_impl(origin_circuit_t *on_circ,
|
|||||||
/* XXXX fails to ever get attempts to get an exit address of
|
/* XXXX fails to ever get attempts to get an exit address of
|
||||||
* google.com.digest[=~]nickname.exit; we need a syntax for this that
|
* google.com.digest[=~]nickname.exit; we need a syntax for this that
|
||||||
* won't make strict RFC952-compliant applications (like us) barf. */
|
* won't make strict RFC952-compliant applications (like us) barf. */
|
||||||
tor_snprintf(extendedaddress, sizeof(extendedaddress),
|
tor_asprintf(&extendedaddress,
|
||||||
"%s.%s.exit", address, exitname);
|
"%s.%s.exit", address, exitname);
|
||||||
tor_snprintf(extendedval, sizeof(extendedval),
|
tor_asprintf(&extendedval,
|
||||||
"%s.%s.exit", name, exitname);
|
"%s.%s.exit", name, exitname);
|
||||||
} else {
|
} else {
|
||||||
tor_snprintf(extendedaddress, sizeof(extendedaddress),
|
tor_asprintf(&extendedaddress,
|
||||||
"%s", address);
|
"%s", address);
|
||||||
tor_snprintf(extendedval, sizeof(extendedval),
|
tor_asprintf(&extendedval,
|
||||||
"%s", name);
|
"%s", name);
|
||||||
}
|
}
|
||||||
addressmap_register(extendedaddress, tor_strdup(extendedval),
|
addressmap_register(extendedaddress, extendedval,
|
||||||
time(NULL) + ttl, ADDRMAPSRC_DNS, 0, 0);
|
time(NULL) + ttl, ADDRMAPSRC_DNS, 0, 0);
|
||||||
|
tor_free(extendedaddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Record the fact that <b>address</b> resolved to <b>val</b>.
|
/** Record the fact that <b>address</b> resolved to <b>val</b>.
|
||||||
@ -620,19 +618,26 @@ client_dns_set_addressmap_impl(origin_circuit_t *on_circ,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
client_dns_set_addressmap(origin_circuit_t *on_circ,
|
client_dns_set_addressmap(origin_circuit_t *on_circ,
|
||||||
const char *address, uint32_t val,
|
const char *address,
|
||||||
|
const tor_addr_t *val,
|
||||||
const char *exitname,
|
const char *exitname,
|
||||||
int ttl)
|
int ttl)
|
||||||
{
|
{
|
||||||
struct in_addr in;
|
tor_addr_t addr_tmp;
|
||||||
char valbuf[INET_NTOA_BUF_LEN];
|
char valbuf[TOR_ADDR_BUF_LEN];
|
||||||
|
|
||||||
tor_assert(address);
|
tor_assert(address);
|
||||||
|
tor_assert(val);
|
||||||
|
|
||||||
if (tor_inet_aton(address, &in))
|
if (tor_addr_parse(&addr_tmp, address) == 0)
|
||||||
return; /* If address was an IP address already, don't add a mapping. */
|
return; /* If address was an IP address already, don't add a mapping. */
|
||||||
in.s_addr = htonl(val);
|
|
||||||
tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
|
/* XXXXX For now, don't cache IPv6 addresses. */
|
||||||
|
if (tor_addr_family(val) != AF_INET)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (! tor_addr_to_str(valbuf, val, sizeof(valbuf), 0)) /* XXXX decorate? */
|
||||||
|
return;
|
||||||
|
|
||||||
client_dns_set_addressmap_impl(on_circ, address, valbuf, exitname, ttl);
|
client_dns_set_addressmap_impl(on_circ, address, valbuf, exitname, ttl);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ int parse_virtual_addr_network(const char *val, int validate_only,
|
|||||||
int client_dns_incr_failures(const char *address);
|
int client_dns_incr_failures(const char *address);
|
||||||
void client_dns_clear_failures(const char *address);
|
void client_dns_clear_failures(const char *address);
|
||||||
void client_dns_set_addressmap(origin_circuit_t *on_circ,
|
void client_dns_set_addressmap(origin_circuit_t *on_circ,
|
||||||
const char *address, uint32_t val,
|
const char *address, const tor_addr_t *val,
|
||||||
const char *exitname, int ttl);
|
const char *exitname, int ttl);
|
||||||
const char *addressmap_register_virtual_address(int type, char *new_address);
|
const char *addressmap_register_virtual_address(int type, char *new_address);
|
||||||
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
|
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
|
||||||
|
@ -1949,10 +1949,19 @@ connection_ap_handshake_socks_resolved(entry_connection_t *conn,
|
|||||||
if (CIRCUIT_IS_ORIGIN(circ)) /* should always be true */
|
if (CIRCUIT_IS_ORIGIN(circ)) /* should always be true */
|
||||||
origin_circ = TO_ORIGIN_CIRCUIT(circ);
|
origin_circ = TO_ORIGIN_CIRCUIT(circ);
|
||||||
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
|
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
|
||||||
uint32_t a = ntohl(get_uint32(answer));
|
tor_addr_t a;
|
||||||
if (a) {
|
tor_addr_from_ipv4n(&a, get_uint32(answer));
|
||||||
|
if (! tor_addr_is_null(&a)) {
|
||||||
client_dns_set_addressmap(origin_circ,
|
client_dns_set_addressmap(origin_circ,
|
||||||
conn->socks_request->address, a,
|
conn->socks_request->address, &a,
|
||||||
|
conn->chosen_exit_name, ttl);
|
||||||
|
}
|
||||||
|
} else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
|
||||||
|
tor_addr_t a;
|
||||||
|
tor_addr_from_ipv6_bytes(&a, (char*)answer);
|
||||||
|
if (! tor_addr_is_null(&a)) {
|
||||||
|
client_dns_set_addressmap(origin_circ,
|
||||||
|
conn->socks_request->address, &a,
|
||||||
conn->chosen_exit_name, ttl);
|
conn->chosen_exit_name, ttl);
|
||||||
}
|
}
|
||||||
} else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
|
} else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
|
||||||
|
@ -108,6 +108,7 @@ typedef struct begin_cell_t {
|
|||||||
|
|
||||||
int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
|
int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
|
||||||
uint8_t *end_reason_out);
|
uint8_t *end_reason_out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
134
src/or/relay.c
134
src/or/relay.c
@ -705,21 +705,37 @@ connection_ap_process_end_not_open(
|
|||||||
switch (reason) {
|
switch (reason) {
|
||||||
case END_STREAM_REASON_EXITPOLICY:
|
case END_STREAM_REASON_EXITPOLICY:
|
||||||
if (rh->length >= 5) {
|
if (rh->length >= 5) {
|
||||||
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
|
tor_addr_t addr;
|
||||||
int ttl;
|
int ttl = -1;
|
||||||
if (!addr) {
|
tor_addr_make_unspec(&addr);
|
||||||
|
if (rh->length == 5 || rh->length == 9) {
|
||||||
|
tor_addr_from_ipv4n(&addr,
|
||||||
|
get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
|
||||||
|
if (rh->length == 9)
|
||||||
|
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5));
|
||||||
|
} else if (rh->length == 17 || rh->length == 21) {
|
||||||
|
tor_addr_from_ipv6_bytes(&addr,
|
||||||
|
(char*)(cell->payload+RELAY_HEADER_SIZE+1));
|
||||||
|
if (rh->length == 21)
|
||||||
|
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+17));
|
||||||
|
}
|
||||||
|
if (tor_addr_is_null(&addr)) {
|
||||||
log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,",
|
log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,",
|
||||||
safe_str(conn->socks_request->address));
|
safe_str(conn->socks_request->address));
|
||||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (rh->length >= 9)
|
|
||||||
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5));
|
|
||||||
else
|
|
||||||
ttl = -1;
|
|
||||||
|
|
||||||
|
if ((tor_addr_family(&addr) == AF_INET && !conn->ipv4_traffic_ok) ||
|
||||||
|
(tor_addr_family(&addr) == AF_INET6 && !conn->ipv6_traffic_ok)) {
|
||||||
|
log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
||||||
|
"Got an EXITPOLICY failure on a connection with a "
|
||||||
|
"mismatched family. Closing.");
|
||||||
|
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (get_options()->ClientDNSRejectInternalAddresses &&
|
if (get_options()->ClientDNSRejectInternalAddresses &&
|
||||||
is_internal_IP(addr, 0)) {
|
tor_addr_is_internal(&addr, 0)) {
|
||||||
log_info(LD_APP,"Address '%s' resolved to internal. Closing,",
|
log_info(LD_APP,"Address '%s' resolved to internal. Closing,",
|
||||||
safe_str(conn->socks_request->address));
|
safe_str(conn->socks_request->address));
|
||||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||||
@ -727,7 +743,7 @@ connection_ap_process_end_not_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
client_dns_set_addressmap(circ,
|
client_dns_set_addressmap(circ,
|
||||||
conn->socks_request->address, addr,
|
conn->socks_request->address, &addr,
|
||||||
conn->chosen_exit_name, ttl);
|
conn->chosen_exit_name, ttl);
|
||||||
}
|
}
|
||||||
/* check if he *ought* to have allowed it */
|
/* check if he *ought* to have allowed it */
|
||||||
@ -830,20 +846,56 @@ connection_ap_process_end_not_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Helper: change the socks_request->address field on conn to the
|
/** Helper: change the socks_request->address field on conn to the
|
||||||
* dotted-quad representation of <b>new_addr</b> (given in host order),
|
* dotted-quad representation of <b>new_addr</b>,
|
||||||
* and send an appropriate REMAP event. */
|
* and send an appropriate REMAP event. */
|
||||||
static void
|
static void
|
||||||
remap_event_helper(entry_connection_t *conn, uint32_t new_addr)
|
remap_event_helper(entry_connection_t *conn, const tor_addr_t *new_addr)
|
||||||
{
|
{
|
||||||
struct in_addr in;
|
tor_addr_to_str(conn->socks_request->address, new_addr,
|
||||||
|
sizeof(conn->socks_request->address),
|
||||||
in.s_addr = htonl(new_addr);
|
0); /* XXXXX Should decorate be 1? */
|
||||||
tor_inet_ntoa(&in, conn->socks_request->address,
|
|
||||||
sizeof(conn->socks_request->address));
|
|
||||||
control_event_stream_status(conn, STREAM_EVENT_REMAP,
|
control_event_stream_status(conn, STREAM_EVENT_REMAP,
|
||||||
REMAP_STREAM_SOURCE_EXIT);
|
REMAP_STREAM_SOURCE_EXIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**DOCDOC*/
|
||||||
|
int
|
||||||
|
connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
|
||||||
|
tor_addr_t *addr_out, int *ttl_out)
|
||||||
|
{
|
||||||
|
uint32_t bytes;
|
||||||
|
const uint8_t *payload = cell->payload + RELAY_HEADER_SIZE;
|
||||||
|
|
||||||
|
tor_addr_make_unspec(addr_out);
|
||||||
|
*ttl_out = -1;
|
||||||
|
if (rh->length == 0)
|
||||||
|
return 0;
|
||||||
|
if (rh->length < 4)
|
||||||
|
return -1;
|
||||||
|
bytes = ntohl(get_uint32(payload));
|
||||||
|
|
||||||
|
/* If bytes is 0, this is maybe a v6 address. Otherwise it's a v4 address */
|
||||||
|
if (bytes != 0) {
|
||||||
|
/* v4 address */
|
||||||
|
tor_addr_from_ipv4h(addr_out, bytes);
|
||||||
|
if (rh->length >= 8) {
|
||||||
|
bytes = ntohl(get_uint32(payload + 4));
|
||||||
|
if (bytes <= INT32_MAX)
|
||||||
|
*ttl_out = bytes;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rh->length < 25) /* 4 bytes of 0s, 1 addr, 16 ipv4, 4 ttl. */
|
||||||
|
return -1;
|
||||||
|
if (get_uint8(payload + 4) != 6)
|
||||||
|
return -1;
|
||||||
|
tor_addr_from_ipv6_bytes(addr_out, (char*)(payload + 5));
|
||||||
|
bytes = ntohl(get_uint32(payload + 21));
|
||||||
|
if (bytes <= INT32_MAX)
|
||||||
|
*ttl_out = (int) bytes;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** An incoming relay cell has arrived from circuit <b>circ</b> to
|
/** An incoming relay cell has arrived from circuit <b>circ</b> to
|
||||||
* stream <b>conn</b>.
|
* stream <b>conn</b>.
|
||||||
*
|
*
|
||||||
@ -874,6 +926,8 @@ connection_edge_process_relay_cell_not_open(
|
|||||||
|
|
||||||
if (conn->base_.type == CONN_TYPE_AP &&
|
if (conn->base_.type == CONN_TYPE_AP &&
|
||||||
rh->command == RELAY_COMMAND_CONNECTED) {
|
rh->command == RELAY_COMMAND_CONNECTED) {
|
||||||
|
tor_addr_t addr;
|
||||||
|
int ttl;
|
||||||
entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
|
entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
|
||||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||||
if (conn->base_.state != AP_CONN_STATE_CONNECT_WAIT) {
|
if (conn->base_.state != AP_CONN_STATE_CONNECT_WAIT) {
|
||||||
@ -884,27 +938,41 @@ connection_edge_process_relay_cell_not_open(
|
|||||||
conn->base_.state = AP_CONN_STATE_OPEN;
|
conn->base_.state = AP_CONN_STATE_OPEN;
|
||||||
log_info(LD_APP,"'connected' received after %d seconds.",
|
log_info(LD_APP,"'connected' received after %d seconds.",
|
||||||
(int)(time(NULL) - conn->base_.timestamp_lastread));
|
(int)(time(NULL) - conn->base_.timestamp_lastread));
|
||||||
if (rh->length >= 4) {
|
if (connected_cell_parse(rh, cell, &addr, &ttl) < 0) {
|
||||||
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
|
log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
||||||
int ttl;
|
"Got a badly formatted connected cell. Closing.");
|
||||||
if (!addr || (get_options()->ClientDNSRejectInternalAddresses &&
|
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||||
is_internal_IP(addr, 0))) {
|
connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
|
||||||
|
}
|
||||||
|
if (tor_addr_family(&addr) != AF_UNSPEC) {
|
||||||
|
const sa_family_t family = tor_addr_family(&addr);
|
||||||
|
if (tor_addr_is_null(&addr) ||
|
||||||
|
(get_options()->ClientDNSRejectInternalAddresses &&
|
||||||
|
tor_addr_is_internal(&addr, 0))) {
|
||||||
log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
|
log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
|
||||||
fmt_addr32(addr));
|
fmt_addr(&addr));
|
||||||
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||||
connection_mark_unattached_ap(entry_conn,
|
connection_mark_unattached_ap(entry_conn,
|
||||||
END_STREAM_REASON_TORPROTOCOL);
|
END_STREAM_REASON_TORPROTOCOL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (rh->length >= 8)
|
|
||||||
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4));
|
if ((family == AF_INET && ! entry_conn->ipv4_traffic_ok) ||
|
||||||
else
|
(family == AF_INET6 && ! entry_conn->ipv6_traffic_ok)) {
|
||||||
ttl = -1;
|
log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
||||||
|
"Got a connected cell to %s with unsupported address family."
|
||||||
|
" Closing.", fmt_addr(&addr));
|
||||||
|
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||||
|
connection_mark_unattached_ap(entry_conn,
|
||||||
|
END_STREAM_REASON_TORPROTOCOL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
client_dns_set_addressmap(TO_ORIGIN_CIRCUIT(circ),
|
client_dns_set_addressmap(TO_ORIGIN_CIRCUIT(circ),
|
||||||
entry_conn->socks_request->address, addr,
|
entry_conn->socks_request->address, &addr,
|
||||||
entry_conn->chosen_exit_name, ttl);
|
entry_conn->chosen_exit_name, ttl);
|
||||||
|
|
||||||
remap_event_helper(entry_conn, addr);
|
remap_event_helper(entry_conn, &addr);
|
||||||
}
|
}
|
||||||
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
|
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
|
||||||
/* don't send a socks reply to transparent conns */
|
/* don't send a socks reply to transparent conns */
|
||||||
@ -994,8 +1062,14 @@ connection_edge_process_relay_cell_not_open(
|
|||||||
ttl,
|
ttl,
|
||||||
-1);
|
-1);
|
||||||
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
|
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
|
||||||
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
|
tor_addr_t addr;
|
||||||
remap_event_helper(entry_conn, addr);
|
tor_addr_from_ipv4n(&addr, get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
|
||||||
|
remap_event_helper(entry_conn, &addr);
|
||||||
|
} else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
|
||||||
|
tor_addr_t addr;
|
||||||
|
tor_addr_from_ipv6_bytes(&addr,
|
||||||
|
(char*)(cell->payload+RELAY_HEADER_SIZE+2));
|
||||||
|
remap_event_helper(entry_conn, &addr);
|
||||||
}
|
}
|
||||||
connection_mark_unattached_ap(entry_conn,
|
connection_mark_unattached_ap(entry_conn,
|
||||||
END_STREAM_REASON_DONE |
|
END_STREAM_REASON_DONE |
|
||||||
|
@ -68,6 +68,8 @@ void circuit_clear_cell_queue(circuit_t *circ, channel_t *chan);
|
|||||||
#ifdef RELAY_PRIVATE
|
#ifdef RELAY_PRIVATE
|
||||||
int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
|
int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
|
||||||
crypt_path_t **layer_hint, char *recognized);
|
crypt_path_t **layer_hint, char *recognized);
|
||||||
|
int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
|
||||||
|
tor_addr_t *addr_out, int *ttl_out);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "orconfig.h"
|
#include "orconfig.h"
|
||||||
|
|
||||||
#define CONNECTION_EDGE_PRIVATE
|
#define CONNECTION_EDGE_PRIVATE
|
||||||
|
#define RELAY_PRIVATE
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
#include "connection_edge.h"
|
#include "connection_edge.h"
|
||||||
#include "relay.h"
|
#include "relay.h"
|
||||||
@ -223,12 +224,125 @@ test_cfmt_begin_cells(void *arg)
|
|||||||
tor_free(bcell.address);
|
tor_free(bcell.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cfmt_connected_cells(void *arg)
|
||||||
|
{
|
||||||
|
relay_header_t rh;
|
||||||
|
cell_t cell;
|
||||||
|
tor_addr_t addr;
|
||||||
|
int ttl, r;
|
||||||
|
(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);
|
||||||
|
|
||||||
|
done:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
#define TEST(name, flags) \
|
#define TEST(name, flags) \
|
||||||
{ #name, test_cfmt_ ## name, flags, 0, NULL }
|
{ #name, test_cfmt_ ## name, flags, 0, NULL }
|
||||||
|
|
||||||
struct testcase_t cell_format_tests[] = {
|
struct testcase_t cell_format_tests[] = {
|
||||||
TEST(relay_header, 0),
|
TEST(relay_header, 0),
|
||||||
TEST(begin_cells, 0),
|
TEST(begin_cells, 0),
|
||||||
|
TEST(connected_cells, 0),
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user