Index: src/switch_apr.c
===================================================================
--- src/switch_apr.c	(revision 8886)
+++ src/switch_apr.c	(working copy)
@@ -630,7 +630,7 @@
 	if (!in) {
 		return "";
 	}
-	return get_addr(buf, len, &in->sa.sin.sin_addr);
+	return get_addr(buf, len, (struct sockaddr*)&in->sa, in->salen);
 }
 
 SWITCH_DECLARE(uint16_t) switch_sockaddr_get_port(switch_sockaddr_t *sa)
Index: src/switch_rtp.c
===================================================================
--- src/switch_rtp.c	(revision 8886)
+++ src/switch_rtp.c	(working copy)
@@ -121,7 +121,13 @@
 };
 
 struct switch_rtp {
-	switch_socket_t *sock;
+    /* 
+     * Two sockets are needed because we might be transcoding protocol families
+     * (e.g. receive over IPv4 and send over IPv6). In case the protocol
+     * families are equal, sock_input == sock_output and only one socket is
+     * used.
+     */
+	switch_socket_t *sock_input, *sock_output;
 
 	switch_sockaddr_t *local_addr;
 	rtp_msg_t send_msg;
@@ -220,7 +226,7 @@
 	packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, buf);
 	switch_stun_packet_attribute_add_username(packet, rtp_session->ice_user, 32);
 	bytes = switch_stun_packet_length(packet);
-	switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) packet, &bytes);
+	switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) packet, &bytes);
 	rtp_session->stuncount = 25;
 
   end:
@@ -296,7 +302,7 @@
 		remote_ip = switch_get_addr(ipbuf, sizeof(ipbuf), rtp_session->from_addr);
 		switch_stun_packet_attribute_add_binded_address(rpacket, (char *) remote_ip, switch_sockaddr_get_port(rtp_session->from_addr));
 		bytes = switch_stun_packet_length(rpacket);
-		switch_socket_sendto(rtp_session->sock, rtp_session->from_addr, 0, (void *) rpacket, &bytes);
+		switch_socket_sendto(rtp_session->sock_output, rtp_session->from_addr, 0, (void *) rpacket, &bytes);
 	}
 
   end:
@@ -440,11 +446,11 @@
 		goto done;
 	}
 
