[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