forked from acouzens/open5gs
[SMF] Added User-ID, APP_DNN, S-NSSAI (#1986)
Added User-ID, APP_DNN, S-NSSAI in N4 PFCP Session Establishment Request
This commit is contained in:
parent
92efca1fbf
commit
5128ebc6c6
|
@ -686,3 +686,61 @@ int16_t ogs_pfcp_parse_volume_measurement(
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t ogs_pfcp_build_user_id(
|
||||||
|
ogs_tlv_octet_t *octet, ogs_pfcp_user_id_t *user_id,
|
||||||
|
void *data, int data_len)
|
||||||
|
{
|
||||||
|
ogs_pfcp_user_id_t target;
|
||||||
|
int16_t size = 0;
|
||||||
|
|
||||||
|
ogs_assert(user_id);
|
||||||
|
ogs_assert(octet);
|
||||||
|
ogs_assert(data);
|
||||||
|
ogs_assert(data_len);
|
||||||
|
|
||||||
|
octet->data = data;
|
||||||
|
memcpy(&target, user_id, sizeof(ogs_pfcp_user_id_t));
|
||||||
|
|
||||||
|
ogs_assert(size + sizeof(target.flags) <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
&target.flags, sizeof(target.flags));
|
||||||
|
size += sizeof(target.flags);
|
||||||
|
|
||||||
|
if (target.imsif) {
|
||||||
|
ogs_assert(size + sizeof(target.imsi_len) <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
&target.imsi_len, sizeof(target.imsi_len));
|
||||||
|
size += sizeof(target.imsi_len);
|
||||||
|
|
||||||
|
ogs_assert(size + user_id->imsi_len <= data_len);
|
||||||
|
memcpy((char *)octet->data + size, user_id->imsi, user_id->imsi_len);
|
||||||
|
size += user_id->imsi_len;
|
||||||
|
}
|
||||||
|
if (target.imeif) {
|
||||||
|
ogs_assert(size + sizeof(target.imeisv_len) <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
&target.imeisv_len, sizeof(target.imeisv_len));
|
||||||
|
size += sizeof(target.imeisv_len);
|
||||||
|
|
||||||
|
ogs_assert(size + user_id->imeisv_len <= data_len);
|
||||||
|
memcpy((char *)octet->data + size,
|
||||||
|
user_id->imeisv, user_id->imeisv_len);
|
||||||
|
size += user_id->imeisv_len;
|
||||||
|
}
|
||||||
|
if (target.msisdnf) {
|
||||||
|
ogs_assert(size + sizeof(target.msisdn_len) <= data_len);
|
||||||
|
memcpy((unsigned char *)octet->data + size,
|
||||||
|
&target.msisdn_len, sizeof(target.msisdn_len));
|
||||||
|
size += sizeof(target.msisdn_len);
|
||||||
|
|
||||||
|
ogs_assert(size + user_id->msisdn_len <= data_len);
|
||||||
|
memcpy((char *)octet->data + size,
|
||||||
|
user_id->msisdn, user_id->msisdn_len);
|
||||||
|
size += user_id->msisdn_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
octet->len = size;
|
||||||
|
|
||||||
|
return octet->len;
|
||||||
|
}
|
||||||
|
|
109
lib/pfcp/types.h
109
lib/pfcp/types.h
|
@ -1400,6 +1400,115 @@ int16_t ogs_pfcp_build_volume_measurement(ogs_tlv_octet_t *octet,
|
||||||
int16_t ogs_pfcp_parse_volume_measurement(
|
int16_t ogs_pfcp_parse_volume_measurement(
|
||||||
ogs_pfcp_volume_measurement_t *volume, ogs_tlv_octet_t *octet);
|
ogs_pfcp_volume_measurement_t *volume, ogs_tlv_octet_t *octet);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 8.2.101 User ID
|
||||||
|
*
|
||||||
|
* The User ID IE type shall be encoded as shown in Figure 8.2.101-1.
|
||||||
|
*
|
||||||
|
* The following flags are coded within Octet 5:
|
||||||
|
*
|
||||||
|
* -Bit 1 – IMSIF: If this bit is set to "1",
|
||||||
|
* then the Length of IMSI and IMSI fields shall be present,
|
||||||
|
* otherwise these fields shall not be present.
|
||||||
|
* -Bit 2 – IMEIF: If this bit is set to "1",
|
||||||
|
* then the Length of IMEI and IMEI fields shall be present,
|
||||||
|
* otherwise these fields shall not be present.
|
||||||
|
* -Bit 3 – MSISDNF: If this bit is set to "1",
|
||||||
|
* then the Length of MSISDN and MSISDN fields shall be present,
|
||||||
|
* otherwise these fields shall not be present.
|
||||||
|
* -Bit 4 – NAIF: If this bit is set to "1",
|
||||||
|
* then the Length of NAI and NAI fields shall be present,
|
||||||
|
* otherwise these fields shall not be present.
|
||||||
|
* -Bit 5 – SUPIF: If this bit is set to "1",
|
||||||
|
* then the Length of SUPI and SUPI fields shall be present,
|
||||||
|
* otherwise these fields shall not be present.
|
||||||
|
* -Bit 6 – GPSIF: If this bit is set to "1",
|
||||||
|
* then the Length of GPSI and GPSI fields shall be present,
|
||||||
|
* otherwise these fields shall not be present.
|
||||||
|
* -Bit 7 – PEIF: If this bit is set to "1",
|
||||||
|
* then the Length of PEI and PEI fields shall be present,
|
||||||
|
* otherwise these fields shall not be present.
|
||||||
|
* - Bit 8: Spare, for future use and set to "0".
|
||||||
|
*
|
||||||
|
* One or more flags may be set to "1".
|
||||||
|
*
|
||||||
|
* For 5GS User Identities:
|
||||||
|
* -The SUPI field shall only be used for carrying a Global Cable Identifier
|
||||||
|
* (GCI) or a Global Line Identifier (GLI). The IMSI and NAI, if received
|
||||||
|
* by the SMF in the SUPI, shall be included in the IMSI and NAI field respectively.
|
||||||
|
* -The GPSI field shall only be used for carrying an External Identifier.
|
||||||
|
* The MSISDN, if received by the SMF in the SUPI, shall be included
|
||||||
|
* in the MSISDN field.
|
||||||
|
* -The PEI field shall only be used for carrying an MAC address or
|
||||||
|
* an Extended Unique Identifier. The IMEI, if received by the SMF in the PEI,
|
||||||
|
* shall be included in the IMEI field.
|
||||||
|
*
|
||||||
|
* The coding of IMSI field, from octets 7 to 'a' shall be encoded
|
||||||
|
* as the octets 5 to n+4 of the IMSI IE type
|
||||||
|
* specified in clause 8.3 of 3GPP TS 29.274 [9].
|
||||||
|
*
|
||||||
|
* The coding of IMEI field, in octets 'b+1' to 'c' shall be encoded
|
||||||
|
* as the octets 5 to n+4 of the MEI IE type
|
||||||
|
* specified in clause 8.10 of 3GPP TS 29.274 [9].
|
||||||
|
*
|
||||||
|
* The coding of MSISDN field, in octets 'd+1' to 'e' shall be encoded
|
||||||
|
* as the octets 5 to n+4 of the MSISDN IE type
|
||||||
|
* specified in clause 8.11 of 3GPP TS 29.274 [9].
|
||||||
|
*
|
||||||
|
* The coding of the SUPI field, in octets 'h+1' to 'i' shall be encoded
|
||||||
|
* as the Supi data type specified in clause 5.3.2 of 3GPP TS 29.571 [61].
|
||||||
|
*
|
||||||
|
* The coding of the GPSI field, in octets 'j+1' to 'k' shall be encoded
|
||||||
|
* as the Gpsi data type specified in clause 5.3.2 of 3GPP TS 29.571 [61].
|
||||||
|
*
|
||||||
|
* The coding of the PEI field, in octets 'l+1' to 'm' shall be encoded
|
||||||
|
* as the Pei data type specified in clause 5.3.2 of 3GPP TS 29.571 [61].
|
||||||
|
*
|
||||||
|
* The NAI field, in octets 'f+1' to 'g' shall be encoded as an Octet String
|
||||||
|
* (see IETF RFC 4282 [36]).
|
||||||
|
*/
|
||||||
|
typedef struct ogs_pfcp_user_id_flags_s {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
ED8(uint8_t spare:1;,
|
||||||
|
uint8_t peif:1;,
|
||||||
|
uint8_t gpsif:1;,
|
||||||
|
uint8_t supif:1;,
|
||||||
|
uint8_t naif:1;,
|
||||||
|
uint8_t msisdnf:1;,
|
||||||
|
uint8_t imeif:1;,
|
||||||
|
uint8_t imsif:1;)
|
||||||
|
};
|
||||||
|
uint8_t flags;
|
||||||
|
};
|
||||||
|
} ogs_pfcp_user_id_flags_t;
|
||||||
|
|
||||||
|
typedef struct ogs_pfcp_user_id_s {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
ED8(uint8_t spare:1;,
|
||||||
|
uint8_t peif:1;,
|
||||||
|
uint8_t gpsif:1;,
|
||||||
|
uint8_t supif:1;,
|
||||||
|
uint8_t naif:1;,
|
||||||
|
uint8_t msisdnf:1;,
|
||||||
|
uint8_t imeif:1;,
|
||||||
|
uint8_t imsif:1;)
|
||||||
|
};
|
||||||
|
uint8_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t imsi_len;
|
||||||
|
uint8_t imsi[OGS_MAX_IMSI_LEN];
|
||||||
|
uint8_t imeisv_len;
|
||||||
|
uint8_t imeisv[OGS_MAX_IMEISV_LEN];
|
||||||
|
uint8_t msisdn_len;
|
||||||
|
uint8_t msisdn[OGS_MAX_MSISDN_LEN];
|
||||||
|
} ogs_pfcp_user_id_t;
|
||||||
|
|
||||||
|
int16_t ogs_pfcp_build_user_id(
|
||||||
|
ogs_tlv_octet_t *octet, ogs_pfcp_user_id_t *user_id,
|
||||||
|
void *data, int data_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,7 @@ ogs_amf_id_t *ogs_amf_id_build(ogs_amf_id_t *amf_id,
|
||||||
* SUPI/GPSI */
|
* SUPI/GPSI */
|
||||||
#define OGS_ID_SUPI_TYPE_IMSI "imsi"
|
#define OGS_ID_SUPI_TYPE_IMSI "imsi"
|
||||||
#define OGS_ID_GPSI_TYPE_MSISDN "msisdn"
|
#define OGS_ID_GPSI_TYPE_MSISDN "msisdn"
|
||||||
|
#define OGS_ID_SUPI_TYPE_IMEISV "imeisv"
|
||||||
char *ogs_id_get_type(char *str);
|
char *ogs_id_get_type(char *str);
|
||||||
char *ogs_id_get_value(char *str);
|
char *ogs_id_get_value(char *str);
|
||||||
|
|
||||||
|
|
|
@ -57,21 +57,18 @@ int amf_nudm_sdm_handle_provisioned(
|
||||||
char *gpsi = NULL;
|
char *gpsi = NULL;
|
||||||
|
|
||||||
gpsi = ogs_id_get_type(node->data);
|
gpsi = ogs_id_get_type(node->data);
|
||||||
ogs_assert(gpsi);
|
if (gpsi) {
|
||||||
|
if (strncmp(gpsi, OGS_ID_GPSI_TYPE_MSISDN,
|
||||||
|
strlen(OGS_ID_GPSI_TYPE_MSISDN)) == 0) {
|
||||||
|
amf_ue->msisdn[amf_ue->num_of_msisdn] =
|
||||||
|
ogs_id_get_value(node->data);
|
||||||
|
ogs_assert(amf_ue->
|
||||||
|
msisdn[amf_ue->num_of_msisdn]);
|
||||||
|
|
||||||
if (strncmp(gpsi, OGS_ID_GPSI_TYPE_MSISDN,
|
amf_ue->num_of_msisdn++;
|
||||||
strlen(OGS_ID_GPSI_TYPE_MSISDN)) != 0) {
|
}
|
||||||
ogs_error("Unknown GPSI Type [%s]", gpsi);
|
ogs_free(gpsi);
|
||||||
|
|
||||||
} else {
|
|
||||||
amf_ue->msisdn[amf_ue->num_of_msisdn] =
|
|
||||||
ogs_id_get_value(node->data);
|
|
||||||
ogs_assert(amf_ue->msisdn[amf_ue->num_of_msisdn]);
|
|
||||||
|
|
||||||
amf_ue->num_of_msisdn++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ogs_free(gpsi);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,17 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
|
||||||
|
|
||||||
ogs_pfcp_node_id_t node_id;
|
ogs_pfcp_node_id_t node_id;
|
||||||
ogs_pfcp_f_seid_t f_seid;
|
ogs_pfcp_f_seid_t f_seid;
|
||||||
|
char apn_dnn[OGS_MAX_DNN_LEN+1];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
smf_ue_t *smf_ue = NULL;
|
||||||
|
ogs_pfcp_user_id_t user_id;
|
||||||
|
char user_id_buf[sizeof(ogs_pfcp_user_id_t)];
|
||||||
|
|
||||||
ogs_debug("Session Establishment Request");
|
ogs_debug("Session Establishment Request");
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
|
smf_ue = sess->smf_ue;
|
||||||
|
ogs_assert(smf_ue);
|
||||||
|
|
||||||
req = &pfcp_message.pfcp_session_establishment_request;
|
req = &pfcp_message.pfcp_session_establishment_request;
|
||||||
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
|
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
|
||||||
|
@ -102,6 +109,46 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
|
||||||
req->pdn_type.presence = 1;
|
req->pdn_type.presence = 1;
|
||||||
req->pdn_type.u8 = sess->session.session_type;
|
req->pdn_type.u8 = sess->session.session_type;
|
||||||
|
|
||||||
|
/* User ID */
|
||||||
|
memset(&user_id, 0, sizeof(ogs_pfcp_user_id_t));
|
||||||
|
if (smf_ue->imsi_len) {
|
||||||
|
user_id.imsif = 1;
|
||||||
|
user_id.imsi_len = smf_ue->imsi_len;
|
||||||
|
ogs_assert(smf_ue->imsi_len <= OGS_MAX_IMSI_LEN);
|
||||||
|
memcpy(user_id.imsi, smf_ue->imsi, smf_ue->imsi_len);
|
||||||
|
}
|
||||||
|
if (smf_ue->imeisv_len) {
|
||||||
|
user_id.imeif = 1;
|
||||||
|
user_id.imeisv_len = smf_ue->imeisv_len;
|
||||||
|
ogs_assert(smf_ue->imeisv_len <= OGS_MAX_IMEISV_LEN);
|
||||||
|
memcpy(user_id.imeisv, smf_ue->imeisv, smf_ue->imeisv_len);
|
||||||
|
}
|
||||||
|
if (smf_ue->msisdn_len) {
|
||||||
|
user_id.msisdnf = 1;
|
||||||
|
user_id.msisdn_len = smf_ue->msisdn_len;
|
||||||
|
ogs_assert(smf_ue->msisdn_len <= OGS_MAX_MSISDN_LEN);
|
||||||
|
memcpy(user_id.msisdn, smf_ue->msisdn, smf_ue->msisdn_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user_id.flags) {
|
||||||
|
ogs_pfcp_build_user_id(
|
||||||
|
&req->user_id, &user_id, user_id_buf, sizeof(user_id_buf));
|
||||||
|
req->user_id.presence = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* APN/DNN */
|
||||||
|
len = ogs_fqdn_build(apn_dnn, sess->session.name, strlen(sess->session.name));
|
||||||
|
req->apn_dnn.presence = 1;
|
||||||
|
req->apn_dnn.len = len;
|
||||||
|
req->apn_dnn.data = apn_dnn;
|
||||||
|
|
||||||
|
/* S-NSSAI */
|
||||||
|
if (!sess->epc) {
|
||||||
|
req->s_nssai.presence = 1;
|
||||||
|
req->s_nssai.len = 4;
|
||||||
|
req->s_nssai.data = &sess->s_nssai;
|
||||||
|
}
|
||||||
|
|
||||||
pfcp_message.h.type = type;
|
pfcp_message.h.type = type;
|
||||||
pkbuf = ogs_pfcp_build_msg(&pfcp_message);
|
pkbuf = ogs_pfcp_build_msg(&pfcp_message);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ bool smf_nsmf_handle_create_sm_context(
|
||||||
{
|
{
|
||||||
bool rc;
|
bool rc;
|
||||||
smf_ue_t *smf_ue = NULL;
|
smf_ue_t *smf_ue = NULL;
|
||||||
|
char *type = NULL;
|
||||||
|
|
||||||
ogs_nas_5gsm_header_t *gsm_header = NULL;
|
ogs_nas_5gsm_header_t *gsm_header = NULL;
|
||||||
ogs_pkbuf_t *n1smbuf = NULL;
|
ogs_pkbuf_t *n1smbuf = NULL;
|
||||||
|
@ -164,6 +165,60 @@ bool smf_nsmf_handle_create_sm_context(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SmContextCreateData->supi) {
|
||||||
|
type = ogs_id_get_type(SmContextCreateData->supi);
|
||||||
|
if (type) {
|
||||||
|
if (strncmp(type, OGS_ID_SUPI_TYPE_IMSI,
|
||||||
|
strlen(OGS_ID_SUPI_TYPE_IMSI)) == 0) {
|
||||||
|
char *imsi_bcd = ogs_id_get_value(SmContextCreateData->supi);
|
||||||
|
|
||||||
|
ogs_cpystrn(smf_ue->imsi_bcd, imsi_bcd,
|
||||||
|
ogs_min(strlen(imsi_bcd), OGS_MAX_IMSI_BCD_LEN)+1);
|
||||||
|
ogs_bcd_to_buffer(smf_ue->imsi_bcd,
|
||||||
|
smf_ue->imsi, &smf_ue->imsi_len);
|
||||||
|
|
||||||
|
ogs_free(imsi_bcd);
|
||||||
|
}
|
||||||
|
ogs_free(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SmContextCreateData->pei) {
|
||||||
|
type = ogs_id_get_type(SmContextCreateData->pei);
|
||||||
|
if (type) {
|
||||||
|
if (strncmp(type, OGS_ID_SUPI_TYPE_IMEISV,
|
||||||
|
strlen(OGS_ID_SUPI_TYPE_IMEISV)) == 0) {
|
||||||
|
char *imeisv_bcd = ogs_id_get_value(SmContextCreateData->pei);
|
||||||
|
|
||||||
|
ogs_cpystrn(smf_ue->imeisv_bcd, imeisv_bcd,
|
||||||
|
ogs_min(strlen(imeisv_bcd), OGS_MAX_IMEISV_BCD_LEN)+1);
|
||||||
|
ogs_bcd_to_buffer(smf_ue->imeisv_bcd,
|
||||||
|
smf_ue->imeisv, &smf_ue->imeisv_len);
|
||||||
|
|
||||||
|
ogs_free(imeisv_bcd);
|
||||||
|
}
|
||||||
|
ogs_free(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SmContextCreateData->gpsi) {
|
||||||
|
type = ogs_id_get_type(SmContextCreateData->gpsi);
|
||||||
|
if (type) {
|
||||||
|
if (strncmp(type, OGS_ID_GPSI_TYPE_MSISDN,
|
||||||
|
strlen(OGS_ID_GPSI_TYPE_MSISDN)) == 0) {
|
||||||
|
char *msisdn_bcd = ogs_id_get_value(SmContextCreateData->gpsi);
|
||||||
|
|
||||||
|
ogs_cpystrn(smf_ue->msisdn_bcd, msisdn_bcd,
|
||||||
|
ogs_min(strlen(msisdn_bcd), OGS_MAX_MSISDN_BCD_LEN)+1);
|
||||||
|
ogs_bcd_to_buffer(smf_ue->msisdn_bcd,
|
||||||
|
smf_ue->msisdn, &smf_ue->msisdn_len);
|
||||||
|
|
||||||
|
ogs_free(msisdn_bcd);
|
||||||
|
}
|
||||||
|
ogs_free(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ogs_sbi_parse_plmn_id_nid(&sess->plmn_id, servingNetwork);
|
ogs_sbi_parse_plmn_id_nid(&sess->plmn_id, servingNetwork);
|
||||||
|
|
||||||
sess->sbi_rat_type = SmContextCreateData->rat_type;
|
sess->sbi_rat_type = SmContextCreateData->rat_type;
|
||||||
|
|
Loading…
Reference in New Issue