-	if (rtp_session->sock) {
+	if (rtp_session->sock_input) {
 		switch_rtp_kill_socket(rtp_session);
 	}
 
-	if (switch_socket_create(&new_sock, AF_INET, SOCK_DGRAM, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
+	if (switch_socket_create(&new_sock, switch_sockaddr_get_family(rtp_session->local_addr), SOCK_DGRAM, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
 		*err = "Socket Error!";
 		goto done;
 	}
@@ -483,12 +489,12 @@
 
 #endif
 
-	old_sock = rtp_session->sock;
-	rtp_session->sock = new_sock;
+	old_sock = rtp_session->sock_input;
+	rtp_session->sock_input = new_sock;
 	new_sock = NULL;
 
 	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK)) {
-		switch_socket_opt_set(rtp_session->sock, SWITCH_SO_NONBLOCK, TRUE);
+		switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, TRUE);
 		switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
 	}
 
@@ -522,6 +528,7 @@
 SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err)
 {
 	switch_sockaddr_t *remote_addr;
+    switch_status_t status = SWITCH_STATUS_SUCCESS;
 	*err = "Success";
 
 	if (switch_sockaddr_info_get(&remote_addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS || !remote_addr) {
@@ -530,11 +537,32 @@
 	}
 
 	switch_mutex_lock(rtp_session->write_mutex);
+
 	rtp_session->remote_addr = remote_addr;
 	rtp_session->remote_port = port;
+
+    if (rtp_session->sock_input &&
+            switch_sockaddr_get_family(rtp_session->remote_addr) ==
+            switch_sockaddr_get_family(rtp_session->local_addr)) {
+        rtp_session->sock_output = rtp_session->sock_input;
+    }
+    else {
+        if (rtp_session->sock_output &&
+                rtp_session->sock_output != rtp_session->sock_input) {
+            switch_socket_close(rtp_session->sock_output);
+        }
+        if ((status = switch_socket_create(&rtp_session->sock_output,
+                        switch_sockaddr_get_family(rtp_session->remote_addr),
+                        SOCK_DGRAM, 0, rtp_session->pool)) !=
+                SWITCH_STATUS_SUCCESS)
+        {
+            *err = "Socket Error!";
+        }
+    }
+
 	switch_mutex_unlock(rtp_session->write_mutex);
 
-	return SWITCH_STATUS_SUCCESS;
+	return status;
 }
 
 SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session,
@@ -829,9 +857,9 @@
 
 	switch_assert(rtp_session != NULL);
 	switch_mutex_lock(rtp_session->flag_mutex);
-	if (rtp_session->sock) {
+	if (rtp_session->sock_input) {
 		switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
-		switch_socket_sendto(rtp_session->sock, rtp_session->local_addr, 0, (void *) &o, &len);
+		switch_socket_sendto(rtp_session->sock_input, rtp_session->local_addr, 0, (void *) &o, &len);
 	}
 	switch_mutex_unlock(rtp_session->flag_mutex);
 }
@@ -842,9 +870,13 @@
 	switch_mutex_lock(rtp_session->flag_mutex);
 	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO)) {
 		switch_clear_flag(rtp_session, SWITCH_RTP_FLAG_IO);
-		if (rtp_session->sock) {
-			switch_socket_shutdown(rtp_session->sock, SWITCH_SHUTDOWN_READWRITE);
+		if (rtp_session->sock_input) {
+			switch_socket_shutdown(rtp_session->sock_input, SWITCH_SHUTDOWN_READWRITE);
 		}
+        if (rtp_session->sock_output &&
+                rtp_session->sock_output != rtp_session->sock_input) {
+			switch_socket_shutdown(rtp_session->sock_output, SWITCH_SHUTDOWN_READWRITE);
+        }
 	}
 	switch_mutex_unlock(rtp_session->flag_mutex);
 }
@@ -858,7 +890,7 @@
 	}
 
 	switch_mutex_lock(rtp_session->flag_mutex);
-	ret = (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO) && rtp_session->sock && rtp_session->remote_addr && rtp_session->ready == 2) ? 1 : 0;
+	ret = (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO) && rtp_session->sock_input && rtp_session->sock_output && rtp_session->remote_addr && rtp_session->ready == 2) ? 1 : 0;
 	switch_mutex_unlock(rtp_session->flag_mutex);
 
 	return ret;
@@ -899,10 +931,15 @@
 		stfu_n_destroy(&(*rtp_session)->jb);
 	}
 
-	sock = (*rtp_session)->sock;
-	(*rtp_session)->sock = NULL;
+	sock = (*rtp_session)->sock_input;
+	(*rtp_session)->sock_input = NULL;
 	switch_socket_close(sock);
 
