mirror of
https://github.com/open5gs/open5gs.git
synced 2026-04-28 03:19:31 +00:00
[ePDG] Add Node-Identifier IE support in GTPv2 S2b Create-Session-Request for SMF Diameter S6b Routing (#3507)
Implement support for Node-Identifier IE in GTPv2 S2b Create-Session-Request to SMF for Diameter S6b integration This patch adds support for processing the Node-Identifier IE within GTPv2 Create-Session-Request messages sent via the S2b interface to the SMF. When the ePDG includes the Node-Identifier IE containing both host and realm of the AAA-Server, the SMF now uses this information to populate the Destination-Realm and Destination-Host AVPs in the Diameter S6b AAR message. This enables seamless integration and allows the SMF to route requests directly to the appropriate AAA-Server, enhancing interoperability in setups where the host and realm data are required by the Diameter network.
This commit is contained in:
parent
ce36143f5c
commit
bc02e48d1a
7 changed files with 186 additions and 5 deletions
|
|
@ -26,13 +26,15 @@
|
||||||
int16_t ogs_gtp2_parse_bearer_qos(
|
int16_t ogs_gtp2_parse_bearer_qos(
|
||||||
ogs_gtp2_bearer_qos_t *bearer_qos, ogs_tlv_octet_t *octet)
|
ogs_gtp2_bearer_qos_t *bearer_qos, ogs_tlv_octet_t *octet)
|
||||||
{
|
{
|
||||||
ogs_gtp2_bearer_qos_t *source = (ogs_gtp2_bearer_qos_t *)octet->data;
|
ogs_gtp2_bearer_qos_t *source = NULL;
|
||||||
int16_t size = 0;
|
int16_t size = 0;
|
||||||
|
|
||||||
ogs_assert(bearer_qos);
|
ogs_assert(bearer_qos);
|
||||||
ogs_assert(octet);
|
ogs_assert(octet);
|
||||||
ogs_assert(octet->len == GTP2_BEARER_QOS_LEN);
|
ogs_assert(octet->len == GTP2_BEARER_QOS_LEN);
|
||||||
|
|
||||||
|
source = (ogs_gtp2_bearer_qos_t *)octet->data;
|
||||||
|
|
||||||
memset(bearer_qos, 0, sizeof(ogs_gtp2_bearer_qos_t));
|
memset(bearer_qos, 0, sizeof(ogs_gtp2_bearer_qos_t));
|
||||||
|
|
||||||
bearer_qos->pre_emption_capability = source->pre_emption_capability;
|
bearer_qos->pre_emption_capability = source->pre_emption_capability;
|
||||||
|
|
@ -201,13 +203,15 @@ uint64_t ogs_gtp2_qos_to_kbps(uint8_t br, uint8_t extended, uint8_t extended2)
|
||||||
int16_t ogs_gtp2_parse_flow_qos(
|
int16_t ogs_gtp2_parse_flow_qos(
|
||||||
ogs_gtp2_flow_qos_t *flow_qos, ogs_tlv_octet_t *octet)
|
ogs_gtp2_flow_qos_t *flow_qos, ogs_tlv_octet_t *octet)
|
||||||
{
|
{
|
||||||
ogs_gtp2_flow_qos_t *source = (ogs_gtp2_flow_qos_t *)octet->data;
|
ogs_gtp2_flow_qos_t *source = NULL;
|
||||||
int16_t size = 0;
|
int16_t size = 0;
|
||||||
|
|
||||||
ogs_assert(flow_qos);
|
ogs_assert(flow_qos);
|
||||||
ogs_assert(octet);
|
ogs_assert(octet);
|
||||||
ogs_assert(octet->len == GTP2_FLOW_QOS_LEN);
|
ogs_assert(octet->len == GTP2_FLOW_QOS_LEN);
|
||||||
|
|
||||||
|
source = (ogs_gtp2_flow_qos_t *)octet->data;
|
||||||
|
|
||||||
memset(flow_qos, 0, sizeof(ogs_gtp2_flow_qos_t));
|
memset(flow_qos, 0, sizeof(ogs_gtp2_flow_qos_t));
|
||||||
|
|
||||||
flow_qos->qci = source->qci;
|
flow_qos->qci = source->qci;
|
||||||
|
|
@ -617,12 +621,14 @@ int16_t ogs_gtp2_build_tft(
|
||||||
/* 8.21 User Location Information (ULI) */
|
/* 8.21 User Location Information (ULI) */
|
||||||
int16_t ogs_gtp2_parse_uli(ogs_gtp2_uli_t *uli, ogs_tlv_octet_t *octet)
|
int16_t ogs_gtp2_parse_uli(ogs_gtp2_uli_t *uli, ogs_tlv_octet_t *octet)
|
||||||
{
|
{
|
||||||
ogs_gtp2_uli_t *source = (ogs_gtp2_uli_t *)octet->data;
|
ogs_gtp2_uli_t *source = NULL;
|
||||||
int16_t size = 0;
|
int16_t size = 0;
|
||||||
|
|
||||||
ogs_assert(uli);
|
ogs_assert(uli);
|
||||||
ogs_assert(octet);
|
ogs_assert(octet);
|
||||||
|
|
||||||
|
source = (ogs_gtp2_uli_t *)octet->data;
|
||||||
|
|
||||||
memset(uli, 0, sizeof(ogs_gtp2_uli_t));
|
memset(uli, 0, sizeof(ogs_gtp2_uli_t));
|
||||||
|
|
||||||
uli->flags = source->flags;
|
uli->flags = source->flags;
|
||||||
|
|
@ -796,3 +802,95 @@ int16_t ogs_gtp2_build_uli(
|
||||||
|
|
||||||
return octet->len;
|
return octet->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t ogs_gtp2_parse_node_identifier(
|
||||||
|
ogs_gtp2_node_identifier_t *node_identifier, ogs_tlv_octet_t *octet)
|
||||||
|
{
|
||||||
|
int16_t size = 0;
|
||||||
|
|
||||||
|
ogs_assert(node_identifier);
|
||||||
|
ogs_assert(octet);
|
||||||
|
|
||||||
|
memset(node_identifier, 0, sizeof(ogs_gtp2_node_identifier_t));
|
||||||
|
|
||||||
|
if (size + sizeof(node_identifier->name_len) > octet->len) {
|
||||||
|
ogs_error("Invalid TLV length [%d != %d]", size, octet->len);
|
||||||
|
ogs_log_hexdump(OGS_LOG_ERROR, octet->data, octet->len);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
memcpy(&node_identifier->name_len,
|
||||||
|
(unsigned char *)octet->data + size,
|
||||||
|
sizeof(node_identifier->name_len));
|
||||||
|
size += sizeof(node_identifier->name_len);
|
||||||
|
|
||||||
|
if (size + node_identifier->name_len > octet->len) {
|
||||||
|
ogs_error("Invalid TLV length [%d != %d]", size, octet->len);
|
||||||
|
ogs_log_hexdump(OGS_LOG_ERROR, octet->data, octet->len);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
node_identifier->name = (char *)octet->data + size;
|
||||||
|
size += node_identifier->name_len;
|
||||||
|
|
||||||
|
if (size + sizeof(node_identifier->realm_len) > octet->len) {
|
||||||
|
ogs_error("Invalid TLV length [%d != %d]", size, octet->len);
|
||||||
|
ogs_log_hexdump(OGS_LOG_ERROR, octet->data, octet->len);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
memcpy(&node_identifier->realm_len,
|
||||||
|
(unsigned char *)octet->data + size,
|
||||||
|
sizeof(node_identifier->realm_len));
|
||||||
|
size += sizeof(node_identifier->realm_len);
|
||||||
|
|
||||||
|
if (size + node_identifier->realm_len > octet->len) {
|
||||||
|
ogs_error("Invalid TLV length [%d != %d]", size, octet->len);
|
||||||
|
ogs_log_hexdump(OGS_LOG_ERROR, octet->data, octet->len);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
node_identifier->realm = (char *)octet->data + size;
|
||||||
|
size += node_identifier->realm_len;
|
||||||
|
|
||||||
|
if (size != octet->len) {
|
||||||
|
ogs_error("Invalid TLV length [%d != %d]", size, octet->len);
|
||||||
|
ogs_log_hexdump(OGS_LOG_ERROR, octet->data, octet->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
int16_t ogs_gtp2_build_node_identifier(ogs_tlv_octet_t *octet,
|
||||||
|
ogs_gtp2_node_identifier_t *node_identifier, void *data, int data_len)
|
||||||
|
{
|
||||||
|
int16_t size = 0;
|
||||||
|
|
||||||
|
ogs_assert(node_identifier);
|
||||||
|
ogs_assert(octet);
|
||||||
|
ogs_assert(data);
|
||||||
|
ogs_assert(data_len);
|
||||||
|
|
||||||
|
octet->data = data;
|
||||||
|
|
||||||
|
ogs_assert(size + sizeof(node_identifier->name_len) <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
&node_identifier->name_len,
|
||||||
|
sizeof(node_identifier->name_len));
|
||||||
|
size += sizeof(node_identifier->name_len);
|
||||||
|
|
||||||
|
ogs_assert(size + node_identifier->name_len <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
node_identifier->name, node_identifier->name_len);
|
||||||
|
size += node_identifier->name_len;
|
||||||
|
|
||||||
|
ogs_assert(size + sizeof(node_identifier->realm_len) <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
&node_identifier->realm_len,
|
||||||
|
sizeof(node_identifier->realm_len));
|
||||||
|
size += sizeof(node_identifier->realm_len);
|
||||||
|
|
||||||
|
ogs_assert(size + node_identifier->realm_len <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
node_identifier->realm, node_identifier->realm_len);
|
||||||
|
size += node_identifier->realm_len;
|
||||||
|
|
||||||
|
octet->len = size;
|
||||||
|
|
||||||
|
return octet->len;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -571,6 +571,20 @@ ED5(uint8_t spare1:1;,
|
||||||
uint8_t pre_emption_capability:1;)
|
uint8_t pre_emption_capability:1;)
|
||||||
} __attribute__ ((packed)) ogs_gtp2_arp_t;
|
} __attribute__ ((packed)) ogs_gtp2_arp_t;
|
||||||
|
|
||||||
|
/* 8.107 Node Identifier */
|
||||||
|
#define OGS_GTP2_MAX_NODE_IDENTIFIER_LEN (1+OGS_MAX_FQDN_LEN)*2
|
||||||
|
typedef struct ogs_gtp2_node_identifier_s {
|
||||||
|
uint8_t name_len;
|
||||||
|
char *name;
|
||||||
|
uint8_t realm_len;
|
||||||
|
char *realm;
|
||||||
|
} ogs_gtp2_node_identifier_t;
|
||||||
|
|
||||||
|
int16_t ogs_gtp2_parse_node_identifier(
|
||||||
|
ogs_gtp2_node_identifier_t *node_identifier, ogs_tlv_octet_t *octet);
|
||||||
|
int16_t ogs_gtp2_build_node_identifier(ogs_tlv_octet_t *octet,
|
||||||
|
ogs_gtp2_node_identifier_t *node_identifier, void *data, int data_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1791,6 +1791,11 @@ void smf_sess_remove(smf_sess_t *sess)
|
||||||
/* Free SBI object memory */
|
/* Free SBI object memory */
|
||||||
ogs_sbi_object_free(&sess->sbi);
|
ogs_sbi_object_free(&sess->sbi);
|
||||||
|
|
||||||
|
if (sess->aaa_server_identifier.name)
|
||||||
|
ogs_free(sess->aaa_server_identifier.name);
|
||||||
|
if (sess->aaa_server_identifier.realm)
|
||||||
|
ogs_free(sess->aaa_server_identifier.realm);
|
||||||
|
|
||||||
smf_bearer_remove_all(sess);
|
smf_bearer_remove_all(sess);
|
||||||
|
|
||||||
ogs_assert(sess->pfcp.bar);
|
ogs_assert(sess->pfcp.bar);
|
||||||
|
|
|
||||||
|
|
@ -486,6 +486,12 @@ typedef struct smf_sess_s {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
} charging;
|
} charging;
|
||||||
|
|
||||||
|
/* AAA Node Identifier */
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
char *realm;
|
||||||
|
} aaa_server_identifier;
|
||||||
|
|
||||||
/* Data Forwarding between the CP and UP functions */
|
/* Data Forwarding between the CP and UP functions */
|
||||||
ogs_pfcp_pdr_t *cp2up_pdr;
|
ogs_pfcp_pdr_t *cp2up_pdr;
|
||||||
ogs_pfcp_pdr_t *up2cp_pdr;
|
ogs_pfcp_pdr_t *up2cp_pdr;
|
||||||
|
|
|
||||||
|
|
@ -445,6 +445,34 @@ uint8_t smf_s5c_handle_create_session_request(
|
||||||
smf_ue->imeisv, smf_ue->imeisv_len, smf_ue->imeisv_bcd);
|
smf_ue->imeisv, smf_ue->imeisv_len, smf_ue->imeisv_bcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set Node Identifier */
|
||||||
|
if (req->_aaa_server_identifier.presence) {
|
||||||
|
ogs_gtp2_node_identifier_t node_identifier;
|
||||||
|
decoded = ogs_gtp2_parse_node_identifier(
|
||||||
|
&node_identifier, &req->_aaa_server_identifier);
|
||||||
|
if (req->_aaa_server_identifier.len == decoded) {
|
||||||
|
if (sess->aaa_server_identifier.name)
|
||||||
|
ogs_free(sess->aaa_server_identifier.name);
|
||||||
|
sess->aaa_server_identifier.name = ogs_memdup(
|
||||||
|
node_identifier.name, node_identifier.name_len+1);
|
||||||
|
ogs_assert(sess->aaa_server_identifier.name);
|
||||||
|
sess->aaa_server_identifier.name[node_identifier.name_len] = 0;
|
||||||
|
|
||||||
|
if (sess->aaa_server_identifier.realm)
|
||||||
|
ogs_free(sess->aaa_server_identifier.realm);
|
||||||
|
sess->aaa_server_identifier.realm = ogs_memdup(
|
||||||
|
node_identifier.realm, node_identifier.realm_len+1);
|
||||||
|
ogs_assert(sess->aaa_server_identifier.realm);
|
||||||
|
sess->aaa_server_identifier.realm[node_identifier.realm_len] = 0;
|
||||||
|
} else {
|
||||||
|
ogs_error("Invalid AAA Server Identifier [%d != %d]",
|
||||||
|
req->_aaa_server_identifier.len, decoded);
|
||||||
|
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||||
|
req->_aaa_server_identifier.data,
|
||||||
|
req->_aaa_server_identifier.len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,11 +176,28 @@ void smf_s6b_send_aar(smf_sess_t *sess, ogs_gtp_xact_t *xact)
|
||||||
ret = fd_msg_add_origin(req, 0);
|
ret = fd_msg_add_origin(req, 0);
|
||||||
ogs_assert(ret == 0);
|
ogs_assert(ret == 0);
|
||||||
|
|
||||||
|
/* Set the Destination-Host AVP */
|
||||||
|
if (sess->aaa_server_identifier.name) {
|
||||||
|
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
val.os.data = (unsigned char *)sess->aaa_server_identifier.name;
|
||||||
|
val.os.len = strlen(sess->aaa_server_identifier.name);
|
||||||
|
ret = fd_msg_avp_setvalue(avp, &val);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the Destination-Realm AVP */
|
/* Set the Destination-Realm AVP */
|
||||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||||
ogs_assert(ret == 0);
|
ogs_assert(ret == 0);
|
||||||
val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm);
|
if (sess->aaa_server_identifier.realm) {
|
||||||
val.os.len = strlen(fd_g_config->cnf_diamrlm);
|
val.os.data = (unsigned char *)(sess->aaa_server_identifier.realm);
|
||||||
|
val.os.len = strlen(sess->aaa_server_identifier.realm);
|
||||||
|
} else {
|
||||||
|
val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm);
|
||||||
|
val.os.len = strlen(fd_g_config->cnf_diamrlm);
|
||||||
|
}
|
||||||
ret = fd_msg_avp_setvalue(avp, &val);
|
ret = fd_msg_avp_setvalue(avp, &val);
|
||||||
ogs_assert(ret == 0);
|
ogs_assert(ret == 0);
|
||||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ ogs_pkbuf_t *test_s2b_build_create_session_request(
|
||||||
|
|
||||||
ogs_gtp2_indication_t indication;
|
ogs_gtp2_indication_t indication;
|
||||||
|
|
||||||
|
char node_identifier_buf[OGS_GTP2_MAX_NODE_IDENTIFIER_LEN];
|
||||||
|
ogs_gtp2_node_identifier_t node_identifier;
|
||||||
|
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
test_ue = sess->test_ue;
|
test_ue = sess->test_ue;
|
||||||
ogs_assert(test_ue);
|
ogs_assert(test_ue);
|
||||||
|
|
@ -172,6 +175,16 @@ ogs_pkbuf_t *test_s2b_build_create_session_request(
|
||||||
(uint8_t *)"\x80\x00\x0d\x00";
|
(uint8_t *)"\x80\x00\x0d\x00";
|
||||||
req->additional_protocol_configuration_options.len = 4;
|
req->additional_protocol_configuration_options.len = 4;
|
||||||
|
|
||||||
|
memset(&node_identifier, 0, sizeof(ogs_gtp2_node_identifier_t));
|
||||||
|
node_identifier.name = "aaa.localdomain";
|
||||||
|
node_identifier.name_len = strlen(node_identifier.name);
|
||||||
|
node_identifier.realm = "localdomain";
|
||||||
|
node_identifier.realm_len = strlen(node_identifier.realm);
|
||||||
|
req->_aaa_server_identifier.presence = 1;
|
||||||
|
ogs_gtp2_build_node_identifier(
|
||||||
|
&req->_aaa_server_identifier, &node_identifier,
|
||||||
|
node_identifier_buf, OGS_GTP2_MAX_NODE_IDENTIFIER_LEN);
|
||||||
|
|
||||||
gtp_message.h.type = type;
|
gtp_message.h.type = type;
|
||||||
return ogs_gtp2_build_msg(>p_message);
|
return ogs_gtp2_build_msg(>p_message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue