[asterisk-commits] simon.perreault: branch group/v6-new r266573 - in /team/group/v6-new: channel...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon May 31 13:39:35 CDT 2010
Author: simon.perreault
Date: Mon May 31 13:39:32 2010
New Revision: 266573
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=266573
Log:
A bunch of fixes to the IPv6 code.
Future fixes will be committed individually.
Modified:
team/group/v6-new/channels/chan_sip.c
team/group/v6-new/include/asterisk/netsock2.h
team/group/v6-new/main/netsock2.c
team/group/v6-new/main/rtp_engine.c
Modified: team/group/v6-new/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/channels/chan_sip.c?view=diff&rev=266573&r1=266572&r2=266573
==============================================================================
--- team/group/v6-new/channels/chan_sip.c (original)
+++ team/group/v6-new/channels/chan_sip.c Mon May 31 13:39:32 2010
@@ -2991,7 +2991,7 @@
/*! \brief See if we pass debug IP filter */
static inline int sip_debug_test_addr(const struct ast_sockaddr *addr)
{
- return sipdebug && ast_sockaddr_isnull(addr) && !ast_sockaddr_cmp(&debugaddr, addr);
+ return sipdebug && !ast_sockaddr_isnull(addr) && !ast_sockaddr_cmp_addr(&debugaddr, addr);
}
/*! \brief The real destination address for a write */
@@ -9935,11 +9935,13 @@
snprintf(owner, sizeof(owner), "o=%s %d %d IN %s %s\r\n",
ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner,
p->sessionid, p->sessionversion,
- ast_sockaddr_is_ipv6(&dest) ? "IP6" : "IP4",
+ (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
+ "IP6" : "IP4",
ast_sockaddr_stringify_addr(&dest));
snprintf(connection, sizeof(connection), "c=IN %s %s\r\n",
- ast_sockaddr_is_ipv6(&dest) ? "IP6" : "IP4",
+ (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
+ "IP6" : "IP4",
ast_sockaddr_stringify_addr(&dest));
if (add_audio) {
@@ -16881,7 +16883,7 @@
if (ast_sockaddr_resolve_first(&debugaddr, arg, 0, 0))
return CLI_SHOWUSAGE;
- ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&debugaddr));
+ ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_sockaddr_stringify_addr(&debugaddr));
sipdebug |= sip_debug_console;
return CLI_SUCCESS;
@@ -16897,7 +16899,7 @@
ast_cli(fd, "Unable to get IP address of peer '%s'\n", arg);
else {
ast_sockaddr_copy(&debugaddr,&peer->addr);
- ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&debugaddr));
+ ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_sockaddr_stringify_addr(&debugaddr));
sipdebug |= sip_debug_console;
}
if (peer)
Modified: team/group/v6-new/include/asterisk/netsock2.h
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/include/asterisk/netsock2.h?view=diff&rev=266573&r1=266572&r2=266573
==============================================================================
--- team/group/v6-new/include/asterisk/netsock2.h (original)
+++ team/group/v6-new/include/asterisk/netsock2.h Mon May 31 13:39:32 2010
@@ -83,15 +83,13 @@
* Compares two socket addresses. Returns -1 if \a a is lexicographically
* smaller than \a b, 0 if they are equal, and 1 otherwise.
*/
-static inline int ast_sockaddr_cmp(const struct ast_sockaddr *a,
- const struct ast_sockaddr *b)
-{
- if (a->len < b->len)
- return -1;
- else if (a->len > b->len)
- return 1;
- return memcmp(&a->ss, &b->ss, a->len);
-}
+int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b);
+
+/**
+ * Compares two addresses. Returns -1 if \a a is lexicographically
+ * smaller than \a b, 0 if they are equal, and 1 otherwise.
+ */
+int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b);
/**
* Compares two addresses. Returns -1 if \a a is lexicographically
@@ -246,6 +244,14 @@
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr);
/**
+ * Returns 1 if this is an IPv4-mapped IPv6 address, 0 otherwise.
+ *
+ * \warning You should rarely need this function. Only use if you know what
+ * you're doing.
+ */
+int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr);
+
+/**
* Returns 1 if this is an IPv6 address, 0 otherwise. IPv4-mapped IPv6 addresses
* return 1.
*
@@ -253,6 +259,18 @@
* you're doing.
*/
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr);
+
+
+/**
+ * Returns 1 if this is an "any" address, such as 0.0.0.0 for IPv4 and :: for
+ * IPv6. The port number is ignored.
+ */
+int ast_sockaddr_is_any(const struct ast_sockaddr *addr);
+
+/**
+ * Computes a hash value from the address. The port is ignored.
+ */
+int ast_sockaddr_hash(const struct ast_sockaddr *addr);
/**
* Returns 1 if this is an "any" address, such as 0.0.0.0 for IPv4 and :: for
Modified: team/group/v6-new/main/netsock2.c
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/main/netsock2.c?view=diff&rev=266573&r1=266572&r2=266573
==============================================================================
--- team/group/v6-new/main/netsock2.c (original)
+++ team/group/v6-new/main/netsock2.c Mon May 31 13:39:32 2010
@@ -32,23 +32,55 @@
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
+static int ast_sockaddr_ipv4_mapped(const struct ast_sockaddr *addr, struct ast_sockaddr *ast_mapped)
+{
+ const struct sockaddr_in6 *sin6;
+ struct sockaddr_in sin4;
+
+ if(!ast_sockaddr_is_ipv6(addr))
+ return 0;
+
+ if(!ast_sockaddr_is_ipv4_mapped(addr))
+ return 0;
+
+ sin6 = (const struct sockaddr_in6*)&addr->ss;
+
+ memset(&sin4, 0, sizeof(sin4));
+ sin4.sin_family = AF_INET;
+ sin4.sin_port = sin6->sin6_port;
+ sin4.sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
+
+ *ast_mapped = ast_sockaddr_from_sin(sin4);
+
+ return 1;
+}
+
+
AST_THREADSTORAGE(ast_sockaddr_stringify_buf);
char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *sa, int format)
{
+ struct ast_sockaddr sa_ipv4;
+ const struct ast_sockaddr *sa_tmp;
char host[NI_MAXHOST];
char port[NI_MAXSERV];
char *str;
int e;
static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4;
+
if(ast_sockaddr_isnull(sa))
return "(null)";
if(!(str = ast_threadstorage_get(&ast_sockaddr_stringify_buf, size)))
return "";
- if ((e = getnameinfo((struct sockaddr *)&sa->ss, sa->len,
+ if(ast_sockaddr_ipv4_mapped(sa, &sa_ipv4))
+ sa_tmp = &sa_ipv4;
+ else
+ sa_tmp = sa;
+
+ if ((e = getnameinfo((struct sockaddr *)&sa_tmp->ss, sa->len,
format & AST_SOCKADDR_STR_ADDR ? host : NULL,
format & AST_SOCKADDR_STR_ADDR ? sizeof(host) : 0,
format & AST_SOCKADDR_STR_PORT ? port : 0,
@@ -60,7 +92,7 @@
switch(format) {
case AST_SOCKADDR_STR_DEFAULT:
- snprintf(str, size, sa->ss.ss_family == AF_INET6 ?
+ snprintf(str, size, sa_tmp->ss.ss_family == AF_INET6 ?
"[%s]:%s" : "%s:%s", host, port);
break;
case AST_SOCKADDR_STR_ADDR:
@@ -68,7 +100,7 @@
break;
case AST_SOCKADDR_STR_HOST:
snprintf(str, size,
- sa->ss.ss_family == AF_INET6 ? "[%s]" : "%s", host);
+ sa_tmp->ss.ss_family == AF_INET6 ? "[%s]" : "%s", host);
break;
case AST_SOCKADDR_STR_PORT:
strncpy(str, port, size);
@@ -216,26 +248,61 @@
return res_cnt;
}
+int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
+{
+ const struct ast_sockaddr *a_tmp, *b_tmp;
+ struct ast_sockaddr ipv4_mapped;
+
+ a_tmp = a;
+ b_tmp = b;
+
+ if (a_tmp->len != b_tmp->len) {
+ if (ast_sockaddr_ipv4_mapped(a, &ipv4_mapped))
+ a_tmp = &ipv4_mapped;
+ else if (ast_sockaddr_ipv4_mapped(b, &ipv4_mapped))
+ b_tmp = &ipv4_mapped;
+ }
+
+ if (a_tmp->len < b_tmp->len)
+ return -1;
+ else if (a_tmp->len > b_tmp->len)
+ return 1;
+
+ return memcmp(&a_tmp->ss, &b_tmp->ss, a_tmp->len);
+}
+
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
{
+ const struct ast_sockaddr *a_tmp, *b_tmp;
+ struct ast_sockaddr ipv4_mapped;
const struct in_addr *ip4a, *ip4b;
const struct in6_addr *ip6a, *ip6b;
int ret = -1;
+
+ a_tmp = a;
+ b_tmp = b;
+
+ if (a_tmp->len != b_tmp->len) {
+ if (ast_sockaddr_ipv4_mapped(a, &ipv4_mapped))
+ a_tmp = &ipv4_mapped;
+ else if (ast_sockaddr_ipv4_mapped(b, &ipv4_mapped))
+ b_tmp = &ipv4_mapped;
+ }
if (a->len < b->len)
ret = -1;
else if (a->len > b->len)
ret = 1;
- switch(a->ss.ss_family) {
+ switch(a_tmp->ss.ss_family) {
case AF_INET:
- ip4a = &((const struct sockaddr_in*)&a->ss)->sin_addr;
- ip4b = &((const struct sockaddr_in*)&b->ss)->sin_addr;
+ ip4a = &((const struct sockaddr_in*)&a_tmp->ss)->sin_addr;
+ ip4b = &((const struct sockaddr_in*)&b_tmp->ss)->sin_addr;
ret = memcmp(ip4a, ip4b, sizeof(*ip4a));
break;
case AF_INET6:
- ip6a = &((const struct sockaddr_in6*)&a->ss)->sin6_addr;
- ip6b = &((const struct sockaddr_in6*)&b->ss)->sin6_addr;
+ ip6a = &((const struct sockaddr_in6*)&a_tmp->ss)->sin6_addr;
+ ip6b = &((const struct sockaddr_in6*)&b_tmp->ss)->sin6_addr;
ret = memcmp(ip6a, ip6b, sizeof(*ip6a));
break;
}
@@ -277,6 +344,12 @@
{
return addr->ss.ss_family == AF_INET &&
addr->len == sizeof(struct sockaddr_in);
+}
+
+int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
+{
+ const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr->ss;
+ return addr->len && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr);
}
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Modified: team/group/v6-new/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/main/rtp_engine.c?view=diff&rev=266573&r1=266572&r2=266573
==============================================================================
--- team/group/v6-new/main/rtp_engine.c (original)
+++ team/group/v6-new/main/rtp_engine.c Mon May 31 13:39:32 2010
@@ -1202,6 +1202,7 @@
*vinstance0 = NULL, *vinstance1 = NULL,
*tinstance0 = NULL, *tinstance1 = NULL;
struct ast_rtp_glue *glue0, *glue1;
+ struct ast_sockaddr addr1, addr2;
enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_bridge_result res = AST_BRIDGE_FAILED;
@@ -1248,6 +1249,17 @@
if (audio_glue0_res == AST_RTP_GLUE_RESULT_FORBID || audio_glue1_res == AST_RTP_GLUE_RESULT_FORBID) {
res = AST_BRIDGE_FAILED_NOWARN;
goto done;
+ }
+
+
+ /* If address families differ, force a local bridge */
+ ast_rtp_instance_get_remote_address(instance0, &addr1);
+ ast_rtp_instance_get_remote_address(instance1, &addr2);
+
+ if (addr1.ss.ss_family != addr2.ss.ss_family ||
+ (ast_sockaddr_is_ipv4_mapped(&addr1) != ast_sockaddr_is_ipv4_mapped(&addr2))) {
+ audio_glue0_res = AST_RTP_GLUE_RESULT_LOCAL;
+ audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
}
/* If we need to get DTMF see if we can do it outside of the RTP stream itself */
More information about the asterisk-commits
mailing list