+    if ( (*rtp_session)->sock_output != sock ) {
+        sock = (*rtp_session)->sock_output;
+        (*rtp_session)->sock_output = NULL;
+        switch_socket_close(sock);
+    }
 
 	if (switch_test_flag((*rtp_session), SWITCH_RTP_FLAG_VAD)) {
 		switch_rtp_disable_vad(*rtp_session);
@@ -932,7 +969,7 @@
 
 SWITCH_DECLARE(switch_socket_t *) switch_rtp_get_rtp_socket(switch_rtp_t *rtp_session)
 {
-	return rtp_session->sock;
+	return rtp_session->sock_input;
 }
 
 SWITCH_DECLARE(void) switch_rtp_set_default_samples_per_interval(switch_rtp_t *rtp_session, uint16_t samples_per_interval)
@@ -1096,7 +1133,7 @@
 		int do_cng = 0;
 
 		bytes = sizeof(rtp_msg_t);
-		status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock, 0, (void *) &rtp_session->recv_msg, &bytes);
+		status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes);
 
 		if (bytes < 0) {
 			ret = (int) bytes;
@@ -1184,7 +1221,7 @@
 			}
 
 			if (rtp_session->invalid_handler) {
-				rtp_session->invalid_handler(rtp_session, rtp_session->sock, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
+				rtp_session->invalid_handler(rtp_session, rtp_session->sock_input, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
 			}
 
 			memset(data, 0, 2);
@@ -1783,7 +1820,7 @@
 			bytes = sbytes;
 		}
 
-		if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
+		if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
 			rtp_session->seq--;
 			ret = -1;
 			goto end;
@@ -1889,7 +1926,7 @@
 			return 0;
 		}
 		bytes = frame->packetlen;
-		if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) {
+		if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) {
 			return -1;
 		}
 		return (int) bytes;
@@ -1971,7 +2008,7 @@
 		bytes = sbytes;
 	}
 
-	if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) &rtp_session->write_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
+	if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) &rtp_session->write_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
 		rtp_session->seq--;
 		ret = -1;
 		goto end;
Index: src/mod/endpoints/mod_sofia/sofia_reg.c
===================================================================
--- src/mod/endpoints/mod_sofia/sofia_reg.c	(revision 8886)
+++ src/mod/endpoints/mod_sofia/sofia_reg.c	(working copy)
@@ -403,6 +403,7 @@
 	const char *rpid = "unknown";
 	const char *display = "\"user\"";
 	char network_ip[80];
+    char url_ip[80];
 	char *register_gateway = NULL;
 	int network_port;
 	const char *reg_desc = "Registered";
@@ -410,13 +411,19 @@
 	char *force_user;
 	char received_data[128] = "";
 	char *path_val = NULL;
-	
+    su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
+
 	/* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */
 	switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL);
 
-	get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr);
-	network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
+    get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr,
+            my_addrinfo->ai_addrlen);
+	network_port = get_port(my_addrinfo->ai_addr);
 
+    snprintf(url_ip, sizeof(url_ip),
+            my_addrinfo->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s",
+            network_ip);
+
 	expires = sip->sip_expires;
 	authorization = sip->sip_authorization;
 	contact = sip->sip_contact;
@@ -466,7 +473,7 @@
 			} else {
 				reg_desc = "Registered(UDP-NAT)";
 			}
