Commit 526eec8b authored by Johan Sternerup's avatar Johan Sternerup

Don't try to use link-local addresses outside local network

If we have gathered a host IP-address that is link-local we should
never try to use it for anything else than trying to match it with
another link-local address. Some routers seem to have problems with
traffic from link-local addresses destined at external IP-addresses.
By definition link-local addresses should stay local so there's no
reason to access STUN/TURN from it or try to form a candidate with
another address that is not link-local.
parent 64271494
...@@ -356,6 +356,37 @@ nice_address_is_private (const NiceAddress *a) ...@@ -356,6 +356,37 @@ nice_address_is_private (const NiceAddress *a)
} }
static gboolean
ipv4_address_is_linklocal (guint32 addr)
{
addr = ntohl (addr);
return (addr & 0xffff0000) == 0xa9fe0000;
}
static gboolean
ipv6_address_is_linklocal (const guchar *addr)
{
return (addr[0] == 0xfe) && ((addr[1] & 0xc0) == 0x80);
}
NICEAPI_EXPORT gboolean
nice_address_is_linklocal (const NiceAddress *a)
{
switch (a->s.addr.sa_family)
{
case AF_INET:
return ipv4_address_is_linklocal (a->s.ip4.sin_addr.s_addr);
case AF_INET6:
return ipv6_address_is_linklocal (a->s.ip6.sin6_addr.s6_addr);
default:
g_return_val_if_reached (FALSE);
}
}
NICEAPI_EXPORT gboolean NICEAPI_EXPORT gboolean
nice_address_is_valid (const NiceAddress *a) nice_address_is_valid (const NiceAddress *a)
{ {
......
...@@ -277,6 +277,19 @@ nice_address_to_string (const NiceAddress *addr, gchar *dst); ...@@ -277,6 +277,19 @@ nice_address_to_string (const NiceAddress *addr, gchar *dst);
gboolean gboolean
nice_address_is_private (const NiceAddress *addr); nice_address_is_private (const NiceAddress *addr);
/**
* nice_address_is_linklocal:
* @addr: The #NiceAddress to query
*
* Verifies if the address in @addr is a link-local address or not
*
* Returns: %TRUE if @addr is a link-local address, %FALSE otherwise
*
* Since: 0.1.19
*/
gboolean
nice_address_is_linklocal (const NiceAddress *addr);
/** /**
* nice_address_is_valid: * nice_address_is_valid:
* @addr: The #NiceAddress to query * @addr: The #NiceAddress to query
......
...@@ -3455,6 +3455,7 @@ nice_agent_gather_candidates ( ...@@ -3455,6 +3455,7 @@ nice_agent_gather_candidates (
/* TODO: Add server-reflexive support for TCP candidates */ /* TODO: Add server-reflexive support for TCP candidates */
if (agent->full_mode && agent->stun_server_ip && !agent->force_relay && if (agent->full_mode && agent->stun_server_ip && !agent->force_relay &&
!nice_address_is_linklocal (addr) &&
transport == NICE_CANDIDATE_TRANSPORT_UDP) { transport == NICE_CANDIDATE_TRANSPORT_UDP) {
NiceAddress stun_server; NiceAddress stun_server;
if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) { if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) {
...@@ -3470,7 +3471,7 @@ nice_agent_gather_candidates ( ...@@ -3470,7 +3471,7 @@ nice_agent_gather_candidates (
} }
} }
if (agent->full_mode && component && if (agent->full_mode && component && !nice_address_is_linklocal (addr) &&
transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) { transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
GList *item; GList *item;
int host_ip_version = nice_address_ip_version (&host_candidate->c.addr); int host_ip_version = nice_address_ip_version (&host_candidate->c.addr);
......
...@@ -2432,6 +2432,12 @@ static CandidateCheckPair *priv_conn_check_add_for_candidate_pair_matched ( ...@@ -2432,6 +2432,12 @@ static CandidateCheckPair *priv_conn_check_add_for_candidate_pair_matched (
return pair; return pair;
} }
static gboolean
_is_linklocal_to_non_linklocal (NiceAddress *laddr, NiceAddress *raddr)
{
return nice_address_is_linklocal (laddr) != nice_address_is_linklocal (raddr);
}
gboolean conn_check_add_for_candidate_pair (NiceAgent *agent, gboolean conn_check_add_for_candidate_pair (NiceAgent *agent,
guint stream_id, NiceComponent *component, NiceCandidate *local, guint stream_id, NiceComponent *component, NiceCandidate *local,
NiceCandidate *remote) NiceCandidate *remote)
...@@ -2458,9 +2464,11 @@ gboolean conn_check_add_for_candidate_pair (NiceAgent *agent, ...@@ -2458,9 +2464,11 @@ gboolean conn_check_add_for_candidate_pair (NiceAgent *agent,
return FALSE; return FALSE;
} }
/* note: match pairs only if transport and address family are the same */ /* note: match pairs only if transport and address family are the same
* and make sure link-local stay link-local */
if (local->transport == conn_check_match_transport (remote->transport) && if (local->transport == conn_check_match_transport (remote->transport) &&
local->addr.s.addr.sa_family == remote->addr.s.addr.sa_family) { local->addr.s.addr.sa_family == remote->addr.s.addr.sa_family &&
!_is_linklocal_to_non_linklocal (&local->addr, &remote->addr)) {
if (priv_conn_check_add_for_candidate_pair_matched (agent, stream_id, if (priv_conn_check_add_for_candidate_pair_matched (agent, stream_id,
component, local, remote, NICE_CHECK_FROZEN)) component, local, remote, NICE_CHECK_FROZEN))
ret = TRUE; ret = TRUE;
......
...@@ -143,6 +143,7 @@ nice_address_equal ...@@ -143,6 +143,7 @@ nice_address_equal
nice_address_equal_no_port nice_address_equal_no_port
nice_address_to_string nice_address_to_string
nice_address_is_private nice_address_is_private
nice_address_is_linklocal
nice_address_is_valid nice_address_is_valid
nice_address_ip_version nice_address_ip_version
</SECTION> </SECTION>
......
...@@ -151,6 +151,40 @@ test_ipv4 (void) ...@@ -151,6 +151,40 @@ test_ipv4 (void)
nice_address_free (heap_addr); nice_address_free (heap_addr);
} }
/* test link-local address check */
{
NiceAddress *heap_addr = nice_address_new ();
g_assert_true (nice_address_set_from_string(heap_addr, "169.253.255.255"));
g_assert_true (nice_address_is_linklocal (heap_addr) == FALSE);
g_assert_true (nice_address_set_from_string(heap_addr, "169.254.0.0"));
g_assert_true (nice_address_is_linklocal (heap_addr) == TRUE);
g_assert_true (nice_address_set_from_string(heap_addr, "169.254.255.255"));
g_assert_true (nice_address_is_linklocal (heap_addr) == TRUE);
g_assert_true (nice_address_set_from_string (heap_addr, "127.0.0.1"));
g_assert_true (nice_address_is_linklocal (heap_addr) == FALSE);
g_assert_true (nice_address_set_from_string(heap_addr, "172.31.255.255"));
g_assert_true (nice_address_is_linklocal (heap_addr) == FALSE);
g_assert_true (nice_address_set_from_string(heap_addr, "192.168.15.69"));
g_assert_true (nice_address_is_linklocal (heap_addr) == FALSE);
g_assert_true (nice_address_set_from_string(heap_addr, "fe70::0"));
g_assert_true (nice_address_is_linklocal (heap_addr) == FALSE);
g_assert_true (nice_address_set_from_string(heap_addr, "fe80::0"));
g_assert_true (nice_address_is_linklocal (heap_addr) == TRUE);
g_assert_true (nice_address_set_from_string(heap_addr, "fe81::0"));
g_assert_true (nice_address_is_linklocal (heap_addr) == TRUE);
nice_address_free (heap_addr);
}
} }
static void static void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment