Share private addresses during stun traversal

This commit is contained in:
Jeremy Lakeman 2014-09-26 12:52:38 +09:30 committed by Jeremy Lakeman
parent 73c2c9e6fe
commit 568f431d91
2 changed files with 97 additions and 23 deletions

View File

@ -305,10 +305,6 @@ int overlay_mdp_service_stun(struct internal_mdp_header *header, struct overlay_
}
int overlay_send_stun_request(struct subscriber *server, struct subscriber *request){
if ((!server) || (!request))
return -1;
if (!(server->reachable&REACHABLE))
return -1;
// don't bother with a stun request if the peer is already reachable directly
if (request->reachable&REACHABLE_DIRECT)
return -1;
@ -318,27 +314,67 @@ int overlay_send_stun_request(struct subscriber *server, struct subscriber *requ
return -1;
request->last_stun_request=now;
struct internal_mdp_header header;
bzero(&header, sizeof header);
header.source = my_subscriber;
header.destination = server;
header.source_port = MDP_PORT_STUN;
header.destination_port = MDP_PORT_STUNREQ;
header.qos = OQ_MESH_MANAGEMENT;
struct overlay_buffer *payload = ob_new();
ob_limitsize(payload, MDP_MTU);
overlay_address_append(NULL, payload, request);
if (!ob_overrun(payload)) {
if (config.debug.overlayrouting)
DEBUGF("Sending STUN request to %s", alloca_tohex_sid_t(server->sid));
// If two people are behind the same NAT, but can't hear broadcast packets
// and the NAT doesn't allow internal packets to bounce back based on public addresses
// we need to tell the remote party all of our private addresses
// so we can send them an unrequested stun response to provoke a probe packet
if (request->reachable&REACHABLE || (server && server->reachable & REACHABLE)){
struct internal_mdp_header header;
bzero(&header, sizeof header);
header.source = my_subscriber;
header.destination = request;
header.source_port = MDP_PORT_STUNREQ;
header.destination_port = MDP_PORT_STUN;
header.qos = OQ_MESH_MANAGEMENT;
struct overlay_buffer *payload = ob_new();
ob_limitsize(payload, MDP_MTU);
unsigned i;
for (i=0;i<OVERLAY_MAX_INTERFACES;i++){
if (overlay_interfaces[i].state == INTERFACE_STATE_UP
&& overlay_interfaces[i].address.addr.sa_family == AF_INET){
overlay_address_append(NULL, payload, my_subscriber);
ob_append_ui32(payload, overlay_interfaces[i].address.inet.sin_addr.s_addr);
ob_append_ui16(payload, overlay_interfaces[i].address.inet.sin_port);
if (ob_overrun(payload)){
ob_rewind(payload);
break;
}
ob_checkpoint(payload);
}
}
ob_flip(payload);
if (config.debug.overlayrouting)
DEBUGF("Sending STUN response to %s for my private addresses", alloca_tohex_sid_t(request->sid));
overlay_send_frame(&header, payload);
ob_free(payload);
}
if (server && server->reachable & REACHABLE){
struct internal_mdp_header header;
bzero(&header, sizeof header);
header.source = my_subscriber;
header.destination = server;
header.source_port = MDP_PORT_STUN;
header.destination_port = MDP_PORT_STUNREQ;
header.qos = OQ_MESH_MANAGEMENT;
struct overlay_buffer *payload = ob_new();
ob_limitsize(payload, MDP_MTU);
overlay_address_append(NULL, payload, request);
if (!ob_overrun(payload)) {
if (config.debug.overlayrouting)
DEBUGF("Sending STUN request to %s", alloca_tohex_sid_t(server->sid));
ob_flip(payload);
overlay_send_frame(&header, payload);
}
ob_free(payload);
}
ob_free(payload);
return 0;
}

View File

@ -190,4 +190,42 @@ test_concurrent() {
tfw_cat A_OUT B_OUT C_OUT D_OUT E_OUT
}
doc_stun="Setup a unicast link during call establishment"
setup_stun() {
configure_servald_server() {
executeOk_servald config \
set debug.overlayrouting on \
set debug.linkstate on \
set debug.verbose on \
set vomp.dial_timeout_ms 1000 \
set vomp.ring_timeout_ms 5000 \
set vomp.network_timeout_ms 5000 \
set log.console.level DEBUG \
set log.console.show_time on
}
setup_servald
assert_no_servald_processes
foreach_instance +A +B +C create_single_identity
foreach_instance +A +B +C add_servald_interface --file 1
foreach_instance +A +B \
executeOk_servald config \
set interfaces.1.drop_broadcasts on
start_servald_instances +A +B +C
}
has_unicast_link() {
executeOk_servald route print
tfw_cat --stdout
if ! grep "^${SIDB}:UNICAST:dummy1:0*\$" $_tfw_tmp/stdout; then
return 1
fi
}
test_stun() {
set_instance +A
executeOk_servald route print
assertGrep --matches=1 $_tfw_tmp/stdout "^${SIDB}:INDIRECT::${SIDC}\$"
test_call_lifecycle
set_instance +A
wait_until --timeout=10 has_unicast_link
}
runTests "$@"