-			contact_host = network_ip;
+			contact_host = url_ip;
 			switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
 			port = NULL;
 		} else {
@@ -501,7 +508,7 @@
 		}
 
 		if (is_nat && (profile->pflags & PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) {
-			switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", network_ip, network_port);
+			switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", url_ip, network_port);
 		}
 
 		if (contact->m_url->url_params) {
@@ -556,16 +563,16 @@
 			if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact"))) {
 
 				if (*received_data && (profile->pflags & PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) {
-					switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", network_ip, network_port);
+					switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", url_ip, network_port);
 				}
 
 				if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") ||
 					!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-tls-connectile-dysfunction")) {
 					if (contact->m_url->url_params) {
 						switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s:%d;%s%s;fs_nat=yes>",
-										display, contact->m_url->url_user, network_ip, network_port, contact->m_url->url_params, received_data);
+										display, contact->m_url->url_user, url_ip, network_port, contact->m_url->url_params, received_data);
 					} else {
-						switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s:%d%s;fs_nat=yes>", display, contact->m_url->url_user, network_ip,
+						switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s:%d%s;fs_nat=yes>", display, contact->m_url->url_user, url_ip,
 										network_port, received_data);
 					}
 					if (strstr(v_contact_str, "tls")) {
@@ -762,8 +769,9 @@
 	char *is_nat = NULL;
 
 
-	get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
-	network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
+    get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr,
+            my_addrinfo->ai_addrlen);
+	network_port = get_port(msg_addrinfo(nua_current_request(nua))->ai_addr);
 
 
 	if (!(sip->sip_contact && sip->sip_contact->m_url)) {
Index: src/mod/endpoints/mod_sofia/mod_sofia.c
===================================================================
--- src/mod/endpoints/mod_sofia/mod_sofia.c	(revision 8886)
+++ src/mod/endpoints/mod_sofia/mod_sofia.c	(working copy)
@@ -926,7 +926,9 @@
 			char ref_to[128] = "";
 
 			if (!strstr(msg->string_arg, "sip:")) {
-				switch_snprintf(ref_to, sizeof(ref_to), "sip:%s@%s", msg->string_arg, tech_pvt->profile->sipip);
+                const char *format = strchr(tech_pvt->profile->sipip, ':') ?
+                    "sip:%s@[%s]" : "sip:%s@%s";
+				switch_snprintf(ref_to, sizeof(ref_to), format, msg->string_arg, tech_pvt->profile->sipip);
 			} else {
 				switch_set_string(ref_to, msg->string_arg);
 			}
Index: src/mod/endpoints/mod_sofia/sofia.c
===================================================================
--- src/mod/endpoints/mod_sofia/sofia.c	(revision 8886)
+++ src/mod/endpoints/mod_sofia/sofia.c	(working copy)
@@ -215,7 +215,9 @@
 
 		if (authorization) {
 			char network_ip[80];
-			get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr);
+            su_addrinfo_t *addrinfo = msg_addrinfo(nua_current_request(nua));
+            get_addr(network_ip, sizeof(network_ip), addrinfo->ai_addr,
+                    addrinfo->ai_addrlen);
 			auth_res = sofia_reg_parse_auth(profile, authorization, sip,
 											(char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, NULL, 0,
 											REG_INVITE, NULL);
@@ -893,8 +895,13 @@
 
 			gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s;transport=%s", register_proxy, register_transport);
 			gateway->register_from = switch_core_sprintf(gateway->pool, "<sip:%s@%s;transport=%s>", from_user, from_domain, register_transport);
-			gateway->register_contact = switch_core_sprintf(gateway->pool, "<sip:%s@%s:%d%s>", extension,
-															profile->extsipip ? profile->extsipip : profile->sipip,
+
+            const char *sipip = profile->extsipip ?  profile->extsipip :
+                profile->sipip;
+            const char *format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d%s>" :
+                "<sip:%s@%s:%d%s>";
+			gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
+															sipip,
 															sofia_glue_transport_has_tls(gateway->register_transport) ? profile->tls_sip_port : profile->
 															sip_port, params);
 
@@ -1389,10 +1396,17 @@
 					profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip);
 				}
 				if (profile->extsipip) {
-					profile->url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->extsipip, profile->sip_port);
+                    char *ipv6 = strchr(profile->extsipip, ':');
+					profile->url = switch_core_sprintf(profile->pool,
+                            "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "",
+                            profile->extsipip, ipv6 ? "]" : "",
+                            profile->sip_port);
 					profile->bindurl = switch_core_sprintf(profile->pool, "%s;maddr=%s", profile->url, profile->sipip);
 				} else {
-					profile->url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->sipip, profile->sip_port);
+                    char *ipv6 = strchr(profile->sipip, ':');
+					profile->url = switch_core_sprintf(profile->pool,
+                            "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "",
+                            profile->sipip, ipv6 ? "]" : "", profile->sip_port);
 					profile->bindurl = profile->url;
 				}
 
@@ -1410,12 +1424,28 @@
 					}
 
 					if (profile->extsipip) {
-						profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->extsipip, profile->tls_sip_port);
-						profile->tls_bindurl =
-							switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d;maddr=%s", profile->extsipip, profile->tls_sip_port, profile->sipip);
+                        char *ipv6 = strchr(profile->extsipip, ':');
+						profile->tls_url = switch_core_sprintf(profile->pool,
+                                "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "",
+                                profile->extsipip, ipv6 ? "]" : "",
+                                profile->tls_sip_port);
+                        profile->tls_bindurl =
+                            switch_core_sprintf(profile->pool,
+                                    "sips:mod_sofia@%s%s%s:%d;maddr=%s",
+                                    ipv6 ? "[" : "", profile->extsipip,
+                                    ipv6 ? "]" : "", profile->tls_sip_port,
+                                    profile->sipip);
 					} else {
-						profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port);
-						profile->tls_bindurl = switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port);
+                        char *ipv6 = strchr(profile->sipip, ':');
+                        profile->tls_url = switch_core_sprintf(profile->pool,
+                                "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "",
+                                profile->sipip, ipv6 ? "]" : "",
+                                profile->tls_sip_port);
+                        profile->tls_bindurl =
+                            switch_core_sprintf(profile->pool,
+                                    "sips:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "",
+                                    profile->sipip, ipv6 ? "]" : "",
+                                    profile->tls_sip_port);
 					}
 
 					if (profile->tls_bind_params) {
@@ -2637,7 +2667,8 @@
 		return;
 	}
 
-	get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
+    get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr,
+            my_addrinfo->ai_addrlen);
 	network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
 
 	if ((profile->pflags & PFLAG_AGGRESSIVE_NAT_DETECTION)) {
@@ -2754,9 +2785,13 @@
 		char tmp[35] = "";
 		sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
 
-		tech_pvt->record_route = switch_core_session_sprintf(session, "sip:%s@%s:%d;transport=%s",
-															 sip->sip_contact->m_url->url_user, tech_pvt->remote_ip, 
-															 tech_pvt->remote_port, sofia_glue_transport2str(transport));
+        const char *ipv6 = strchr(tech_pvt->remote_ip, ':');
+        tech_pvt->record_route = switch_core_session_sprintf(session,
+                "sip:%s@%s%s%s:%d;transport=%s",
+                sip->sip_contact->m_url->url_user, ipv6 ? "[" : "",
+                tech_pvt->remote_ip, ipv6 ? "]" : "", tech_pvt->remote_port,
+                sofia_glue_transport2str(transport));
+
 		switch_channel_set_variable(channel, "sip_received_ip", tech_pvt->remote_ip);
 		snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_port);
 		switch_channel_set_variable(channel, "sip_received_port", tmp);
@@ -2887,7 +2922,11 @@
 				port = sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port;
 			}
 
-			tech_pvt->to_uri = switch_core_session_sprintf(session, "sip:%s@%s:%d;transport=%s", user, host, port, sofia_glue_transport2str(transport));
+            const char *ipv6 = strchr(host, ':');
+            tech_pvt->to_uri = switch_core_session_sprintf(session,
+                    "sip:%s@%s%s%s:%d;transport=%s", user, ipv6 ? "[" : "",
+                    host, ipv6 ? "]" : "", port,
+                    sofia_glue_transport2str(transport));
 
 			if (profile->ndlb & PFLAG_NDLB_TO_IN_200_CONTACT) {
 				if (strchr(tech_pvt->to_uri, '>')) {
Index: src/mod/endpoints/mod_sofia/sofia_presence.c
===================================================================
--- src/mod/endpoints/mod_sofia/sofia_presence.c	(revision 8886)
+++ src/mod/endpoints/mod_sofia/sofia_presence.c	(working copy)
@@ -1209,7 +1209,8 @@
 			return;
 		}
 
-		get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
+        get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr,
+                my_addrinfo->ai_addrlen);
 		network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
 
 		tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END());
@@ -1279,11 +1280,18 @@
 			switch_snprintf(new_port, sizeof(new_port), ":%s", port);
 		}
 
