diff --git a/include/asterisk/netsock2.h b/include/asterisk/netsock2.h
index 5c6c7333ca856f4b93f2c781691f1283449d4cc0..b6f2858bf19fcc0c68b59994f2cc0fb4b740d8b3 100644
--- a/include/asterisk/netsock2.h
+++ b/include/asterisk/netsock2.h
@@ -31,6 +31,18 @@ extern "C" {
 
 #include <netinet/in.h>
 
+/*
+ * String buffer size that can accommodate a fully stringified representation of a
+ * supported IP address & port:
+ *
+ * - 45 bytes for an IPv6 address
+ * -  2 bytes for brackets around an IPv6 address
+ * -  1 byte for the port separator (a colon)
+ * -  5 bytes for the port
+ * -  1 byte for the zero-terminator
+ */
+#define AST_SOCKADDR_BUFLEN (45 + 2 + 1 + 5 + 1)
+
 /*!
  * Values for address families that we support. This is reproduced from socket.h
  * because we do not want users to include that file. Only netsock2.c should
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index ece03d38bff9b24bab950a011ac6679cacbd865c..93fa6a38c92d17b104ec0c2db3bdea49959555c2 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -3450,6 +3450,8 @@ int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const
 	ast_copy_string(rdata->pkt_info.packet, packet, sizeof(rdata->pkt_info.packet));
 	ast_copy_string(rdata->pkt_info.src_name, src_name, sizeof(rdata->pkt_info.src_name));
 	rdata->pkt_info.src_port = src_port;
+	pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
+	pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
 
 	pjsip_parse_rdata(packet, strlen(packet), rdata);
 	if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
diff --git a/res/res_pjsip/pjsip_distributor.c b/res/res_pjsip/pjsip_distributor.c
index f9e2997a4009ff8610a92cbdfd57b8cbddb3a7fd..9b3fcdcc31f6ce7058d7deb32628f056e82e27ba 100644
--- a/res/res_pjsip/pjsip_distributor.c
+++ b/res/res_pjsip/pjsip_distributor.c
@@ -638,16 +638,21 @@ static void log_failed_request(pjsip_rx_data *rdata, char *msg, unsigned int cou
 	char from_buf[PJSIP_MAX_URL_SIZE];
 	char callid_buf[PJSIP_MAX_URL_SIZE];
 	char method_buf[PJSIP_MAX_URL_SIZE];
+	char src_addr_buf[AST_SOCKADDR_BUFLEN];
 	pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, rdata->msg_info.from->uri, from_buf, PJSIP_MAX_URL_SIZE);
 	ast_copy_pj_str(callid_buf, &rdata->msg_info.cid->id, PJSIP_MAX_URL_SIZE);
 	ast_copy_pj_str(method_buf, &rdata->msg_info.msg->line.req.method.name, PJSIP_MAX_URL_SIZE);
 	if (count) {
-		ast_log(LOG_NOTICE, "Request '%s' from '%s' failed for '%s:%d' (callid: %s) - %s"
+		ast_log(LOG_NOTICE, "Request '%s' from '%s' failed for '%s' (callid: %s) - %s"
 			" after %u tries in %.3f ms\n",
-			method_buf, from_buf, rdata->pkt_info.src_name, rdata->pkt_info.src_port, callid_buf, msg, count, period / 1000.0);
+			method_buf, from_buf,
+			pj_sockaddr_print(&rdata->pkt_info.src_addr, src_addr_buf, sizeof(src_addr_buf), 3),
+			callid_buf, msg, count, period / 1000.0);
 	} else {
-		ast_log(LOG_NOTICE, "Request '%s' from '%s' failed for '%s:%d' (callid: %s) - %s\n",
-			method_buf, from_buf, rdata->pkt_info.src_name, rdata->pkt_info.src_port, callid_buf, msg);
+		ast_log(LOG_NOTICE, "Request '%s' from '%s' failed for '%s' (callid: %s) - %s\n",
+			method_buf, from_buf,
+			pj_sockaddr_print(&rdata->pkt_info.src_addr, src_addr_buf, sizeof(src_addr_buf), 3),
+			callid_buf, msg);
 	}
 }
 
diff --git a/res/res_pjsip_logger.c b/res/res_pjsip_logger.c
index 2e5c76c29ff61e0923b273b9e65aae61bd98ec52..fe2339291bb4c64be787cae38f9eb475e832cc03 100644
--- a/res/res_pjsip_logger.c
+++ b/res/res_pjsip_logger.c
@@ -101,22 +101,25 @@ static inline int pjsip_log_test_addr(const char *address, int port)
 
 static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
 {
+	char buffer[AST_SOCKADDR_BUFLEN];
+
 	if (!pjsip_log_test_addr(tdata->tp_info.dst_name, tdata->tp_info.dst_port)) {
 		return PJ_SUCCESS;
 	}
 
-	ast_verbose("<--- Transmitting SIP %s (%d bytes) to %s:%s:%d --->\n%.*s\n",
+	ast_verbose("<--- Transmitting SIP %s (%d bytes) to %s:%s --->\n%.*s\n",
 		    tdata->msg->type == PJSIP_REQUEST_MSG ? "request" : "response",
 		    (int) (tdata->buf.cur - tdata->buf.start),
 		    tdata->tp_info.transport->type_name,
-		    tdata->tp_info.dst_name,
-		    tdata->tp_info.dst_port,
+		    pj_sockaddr_print(&tdata->tp_info.dst_addr, buffer, sizeof(buffer), 3),
 		    (int) (tdata->buf.end - tdata->buf.start), tdata->buf.start);
 	return PJ_SUCCESS;
 }
 
 static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
 {
+	char buffer[AST_SOCKADDR_BUFLEN];
+
 	if (!pjsip_log_test_addr(rdata->pkt_info.src_name, rdata->pkt_info.src_port)) {
 		return PJ_FALSE;
 	}
@@ -125,12 +128,11 @@ static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
 		return PJ_FALSE;
 	}
 
-	ast_verbose("<--- Received SIP %s (%d bytes) from %s:%s:%d --->\n%s\n",
+	ast_verbose("<--- Received SIP %s (%d bytes) from %s:%s --->\n%s\n",
 		    rdata->msg_info.msg->type == PJSIP_REQUEST_MSG ? "request" : "response",
 		    rdata->msg_info.len,
 		    rdata->tp_info.transport->type_name,
-		    rdata->pkt_info.src_name,
-		    rdata->pkt_info.src_port,
+		    pj_sockaddr_print(&rdata->pkt_info.src_addr, buffer, sizeof(buffer), 3),
 		    rdata->pkt_info.packet);
 	return PJ_FALSE;
 }
diff --git a/res/res_pjsip_outbound_authenticator_digest.c b/res/res_pjsip_outbound_authenticator_digest.c
index 9440a870a807bbb89d40ad07cb6098e9bd45e274..a94e0a234cdfeee0c1d161a25c04dba93d06e1cf 100644
--- a/res/res_pjsip_outbound_authenticator_digest.c
+++ b/res/res_pjsip_outbound_authenticator_digest.c
@@ -118,8 +118,8 @@ static int digest_create_request_with_auth_from_old(const struct ast_sip_auth_ve
 	}
 	/* If there was no dialog, then this is probably a REGISTER so no endpoint */
 	if (!id) {
-		id = ast_alloca(strlen(challenge->pkt_info.src_name) + 7 /* ':' + port + NULL */);
-		sprintf(id, "%s:%d", challenge->pkt_info.src_name, challenge->pkt_info.src_port);
+		id = ast_alloca(AST_SOCKADDR_BUFLEN);
+		pj_sockaddr_print(&challenge->pkt_info.src_addr, id, AST_SOCKADDR_BUFLEN, 3);
 		id_type = "Host";
 	}
 
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index ed637cdd52a828523a0570b721f0db265f08b6c7..ff40e5504a6f070b37787fac515e3e07422f8d09 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2101,6 +2101,7 @@ static int new_invite(struct new_invite *invite)
 	pjsip_timer_setting timer;
 	pjsip_rdata_sdp_info *sdp_info;
 	pjmedia_sdp_session *local = NULL;
+	char buffer[AST_SOCKADDR_BUFLEN];
 
 	/* From this point on, any calls to pjsip_inv_terminate have the last argument as PJ_TRUE
 	 * so that we will be notified so we can destroy the session properly
@@ -2128,8 +2129,11 @@ static int new_invite(struct new_invite *invite)
 		}
 		goto end;
 	case SIP_GET_DEST_EXTEN_PARTIAL:
-		ast_debug(1, "Call from '%s' (%s:%s:%d) to extension '%s' - partial match\n", ast_sorcery_object_get_id(invite->session->endpoint),
-			invite->rdata->tp_info.transport->type_name, invite->rdata->pkt_info.src_name, invite->rdata->pkt_info.src_port, invite->session->exten);
+		ast_debug(1, "Call from '%s' (%s:%s) to extension '%s' - partial match\n",
+			ast_sorcery_object_get_id(invite->session->endpoint),
+			invite->rdata->tp_info.transport->type_name,
+			pj_sockaddr_print(&invite->rdata->pkt_info.src_addr, buffer, sizeof(buffer), 3),
+			invite->session->exten);
 
 		if (pjsip_inv_initial_answer(invite->session->inv_session, invite->rdata, 484, NULL, NULL, &tdata) == PJ_SUCCESS) {
 			ast_sip_session_send_response(invite->session, tdata);
@@ -2139,9 +2143,12 @@ static int new_invite(struct new_invite *invite)
 		goto end;
 	case SIP_GET_DEST_EXTEN_NOT_FOUND:
 	default:
-		ast_log(LOG_NOTICE, "Call from '%s' (%s:%s:%d) to extension '%s' rejected because extension not found in context '%s'.\n",
-			ast_sorcery_object_get_id(invite->session->endpoint), invite->rdata->tp_info.transport->type_name, invite->rdata->pkt_info.src_name,
-			invite->rdata->pkt_info.src_port, invite->session->exten, invite->session->endpoint->context);
+		ast_log(LOG_NOTICE, "Call from '%s' (%s:%s) to extension '%s' rejected because extension not found in context '%s'.\n",
+			ast_sorcery_object_get_id(invite->session->endpoint),
+			invite->rdata->tp_info.transport->type_name,
+			pj_sockaddr_print(&invite->rdata->pkt_info.src_addr, buffer, sizeof(buffer), 3),
+			invite->session->exten,
+			invite->session->endpoint->context);
 
 		if (pjsip_inv_initial_answer(invite->session->inv_session, invite->rdata, 404, NULL, NULL, &tdata) == PJ_SUCCESS) {
 			ast_sip_session_send_response(invite->session, tdata);
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index d71575d678301cb78fd3fc6b74edbef506f9c260..2cbff335f0f39677934f07ca9dec0eb4798b9e5a 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -429,12 +429,23 @@ static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata)
 		pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);
 		const pj_str_t *txp_str = &STR_WS;
 
-		ast_debug(4, "%s re-writing Contact URI from %.*s:%d%s%.*s to %s:%d;transport=%s\n",
-			pjsip_rx_data_get_info(rdata),
-			(int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port,
-			pj_strlen(&uri->transport_param) ? ";transport=" : "",
-			(int)pj_strlen(&uri->transport_param), pj_strbuf(&uri->transport_param),
-			rdata->pkt_info.src_name ?: "", rdata->pkt_info.src_port, pj_strbuf(txp_str));
+		if (DEBUG_ATLEAST(4)) {
+			char src_addr_buffer[AST_SOCKADDR_BUFLEN];
+			const char *ipv6_s = "", *ipv6_e = "";
+
+			if (pj_strchr(&uri->host, ':')) {
+				ipv6_s = "[";
+				ipv6_e = "]";
+			}
+
+			ast_log(LOG_DEBUG, "%s re-writing Contact URI from %s%.*s%s:%d%s%.*s to %s;transport=%s\n",
+				pjsip_rx_data_get_info(rdata),
+				ipv6_s, (int) pj_strlen(&uri->host), pj_strbuf(&uri->host), ipv6_e, uri->port,
+				pj_strlen(&uri->transport_param) ? ";transport=" : "",
+				(int) pj_strlen(&uri->transport_param), pj_strbuf(&uri->transport_param),
+				pj_sockaddr_print(&rdata->pkt_info.src_addr, src_addr_buffer, sizeof(src_addr_buffer), 3),
+				pj_strbuf(txp_str));
+		}
 
 		pj_cstr(&uri->host, rdata->pkt_info.src_name);
 		uri->port = rdata->pkt_info.src_port;