CVE-2024-35190: Insufficient Information (NVD-CWE-noinfo)
value: Asterisk is an open source private branch exchange and telephony toolkit. After upgrade to 18.23.0, ALL unauthorized SIP requests are identified as PJSIP Endpoint of local asterisk server. This vulnerability is fixed in 18.23.1, 20.8.1, and 21.3.1.

CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-05-17T17:15Z
Repository: https://github.com/asterisk/asterisk
Language: C
Files changed: configs/samples/pjsip.conf.sample, contrib/ast-db-manage/config/versions/bd9c5159c7ea_revert_d5122576cca8_add_transport_.py, include/asterisk/res_pjsip.h, res/res_pjsip/pjsip_config.xml, res/res_pjsip/pjsip_configuration.c, res/res_pjsip_endpoint_identifier_ip.c
Commit date: 2024-05-17 16:34:45 +0000
Commit message: Revert "res_pjsip_endpoint_identifier_ip: Add endpoint identifier transport address."

This reverts PR #602

Resolves: #GHSA-qqxj-v78h-hrf9

Diff: diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index d52c7afb4e..6b8936b2d4 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -195,51 +195,10 @@
 ;tcp_keepalive_enable=yes        ; Enable TCP keepalive (yes/no)
 ;tcp_keepalive_idle_time=30      ; Time in seconds the connection needs to remain idle before TCP starts sending keepalive probes
 ;tcp_keepalive_interval_time=10  ; The time in seconds between individual keepalive probes
 ;tcp_keepalive_probe_count=5     ; The maximum number of keepalive probes TCP should send before dropping the connection
 
-;===============ENDPOINT IDENTIFIER TRANSPORT EXAMPLE==========================
-;
-; When Asterisk has multiple bound IP addresses, and endpoints don't use any
-; other means of identification (e.g.: username), the transports' bind addresses
-; can be used to identify them. Can be useful in case you're connecting to the
-; same ITSP multiple times on different IPs / NICs.
-;
-;[transport-eth0]
-;type=transport
-;protocol=tcp
-;bind=192.168.1.1:5060
-;
-;[transport-eth1]
-;type=transport
-;protocol=udp
-;bind=192.168.2.1:5060
-;
-;
-;[myprovider-a]
-;type=endpoint
-;transport=transport-eth0
-;identify_by=transport
-;
-;[myprovider-b]
-;type=endpoint
-;transport=transport-eth1
-;identify_by=transport
-;
-;
-;[identify-a]
-;type=identify
-;endpoint=myprovider-a
-;match=192.168.1.1:5060	; This is the bind address of [transport-eth0]
-;;transport=tcp		; Optionally, this is the transport protocol of [transport-eth0]
-;
-;[identify-b]
-;type=identify
-;endpoint=myprovider-b
-;match=192.168.2.1:5060	; This is the bind address of [transport-eth1]
-;;transport=udp		; Optionally, This is the transport protocol of [transport-eth1]
-
 ;===============OUTBOUND REGISTRATION WITH OUTBOUND AUTHENTICATION============
 ;
 ; This is a simple registration that works with some SIP trunking providers.
 ; You'll need to set up the auth example "mytrunk_auth" below to enable outbound
 ; authentication. Note that we use "outbound_auth=" for outbound authentication
@@ -723,14 +682,13 @@
 ;ice_support=no ; Enable the ICE mechanism to help traverse NAT (default: "no")
 ;identify_by=username   ; A comma-separated list of ways the Endpoint or AoR can be
                         ; identified.
                         ; "username": Identify by the From or To username and domain
                         ; "auth_username": Identify by the Authorization username and realm
-                        ; "ip": Identify by the source (remote) IP address
+                        ; "ip": Identify by the source IP address
                         ; "header": Identify by a configured SIP header value.
                         ; "request_uri": Identify by the configured SIP request URI.