+        const char *ipv6 = strchr(contact_host, ':');
 		if (contact->m_url->url_params) {
-			contact_str = switch_mprintf("%s <sip:%s@%s%s;%s>%s",
-										 display, contact->m_url->url_user, contact_host, new_port, contact->m_url->url_params, is_nat ? ";nat" : "");
+			contact_str = switch_mprintf("%s <sip:%s@%s%s%s%s;%s>%s",
+										 display, contact->m_url->url_user,
+                                         ipv6 ? "[" : "", contact_host,
+                                         ipv6 ? "]" : "", new_port,
+                                         contact->m_url->url_params, is_nat ?
+                                         ";nat" : "");
 		} else {
-			contact_str = switch_mprintf("%s <sip:%s@%s%s>%s", display, contact->m_url->url_user, contact_host, new_port, is_nat ? ";nat" : "");
+            contact_str = switch_mprintf("%s <sip:%s@%s%s%s%s>%s", display,
+                    contact->m_url->url_user, ipv6 ? "[" : "", contact_host,
+                    ipv6 ? "]" : "", new_port, is_nat ?  ";nat" : "");
 		}
 
 
@@ -1398,7 +1406,10 @@
 			char *sticky = NULL;
 
 			if (is_nat) {
-				sticky = switch_mprintf("sip:%s@%s:%d", contact_user, network_ip, network_port);
+                const char *ipv6 = strchr(network_ip, ':');
+				sticky = switch_mprintf("sip:%s@%s%s%s:%d", contact_user,
+                        ipv6 ? "[" : "", network_ip, ipv6 ? "]" : "",
+                        network_port);
 			}
 
 			nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS(nua), SIPTAG_SUBSCRIPTION_STATE_STR(sstr), TAG_IF(sticky, NUTAG_PROXY(sticky)),
Index: src/mod/endpoints/mod_sofia/sofia_glue.c
===================================================================
--- src/mod/endpoints/mod_sofia/sofia_glue.c	(revision 8886)
+++ src/mod/endpoints/mod_sofia/sofia_glue.c	(working copy)
@@ -82,13 +82,14 @@
 
 	tech_pvt->session_id++;
 
+    const char *family = strchr(ip, ':') ? "IP6" : "IP4";
 	switch_snprintf(buf, sizeof(buf),
 					"v=0\n"
-					"o=FreeSWITCH %010u %010u IN IP4 %s\n"
+					"o=FreeSWITCH %010u %010u IN %s %s\n"
 					"s=FreeSWITCH\n"
-					"c=IN IP4 %s\n" "t=0 0\n"
+					"c=IN %s %s\n" "t=0 0\n"
 					"a=%s\n"
-					"m=audio %d RTP/%sAVP", tech_pvt->owner_id, tech_pvt->session_id, ip, ip, sr, port,
+					"m=audio %d RTP/%sAVP", tech_pvt->owner_id, tech_pvt->session_id, family, ip, family, ip, sr, port,
 					(!switch_strlen_zero(tech_pvt->local_crypto_key) && switch_test_flag(tech_pvt, TFLAG_SECURE)) ? "S" : "");
 
 
@@ -730,7 +731,8 @@
 		return SWITCH_STATUS_FALSE;
 	}
 
-	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str))) {
+	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str)) ||
+	    (p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->remote_sdp_str))) {
 		ip_ptr = p + 9;
 	}
 
@@ -833,7 +835,8 @@
 
 	len = strlen(tech_pvt->local_sdp_str) + 384;
 
-	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->local_sdp_str))) {
+	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->local_sdp_str)) ||
+	    (p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->local_sdp_str))) {
 		ip_ptr = p + 9;
 	}
 
