--- asterisk-16.21.1.orig/res/res_pjsip_diversion.c	2021-10-11 19:37:25.000000000 +0100
+++ asterisk-16.21.1/res/res_pjsip_diversion.c	2021-10-27 09:50:57.000000000 +0100
@@ -501,9 +501,10 @@
  * \param tdata The outbound message
  * \param data The redirecting data used to fill parts of the diversion header
  */
-static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
+static void add_diversion_header(pjsip_tx_data *tdata, struct ast_sip_session *session)
 {
 	static const pj_str_t reason_name = { "reason", 6 };
+	static const pj_str_t privacy_name = { "privacy", 7 };
 
 	pjsip_fromto_hdr *hdr;
 	pjsip_name_addr *name_addr;
@@ -512,23 +513,29 @@
 	pjsip_fromto_hdr *old_hdr;
 	const char *reason_str;
 	const char *quote_str;
+	const char *privacy_str;
 	char *reason_buf;
+	char *privacy_buf;
 	pjsip_uri *base;
+	int restricted;
 
-	struct ast_party_id *id = NULL;
+	struct ast_party_id id;
 	if (tdata->msg->type == PJSIP_REQUEST_MSG) {
-		id = &data->from;
+		id = ast_channel_redirecting_effective_from(session->channel);
 	} else {
 		/* In responses indicate the new destination */
-		id = &data->to;
+		id = ast_channel_redirecting_effective_to(session->channel);
 	}
 
 	base = PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
 
-	if (!id->number.valid || ast_strlen_zero(id->number.str)) {
+	if (!id.number.valid || ast_strlen_zero(id.number.str)) {
 		return;
 	}
 
+	restricted =
+		((ast_party_id_presentation(&id) & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED);
+
 	hdr = pjsip_from_hdr_create(tdata->pool);
 	hdr->type = PJSIP_H_OTHER;
 	hdr->sname = hdr->name = diversion_name;
@@ -536,22 +543,45 @@
 	name_addr = pjsip_uri_clone(tdata->pool, base);
 	uri = pjsip_uri_get_uri(name_addr->uri);
 
-	pj_strdup2(tdata->pool, &name_addr->display, id->name.str);
-	pj_strdup2(tdata->pool, &uri->user, id->number.str);
+	if (restricted) {
+		privacy_str = "full";
+	} else {
+		privacy_str = "off";
+	}
+
+	if (session->endpoint->id.trust_outbound || !restricted) {
+		pj_strdup2(tdata->pool, &name_addr->display, id.name.str);
+		pj_strdup2(tdata->pool, &uri->user, id.number.str);
+	} else {
+		pj_strdup2(tdata->pool, &name_addr->display, "Anonymous");
+		pj_strdup2(tdata->pool, &uri->user, "anonymous");
+		pj_strdup2(tdata->pool, &uri->host, "anonymous.invalid");
+		uri->port = 0;
+	}
 
 	param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
 	param->name = reason_name;
-
-	reason_str = reason_code_to_str(&data->reason);
+	reason_str = reason_code_to_str(&ast_channel_redirecting(session->channel)->reason);
 
 	/* Reason is either already quoted or it is a token to not need quotes added. */
 	quote_str = *reason_str == '\"' || sip_is_token(reason_str) ? "" : "\"";
 
 	reason_buf = pj_pool_alloc(tdata->pool, strlen(reason_str) + 3);
 	sprintf(reason_buf, "%s%s%s", quote_str, reason_str, quote_str);/* Safe */
-
 	param->value = pj_str(reason_buf);
+	
+	pj_list_insert_before(&hdr->other_param, param);
 
+	param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
+	param->name = privacy_name;
+	
+	/* Privacy is either already quoted or it is a token to not need quotes added. */
+        quote_str = *privacy_str == '\"' || sip_is_token(privacy_str) ? "" : "\"";
+
+	privacy_buf = pj_pool_alloc(tdata->pool, strlen(privacy_str) + 3);
+	sprintf(privacy_buf, "%s%s%s", quote_str, privacy_str, quote_str);/* Safe */
+	param->value = pj_str(privacy_buf);
+	
 	pj_list_insert_before(&hdr->other_param, param);
 
 	hdr->uri = (pjsip_uri *) name_addr;
@@ -569,7 +599,7 @@
  * \param tdata The outbound message
  * \param data The redirecting data used to fill parts of the history-info header
  */
-static void add_history_info_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
+static void add_history_info_header(pjsip_tx_data *tdata, struct ast_sip_session *session)
 {
 	static const pj_str_t index_name = { "index", 5 };
 	static const pj_str_t cause_name = { "cause", 5 };
@@ -583,32 +613,43 @@
 	pjsip_fromto_hdr *old_hdr;
 	unsigned int cause;
 	char *cause_buf;
+	int restricted_to;
+	int restricted_from;
 
-	struct ast_party_id *to = &data->to;
-	struct ast_party_id *from = &data->from;
+	struct ast_party_id to = ast_channel_redirecting_effective_to(session->channel);
+	struct ast_party_id from = ast_channel_redirecting_effective_from(session->channel);
 
 	pjsip_uri *base = PJSIP_MSG_TO_HDR(tdata->msg)->uri;
 
-
 	hdr = pjsip_from_hdr_create(tdata->pool);
 	hdr->type = PJSIP_H_OTHER;
 	hdr->sname = hdr->name = history_info_name;
 
 	name_addr = pjsip_uri_clone(tdata->pool, base);
 	uri = pjsip_uri_get_uri(name_addr->uri);
+	
+	restricted_from =
+		((ast_party_id_presentation(&from) & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED);
 
 	/* if no redirecting information, then TO is the original destination */
-	if (from->number.valid && !ast_strlen_zero(from->number.str)) {
-		pj_strdup2(tdata->pool, &name_addr->display, from->name.str);
-		pj_strdup2(tdata->pool, &uri->user, from->number.str);
+	if (from.number.valid && !ast_strlen_zero(from.number.str)) {
+		if (session->endpoint->id.trust_outbound || !restricted_from) {
+			pj_strdup2(tdata->pool, &name_addr->display, from.name.str);
+			pj_strdup2(tdata->pool, &uri->user, from.number.str);
+		} else {
+			pj_strdup2(tdata->pool, &name_addr->display, "Anonymous");
+			pj_strdup2(tdata->pool, &uri->user, "anonymous");
+			pj_strdup2(tdata->pool, &uri->host, "anonymous.invalid");
+			uri->port = 0;
+		}
 	}
 
 	param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
 	param->name = index_name;
 	param->value = first_index;
 
-
 	pj_list_insert_before(&hdr->other_param, param);
+
 	hdr->uri = (pjsip_uri *) name_addr;
 
 	while ((old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &history_info_name, NULL)) != NULL) {
@@ -617,7 +658,7 @@
 
 	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
 
-	if (!to->number.valid || ast_strlen_zero(to->number.str)) {
+	if (!to.number.valid || ast_strlen_zero(to.number.str)) {
 		return;
 	}
 
@@ -628,8 +669,18 @@
 	name_addr = pjsip_uri_clone(tdata->pool, base);
 	uri = pjsip_uri_get_uri(name_addr->uri);
 
-	pj_strdup2(tdata->pool, &name_addr->display, to->name.str);
-	pj_strdup2(tdata->pool, &uri->user, to->number.str);
+	restricted_to =
+		((ast_party_id_presentation(&to) & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED);
+
+	if (session->endpoint->id.trust_outbound || !restricted_to) {
+		pj_strdup2(tdata->pool, &name_addr->display, to.name.str);
+		pj_strdup2(tdata->pool, &uri->user, to.number.str);
+	} else {
+		pj_strdup2(tdata->pool, &name_addr->display, "Anonymous");
+		pj_strdup2(tdata->pool, &uri->user, "anonymous");
+		pj_strdup2(tdata->pool, &uri->host, "anonymous.invalid");
+		uri->port = 0;
+	}
 
 	param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
 	param->name = index_name;
@@ -638,11 +689,12 @@
 
 	param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
 	param->name = cause_name;
-	cause = reason_code_to_cause(&data->reason);
+	cause = reason_code_to_cause(&ast_channel_redirecting(session->channel)->reason);
 	cause_buf = pj_pool_alloc(tdata->pool, 4);
 	snprintf(cause_buf, 4, "%ud", cause);
 	param->value = pj_str(cause_buf);
 	pj_list_insert_before(&uri->other_param, param);
+
 	hdr->uri = (pjsip_uri *) name_addr;
 
 	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
@@ -650,17 +702,14 @@
 
 static void get_redirecting_add_diversion(struct ast_sip_session *session, pjsip_tx_data *tdata)
 {
-	struct ast_party_redirecting *data;
-
 	add_supported(tdata);
 
 	if (session->channel && session->endpoint->id.send_diversion &&
-	    (data = ast_channel_redirecting(session->channel))->count) {
-		add_diversion_header(tdata, data);
+	    ast_channel_redirecting(session->channel)->count) {
+		add_diversion_header(tdata, session);
 	}
 	if (session->channel && session->endpoint->id.send_history_info) {
-		data = ast_channel_redirecting(session->channel);
-		add_history_info_header(tdata, data);
+		add_history_info_header(tdata, session);
 	}
 }
 