-                        ; "transport": Identify by the bound (local) IP address
                         ; In the username and auth_username cases, if an exact match
                         ; on both username and domain/realm fails, the match is
                         ; retried with just the username.
                         ; (default: "username,ip")
 ;redirect_method=user   ; How redirects received from an endpoint are handled
@@ -1311,14 +1269,13 @@
             ; If disabled it can improve realtime performace by reducing
             ; number of database requsts
             ; (default: "no")
 ;endpoint_identifier_order=ip,username,anonymous
             ; The order by which endpoint identifiers are given priority.
-            ; Currently, "ip", "header", "request_uri", "transport", "username",
-            ; "auth_username" and "anonymous"  are valid identifiers as registered by
-            ; the res_pjsip_endpoint_identifier_* modules.
-            ; Some modules like res_pjsip_endpoint_identifier_user register
+            ; Currently, "ip", "header", "username", "auth_username" and "anonymous"
+            ; are valid identifiers as registered by the res_pjsip_endpoint_identifier_*
+            ; modules.  Some modules like res_pjsip_endpoint_identifier_user register
             ; more than one identifier.  Use the CLI command "pjsip show identifiers"
             ; to see the identifiers currently available.
             ; (default: ip,username,anonymous)
 ;max_initial_qualify_time=4 ; The maximum amount of time (in seconds) from
                             ; startup that qualifies should be attempted on all
@@ -1502,12 +1459,10 @@
 ;endpoint=      ; Name of endpoint identified (default: "")
 ;srv_lookups=yes        ; Perform SRV lookups for provided hostnames. (default: yes)
 ;match= ; Comma separated list of IP addresses, networks, or hostnames to match
         ; against (default: "")
 ;match_header= ; SIP header with specified value to match against (default: "")
-;match_request_uri= ; SIP request URI to match against (default: "")
-;transport= ; Match ageinst the transport protocol (tcp or udp) (default: "")
 ;type=  ; Must be of type identify (default: "")
 
 
 
 
diff --git a/contrib/ast-db-manage/config/versions/bd9c5159c7ea_revert_d5122576cca8_add_transport_.py b/contrib/ast-db-manage/config/versions/bd9c5159c7ea_revert_d5122576cca8_add_transport_.py
new file mode 100644
index 0000000000..5b3c1c2b3a
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/bd9c5159c7ea_revert_d5122576cca8_add_transport_.py
@@ -0,0 +1,22 @@
+"""Revert d5122576cca8 add transport attribute to identify
+
+Revision ID: bd9c5159c7ea
+Revises: 6c475a93f48a
+Create Date: 2024-05-17 08:30:58.299083
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'bd9c5159c7ea'
+down_revision = '6c475a93f48a'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.drop_column('ps_endpoint_id_ips', 'transport')
+
+
+def downgrade():
+    op.add_column('ps_endpoint_id_ips', sa.Column('transport', sa.String(128)))
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 984a38c673..d0e1e59223 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -615,12 +615,10 @@ enum ast_sip_endpoint_identifier_type {
 	AST_SIP_ENDPOINT_IDENTIFY_BY_IP = (1 << 2),
 	/*! Identify based on arbitrary headers */
 	AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER = (1 << 3),
 	/*! Identify based on request uri */
 	AST_SIP_ENDPOINT_IDENTIFY_BY_REQUEST_URI = (1 << 4),
-	/*! Identify based on bound (local) IP address */
-	AST_SIP_ENDPOINT_IDENTIFY_BY_TRANSPORT = (1 << 5),
 };
 AST_VECTOR(ast_sip_identify_by_vector, enum ast_sip_endpoint_identifier_type);
 
 enum ast_sip_session_refresh_method {
 	/*! Use reinvite to negotiate direct media */
diff --git a/res/res_pjsip/pjsip_config.xml b/res/res_pjsip/pjsip_config.xml
index 094123fff5..753037b555 100644
--- a/res/res_pjsip/pjsip_config.xml
+++ b/res/res_pjsip/pjsip_config.xml
@@ -563,18 +563,10 @@
 								</para>
 								<para>This method of identification is not configured here
 								but simply allowed by this configuration option.
 								</para>
 							</enum>
-							<enum name="transport">
-								<para>Matches the endpoint based on the destination IP
-								address.
-								</para>
-								<para>This method of identification is not configured here
-								but simply allowed by this configuration option.
-								</para>
-							</enum>
 						</enumlist>
 					</description>
 				</configOption>
 				<configOption name="redirect_method">
 					<synopsis>How redirects received from an endpoint are handled</synopsis>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 268607a988..58a50c484a 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -424,13 +424,10 @@ static const char *sip_endpoint_identifier_type2str(enum ast_sip_endpoint_identi
 		str = "header";
 		break;
 	case AST_SIP_ENDPOINT_IDENTIFY_BY_REQUEST_URI:
 		str = "request_uri";
 		break;
-	case AST_SIP_ENDPOINT_IDENTIFY_BY_TRANSPORT:
-		str = "transport";
-		break;
 	}
 	return str;
 }
 
 /*!
@@ -454,12 +451,10 @@ static int sip_endpoint_identifier_str2type(const char *str)
 		method = AST_SIP_ENDPOINT_IDENTIFY_BY_IP;
 	} else if (!strcasecmp(str, "header")) {
 		method = AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER;
 	} else if (!strcasecmp(str, "request_uri")) {
 		method = AST_SIP_ENDPOINT_IDENTIFY_BY_REQUEST_URI;
-	} else if (!strcasecmp(str, "transport")) {
-		method = AST_SIP_ENDPOINT_IDENTIFY_BY_TRANSPORT;
 	} else {
 		method = -1;
 	}
 	return method;
 }
diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c
index 69e0c76064..da5c363f3a 100644
--- a/res/res_pjsip_endpoint_identifier_ip.c
+++ b/res/res_pjsip_endpoint_identifier_ip.c
@@ -122,20 +122,10 @@
 						<note><para>Use of a regex is expensive so be sure you need
 						to use a regex to match your endpoint.
 						</para></note>
 					</description>
 				</configOption>
-				<configOption name="transport">
-					<synopsis>Match against a transport type.</synopsis>
-					<description>
-						<para>When using the ip or transport identifier, this option
-						can be used to match the transport type <literal>(udp or tcp)
-						</literal> as well.</para>
-						<para>When omitted, or left empty, which is the default, it
-						won't match against the transport type.</para>
-					</description>
-				</configOption>
 				<configOption name="type">
 					<synopsis>Must be of type 'identify'.</synopsis>
 				</configOption>
 			</configObject>
 		</configFile>
@@ -159,12 +149,10 @@ struct ip_identify_match {
 		AST_STRING_FIELD(match_header);
 		/*! SIP header name of the match_header string */
 		AST_STRING_FIELD(match_header_name);
 		/*! SIP header value of the match_header string */
 		AST_STRING_FIELD(match_header_value);
-		/*! The name of the transport type */
-		AST_STRING_FIELD(transport);
 	);
 	/*! Compiled match_header regular expression when is_header_regex is non-zero */
 	regex_t regex_header_buf;
 	/*! Compiled match_request_uri regular expression when is_request_uri_regex is non-zero */
 	regex_t regex_request_uri_buf;
@@ -178,16 +166,10 @@ struct ip_identify_match {
 	unsigned int is_header_regex:1;
 	/*! Non-zero if match_header or match_request has a regular expression (i.e., regex_request_uri_buf is valid) */
 	unsigned int is_request_uri_regex:1;
 };
 
-/*! \brief Structure for a socket address with transport */
-struct ast_sockaddr_with_tp {
-	struct ast_sockaddr addr;
-	char tp[128];
-};
-
 /*! \brief Destructor function for a matching object */
 static void ip_identify_destroy(void *obj)
 {
 	struct ip_identify_match *identify = obj;
 
@@ -319,33 +301,22 @@ static int request_identify_match_check(void *obj, void *arg, int flags)
 
 /*! \brief Comparator function for matching an object by IP address */
 static int ip_identify_match_check(void *obj, void *arg, int flags)
 {
 	struct ip_identify_match *identify = obj;
-	struct ast_sockaddr_with_tp *addr_with_tp = arg;
-	struct ast_sockaddr address = addr_with_tp->addr;
+	struct ast_sockaddr *addr = arg;
 	int sense;
 
-	sense = ast_apply_ha(identify->matches, &address);
+	sense = ast_apply_ha(identify->matches, addr);
 	if (sense != AST_SENSE_ALLOW) {
-		ast_debug(3, "Address %s matches identify '%s'\n",
-				ast_sockaddr_stringify(&address),
-				ast_sorcery_object_get_id(identify));
-		if (ast_strlen_zero(identify->transport) || !strcasecmp(identify->transport, addr_with_tp->tp)) {
-			ast_debug(3, "Transport %s matches identify '%s'\n",
-				addr_with_tp->tp,
-				ast_sorcery_object_get_id(identify));
-			return CMP_MATCH;
-		} else {
-			ast_debug(3, "Transport %s match not matched identify '%s'\n",
-				addr_with_tp->tp,
+		ast_debug(3, "Source address %s matches identify '%s'\n",
+				ast_sockaddr_stringify(addr),
 				ast_sorcery_object_get_id(identify));
-			return 0;
-		}
+		return CMP_MATCH;
 	} else {
-		ast_debug(3, "Address %s does not match identify '%s'\n",
-				ast_sockaddr_stringify(&address),
+		ast_debug(3, "Source address %s does not match identify '%s'\n",
+				ast_sockaddr_stringify(addr),
 				ast_sorcery_object_get_id(identify));
 		return 0;
 	}
 }
 
@@ -382,58 +353,22 @@ static struct ast_sip_endpoint *common_identify(ao2_callback_fn *identify_match_
 	return endpoint;
 }
 
 static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata)
 {
-	struct ast_sockaddr_with_tp addr_with_tp = { { { 0, } }, };
-	pj_ansi_strxcpy(addr_with_tp.tp, rdata->tp_info.transport->type_name, sizeof(addr_with_tp.tp));
-
-	ast_sockaddr_parse(&addr_with_tp.addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
-	ast_sockaddr_set_port(&addr_with_tp.addr, rdata->pkt_info.src_port);
-
-	return common_identify(ip_identify_match_check, &addr_with_tp);
-}
-
-static struct ast_sip_endpoint *transport_identify(pjsip_rx_data *rdata)
-{
-	char buffer[PJ_INET6_ADDRSTRLEN];
-	pj_status_t status;
-	struct ast_sockaddr_with_tp addr_with_tp = { { { 0, } }, };
-	union pj_sockaddr sock = rdata->tp_info.transport->local_addr;
-
-	pj_ansi_strxcpy(addr_with_tp.tp, rdata->tp_info.transport->type_name, sizeof(addr_with_tp.tp));
-
-	if (sock.addr.sa_family == PJ_AF_INET6) {
-		status = pj_inet_ntop(PJ_AF_INET6, &(sock.ipv6.sin6_addr), buffer, PJ_INET6_ADDRSTRLEN);
-		if (status == PJ_SUCCESS && !strcmp(buffer, "::")) {
-			ast_log(LOG_WARNING, "Matching against '::' may be unpredictable.\n");
-		}
-	} else {
-		status = pj_inet_ntop(PJ_AF_INET, &(sock.ipv4.sin_addr), buffer, PJ_INET_ADDRSTRLEN);
-		if (status == PJ_SUCCESS && !strcmp(buffer, "0.0.0.0")) {
-			ast_log(LOG_WARNING, "Matching against '0.0.0.0' may be unpredictable.\n");
-		}
-	}
+	struct ast_sockaddr addr = { { 0, } };
 
-	if (status == PJ_SUCCESS) {
-		ast_sockaddr_parse(&addr_with_tp.addr, buffer, PARSE_PORT_FORBID);
-		ast_sockaddr_set_port(&addr_with_tp.addr, rdata->tp_info.transport->local_name.port);
+	ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
+	ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
 
-		return common_identify(ip_identify_match_check, &addr_with_tp);
-	} else {
-		return NULL;
-	}
+	return common_identify(ip_identify_match_check, &addr);
 }
 
 static struct ast_sip_endpoint_identifier ip_identifier = {
 	.identify_endpoint = ip_identify,
 };
 
-static struct ast_sip_endpoint_identifier transport_identifier = {
-	.identify_endpoint = transport_identify,
-};
-
 static struct ast_sip_endpoint *header_identify(pjsip_rx_data *rdata)
 {
 	return common_identify(header_identify_match_check, rdata);
 }
 
@@ -593,16 +528,10 @@ static int ip_identify_apply(const struct ast_sorcery *sorcery, void *obj)
 		ast_log(LOG_ERROR, "Identify '%s' is not configured to match anything.\n",
 			ast_sorcery_object_get_id(identify));
 		return -1;
 	}
 
-	if (!ast_strlen_zero(identify->transport)) {
-		if (ast_string_field_set(identify, transport, identify->transport)) {
-			return -1;
-		}
-	}
-
 	if (!ast_strlen_zero(identify->match_header)) {
 		char *c_header;
 		char *c_value;
 		int len;
 
@@ -948,17 +877,10 @@ static int cli_print_body(void *obj, void *arg, int flags)
 				"Match",
 				match->sense == AST_SENSE_ALLOW ? "!" : "",
 				addr, ast_sockaddr_cidr_bits(&match->netmask));
 		}
 
-		if (!ast_strlen_zero(ident->transport)) {
-			ast_str_append(&context->output_buffer, 0, "%*s: %s\n",
-				indent,
-				"Transport",
-				ident->transport);
-		}
-
 		if (!ast_strlen_zero(ident->match_header)) {
 			ast_str_append(&context->output_buffer, 0, "%*s: %s\n",
 				indent,
 				"Header",
 				ident->match_header);
@@ -1030,17 +952,15 @@ static int load_module(void)
 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, endpoint_name));
 	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "identify", "match", "", ip_identify_match_handler, match_to_str, match_to_var_list, 0, 0);
 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "match_header", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, match_header));
 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "match_request_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, match_request_uri));
 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "srv_lookups", "yes", OPT_BOOL_T, 1, FLDSET(struct ip_identify_match, srv_lookups));
-	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, transport));
 	ast_sorcery_load_object(ast_sip_get_sorcery(), "identify");
 
 	ast_sip_register_endpoint_identifier_with_name(&ip_identifier, "ip");
 	ast_sip_register_endpoint_identifier_with_name(&header_identifier, "header");
 	ast_sip_register_endpoint_identifier_with_name(&request_identifier, "request_uri");
-	ast_sip_register_endpoint_identifier_with_name(&transport_identifier, "transport");
 	ast_sip_register_endpoint_formatter(&endpoint_identify_formatter);
 
 	cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
 	if (!cli_formatter) {
 		ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
@@ -1073,11 +993,10 @@ static int unload_module(void)
 	ast_sip_unregister_cli_formatter(cli_formatter);
 	ast_sip_unregister_endpoint_formatter(&endpoint_identify_formatter);
 	ast_sip_unregister_endpoint_identifier(&header_identifier);
 	ast_sip_unregister_endpoint_identifier(&request_identifier);
 	ast_sip_unregister_endpoint_identifier(&ip_identifier);
-	ast_sip_unregister_endpoint_identifier(&transport_identifier);
 
 	return 0;
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP IP endpoint identifier",

Vulnerable code: ;===============ENDPOINT IDENTIFIER TRANSPORT EXAMPLE==========================
;
; When Asterisk has multiple bound IP addresses, and endpoints don't use any
; other means of identification (e.g.: username), the transports' bind addresses
; can be used to identify them. Can be useful in case you're connecting to the
; same ITSP multiple times on different IPs / NICs.
;
;[transport-eth0]
;type=transport
;protocol=tcp
;bind=192.168.1.1:5060
;
;[transport-eth1]
;type=transport
;protocol=udp
;bind=192.168.2.1:5060
;
;
;[myprovider-a]
;type=endpoint
;transport=transport-eth0
;identify_by=transport
;
;[myprovider-b]
;type=endpoint
;transport=transport-eth1
;identify_by=transport
;
;
;[identify-a]
;type=identify
;endpoint=myprovider-a
;match=192.168.1.1:5060	; This is the bind address of [transport-eth0]
;;transport=tcp		; Optionally, this is the transport protocol of [transport-eth0]
;
;[identify-b]
;type=identify
;endpoint=myprovider-b
;match=192.168.2.1:5060	; This is the bind address of [transport-eth1]
;;transport=udp		; Optionally, This is the transport protocol of [transport-eth1]

                        ; "ip": Identify by the source (remote) IP address
                        ; "transport": Identify by the bound (local) IP address
            ; Currently, "ip", "header", "request_uri", "transport", "username",
            ; "auth_username" and "anonymous"  are valid identifiers as registered by
            ; the res_pjsip_endpoint_identifier_* modules.
            ; Some modules like res_pjsip_endpoint_identifier_user register
;match_request_uri= ; SIP request URI to match against (default: "")
;transport= ; Match ageinst the transport protocol (tcp or udp) (default: "")
	/*! Identify based on bound (local) IP address */
	AST_SIP_ENDPOINT_IDENTIFY_BY_TRANSPORT = (1 << 5),
							<enum name="transport">
								<para>Matches the endpoint based on the destination IP
								address.
								</para>
								<para>This method of identification is not configured here
								but simply allowed by this configuration option.
								</para>
							</enum>
	case AST_SIP_ENDPOINT_IDENTIFY_BY_TRANSPORT:
		str = "transport";
		break;
	} else if (!strcasecmp(str, "transport")) {
		method = AST_SIP_ENDPOINT_IDENTIFY_BY_TRANSPORT;
				<configOption name="transport">
					<synopsis>Match against a transport type.</synopsis>
					<description>
						<para>When using the ip or transport identifier, this option
						can be used to match the transport type <literal>(udp or tcp)
						</literal> as well.</para>
						<para>When omitted, or left empty, which is the default, it
						won't match against the transport type.</para>
					</description>
				</configOption>
		/*! The name of the transport type */
		AST_STRING_FIELD(transport);
/*! \brief Structure for a socket address with transport */
struct ast_sockaddr_with_tp {
	struct ast_sockaddr addr;
	char tp[128];
};

	struct ast_sockaddr_with_tp *addr_with_tp = arg;
	struct ast_sockaddr address = addr_with_tp->addr;
	sense = ast_apply_ha(identify->matches, &address);
		ast_debug(3, "Address %s matches identify '%s'\n",
				ast_sockaddr_stringify(&address),
				ast_sorcery_object_get_id(identify));
		if (ast_strlen_zero(identify->transport) || !strcasecmp(identify->transport, addr_with_tp->tp)) {
			ast_debug(3, "Transport %s matches identify '%s'\n",
				addr_with_tp->tp,
				ast_sorcery_object_get_id(identify));
			return CMP_MATCH;
		} else {
			ast_debug(3, "Transport %s match not matched identify '%s'\n",
				addr_with_tp->tp,
			return 0;
		}
		ast_debug(3, "Address %s does not match identify '%s'\n",
				ast_sockaddr_stringify(&address),
	struct ast_sockaddr_with_tp addr_with_tp = { { { 0, } }, };
	pj_ansi_strxcpy(addr_with_tp.tp, rdata->tp_info.transport->type_name, sizeof(addr_with_tp.tp));

	ast_sockaddr_parse(&addr_with_tp.addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
	ast_sockaddr_set_port(&addr_with_tp.addr, rdata->pkt_info.src_port);

	return common_identify(ip_identify_match_check, &addr_with_tp);
}

static struct ast_sip_endpoint *transport_identify(pjsip_rx_data *rdata)
{
	char buffer[PJ_INET6_ADDRSTRLEN];
	pj_status_t status;
	struct ast_sockaddr_with_tp addr_with_tp = { { { 0, } }, };
	union pj_sockaddr sock = rdata->tp_info.transport->local_addr;

	pj_ansi_strxcpy(addr_with_tp.tp, rdata->tp_info.transport->type_name, sizeof(addr_with_tp.tp));

	if (sock.addr.sa_family == PJ_AF_INET6) {
		status = pj_inet_ntop(PJ_AF_INET6, &(sock.ipv6.sin6_addr), buffer, PJ_INET6_ADDRSTRLEN);
		if (status == PJ_SUCCESS && !strcmp(buffer, "::")) {
			ast_log(LOG_WARNING, "Matching against '::' may be unpredictable.\n");
		}
	} else {
		status = pj_inet_ntop(PJ_AF_INET, &(sock.ipv4.sin_addr), buffer, PJ_INET_ADDRSTRLEN);
		if (status == PJ_SUCCESS && !strcmp(buffer, "0.0.0.0")) {
			ast_log(LOG_WARNING, "Matching against '0.0.0.0' may be unpredictable.\n");
		}
	}
	if (status == PJ_SUCCESS) {
		ast_sockaddr_parse(&addr_with_tp.addr, buffer, PARSE_PORT_FORBID);
		ast_sockaddr_set_port(&addr_with_tp.addr, rdata->tp_info.transport->local_name.port);
		return common_identify(ip_identify_match_check, &addr_with_tp);
	} else {
		return NULL;
	}
static struct ast_sip_endpoint_identifier transport_identifier = {
	.identify_endpoint = transport_identify,
};

	if (!ast_strlen_zero(identify->transport)) {
		if (ast_string_field_set(identify, transport, identify->transport)) {
			return -1;
		}
	}

		if (!ast_strlen_zero(ident->transport)) {
			ast_str_append(&context->output_buffer, 0, "%*s: %s\n",
				indent,
				"Transport",
				ident->transport);
		}

	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, transport));
	ast_sip_register_endpoint_identifier_with_name(&transport_identifier, "transport");
	ast_sip_unregister_endpoint_identifier(&transport_identifier);
Fixed code:                         ; "ip": Identify by the source IP address
            ; Currently, "ip", "header", "username", "auth_username" and "anonymous"
            ; are valid identifiers as registered by the res_pjsip_endpoint_identifier_*
            ; modules.  Some modules like res_pjsip_endpoint_identifier_user register
"""Revert d5122576cca8 add transport attribute to identify

Revision ID: bd9c5159c7ea
Revises: 6c475a93f48a
Create Date: 2024-05-17 08:30:58.299083

"""

# revision identifiers, used by Alembic.
revision = 'bd9c5159c7ea'
down_revision = '6c475a93f48a'

from alembic import op
import sqlalchemy as sa


def upgrade():
    op.drop_column('ps_endpoint_id_ips', 'transport')


def downgrade():
    op.add_column('ps_endpoint_id_ips', sa.Column('transport', sa.String(128)))
	struct ast_sockaddr *addr = arg;
	sense = ast_apply_ha(identify->matches, addr);
		ast_debug(3, "Source address %s matches identify '%s'\n",
				ast_sockaddr_stringify(addr),
		return CMP_MATCH;
		ast_debug(3, "Source address %s does not match identify '%s'\n",
				ast_sockaddr_stringify(addr),
	struct ast_sockaddr addr = { { 0, } };
	ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
	ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
	return common_identify(ip_identify_match_check, &addr);