@@ -956,11 +959,13 @@
 	check_decode(cid_num, session);
 
 	if (!tech_pvt->from_str) {
-		tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, "\"%s\" <sip:%s%s%s>",
-														 cid_name,
-														 cid_num,
-														 !switch_strlen_zero(cid_num) ? "@" : "",
-														 tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip);
+        const char* sipip = tech_pvt->profile->extsipip ?
+            tech_pvt->profile->extsipip : tech_pvt->profile->sipip;
+        const char* format = strchr(sipip, ':') ?
+            "\"%s\" <sip:%s%s[%s]>" : "\"%s\" <sip:%s%s%s>";
+        tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session,
+                format, cid_name, cid_num,
+                !switch_strlen_zero(cid_num) ? "@" : "", sipip);
 	}
 
 	if ((alertbuf = switch_channel_get_variable(channel, "alert_info"))) {
@@ -1228,10 +1233,13 @@
 
 	caller_profile = switch_channel_get_caller_profile(channel);
 
-	if ((tech_pvt->from_str = switch_core_session_sprintf(session, "\"%s\" <sip:%s@%s>",
-														  caller_profile->caller_id_name,
-														  caller_profile->caller_id_number,
-														  tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip))) {
+    const char* sipip = tech_pvt->profile->extsipip ?
+        tech_pvt->profile->extsipip : tech_pvt->profile->sipip;
+    const char* format = strchr(sipip, ':') ?
+        "\"%s\" <sip:%s@[%s]>" : "\"%s\" <sip:%s@%s>";
+    if ((tech_pvt->from_str = switch_core_session_sprintf(session, format,
+                    caller_profile->caller_id_name,
+                    caller_profile->caller_id_number, sipip))) {
 
 		const char *rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
 
@@ -1637,7 +1645,7 @@
 	}
 
 	if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n",
 						  switch_channel_get_name(tech_pvt->channel),
 						  tech_pvt->local_sdp_audio_ip,
 						  tech_pvt->local_sdp_audio_port,
Index: src/include/switch_utils.h
===================================================================
--- src/include/switch_utils.h	(revision 8886)
+++ src/include/switch_utils.h	(working copy)
@@ -118,11 +118,43 @@
   \brief find the char representation of an ip adress
   \param buf the buffer to write the ip adress found into
   \param len the length of the buf
-  \param in the struct in_addr * to get the adress from
+  \param sa the struct sockaddr * to get the adress from
+  \param salen the length of sa
   \return the ip adress string
 */
-SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct in_addr *in);
+SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len,
+        struct sockaddr *sa, socklen_t salen);
 
+/*!
+  \brief get the port number of an ip address
+  \param sa the struct sockaddr * to get the port from
+  \return the ip adress string
+*/
+SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa);
+
+/*!
+  \brief flags to be used with switch_build_uri()
+ */
+enum switch_uri_flags {
+    SWITCH_URI_NUMERIC_HOST = 1,
+    SWITCH_URI_NUMERIC_PORT = 2,
+    SWITCH_URI_NO_SCOPE = 4,
+};
+
+/*!
+  \brief build a URI string from components
+  \param uri output string
+  \param size maximum size of output string (including trailing null)
+  \param scheme URI scheme
+  \param user user part or null if none
+  \param sa host address
+  \param flags logical OR-ed combination of flags from \ref switch_uri_flags
+  \return number of characters printed (not including the trailing null)
+ */
+SWITCH_DECLARE(int) switch_build_uri(char *uri, switch_size_t size,
+        const char *scheme, const char *user, const switch_sockaddr_t *sa,
+        int flags);
+
 #define SWITCH_STATUS_IS_BREAK(x) (x == SWITCH_STATUS_BREAK || x == 730035 || x == 35)
 
 /*!
Index: src/switch_utils.c
===================================================================
--- src/switch_utils.c	(revision 8886)
+++ src/switch_utils.c	(working copy)
@@ -32,6 +32,7 @@
  */
 
 #include <switch.h>
+#include <netdb.h>
 #ifndef WIN32
 #include <arpa/inet.h>
 #endif
@@ -757,7 +758,8 @@
 				goto doh;
 			}
 
-			switch_copy_string(buf, get_addr(abuf, sizeof(abuf), &iface_out.sin_addr), len);
+			switch_copy_string(buf, get_addr(abuf, sizeof(abuf),
+                        (struct sockaddr*)&iface_out, sizeof(iface_out)), len);
 			status = SWITCH_STATUS_SUCCESS;
 		}
 		break;
@@ -768,20 +770,16 @@
 			memset(&remote, 0, sizeof(struct sockaddr_in6));
 
 			remote.sin6_family = AF_INET6;
-			switch_inet_pton(AF_INET6, buf, &remote.sin6_addr);
+			switch_inet_pton(AF_INET6, base, &remote.sin6_addr);
 			remote.sin6_port = htons(4242);
 
 			memset(&iface_out, 0, sizeof(iface_out));
 			tmp_socket = socket(AF_INET6, SOCK_DGRAM, 0);
 
-			if (setsockopt(tmp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) {
+			if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(remote)) == -1) {
 				goto doh;
 			}
 
-			if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(struct sockaddr_in)) == -1) {
-				goto doh;
-			}
-
 			ilen = sizeof(iface_out);
 			if (getsockname(tmp_socket, (struct sockaddr *) &iface_out, &ilen) == -1) {
 				goto doh;
@@ -1054,16 +1052,64 @@
 
 #endif
 
-SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct in_addr *in)
+SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len,
+        struct sockaddr *sa, socklen_t salen)
 {
 	switch_assert(buf);
 	*buf = '\0';
-	if (in) {
-		switch_inet_ntop(AF_INET, in, buf, len);
+	if (sa) {
+        getnameinfo(sa, salen, buf, len, NULL, 0, NI_NUMERICHOST);
 	}
 	return buf;
 }
 
+SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa)
+{
+    unsigned short port = 0;
+    if (sa) {
+        switch (sa->sa_family) {
+            case AF_INET:
+                port = ntohs(((struct sockaddr_in*)sa)->sin_port);
+                break;
+            case AF_INET6:
+                port = ntohs(((struct sockaddr_in6*)sa)->sin6_port);
+                break;
+        }
+    }
+    return port;
+}
+
+SWITCH_DECLARE(int) switch_build_uri(char *uri, switch_size_t size,
+        const char *scheme, const char *user, const switch_sockaddr_t *sa,
+        int flags)
+{
+    char host[NI_MAXHOST], serv[NI_MAXSERV];
+    struct sockaddr_storage ss;
+    const struct sockaddr *addr;
+    const char *colon;
+
+    if (flags & SWITCH_URI_NO_SCOPE && sa->family == AF_INET6) {
+        memcpy(&ss, &sa->sa, sa->salen);
+        ((struct sockaddr_in6*) &ss)->sin6_scope_id = 0;
+        addr = (const struct sockaddr*) &ss;
+    } else {
+        addr = (const struct sockaddr*) &sa->sa;
+    }
+
+    if (getnameinfo(addr, sa->salen, host, sizeof(host), serv, sizeof(serv),
+                (flags & SWITCH_URI_NUMERIC_HOST) ? NI_NUMERICHOST : 0 |
+                (flags & SWITCH_URI_NUMERIC_PORT) ? NI_NUMERICSERV : 0) != 0) {
+        return 0;
+    }
+
+    colon = strchr(host, ':');
+
+    return switch_snprintf(uri, size, "%s:%s%s%s%s%s%s%s", scheme,
+            user ? user : "", user ? "@" : "",
+            colon ? "[" : "", host, colon ? "]" : "",
+            serv[0] ? ":" : "", serv[0] ? serv : "");
+}
+
 SWITCH_DECLARE(char) switch_rfc2833_to_char(int event)
 {
 	if (event > -1 && event < (int32_t) sizeof(RFC2833_CHARS)) {
