forked from acouzens/open5gs
new: HSS Cx interface is added
This commit is contained in:
parent
23c1fee516
commit
41c6bb4681
|
@ -167,6 +167,8 @@ hss:
|
|||
connect:
|
||||
- identity: mme.localdomain
|
||||
addr: 127.0.0.2
|
||||
- identity: ims.localdomain
|
||||
addr: 127.0.0.1
|
||||
pcrf:
|
||||
freeDiameter:
|
||||
identity: pcrf.localdomain
|
||||
|
@ -184,7 +186,7 @@ pcrf:
|
|||
connect:
|
||||
- identity: smf.localdomain
|
||||
addr: 127.0.0.4
|
||||
- identity: pcscf.localdomain
|
||||
- identity: ims.localdomain
|
||||
addr: 127.0.0.1
|
||||
|
||||
#nrf:
|
||||
|
|
|
@ -97,6 +97,10 @@ static void recalculate_pool_size(void)
|
|||
|
||||
#define MAX_CSMAP_POOL 128
|
||||
self.pool.csmap = MAX_CSMAP_POOL; /* Num of TAI-LAI Mapping Table */
|
||||
|
||||
#define MAX_NUM_OF_IMPU 8
|
||||
self.pool.impi = self.max.ue;
|
||||
self.pool.impu = self.pool.impi * MAX_NUM_OF_IMPU;
|
||||
}
|
||||
|
||||
static void regenerate_all_timer_duration(void)
|
||||
|
|
|
@ -126,6 +126,9 @@ typedef struct ogs_app_context_s {
|
|||
uint64_t gtp_node;
|
||||
uint64_t pfcp_xact;
|
||||
uint64_t pfcp_node;
|
||||
|
||||
uint64_t impi;
|
||||
uint64_t impu;
|
||||
} pool;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -604,7 +604,7 @@ typedef struct ogs_subscription_data_s {
|
|||
int num_of_slice;
|
||||
ogs_slice_data_t slice[OGS_MAX_NUM_OF_SLICE];
|
||||
|
||||
#define OGS_MAX_NUM_OF_MSISDN 4
|
||||
#define OGS_MAX_NUM_OF_MSISDN 2
|
||||
int num_of_msisdn;
|
||||
struct {
|
||||
uint8_t buf[OGS_MAX_MSISDN_LEN];
|
||||
|
|
|
@ -230,3 +230,17 @@ uint64_t ogs_uint64_from_string(char *str)
|
|||
|
||||
return x;
|
||||
}
|
||||
|
||||
void ogs_extract_digit_from_string(char *digit, char *string)
|
||||
{
|
||||
ogs_assert(string);
|
||||
ogs_assert(digit);
|
||||
|
||||
while(*string) {
|
||||
if (*string >= '0' && *string <= '9')
|
||||
*digit++ = *string;
|
||||
string++;
|
||||
}
|
||||
|
||||
*digit = 0;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ char *ogs_uint64_to_string(uint64_t x);
|
|||
ogs_uint24_t ogs_uint24_from_string(char *str);
|
||||
uint64_t ogs_uint64_from_string(char *str);
|
||||
|
||||
void ogs_extract_digit_from_string(char *digit, char *string);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
#define CHECK_dict_search( _type, _criteria, _what, _result ) \
|
||||
CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
|
||||
|
||||
#define OGS_3GPP_VENDOR_ID 10415
|
||||
|
||||
struct dict_object *ogs_diam_session_id = NULL;
|
||||
struct dict_object *ogs_diam_origin_host = NULL;
|
||||
struct dict_object *ogs_diam_origin_realm = NULL;
|
||||
|
|
|
@ -28,16 +28,18 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OGS_DIAM_AVP_CODE_FRAME_IP_ADDRESS 8
|
||||
#define OGS_DIAM_AVP_CODE_FRAME_IPV6_PREFIX 97
|
||||
#define OGS_3GPP_VENDOR_ID 10415
|
||||
|
||||
#define OGS_DIAM_AVP_CODE_FRAME_IP_ADDRESS 8
|
||||
#define OGS_DIAM_AVP_CODE_FRAME_IPV6_PREFIX 97
|
||||
|
||||
/* Result-Code AVP */
|
||||
#define OGS_DIAM_UNKNOWN_PEER 3010
|
||||
#define OGS_DIAM_AVP_UNSUPPORTED 5001
|
||||
#define OGS_DIAM_UNKNOWN_SESSION_ID 5002
|
||||
#define OGS_DIAM_AUTHORIZATION_REJECTED 5003
|
||||
#define OGS_DIAM_MISSING_AVP 5004
|
||||
#define OGS_DIAM_INVALID_AVP_VALUE 5005
|
||||
#define OGS_DIAM_UNKNOWN_PEER 3010
|
||||
#define OGS_DIAM_AVP_UNSUPPORTED 5001
|
||||
#define OGS_DIAM_UNKNOWN_SESSION_ID 5002
|
||||
#define OGS_DIAM_AUTHORIZATION_REJECTED 5003
|
||||
#define OGS_DIAM_MISSING_AVP 5004
|
||||
#define OGS_DIAM_INVALID_AVP_VALUE 5005
|
||||
|
||||
extern struct dict_object *ogs_diam_session_id;
|
||||
extern struct dict_object *ogs_diam_origin_host;
|
||||
|
|
|
@ -0,0 +1,567 @@
|
|||
/*********************************************************************************************************
|
||||
* Software License Agreement (BSD License) *
|
||||
* Author: Thomas Klausner <tk@giga.or.at> *
|
||||
* *
|
||||
* Copyright (c) 2013, Thomas Klausner *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Written under contract by nfotex IT GmbH, http://nfotex.com/ *
|
||||
* *
|
||||
* Redistribution and use of this software in source and binary forms, with or without modification, are *
|
||||
* permitted provided that the following conditions are met: *
|
||||
* *
|
||||
* * Redistributions of source code must retain the above *
|
||||
* copyright notice, this list of conditions and the *
|
||||
* following disclaimer. *
|
||||
* *
|
||||
* * Redistributions in binary form must reproduce the above *
|
||||
* copyright notice, this list of conditions and the *
|
||||
* following disclaimer in the documentation and/or other *
|
||||
* materials provided with the distribution. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*********************************************************************************************************/
|
||||
|
||||
/*
|
||||
* Dictionary definitions for objects specified for DCCA by 3GPP.
|
||||
*
|
||||
* This extensions contains a lot of AVPs from various 3GPP standards
|
||||
* documents, and some rules for the grouped AVPs described therein.
|
||||
*
|
||||
* This extension does not contain ALL AVPs described by 3GPP, but
|
||||
* quite a big number of them.
|
||||
*
|
||||
* When extending the AVPs, please edit dict_rx.org instead and
|
||||
* create pastable code with contrib/tools/org_to_fd.pl.
|
||||
*
|
||||
* Some points of consideration:
|
||||
* 1. This dictionary could be split up per document.
|
||||
*
|
||||
* + pro: you can only load the AVPs/Rules you're interested in ->
|
||||
* smaller memory size
|
||||
*
|
||||
* - con: the documents use AVPs from each other A LOT, so setting the
|
||||
* dependencies correctly will be annoying
|
||||
*
|
||||
* - con: you need to load all of them as extensions
|
||||
*
|
||||
* 2. This dictionary contains ONE AVP in the "3GPP2" vendor space,
|
||||
* since I found it wasteful to write a separate dictionary just for
|
||||
* one AVP. Also, it is defined in a 3GPP document.
|
||||
*
|
||||
* 3. While there are quite a number of rules here already, many more
|
||||
* are missing. I've only added rules for those grouped AVPs or
|
||||
* commands in which I was concretely interested so far; many more
|
||||
* will need to be added to make this complete.
|
||||
*
|
||||
* That being said, I hope this will be useful for you.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Some comments on the 3GPP Standards documents themselves:
|
||||
*
|
||||
* 1. It would be good if 29.061 was reviewed to check for each AVP if
|
||||
* it is Mandatory or not. The data currently in the document does not
|
||||
* match what was in the previous version of the freeDiameter
|
||||
* extension (the one that existedbefore I rewrote it) or what I saw
|
||||
* so far. IIRC, even the table and the document contradict each
|
||||
* other. The AVP table is also missing an entry for
|
||||
* "External-Identifier", 28.
|
||||
*
|
||||
* 2. 29.140 has conflicting AVP names with other documents:
|
||||
* - Sequence-Number is also in 32.329
|
||||
* - Recipient-Address is also in 32.299
|
||||
* - Status is also in 32.299
|
||||
*
|
||||
* 3. 29.229 has name conflict with 29.329 about User-Data (different
|
||||
* AVP code 702, instead of 606) -- the weird thing is, the latter
|
||||
* uses some AVPs from the former, but not this one.
|
||||
*/
|
||||
#include <freeDiameter/extension.h>
|
||||
|
||||
|
||||
/* The content of this file follows the same structure as dict_base_proto.c */
|
||||
|
||||
#define CHECK_dict_new( _type, _data, _parent, _ref ) \
|
||||
CHECK_FCT( fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref)) );
|
||||
|
||||
#define CHECK_dict_search( _type, _criteria, _what, _result ) \
|
||||
CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
|
||||
|
||||
struct local_rules_definition {
|
||||
struct dict_avp_request avp_vendor_plus_name;
|
||||
enum rule_position position;
|
||||
int min;
|
||||
int max;
|
||||
};
|
||||
|
||||
#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
|
||||
|
||||
/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
|
||||
#define PARSE_loc_rules( _rulearray, _parent) { \
|
||||
int __ar; \
|
||||
for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) { \
|
||||
struct dict_rule_data __data = { NULL, \
|
||||
(_rulearray)[__ar].position, \
|
||||
0, \
|
||||
(_rulearray)[__ar].min, \
|
||||
(_rulearray)[__ar].max}; \
|
||||
__data.rule_order = RULE_ORDER(__data.rule_position); \
|
||||
CHECK_FCT( fd_dict_search( \
|
||||
fd_g_config->cnf_dict, \
|
||||
DICT_AVP, \
|
||||
AVP_BY_NAME_AND_VENDOR, \
|
||||
&(_rulearray)[__ar].avp_vendor_plus_name, \
|
||||
&__data.rule_avp, 0 ) ); \
|
||||
if ( !__data.rule_avp ) { \
|
||||
TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name); \
|
||||
return ENOENT; \
|
||||
} \
|
||||
CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL), \
|
||||
{ \
|
||||
TRACE_DEBUG(INFO, "Error on rule with AVP '%s'", \
|
||||
(_rulearray)[__ar].avp_vendor_plus_name.avp_name); \
|
||||
return EINVAL; \
|
||||
} ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define enumval_def_u32( _val_, _str_ ) \
|
||||
{ _str_, { .u32 = _val_ }}
|
||||
|
||||
#define enumval_def_os( _len_, _val_, _str_ ) \
|
||||
{ _str_, { .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
|
||||
|
||||
|
||||
int ogs_dict_cx_entry(char *conffile)
|
||||
{
|
||||
/* Applications section */
|
||||
{
|
||||
/* Create the vendors */
|
||||
|
||||
{
|
||||
struct dict_object * vendor;
|
||||
CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor, ENOENT));
|
||||
struct dict_application_data app_data = { 16777216, "Cx" };
|
||||
CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_APPLICATION, &app_data, vendor, NULL));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Command section */
|
||||
|
||||
{
|
||||
struct dict_object *cx;
|
||||
CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Cx", &cx, ENOENT));
|
||||
|
||||
/* User-Authorization-Request (UAR) Command */
|
||||
{
|
||||
struct dict_object* cmd_uar;
|
||||
struct dict_cmd_data data = {
|
||||
300, /* Code */
|
||||
"3GPP/User-Authorization-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Visited-Network-Identifier" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Authorization-Type" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "UAR-Flags" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_uar);
|
||||
PARSE_loc_rules(rules, cmd_uar);
|
||||
}
|
||||
|
||||
/* User-Authorization-Answer (UAA) Command */
|
||||
{
|
||||
struct dict_object* cmd_uaa;
|
||||
struct dict_cmd_data data = {
|
||||
300, /* Code */
|
||||
"3GPP/User-Authorization-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_uaa);
|
||||
PARSE_loc_rules(rules, cmd_uaa);
|
||||
}
|
||||
|
||||
/* Location-Info-Request (LIR) Command */
|
||||
{
|
||||
struct dict_object* cmd_lir;
|
||||
struct dict_cmd_data data = {
|
||||
302, /* Code */
|
||||
"3GPP/Location-Info-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Originating-Request" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Authorization-Type" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Session-Priority" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_lir);
|
||||
PARSE_loc_rules(rules, cmd_lir);
|
||||
}
|
||||
|
||||
/* Location-Info-Answer (LIA) Command */
|
||||
{
|
||||
struct dict_object* cmd_lia;
|
||||
struct dict_cmd_data data = {
|
||||
302, /* Code */
|
||||
"3GPP/Location-Info-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "LIA-Flags" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_lia);
|
||||
PARSE_loc_rules(rules, cmd_lia);
|
||||
}
|
||||
|
||||
/* Multimedia-Auth-Request (MAR) Command */
|
||||
{
|
||||
struct dict_object* cmd_mar;
|
||||
struct dict_cmd_data data = {
|
||||
303, /* Code */
|
||||
"3GPP/Multimedia-Auth-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Number-Auth-Items" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 },
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_mar);
|
||||
PARSE_loc_rules(rules, cmd_mar);
|
||||
}
|
||||
|
||||
/* Multimedia-Auth-Answer (MAA) Command */
|
||||
{
|
||||
struct dict_object* cmd_maa;
|
||||
struct dict_cmd_data data = {
|
||||
303, /* Code */
|
||||
"3GPP/Multimedia-Auth-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Number-Auth-Items" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_maa);
|
||||
PARSE_loc_rules(rules, cmd_maa);
|
||||
}
|
||||
|
||||
/* Server-Assignment-Request (SAR) Command */
|
||||
{
|
||||
struct dict_object* cmd_sar;
|
||||
struct dict_cmd_data data = {
|
||||
301, /* Code */
|
||||
"3GPP/Server-Assignment-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Assignment-Type" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Data-Already-Available" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SCSCF-Restoration-Info" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Multiple-Registration-Indication" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Session-Priority" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_sar);
|
||||
PARSE_loc_rules(rules, cmd_sar);
|
||||
}
|
||||
|
||||
/* Server-Assignment-Answer (SAA) Command */
|
||||
{
|
||||
struct dict_object* cmd_saa;
|
||||
struct dict_cmd_data data = {
|
||||
301, /* Code */
|
||||
"3GPP/Server-Assignment-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Data" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Charging-Information" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Loose-Route-Indication" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SCSCF-Restoration-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Registered-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Priviledged-Sender-Indication" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_saa);
|
||||
PARSE_loc_rules(rules, cmd_saa);
|
||||
}
|
||||
|
||||
/* Registration-Termination-Request (RTR) Command */
|
||||
{
|
||||
struct dict_object* cmd_rtr;
|
||||
struct dict_cmd_data data = {
|
||||
304, /* Code */
|
||||
"3GPP/Registration-Termination-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Deregistration-Reason" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_rtr);
|
||||
PARSE_loc_rules(rules, cmd_rtr);
|
||||
}
|
||||
|
||||
/* Registration-Termination-Answer (RTA) Command */
|
||||
{
|
||||
struct dict_object* cmd_rta;
|
||||
struct dict_cmd_data data = {
|
||||
304, /* Code */
|
||||
"3GPP/Registration-Termination-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Identity-with-Emergency-Registration" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_rta);
|
||||
PARSE_loc_rules(rules, cmd_rta);
|
||||
}
|
||||
|
||||
/* Push-Profile-Request (PPR) Command */
|
||||
{
|
||||
struct dict_object* cmd_ppr;
|
||||
struct dict_cmd_data data = {
|
||||
305, /* Code */
|
||||
"3GPP/Push-Profile-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Data" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Charging-Information" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_ppr);
|
||||
PARSE_loc_rules(rules, cmd_ppr);
|
||||
}
|
||||
|
||||
/* Push-Profile-Answer (PPA) Command */
|
||||
{
|
||||
struct dict_object* cmd_ppa;
|
||||
struct dict_cmd_data data = {
|
||||
305, /* Code */
|
||||
"3GPP/Push-Profile-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, cx, &cmd_ppa);
|
||||
PARSE_loc_rules(rules, cmd_ppa);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D( "Extension 'Dictionary definitions for DCCA 3GPP' initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0 /* modified by acetcom */
|
||||
EXTENSION_ENTRY("dict_cx", ogs_dict_cx_entry, "dict_dcca_3gpp");
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
|
||||
# This file is part of Open5GS.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
libdiameter_cx_sources = files('''
|
||||
ogs-diameter-cx.h
|
||||
|
||||
message.h
|
||||
|
||||
dict.c
|
||||
message.c
|
||||
'''.split())
|
||||
|
||||
libdiameter_cx_inc = include_directories('.')
|
||||
|
||||
libdiameter_cx = library('ogsdiameter-cx',
|
||||
sources : libdiameter_cx_sources,
|
||||
version : libogslib_version,
|
||||
c_args : libdiameter_common_cc_flags,
|
||||
include_directories : libdiameter_cx_inc,
|
||||
dependencies : libdiameter_common_dep,
|
||||
install : true)
|
||||
|
||||
libdiameter_cx_dep = declare_dependency(
|
||||
link_with : libdiameter_cx,
|
||||
include_directories : libdiameter_cx_inc,
|
||||
dependencies : libdiameter_common_dep)
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-diameter-cx.h"
|
||||
|
||||
#define CHECK_dict_search( _type, _criteria, _what, _result ) \
|
||||
CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
|
||||
|
||||
struct dict_object *ogs_diam_cx_application = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_cx_cmd_uar = NULL;
|
||||
struct dict_object *ogs_diam_cx_cmd_uaa = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_cx_cmd_mar = NULL;
|
||||
struct dict_object *ogs_diam_cx_cmd_maa = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_cx_cmd_sar = NULL;
|
||||
struct dict_object *ogs_diam_cx_cmd_saa = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_cx_public_identity = NULL;
|
||||
struct dict_object *ogs_diam_cx_visited_network_identifier = NULL;
|
||||
struct dict_object *ogs_diam_cx_server_name = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_cx_sip_number_auth_items = NULL;
|
||||
struct dict_object *ogs_diam_cx_sip_item_number = NULL;
|
||||
struct dict_object *ogs_diam_cx_sip_auth_data_item = NULL;
|
||||
struct dict_object *ogs_diam_cx_sip_authentication_scheme = NULL;
|
||||
struct dict_object *ogs_diam_cx_sip_authenticate = NULL;
|
||||
struct dict_object *ogs_diam_cx_sip_authorization = NULL;
|
||||
struct dict_object *ogs_diam_cx_confidentiality_key = NULL;
|
||||
struct dict_object *ogs_diam_cx_integrity_key = NULL;
|
||||
struct dict_object *ogs_diam_cx_server_assignment_type = NULL;
|
||||
struct dict_object *ogs_diam_cx_user_data_already_available = NULL;
|
||||
struct dict_object *ogs_diam_cx_user_data = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_cx_charging_information = NULL;
|
||||
struct dict_object *ogs_diam_cx_primary_event_charging_function_name = NULL;
|
||||
struct dict_object *ogs_diam_cx_secondary_event_charging_function_name = NULL;
|
||||
struct dict_object
|
||||
*ogs_diam_cx_primary_charging_collection_function_name = NULL;
|
||||
struct dict_object
|
||||
*ogs_diam_cx_secondary_charging_collection_function_name = NULL;
|
||||
|
||||
const char *ogs_diam_cx_xml_version="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||
const char *ogs_diam_cx_xml_ims_subscription_s="<IMSSubscription>";
|
||||
const char *ogs_diam_cx_xml_ims_subscription_e="</IMSSubscription>";
|
||||
const char *ogs_diam_cx_xml_private_id_s="<PrivateID>";
|
||||
const char *ogs_diam_cx_xml_private_id_e="</PrivateID>";
|
||||
const char *ogs_diam_cx_xml_service_profile_s="<ServiceProfile>";
|
||||
const char *ogs_diam_cx_xml_service_profile_e="</ServiceProfile>";
|
||||
const char *ogs_diam_cx_xml_public_id_s="<PublicIdentity>";
|
||||
const char *ogs_diam_cx_xml_public_id_e="</PublicIdentity>";
|
||||
const char *ogs_diam_cx_xml_barring_indication_s="<BarringIndication>";
|
||||
const char *ogs_diam_cx_xml_barring_indication_e="</BarringIndication>";
|
||||
const char *ogs_diam_cx_xml_identity_s="<Identity>";
|
||||
const char *ogs_diam_cx_xml_identity_e="</Identity>";
|
||||
const char *ogs_diam_cx_xml_identity_type_s="<IdentityType>";
|
||||
const char *ogs_diam_cx_xml_identity_type_e="</IdentityType>";
|
||||
const char *ogs_diam_cx_xml_wildcarded_psi_s="<WildcardedPSI>";
|
||||
const char *ogs_diam_cx_xml_wildcarded_psi_e="</WildcardedPSI>";
|
||||
const char *ogs_diam_cx_xml_display_name_s="<DisplayName>";
|
||||
const char *ogs_diam_cx_xml_display_name_e="</DisplayName>";
|
||||
|
||||
const char *ogs_diam_cx_xml_ifc_s="<InitialFilterCriteria>";
|
||||
const char *ogs_diam_cx_xml_ifc_e="</InitialFilterCriteria>";
|
||||
const char *ogs_diam_cx_xml_priority_s="<Priority>";
|
||||
const char *ogs_diam_cx_xml_priority_e="</Priority>";
|
||||
const char *ogs_diam_cx_xml_tp_s="<TriggerPoint>";
|
||||
const char *ogs_diam_cx_xml_tp_e="</TriggerPoint>";
|
||||
const char *ogs_diam_cx_xml_cnf_s="<ConditionTypeCNF>";
|
||||
const char *ogs_diam_cx_xml_cnf_e="</ConditionTypeCNF>";
|
||||
const char *ogs_diam_cx_xml_spt_s="<SPT>";
|
||||
const char *ogs_diam_cx_xml_spt_e="</SPT>";
|
||||
const char *ogs_diam_cx_xml_condition_negated_s="<ConditionNegated>";
|
||||
const char *ogs_diam_cx_xml_condition_negated_e="</ConditionNegated>";
|
||||
const char *ogs_diam_cx_xml_group_s="<Group>";
|
||||
const char *ogs_diam_cx_xml_group_e="</Group>";
|
||||
const char *ogs_diam_cx_xml_req_uri_s="<RequestURI>";
|
||||
const char *ogs_diam_cx_xml_req_uri_e="</RequestURI>";
|
||||
const char *ogs_diam_cx_xml_method_s="<Method>";
|
||||
const char *ogs_diam_cx_xml_method_e="</Method>";
|
||||
const char *ogs_diam_cx_xml_sip_hdr_s="<SIPHeader>";
|
||||
const char *ogs_diam_cx_xml_sip_hdr_e="</SIPHeader>";
|
||||
const char *ogs_diam_cx_xml_session_case_s="<SessionCase>";
|
||||
const char *ogs_diam_cx_xml_session_case_e="</SessionCase>";
|
||||
const char *ogs_diam_cx_xml_session_desc_s="<SessionDescription>";
|
||||
const char *ogs_diam_cx_xml_session_desc_e="</SessionDescription>";
|
||||
const char *ogs_diam_cx_xml_registration_type_s="<RegistrationType>";
|
||||
const char *ogs_diam_cx_xml_registration_type_e="</RegistrationType>";
|
||||
const char *ogs_diam_cx_xml_header_s="<Header>";
|
||||
const char *ogs_diam_cx_xml_header_e="</Header>";
|
||||
const char *ogs_diam_cx_xml_content_s="<Content>";
|
||||
const char *ogs_diam_cx_xml_content_e="</Content>";
|
||||
const char *ogs_diam_cx_xml_line_s="<Line>";
|
||||
const char *ogs_diam_cx_xml_line_e="</Line>";
|
||||
|
||||
const char *ogs_diam_cx_xml_app_server_s="<ApplicationServer>";
|
||||
const char *ogs_diam_cx_xml_app_server_e="</ApplicationServer>";
|
||||
const char *ogs_diam_cx_xml_server_name_s="<ServerName>";
|
||||
const char *ogs_diam_cx_xml_server_name_e="</ServerName>";
|
||||
const char *ogs_diam_cx_xml_default_handling_s="<DefaultHandling>";
|
||||
const char *ogs_diam_cx_xml_default_handling_e="</DefaultHandling>";
|
||||
const char *ogs_diam_cx_xml_service_info_s="<ServiceInfo>";
|
||||
const char *ogs_diam_cx_xml_service_info_e="</ServiceInfo>";
|
||||
const char *ogs_diam_cx_xml_include_register_request="<IncludeRegisterRequest/>";
|
||||
const char *ogs_diam_cx_xml_include_register_response="<IncludeRegisterResponse/>";
|
||||
|
||||
const char *ogs_diam_cx_xml_profile_part_ind_s="<ProfilePartIndicator>";
|
||||
const char *ogs_diam_cx_xml_profile_part_ind_e="</ProfilePartIndicator>";
|
||||
|
||||
const char *ogs_diam_cx_xml_cn_services_auth_s="<CoreNetworkServicesAuthorization>";
|
||||
const char *ogs_diam_cx_xml_cn_services_auth_e="</CoreNetworkServicesAuthorization>";
|
||||
const char *ogs_diam_cx_xml_subs_media_profile_id_s="<SubscribedMediaProfileId>";
|
||||
const char *ogs_diam_cx_xml_subs_media_profile_id_e="</SubscribedMediaProfileId>";
|
||||
const char *ogs_diam_cx_xml_shared_ifc_set_id_s="<Extension><SharedIFCSetID>";
|
||||
const char *ogs_diam_cx_xml_shared_ifc_set_id_e="</SharedIFCSetID></Extension>";
|
||||
|
||||
const char *ogs_diam_cx_xml_extension_s="<Extension>";
|
||||
const char *ogs_diam_cx_xml_extension_e="</Extension>";
|
||||
|
||||
extern int ogs_dict_cx_entry(char *conffile);
|
||||
|
||||
int ogs_diam_cx_init(void)
|
||||
{
|
||||
application_id_t id = OGS_DIAM_CX_APPLICATION_ID;
|
||||
|
||||
ogs_assert(ogs_dict_cx_entry(NULL) == 0);
|
||||
|
||||
CHECK_dict_search(DICT_APPLICATION, APPLICATION_BY_ID,
|
||||
(void *)&id, &ogs_diam_cx_application);
|
||||
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME,
|
||||
"3GPP/User-Authorization-Request", &ogs_diam_cx_cmd_uar);
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME,
|
||||
"3GPP/User-Authorization-Answer", &ogs_diam_cx_cmd_uaa);
|
||||
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME,
|
||||
"3GPP/Multimedia-Auth-Request", &ogs_diam_cx_cmd_mar);
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME,
|
||||
"3GPP/Multimedia-Auth-Answer", &ogs_diam_cx_cmd_maa);
|
||||
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME,
|
||||
"3GPP/Server-Assignment-Request", &ogs_diam_cx_cmd_sar);
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME,
|
||||
"3GPP/Server-Assignment-Answer", &ogs_diam_cx_cmd_saa);
|
||||
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Public-Identity", &ogs_diam_cx_public_identity);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Visited-Network-Identifier",
|
||||
&ogs_diam_cx_visited_network_identifier);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Server-Name", &ogs_diam_cx_server_name);
|
||||
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"SIP-Number-Auth-Items", &ogs_diam_cx_sip_number_auth_items);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"SIP-Item-Number", &ogs_diam_cx_sip_item_number);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"SIP-Auth-Data-Item", &ogs_diam_cx_sip_auth_data_item);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"SIP-Authentication-Scheme",
|
||||
&ogs_diam_cx_sip_authentication_scheme);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"SIP-Authenticate", &ogs_diam_cx_sip_authenticate);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"SIP-Authorization", &ogs_diam_cx_sip_authorization);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Confidentiality-Key", &ogs_diam_cx_confidentiality_key);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Integrity-Key", &ogs_diam_cx_integrity_key);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Server-Assignment-Type", &ogs_diam_cx_server_assignment_type);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"User-Data-Already-Available",
|
||||
&ogs_diam_cx_user_data_already_available);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"User-Data", &ogs_diam_cx_user_data);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Charging-Information", &ogs_diam_cx_charging_information);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Primary-Event-Charging-Function-Name",
|
||||
&ogs_diam_cx_primary_event_charging_function_name);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Secondary-Event-Charging-Function-Name",
|
||||
&ogs_diam_cx_secondary_event_charging_function_name);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Primary-Charging-Collection-Function-Name",
|
||||
&ogs_diam_cx_primary_charging_collection_function_name);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS,
|
||||
"Secondary-Charging-Collection-Function-Name",
|
||||
&ogs_diam_cx_secondary_charging_collection_function_name);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(OGS_DIAMETER_INSIDE) && !defined(OGS_DIAMETER_COMPILATION)
|
||||
#error "This header cannot be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef OGS_DIAM_CX_MESSAGE_H
|
||||
#define OGS_DIAM_CX_MESSAGE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OGS_DIAM_CX_APPLICATION_ID 16777216
|
||||
|
||||
extern struct dict_object *ogs_diam_cx_application;
|
||||
|
||||
extern struct dict_object *ogs_diam_cx_cmd_uar;
|
||||
extern struct dict_object *ogs_diam_cx_cmd_uaa;
|
||||
extern struct dict_object *ogs_diam_cx_cmd_mar;
|
||||
extern struct dict_object *ogs_diam_cx_cmd_maa;
|
||||
extern struct dict_object *ogs_diam_cx_cmd_sar;
|
||||
extern struct dict_object *ogs_diam_cx_cmd_saa;
|
||||
|
||||
extern struct dict_object *ogs_diam_cx_public_identity;
|
||||
extern struct dict_object *ogs_diam_cx_visited_network_identifier;
|
||||
extern struct dict_object *ogs_diam_cx_server_name;
|
||||
|
||||
extern struct dict_object *ogs_diam_cx_sip_number_auth_items;
|
||||
extern struct dict_object *ogs_diam_cx_sip_item_number;
|
||||
extern struct dict_object *ogs_diam_cx_sip_auth_data_item;
|
||||
#define OGS_DIAM_CX_AUTH_SCHEME_IMS_AKA "Digest-AKAv1-MD5"
|
||||
#define OGS_DIAM_CX_AUTH_SCHEME_SIP_DIGEST "SIP Digest"
|
||||
#define OGS_DIAM_CX_AUTH_SCHEME_NASS_BUNDLED "NASS-Bundled"
|
||||
#define OGS_DIAM_CX_AUTH_SCHEME_GPRS_IMS_BUNDLED "Early-IMS-Security"
|
||||
#define OGS_DIAM_CX_AUTH_SCHEME_UNKNOWN "Unknown"
|
||||
extern struct dict_object *ogs_diam_cx_sip_authentication_scheme;
|
||||
extern struct dict_object *ogs_diam_cx_sip_authenticate;
|
||||
extern struct dict_object *ogs_diam_cx_sip_authorization;
|
||||
extern struct dict_object *ogs_diam_cx_confidentiality_key;
|
||||
extern struct dict_object *ogs_diam_cx_integrity_key;
|
||||
#define OGS_DIAM_CX_SERVER_NO_ASSIGNMENT 0
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_REGISTRATION 1
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_RE_REGISTRATION 2
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_UNREGISTERED_USER 3
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_TIMEOUT_DEREGISTRATION 4
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_USER_DEREGISTRATION 5
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME 6
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_USER_DEREGISTRATION_STORE_SERVER_NAME 7
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_ADMINISTRATIVE_DEREGISTRATION 8
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_AUTHENTICATION_FAILURE 9
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_AUTHENTICATION_TIMEOUT 10
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_DEREGISTRATION_TOO_MUCH_DATA 11
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_AAA_USER_DATA_REQUEST 12
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_PGW_UPDATE 13
|
||||
#define OGS_DIAM_CX_SERVER_ASSIGNMENT_RESTORATION 14
|
||||
extern struct dict_object *ogs_diam_cx_server_assignment_type;
|
||||
#define OGS_DIAM_CX_USER_DATA_NOT_AVAILABLE 0
|
||||
#define OGS_DIAM_CX_USER_DATA_ALREADY_AVAILABLE 1
|
||||
extern struct dict_object *ogs_diam_cx_user_data_already_available;
|
||||
extern struct dict_object *ogs_diam_cx_user_data;
|
||||
extern struct dict_object *ogs_diam_cx_charging_information;
|
||||
extern struct dict_object *ogs_diam_cx_primary_event_charging_function_name;
|
||||
extern struct dict_object *ogs_diam_cx_secondary_event_charging_function_name;
|
||||
extern struct dict_object
|
||||
*ogs_diam_cx_primary_charging_collection_function_name;
|
||||
extern struct dict_object
|
||||
*ogs_diam_cx_secondary_charging_collection_function_name;
|
||||
|
||||
#define OGS_DIAM_CX_FIRST_REGISTRATION 2001
|
||||
#define OGS_DIAM_CX_SUBSEQUENT_REGISTRATION 2002
|
||||
#define OGS_DIAM_CX_UNREGISTERED_SERVICE 2003
|
||||
#define OGS_DIAM_CX_SERVER_NAME_NOT_STORED 2004
|
||||
#define OGS_DIAM_CX_ERROR_USER_UNKNOWN 5001
|
||||
#define OGS_DIAM_CX_ERROR_IDENTITIES_DONT_MATCH 5002
|
||||
#define OGS_DIAM_CX_ERROR_IDENTITY_NOT_REGISTERED 5003
|
||||
#define OGS_DIAM_CX_ERROR_ROAMING_NOT_ALLOWED 5004
|
||||
#define OGS_DIAM_CX_ERROR_IDENTITY_ALREADY_REGISTERED 5005
|
||||
#define OGS_DIAM_CX_ERROR_AUTH_SCHEME_NOT_SUPPORTED 5006
|
||||
#define OGS_DIAM_CX_ERROR_IN_ASSIGNMENT_TYPE 5007
|
||||
#define OGS_DIAM_CX_ERROR_TOO_MUCH_DATA 5008
|
||||
#define OGS_DIAM_CX_ERROR_NOT_SUPPORTED_USER_DATA 5009
|
||||
#define OGS_DIAM_CX_ERROR_FEATURE_UNSUPPORTED 5011
|
||||
#define OGS_DIAM_CX_ERROR_SERVING_NODE_FEATURE_UNSUPPORTED 5012
|
||||
|
||||
int ogs_diam_cx_init(void);
|
||||
|
||||
extern const char *ogs_diam_cx_xml_version;
|
||||
extern const char *ogs_diam_cx_xml_ims_subscription_s;
|
||||
extern const char *ogs_diam_cx_xml_ims_subscription_e;
|
||||
extern const char *ogs_diam_cx_xml_private_id_s;
|
||||
extern const char *ogs_diam_cx_xml_private_id_e;
|
||||
extern const char *ogs_diam_cx_xml_service_profile_s;
|
||||
extern const char *ogs_diam_cx_xml_service_profile_e;
|
||||
extern const char *ogs_diam_cx_xml_public_id_s;
|
||||
extern const char *ogs_diam_cx_xml_public_id_e;
|
||||
extern const char *ogs_diam_cx_xml_barring_indication_s;
|
||||
extern const char *ogs_diam_cx_xml_barring_indication_e;
|
||||
extern const char *ogs_diam_cx_xml_identity_s;
|
||||
extern const char *ogs_diam_cx_xml_identity_e;
|
||||
extern const char *ogs_diam_cx_xml_identity_type_s;
|
||||
extern const char *ogs_diam_cx_xml_identity_type_e;
|
||||
extern const char *ogs_diam_cx_xml_wildcarded_psi_s;
|
||||
extern const char *ogs_diam_cx_xml_wildcarded_psi_e;
|
||||
extern const char *ogs_diam_cx_xml_display_name_s;
|
||||
extern const char *ogs_diam_cx_xml_display_name_e;
|
||||
|
||||
extern const char *ogs_diam_cx_xml_ifc_s;
|
||||
extern const char *ogs_diam_cx_xml_ifc_e;
|
||||
extern const char *ogs_diam_cx_xml_priority_s;
|
||||
extern const char *ogs_diam_cx_xml_priority_e;
|
||||
extern const char *ogs_diam_cx_xml_tp_s;
|
||||
extern const char *ogs_diam_cx_xml_tp_e;
|
||||
extern const char *ogs_diam_cx_xml_cnf_s;
|
||||
extern const char *ogs_diam_cx_xml_cnf_e;
|
||||
extern const char *ogs_diam_cx_xml_spt_s;
|
||||
extern const char *ogs_diam_cx_xml_spt_e;
|
||||
extern const char *ogs_diam_cx_xml_condition_negated_s;
|
||||
extern const char *ogs_diam_cx_xml_condition_negated_e;
|
||||
extern const char *ogs_diam_cx_xml_group_s;
|
||||
extern const char *ogs_diam_cx_xml_group_e;
|
||||
extern const char *ogs_diam_cx_xml_req_uri_s;
|
||||
extern const char *ogs_diam_cx_xml_req_uri_e;
|
||||
extern const char *ogs_diam_cx_xml_method_s;
|
||||
extern const char *ogs_diam_cx_xml_method_e;
|
||||
extern const char *ogs_diam_cx_xml_sip_hdr_s;
|
||||
extern const char *ogs_diam_cx_xml_sip_hdr_e;
|
||||
extern const char *ogs_diam_cx_xml_session_case_s;
|
||||
extern const char *ogs_diam_cx_xml_session_case_e;
|
||||
extern const char *ogs_diam_cx_xml_session_desc_s;
|
||||
extern const char *ogs_diam_cx_xml_session_desc_e;
|
||||
extern const char *ogs_diam_cx_xml_registration_type_s;
|
||||
extern const char *ogs_diam_cx_xml_registration_type_e;
|
||||
extern const char *ogs_diam_cx_xml_header_s;
|
||||
extern const char *ogs_diam_cx_xml_header_e;
|
||||
extern const char *ogs_diam_cx_xml_content_s;
|
||||
extern const char *ogs_diam_cx_xml_content_e;
|
||||
extern const char *ogs_diam_cx_xml_line_s;
|
||||
extern const char *ogs_diam_cx_xml_line_e;
|
||||
|
||||
extern const char *ogs_diam_cx_xml_app_server_s;
|
||||
extern const char *ogs_diam_cx_xml_app_server_e;
|
||||
extern const char *ogs_diam_cx_xml_server_name_s;
|
||||
extern const char *ogs_diam_cx_xml_server_name_e;
|
||||
extern const char *ogs_diam_cx_xml_default_handling_s;
|
||||
extern const char *ogs_diam_cx_xml_default_handling_e;
|
||||
extern const char *ogs_diam_cx_xml_service_info_s;
|
||||
extern const char *ogs_diam_cx_xml_service_info_e;
|
||||
extern const char *ogs_diam_cx_xml_include_register_request;
|
||||
extern const char *ogs_diam_cx_xml_include_register_response;
|
||||
|
||||
extern const char *ogs_diam_cx_xml_profile_part_ind_s;
|
||||
extern const char *ogs_diam_cx_xml_profile_part_ind_e;
|
||||
|
||||
extern const char *ogs_diam_cx_xml_cn_services_auth_s;
|
||||
extern const char *ogs_diam_cx_xml_cn_services_auth_e;
|
||||
extern const char *ogs_diam_cx_xml_subs_media_profile_id_s;
|
||||
extern const char *ogs_diam_cx_xml_subs_media_profile_id_e;
|
||||
extern const char *ogs_diam_cx_xml_shared_ifc_set_id_s;
|
||||
extern const char *ogs_diam_cx_xml_shared_ifc_set_id_e;
|
||||
|
||||
extern const char *ogs_diam_cx_xml_extension_s;
|
||||
extern const char *ogs_diam_cx_xml_extension_e;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OGS_DIAM_OGS_DIAM_CX_MESSAGE_H */
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OGS_DIAMETER_CX_H
|
||||
#define OGS_DIAMETER_CX_H
|
||||
|
||||
#include "ogs-diameter-common.h"
|
||||
|
||||
#define OGS_DIAMETER_INSIDE
|
||||
|
||||
#include "diameter/cx/message.h"
|
||||
|
||||
#undef OGS_DIAMETER_INSIDE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Nothing */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OGS_DIAMETER_CX_H */
|
|
@ -19,3 +19,4 @@ subdir('common')
|
|||
subdir('gx')
|
||||
subdir('rx')
|
||||
subdir('s6a')
|
||||
subdir('cx')
|
||||
|
|
|
@ -148,13 +148,6 @@ int ogs_dict_rx_entry(char *conffile)
|
|||
{
|
||||
/* Create the vendors */
|
||||
|
||||
{
|
||||
struct dict_object * vendor;
|
||||
CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor, ENOENT));
|
||||
struct dict_application_data app_data = { 16777216, "Cx" };
|
||||
CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_APPLICATION, &app_data, vendor, NULL));
|
||||
}
|
||||
|
||||
{
|
||||
struct dict_object * vendor;
|
||||
CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor, ENOENT));
|
||||
|
@ -165,404 +158,6 @@ int ogs_dict_rx_entry(char *conffile)
|
|||
}
|
||||
|
||||
/* Command section */
|
||||
{
|
||||
struct dict_object* app;
|
||||
CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Cx", &app, ENOENT));
|
||||
|
||||
/* User-Authorization-Request (UAR) Command */
|
||||
{
|
||||
struct dict_object* cmd_uar;
|
||||
struct dict_cmd_data data = {
|
||||
300, /* Code */
|
||||
"3GPP/User-Authorization-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Visited-Network-Identifier" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Authorization-Type" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "UAR-Flags" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_uar);
|
||||
PARSE_loc_rules(rules, cmd_uar);
|
||||
}
|
||||
|
||||
/* User-Authorization-Answer (UAA) Command */
|
||||
{
|
||||
struct dict_object* cmd_uaa;
|
||||
struct dict_cmd_data data = {
|
||||
300, /* Code */
|
||||
"3GPP/User-Authorization-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_uaa);
|
||||
PARSE_loc_rules(rules, cmd_uaa);
|
||||
}
|
||||
|
||||
/* Location-Info-Request (LIR) Command */
|
||||
{
|
||||
struct dict_object* cmd_lir;
|
||||
struct dict_cmd_data data = {
|
||||
302, /* Code */
|
||||
"3GPP/Location-Info-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Originating-Request" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Authorization-Type" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Session-Priority" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_lir);
|
||||
PARSE_loc_rules(rules, cmd_lir);
|
||||
}
|
||||
|
||||
/* Location-Info-Answer (LIA) Command */
|
||||
{
|
||||
struct dict_object* cmd_lia;
|
||||
struct dict_cmd_data data = {
|
||||
302, /* Code */
|
||||
"3GPP/Location-Info-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "LIA-Flags" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_lia);
|
||||
PARSE_loc_rules(rules, cmd_lia);
|
||||
}
|
||||
|
||||
/* Multimedia-Auth-Request (MAR) Command */
|
||||
{
|
||||
struct dict_object* cmd_mar;
|
||||
struct dict_cmd_data data = {
|
||||
303, /* Code */
|
||||
"3GPP/Multimedia-Auth-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Number-Auth-Items" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 },
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_mar);
|
||||
PARSE_loc_rules(rules, cmd_mar);
|
||||
}
|
||||
|
||||
/* Multimedia-Auth-Answer (MAA) Command */
|
||||
{
|
||||
struct dict_object* cmd_maa;
|
||||
struct dict_cmd_data data = {
|
||||
303, /* Code */
|
||||
"3GPP/Multimedia-Auth-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Number-Auth-Items" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_maa);
|
||||
PARSE_loc_rules(rules, cmd_maa);
|
||||
}
|
||||
|
||||
/* Server-Assignment-Request (SAR) Command */
|
||||
{
|
||||
struct dict_object* cmd_sar;
|
||||
struct dict_cmd_data data = {
|
||||
301, /* Code */
|
||||
"3GPP/Server-Assignment-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Assignment-Type" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Data-Already-Available" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SCSCF-Restoration-Info" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Multiple-Registration-Indication" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Session-Priority" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_sar);
|
||||
PARSE_loc_rules(rules, cmd_sar);
|
||||
}
|
||||
|
||||
/* Server-Assignment-Answer (SAA) Command */
|
||||
{
|
||||
struct dict_object* cmd_saa;
|
||||
struct dict_cmd_data data = {
|
||||
301, /* Code */
|
||||
"3GPP/Server-Assignment-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Data" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Charging-Information" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Loose-Route-Indication" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SCSCF-Restoration-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Registered-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Server-Name" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Priviledged-Sender-Indication" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_saa);
|
||||
PARSE_loc_rules(rules, cmd_saa);
|
||||
}
|
||||
|
||||
/* Registration-Termination-Request (RTR) Command */
|
||||
{
|
||||
struct dict_object* cmd_rtr;
|
||||
struct dict_cmd_data data = {
|
||||
304, /* Code */
|
||||
"3GPP/Registration-Termination-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Public-Identity" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Deregistration-Reason" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_rtr);
|
||||
PARSE_loc_rules(rules, cmd_rtr);
|
||||
}
|
||||
|
||||
/* Registration-Termination-Answer (RTA) Command */
|
||||
{
|
||||
struct dict_object* cmd_rta;
|
||||
struct dict_cmd_data data = {
|
||||
304, /* Code */
|
||||
"3GPP/Registration-Termination-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Associated-Identities" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Identity-with-Emergency-Registration" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_rta);
|
||||
PARSE_loc_rules(rules, cmd_rta);
|
||||
}
|
||||
|
||||
/* Push-Profile-Request (PPR) Command */
|
||||
{
|
||||
struct dict_object* cmd_ppr;
|
||||
struct dict_cmd_data data = {
|
||||
305, /* Code */
|
||||
"3GPP/Push-Profile-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "User-Data" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Charging-Information" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_ppr);
|
||||
PARSE_loc_rules(rules, cmd_ppr);
|
||||
}
|
||||
|
||||
/* Push-Profile-Answer (PPA) Command */
|
||||
{
|
||||
struct dict_object* cmd_ppa;
|
||||
struct dict_cmd_data data = {
|
||||
305, /* Code */
|
||||
"3GPP/Push-Profile-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 }
|
||||
};
|
||||
|
||||
CHECK_dict_new(DICT_COMMAND, &data, app, &cmd_ppa);
|
||||
PARSE_loc_rules(rules, cmd_ppa);
|
||||
}
|
||||
}
|
||||
|
||||
struct dict_object* rx;
|
||||
CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Rx", &rx, ENOENT));
|
||||
|
|
|
@ -27,6 +27,21 @@ int __hss_log_domain;
|
|||
|
||||
static int context_initialized = 0;
|
||||
|
||||
static OGS_POOL(impi_pool, hss_impi_t);
|
||||
static OGS_POOL(impu_pool, hss_impu_t);
|
||||
|
||||
static hss_impi_t *impi_add(char *id);
|
||||
static void impi_remove(hss_impi_t *impi);
|
||||
static void impi_remove_all(void);
|
||||
|
||||
static hss_impi_t *impi_find_by_id(char *id);
|
||||
static char *impi_get_server_name(hss_impi_t *impi);
|
||||
|
||||
static hss_impu_t *impu_add(hss_impi_t *impi, char *id);
|
||||
static void impu_remove(hss_impu_t *impu);
|
||||
static void impu_remove_all(hss_impi_t *impi);
|
||||
static hss_impu_t *impu_find_by_id(hss_impi_t *impi, char *id);
|
||||
|
||||
hss_context_t* hss_self(void)
|
||||
{
|
||||
return &self;
|
||||
|
@ -47,7 +62,13 @@ void hss_context_init(void)
|
|||
ogs_log_install_domain(&__ogs_dbi_domain, "dbi", ogs_core()->log.level);
|
||||
ogs_log_install_domain(&__hss_log_domain, "hss", ogs_core()->log.level);
|
||||
|
||||
ogs_pool_init(&impi_pool, ogs_app()->pool.impi);
|
||||
ogs_pool_init(&impu_pool, ogs_app()->pool.impu);
|
||||
|
||||
self.impi_hash = ogs_hash_make();
|
||||
|
||||
ogs_thread_mutex_init(&self.db_lock);
|
||||
ogs_thread_mutex_init(&self.cx_lock);
|
||||
|
||||
context_initialized = 1;
|
||||
}
|
||||
|
@ -56,7 +77,16 @@ void hss_context_final(void)
|
|||
{
|
||||
ogs_assert(context_initialized == 1);
|
||||
|
||||
impi_remove_all();
|
||||
|
||||
ogs_assert(self.impi_hash);
|
||||
ogs_hash_destroy(self.impi_hash);
|
||||
|
||||
ogs_pool_final(&impi_pool);
|
||||
ogs_pool_final(&impu_pool);
|
||||
|
||||
ogs_thread_mutex_destroy(&self.db_lock);
|
||||
ogs_thread_mutex_destroy(&self.cx_lock);
|
||||
|
||||
context_initialized = 0;
|
||||
}
|
||||
|
@ -276,8 +306,7 @@ int hss_db_auth_info(char *imsi_bcd, ogs_dbi_auth_info_t *auth_info)
|
|||
return rv;
|
||||
}
|
||||
|
||||
int hss_db_update_rand_and_sqn(
|
||||
char *imsi_bcd, uint8_t *rand, uint64_t sqn)
|
||||
int hss_db_update_sqn(char *imsi_bcd, uint8_t *rand, uint64_t sqn)
|
||||
{
|
||||
int rv;
|
||||
char *supi = NULL;
|
||||
|
@ -335,3 +364,236 @@ int hss_db_subscription_data(
|
|||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static hss_impi_t *impi_add(char *id)
|
||||
{
|
||||
hss_impi_t *impi = NULL;
|
||||
|
||||
ogs_assert(id);
|
||||
|
||||
ogs_pool_alloc(&impi_pool, &impi);
|
||||
ogs_assert(impi);
|
||||
memset(impi, 0, sizeof *impi);
|
||||
|
||||
impi->id = ogs_strdup(id);
|
||||
ogs_assert(impi->id);
|
||||
|
||||
ogs_hash_set(self.impi_hash, impi->id, strlen(impi->id), impi);
|
||||
|
||||
ogs_list_add(&self.impi_list, impi);
|
||||
|
||||
return impi;
|
||||
}
|
||||
|
||||
static void impi_remove(hss_impi_t *impi)
|
||||
{
|
||||
ogs_assert(impi);
|
||||
|
||||
ogs_list_remove(&self.impi_list, impi);
|
||||
|
||||
impu_remove_all(impi);
|
||||
|
||||
ogs_assert(impi->id);
|
||||
ogs_hash_set(self.impi_hash, impi->id, strlen(impi->id), NULL);
|
||||
ogs_free(impi->id);
|
||||
|
||||
ogs_pool_free(&impi_pool, impi);
|
||||
}
|
||||
|
||||
static void impi_remove_all(void)
|
||||
{
|
||||
hss_impi_t *impi = NULL, *next = NULL;
|
||||
|
||||
ogs_list_for_each_safe(&self.impi_list, next, impi)
|
||||
impi_remove(impi);
|
||||
}
|
||||
|
||||
static hss_impi_t *impi_find_by_id(char *id)
|
||||
{
|
||||
ogs_assert(id);
|
||||
return (hss_impi_t *)ogs_hash_get(self.impi_hash, id, strlen(id));
|
||||
}
|
||||
|
||||
static char *impi_get_server_name(hss_impi_t *impi)
|
||||
{
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
ogs_assert(impi);
|
||||
|
||||
ogs_list_for_each(&impi->impu_list, impu) {
|
||||
if (impu->server_name)
|
||||
return impu->server_name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static hss_impu_t *impu_add(hss_impi_t *impi, char *id)
|
||||
{
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
ogs_assert(impi);
|
||||
ogs_assert(id);
|
||||
|
||||
ogs_pool_alloc(&impu_pool, &impu);
|
||||
ogs_assert(impu);
|
||||
memset(impu, 0, sizeof *impu);
|
||||
|
||||
impu->id = ogs_strdup(id);
|
||||
ogs_assert(impu->id);
|
||||
|
||||
impu->impi = impi;
|
||||
ogs_list_add(&impi->impu_list, impu);
|
||||
|
||||
return impu;
|
||||
}
|
||||
|
||||
static void impu_remove(hss_impu_t *impu)
|
||||
{
|
||||
hss_impi_t *impi = NULL;
|
||||
|
||||
ogs_assert(impu);
|
||||
impi = impu->impi;
|
||||
ogs_assert(impi);
|
||||
|
||||
ogs_list_remove(&impi->impu_list, impu);
|
||||
|
||||
ogs_assert(impu->id);
|
||||
ogs_free(impu->id);
|
||||
|
||||
if (impu->server_name)
|
||||
ogs_free(impu->server_name);
|
||||
|
||||
ogs_pool_free(&impu_pool, impu);
|
||||
}
|
||||
|
||||
static void impu_remove_all(hss_impi_t *impi)
|
||||
{
|
||||
hss_impu_t *impu = NULL, *next = NULL;
|
||||
|
||||
ogs_list_for_each_safe(&impi->impu_list, next, impu)
|
||||
impu_remove(impu);
|
||||
}
|
||||
|
||||
static hss_impu_t *impu_find_by_id(hss_impi_t *impi, char *id)
|
||||
{
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
ogs_assert(impi);
|
||||
ogs_assert(id);
|
||||
|
||||
ogs_list_for_each(&impi->impu_list, impu) {
|
||||
if (!strcmp(impu->id, id))
|
||||
return impu;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hss_cx_associate_identity(char *user_name, char *public_identity)
|
||||
{
|
||||
hss_impi_t *impi = NULL;
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
ogs_assert(user_name);
|
||||
ogs_assert(public_identity);
|
||||
|
||||
ogs_thread_mutex_lock(&self.cx_lock);
|
||||
|
||||
impi = impi_find_by_id(user_name);
|
||||
if (!impi) {
|
||||
impi = impi_add(user_name);
|
||||
ogs_assert(impi);
|
||||
}
|
||||
|
||||
impu = impu_find_by_id(impi, public_identity);
|
||||
if (!impu) {
|
||||
impu = impu_add(impi, public_identity);
|
||||
ogs_assert(impu);
|
||||
}
|
||||
|
||||
ogs_thread_mutex_unlock(&self.cx_lock);
|
||||
}
|
||||
|
||||
bool hss_cx_identity_is_associated(char *user_name, char *public_identity)
|
||||
{
|
||||
bool match_result = false;
|
||||
|
||||
hss_impi_t *impi = NULL;
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
ogs_thread_mutex_lock(&self.cx_lock);
|
||||
|
||||
impi = impi_find_by_id(user_name);
|
||||
if (impi) {
|
||||
impu = impu_find_by_id(impi, public_identity);
|
||||
if (impu) {
|
||||
match_result = true;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_thread_mutex_unlock(&self.cx_lock);
|
||||
|
||||
return match_result;
|
||||
}
|
||||
|
||||
char *hss_cx_get_server_name(char *user_name, char *public_identity)
|
||||
{
|
||||
char *server_name = NULL;
|
||||
|
||||
hss_impi_t *impi = NULL;
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
ogs_thread_mutex_lock(&self.cx_lock);
|
||||
|
||||
impi = impi_find_by_id(user_name);
|
||||
ogs_assert(impi);
|
||||
|
||||
impu = impu_find_by_id(impi, public_identity);
|
||||
ogs_assert(impu);
|
||||
|
||||
server_name = impu->server_name;
|
||||
if (!server_name) {
|
||||
server_name = impi_get_server_name(impi);
|
||||
}
|
||||
|
||||
ogs_thread_mutex_unlock(&self.cx_lock);
|
||||
|
||||
return server_name;
|
||||
}
|
||||
|
||||
void hss_cx_set_server_name(
|
||||
char *user_name, char *public_identity,
|
||||
char *server_name, bool overwrite)
|
||||
{
|
||||
hss_impi_t *impi = NULL;
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
ogs_thread_mutex_lock(&self.cx_lock);
|
||||
|
||||
impi = impi_find_by_id(user_name);
|
||||
ogs_assert(impi);
|
||||
|
||||
impu = impu_find_by_id(impi, public_identity);
|
||||
ogs_assert(impu);
|
||||
|
||||
if (!impu->server_name) {
|
||||
impu->server_name = ogs_strdup(server_name);
|
||||
ogs_assert(impu->server_name);
|
||||
} else {
|
||||
if (strcmp(impu->server_name, server_name) != 0) {
|
||||
if (overwrite == true) {
|
||||
ogs_warn("S-CSCF reassignment[%s->%s]",
|
||||
impu->server_name, server_name);
|
||||
ogs_free(impu->server_name);
|
||||
impu->server_name = ogs_strdup(server_name);
|
||||
ogs_assert(impu->server_name);
|
||||
} else {
|
||||
ogs_error("Use Old S-CSCF[%s!=%s]",
|
||||
server_name, impu->server_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ogs_thread_mutex_unlock(&self.cx_lock);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define HSS_CONTEXT_H
|
||||
|
||||
#include "ogs-diameter-s6a.h"
|
||||
#include "ogs-diameter-cx.h"
|
||||
#include "ogs-dbi.h"
|
||||
#include "ogs-app.h"
|
||||
|
||||
|
@ -34,12 +35,33 @@ extern int __hss_log_domain;
|
|||
#define OGS_LOG_DOMAIN __hss_log_domain
|
||||
|
||||
typedef struct _hss_context_t {
|
||||
const char *diam_conf_path; /* HSS Diameter conf path */
|
||||
ogs_diam_config_t *diam_config; /* HSS Diameter config */
|
||||
const char *diam_conf_path;/* HSS Diameter conf path */
|
||||
ogs_diam_config_t *diam_config; /* HSS Diameter config */
|
||||
|
||||
ogs_thread_mutex_t db_lock;
|
||||
ogs_thread_mutex_t cx_lock;
|
||||
|
||||
ogs_list_t impi_list;
|
||||
ogs_hash_t *impi_hash; /* hash table (IMPI) */
|
||||
} hss_context_t;
|
||||
|
||||
typedef struct hss_impi_s {
|
||||
ogs_lnode_t lnode;
|
||||
|
||||
char *id;
|
||||
|
||||
ogs_list_t impu_list;
|
||||
} hss_impi_t;
|
||||
|
||||
typedef struct hss_impu_s {
|
||||
ogs_lnode_t lnode;
|
||||
|
||||
char *id;
|
||||
char *server_name;
|
||||
|
||||
hss_impi_t *impi;
|
||||
} hss_impu_t;
|
||||
|
||||
void hss_context_init(void);
|
||||
void hss_context_final(void);
|
||||
hss_context_t *hss_self(void);
|
||||
|
@ -47,12 +69,20 @@ hss_context_t *hss_self(void);
|
|||
int hss_context_parse_config(void);
|
||||
|
||||
int hss_db_auth_info(char *imsi_bcd, ogs_dbi_auth_info_t *auth_info);
|
||||
int hss_db_update_rand_and_sqn(char *imsi_bcd, uint8_t *rand, uint64_t sqn);
|
||||
int hss_db_update_sqn(char *imsi_bcd, uint8_t *rand, uint64_t sqn);
|
||||
int hss_db_increment_sqn(char *imsi_bcd);
|
||||
|
||||
int hss_db_subscription_data(
|
||||
char *imsi_bcd, ogs_subscription_data_t *subscription_data);
|
||||
|
||||
void hss_cx_associate_identity(char *user_name, char *public_identity);
|
||||
bool hss_cx_identity_is_associated(char *user_name, char *public_identity);
|
||||
|
||||
char *hss_cx_get_server_name(char *user_name, char *public_identity);
|
||||
void hss_cx_set_server_name(
|
||||
char *user_name, char *public_identity,
|
||||
char *server_name, bool overwrite);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,999 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-crypt.h"
|
||||
|
||||
#include "hss-context.h"
|
||||
#include "hss-fd-path.h"
|
||||
|
||||
/* handler for fallback cb */
|
||||
static struct disp_hdl *hdl_cx_fb = NULL;
|
||||
/* handler for User-Authorization-Request cb */
|
||||
static struct disp_hdl *hdl_cx_uar = NULL;
|
||||
/* handler for Multimedia-Auth-Request cb */
|
||||
static struct disp_hdl *hdl_cx_mar = NULL;
|
||||
/* handler for Server-Assignment-Request cb */
|
||||
static struct disp_hdl *hdl_cx_sar = NULL;
|
||||
|
||||
static char *download_user_data(
|
||||
char *user_name, ogs_subscription_data_t *subscription_data);
|
||||
|
||||
/* Default callback for the application. */
|
||||
static int hss_ogs_diam_cx_fb_cb(struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
/* This CB should never be called */
|
||||
ogs_warn("Unexpected message received!");
|
||||
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
/* Callback for incoming User-Authorization-Request messages */
|
||||
static int hss_ogs_diam_cx_uar_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int rv, ret;
|
||||
uint32_t result_code = 0;
|
||||
|
||||
struct msg *ans, *qry;
|
||||
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char *user_name = NULL;
|
||||
char *public_identity = NULL;
|
||||
char *server_name = NULL;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
char msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1];
|
||||
|
||||
ogs_subscription_data_t subscription_data;
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_debug("User-Authorization-Request");
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
/* Get User-Name AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
user_name = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(user_name);
|
||||
|
||||
ogs_extract_digit_from_string(imsi_bcd, user_name);
|
||||
|
||||
/* Get Public-Identity AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
public_identity = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(public_identity);
|
||||
|
||||
ogs_extract_digit_from_string(msisdn_bcd, public_identity);
|
||||
|
||||
memset(&subscription_data, 0, sizeof(ogs_subscription_data_t));
|
||||
rv = hss_db_subscription_data(imsi_bcd, &subscription_data);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Associate IMPI(User-Name) + IMPU(Public-Identity) */
|
||||
hss_cx_associate_identity(user_name, public_identity);
|
||||
|
||||
/* Get Server-Name for IMPI(User-Name) + IMPU(Public-Identity) */
|
||||
server_name = hss_cx_get_server_name(user_name, public_identity);
|
||||
if (!server_name)
|
||||
result_code = OGS_DIAM_CX_FIRST_REGISTRATION;
|
||||
else
|
||||
result_code = OGS_DIAM_CX_SUBSEQUENT_REGISTRATION;
|
||||
|
||||
/* Set the Experimental-Result, Origin-Host and Origin-Realm AVPs */
|
||||
ret = ogs_diam_message_experimental_rescode_set(
|
||||
ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Server-Name AVP */
|
||||
if (server_name) {
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_server_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)server_name;
|
||||
val.os.len = strlen(server_name);
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("User-Authorization-Answer");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
ogs_free(user_name);
|
||||
ogs_free(public_identity);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Experimental-Result, Origin-Host and Origin-Realm AVPs */
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
ogs_free(user_name);
|
||||
ogs_free(public_identity);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback for incoming Multimedia-Auth-Request messages */
|
||||
static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int rv, ret;
|
||||
uint32_t result_code = 0;
|
||||
|
||||
struct msg *ans, *qry;
|
||||
|
||||
struct avp *sip_auth_data_item_avp = NULL;
|
||||
struct avp *authentication_scheme_avp = NULL;
|
||||
struct avp *sip_authorization_avp = NULL;
|
||||
|
||||
struct avp *avpch = NULL;
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char *user_name = NULL;
|
||||
char *public_identity = NULL;
|
||||
char *server_name = NULL;
|
||||
char *authentication_scheme = NULL;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
char msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1];
|
||||
|
||||
ogs_dbi_auth_info_t auth_info;
|
||||
uint8_t zero[OGS_RAND_LEN];
|
||||
|
||||
uint8_t authenticate[OGS_KEY_LEN*2];
|
||||
|
||||
uint8_t opc[OGS_KEY_LEN];
|
||||
uint8_t sqn[OGS_SQN_LEN];
|
||||
|
||||
uint8_t autn[OGS_AUTN_LEN];
|
||||
uint8_t ik[OGS_KEY_LEN];
|
||||
uint8_t ck[OGS_KEY_LEN];
|
||||
uint8_t ak[OGS_AK_LEN];
|
||||
uint8_t xres[OGS_MAX_RES_LEN];
|
||||
size_t xres_len = 8;
|
||||
|
||||
uint8_t mac_s[OGS_MAC_S_LEN];
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_debug("Multimedia-Auth-Request");
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
/* Get User-Name AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
user_name = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(user_name);
|
||||
|
||||
ogs_extract_digit_from_string(imsi_bcd, user_name);
|
||||
|
||||
/* Get Public-Identity AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
public_identity = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(public_identity);
|
||||
|
||||
ogs_extract_digit_from_string(msisdn_bcd, public_identity);
|
||||
|
||||
/* Get Server-Name AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_cx_server_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
server_name = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(server_name);
|
||||
|
||||
/* Check if IMPI(User-Name) + IMPU(Public-Identity) is associated */
|
||||
bool matched = hss_cx_identity_is_associated(user_name, public_identity);
|
||||
if (!matched) {
|
||||
ogs_error("User-Name[%s] Public-Identity[%s] is not assocated",
|
||||
user_name, public_identity);
|
||||
result_code = OGS_DIAM_CX_ERROR_IDENTITIES_DONT_MATCH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get the SIP-Auth-Data-Item AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(
|
||||
qry, ogs_diam_cx_sip_auth_data_item, &sip_auth_data_item_avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(sip_auth_data_item_avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Get the Authentication-Scheme AVP */
|
||||
ret = fd_msg_search_avp(sip_auth_data_item_avp,
|
||||
ogs_diam_cx_sip_authentication_scheme, &authentication_scheme_avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (authentication_scheme_avp) {
|
||||
ret = fd_msg_avp_hdr(authentication_scheme_avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
authentication_scheme = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(authentication_scheme);
|
||||
}
|
||||
|
||||
/* IMS_AKA is only supported */
|
||||
if (authentication_scheme &&
|
||||
strcmp(authentication_scheme, OGS_DIAM_CX_AUTH_SCHEME_IMS_AKA) != 0 &&
|
||||
strcmp(authentication_scheme, OGS_DIAM_CX_AUTH_SCHEME_UNKNOWN) != 0) {
|
||||
ogs_error("Authentication-Scheme[%s] is not supported",
|
||||
authentication_scheme);
|
||||
result_code = OGS_DIAM_CX_ERROR_AUTH_SCHEME_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = hss_db_auth_info(imsi_bcd, &auth_info);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Overwrite Server-Name for IMPI(User-Name) + IMPU(Public-Identity) */
|
||||
hss_cx_set_server_name(user_name, public_identity, server_name, true);
|
||||
|
||||
memset(zero, 0, sizeof(zero));
|
||||
if (memcmp(auth_info.rand, zero, OGS_RAND_LEN) == 0) {
|
||||
ogs_random(auth_info.rand, OGS_RAND_LEN);
|
||||
}
|
||||
|
||||
if (auth_info.use_opc)
|
||||
memcpy(opc, auth_info.opc, sizeof(opc));
|
||||
else
|
||||
milenage_opc(auth_info.k, auth_info.op, opc);
|
||||
|
||||
/* Get the SIP-Authorization AVP */
|
||||
ret = fd_msg_search_avp(sip_auth_data_item_avp,
|
||||
ogs_diam_cx_sip_authorization, &sip_authorization_avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (sip_authorization_avp) {
|
||||
ret = fd_msg_avp_hdr(sip_authorization_avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_auc_sqn(opc, auth_info.k,
|
||||
hdr->avp_value->os.data,
|
||||
hdr->avp_value->os.data + OGS_RAND_LEN,
|
||||
sqn, mac_s);
|
||||
if (memcmp(mac_s, hdr->avp_value->os.data +
|
||||
OGS_RAND_LEN + OGS_SQN_LEN, OGS_MAC_S_LEN) == 0) {
|
||||
ogs_random(auth_info.rand, OGS_RAND_LEN);
|
||||
auth_info.sqn = ogs_buffer_to_uint64(sqn, OGS_SQN_LEN);
|
||||
/* 33.102 C.3.4 Guide : IND + 1 */
|
||||
auth_info.sqn = (auth_info.sqn + 32 + 1) & OGS_MAX_SQN;
|
||||
} else {
|
||||
ogs_error("Re-synch MAC failed for IMSI:`%s`", imsi_bcd);
|
||||
ogs_log_print(OGS_LOG_ERROR, "MAC_S: ");
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, mac_s, OGS_MAC_S_LEN);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
(void*)(hdr->avp_value->os.data +
|
||||
OGS_RAND_LEN + OGS_SQN_LEN),
|
||||
OGS_MAC_S_LEN);
|
||||
ogs_log_print(OGS_LOG_ERROR, "SQN: ");
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, sqn, OGS_SQN_LEN);
|
||||
result_code = OGS_DIAM_CX_ERROR_AUTH_SCHEME_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rv = hss_db_update_sqn(imsi_bcd, auth_info.rand, auth_info.sqn);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot update rand and sqn for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_CX_ERROR_IN_ASSIGNMENT_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = hss_db_increment_sqn(imsi_bcd);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot increment sqn for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_CX_ERROR_IN_ASSIGNMENT_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if 0 /* Test Vector for ipsec_reg.pcapng */
|
||||
/*
|
||||
* Ki : 8baf473f2f8fd09487cccbd7097c6862
|
||||
* OP : 11111111111111111111111111111111
|
||||
* OPc : 8E27B6AF0E692E750F32667A3B14605D
|
||||
* open5gs SQN : 44254 (dec)
|
||||
* Fhoss SQN : 00000000ad25 (hex)
|
||||
* RAND : a0944c75ff3c4f0853a2f910aa1f104f
|
||||
* AMF : c6e2f46c8f4280007f3bb9b84b7c3ff6
|
||||
*
|
||||
* New SQN : 000017242898 (hex)
|
||||
*/
|
||||
|
||||
auth_info.sqn = 0x17242898;
|
||||
#define RAND "a0944c75ff3c4f0853a2f910aa1f104f"
|
||||
OGS_HEX(RAND, strlen(RAND), auth_info.rand);
|
||||
#endif
|
||||
|
||||
milenage_generate(opc, auth_info.amf, auth_info.k,
|
||||
ogs_uint64_to_buffer(auth_info.sqn, OGS_SQN_LEN, sqn), auth_info.rand,
|
||||
autn, ik, ck, ak, xres, &xres_len);
|
||||
|
||||
memcpy(authenticate, auth_info.rand, OGS_RAND_LEN);
|
||||
memcpy(authenticate + OGS_RAND_LEN, autn, OGS_AUTN_LEN);
|
||||
|
||||
ogs_log_print(OGS_LOG_DEBUG, "K - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, auth_info.k, OGS_KEY_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "AMF - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, auth_info.amf, OGS_AMF_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "OPc - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, opc, OGS_KEY_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "RAND - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, auth_info.rand, OGS_RAND_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "SQN - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, sqn, OGS_SQN_LEN);
|
||||
|
||||
ogs_log_print(OGS_LOG_DEBUG, "AUTN - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, autn, OGS_KEY_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "ck - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, ck, OGS_KEY_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "ik - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, ik, OGS_KEY_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "ak - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, ak, OGS_KEY_LEN);
|
||||
ogs_log_print(OGS_LOG_DEBUG, "xles - ");
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, xres, xres_len);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
||||
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the User-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)user_name;
|
||||
val.os.len = strlen(user_name);
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Public-Identity AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_public_identity, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)public_identity;
|
||||
val.os.len = strlen(public_identity);
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the SIP-Number-Auth-Items AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_number_auth_items, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the SIP-Auth-Data-Item AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_auth_data_item, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the SIP-Item-Number AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_item_number, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the SIP-Authentication-Scheme AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_authentication_scheme, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)OGS_DIAM_CX_AUTH_SCHEME_IMS_AKA;
|
||||
val.os.len = strlen(OGS_DIAM_CX_AUTH_SCHEME_IMS_AKA);
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the SIP-Authenticatie AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_authenticate, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = authenticate;
|
||||
val.os.len = OGS_KEY_LEN * 2;
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the SIP-Authorization AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_authorization, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = xres;
|
||||
val.os.len = xres_len;
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Confidentiality-Key AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_confidentiality_key, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = ck;
|
||||
val.os.len = OGS_KEY_LEN;
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Integirty-Key AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_integrity_key, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = ik;
|
||||
val.os.len = OGS_KEY_LEN;
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("Multimedia-Auth-Answer");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
if (authentication_scheme)
|
||||
ogs_free(authentication_scheme);
|
||||
|
||||
ogs_free(user_name);
|
||||
ogs_free(public_identity);
|
||||
ogs_free(server_name);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Experimental-Result, Origin-Host and Origin-Realm AVPs */
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
if (authentication_scheme)
|
||||
ogs_free(authentication_scheme);
|
||||
|
||||
ogs_free(user_name);
|
||||
ogs_free(public_identity);
|
||||
ogs_free(server_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback for incoming Server-Assignment-Request messages */
|
||||
static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int rv, ret;
|
||||
uint32_t result_code = 0;
|
||||
|
||||
struct msg *ans, *qry;
|
||||
|
||||
struct avp *avpch = NULL;
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char *user_name = NULL;
|
||||
char *public_identity = NULL;
|
||||
char *server_name = NULL;
|
||||
char *user_data = NULL;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
char msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1];
|
||||
|
||||
ogs_subscription_data_t subscription_data;
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_debug("Server-Assignment-Request");
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
/* Get User-Name AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
user_name = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(user_name);
|
||||
|
||||
ogs_extract_digit_from_string(imsi_bcd, user_name);
|
||||
|
||||
/* Get Public-Identity AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
public_identity = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(public_identity);
|
||||
|
||||
ogs_extract_digit_from_string(msisdn_bcd, public_identity);
|
||||
|
||||
memset(&subscription_data, 0, sizeof(ogs_subscription_data_t));
|
||||
rv = hss_db_subscription_data(imsi_bcd, &subscription_data);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get Server-Name AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_cx_server_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
server_name = ogs_strndup(
|
||||
(char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
ogs_assert(server_name);
|
||||
|
||||
/* Check if IMPI(User-Name) + IMPU(Public-Identity) is associated */
|
||||
bool matched = hss_cx_identity_is_associated(user_name, public_identity);
|
||||
if (!matched) {
|
||||
ogs_error("User-Name[%s] Public-Identity[%s] is not assocated",
|
||||
user_name, public_identity);
|
||||
result_code = OGS_DIAM_CX_ERROR_IDENTITIES_DONT_MATCH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Overwrite Server-Name for IMPI(User-Name) + IMPU(Public-Identity) */
|
||||
hss_cx_set_server_name(user_name, public_identity, server_name, true);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
||||
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the User-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)user_name;
|
||||
val.os.len = strlen(user_name);
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Get User-Data-Already-Available AVP (Mandatory has already been checked) */
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_cx_user_data_already_available, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
if (hdr->avp_value->i32 == OGS_DIAM_CX_USER_DATA_ALREADY_AVAILABLE) {
|
||||
/* Nothing to do */
|
||||
} else {
|
||||
/* Set the User-Data AVP */
|
||||
user_data = download_user_data(user_name, &subscription_data);
|
||||
ogs_assert(user_data);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_user_data, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)user_data;
|
||||
val.os.len = strlen(user_data);
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Charging-Information AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_charging_information, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Charging-Information AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_charging_information, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Primary-Charging-Collection-Function-Name AVP */
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_cx_primary_charging_collection_function_name, 0,
|
||||
&avpch);
|
||||
ogs_assert(ret == 0);
|
||||
#define PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME "pcrf"
|
||||
val.os.data = (uint8_t *)PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME;
|
||||
val.os.len = strlen(PRIMARY_CHARGING_COLLECTION_FUNCTION_NAME);
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("Server-Assignment-Answer");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
if (user_data)
|
||||
ogs_free(user_data);
|
||||
ogs_free(user_name);
|
||||
ogs_free(public_identity);
|
||||
ogs_free(server_name);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Experimental-Result, Origin-Host and Origin-Realm AVPs */
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
if (user_data)
|
||||
ogs_free(user_data);
|
||||
ogs_free(user_name);
|
||||
ogs_free(public_identity);
|
||||
ogs_free(server_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *download_user_data(
|
||||
char *user_name, ogs_subscription_data_t *subscription_data)
|
||||
{
|
||||
char *user_data = NULL;
|
||||
int i;
|
||||
|
||||
ogs_assert(user_name);
|
||||
ogs_assert(subscription_data);
|
||||
|
||||
user_data = ogs_strdup(ogs_diam_cx_xml_version);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_ims_subscription_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_private_id_s,
|
||||
user_name,
|
||||
ogs_diam_cx_xml_private_id_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_service_profile_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_public_id_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_barring_indication_s,
|
||||
"1",
|
||||
ogs_diam_cx_xml_barring_indication_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%ssip:%s%s",
|
||||
ogs_diam_cx_xml_identity_s,
|
||||
user_name,
|
||||
ogs_diam_cx_xml_identity_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_identity_type_s,
|
||||
"0",
|
||||
ogs_diam_cx_xml_identity_type_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_public_id_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
for (i = 0; i < subscription_data->num_of_msisdn; i++) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_public_id_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%stel:%s%s",
|
||||
ogs_diam_cx_xml_identity_s,
|
||||
subscription_data->msisdn[i].bcd,
|
||||
ogs_diam_cx_xml_identity_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_identity_type_s,
|
||||
"0",
|
||||
ogs_diam_cx_xml_identity_type_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_public_id_e);
|
||||
ogs_assert(user_data);
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_public_id_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%ssip:%s%s",
|
||||
ogs_diam_cx_xml_identity_s,
|
||||
subscription_data->msisdn[i].bcd,
|
||||
ogs_diam_cx_xml_identity_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_identity_type_s,
|
||||
"0",
|
||||
ogs_diam_cx_xml_identity_type_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_public_id_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_service_profile_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data,
|
||||
"%s", ogs_diam_cx_xml_ims_subscription_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
return user_data;
|
||||
}
|
||||
|
||||
int hss_cx_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct disp_when data;
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
ret = ogs_diam_cx_init();
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.app = ogs_diam_cx_application;
|
||||
|
||||
/* Fallback CB if command != unexpected message received */
|
||||
ret = fd_disp_register(hss_ogs_diam_cx_fb_cb, DISP_HOW_APPID,
|
||||
&data, NULL, &hdl_cx_fb);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for User-Authorization-Request */
|
||||
data.command = ogs_diam_cx_cmd_uar;
|
||||
ret = fd_disp_register(hss_ogs_diam_cx_uar_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_cx_uar);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for Multimedia-Auth-Request */
|
||||
data.command = ogs_diam_cx_cmd_mar;
|
||||
ret = fd_disp_register(hss_ogs_diam_cx_mar_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_cx_mar);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for Server-Assignment-Request */
|
||||
data.command = ogs_diam_cx_cmd_sar;
|
||||
ret = fd_disp_register(hss_ogs_diam_cx_sar_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_cx_sar);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
ret = fd_disp_app_support(ogs_diam_cx_application, ogs_diam_vendor, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void hss_cx_final(void)
|
||||
{
|
||||
if (hdl_cx_fb)
|
||||
(void) fd_disp_unregister(&hdl_cx_fb, NULL);
|
||||
if (hdl_cx_uar)
|
||||
(void) fd_disp_unregister(&hdl_cx_uar, NULL);
|
||||
if (hdl_cx_mar)
|
||||
(void) fd_disp_unregister(&hdl_cx_mar, NULL);
|
||||
if (hdl_cx_sar)
|
||||
(void) fd_disp_unregister(&hdl_cx_sar, NULL);
|
||||
}
|
|
@ -22,833 +22,26 @@
|
|||
#include "hss-context.h"
|
||||
#include "hss-fd-path.h"
|
||||
|
||||
/* handler for fallback cb */
|
||||
static struct disp_hdl *hdl_s6a_fb = NULL;
|
||||
/* handler for Authentication-Information-Request cb */
|
||||
static struct disp_hdl *hdl_s6a_air = NULL;
|
||||
/* handler for Update-Location-Request cb */
|
||||
static struct disp_hdl *hdl_s6a_ulr = NULL;
|
||||
|
||||
/* Default callback for the application. */
|
||||
static int hss_ogs_diam_s6a_fb_cb(struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
/* This CB should never be called */
|
||||
ogs_warn("Unexpected message received!");
|
||||
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
/* Callback for incoming Authentication-Information-Request messages */
|
||||
static int hss_ogs_diam_s6a_air_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct msg *ans, *qry;
|
||||
struct avp *avpch;
|
||||
struct avp *avp_e_utran_vector, *avp_xres, *avp_kasme, *avp_rand, *avp_autn;
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
uint8_t opc[OGS_KEY_LEN];
|
||||
uint8_t sqn[OGS_SQN_LEN];
|
||||
uint8_t autn[OGS_AUTN_LEN];
|
||||
uint8_t ik[OGS_KEY_LEN];
|
||||
uint8_t ck[OGS_KEY_LEN];
|
||||
uint8_t ak[OGS_AK_LEN];
|
||||
uint8_t xres[OGS_MAX_RES_LEN];
|
||||
uint8_t kasme[OGS_SHA256_DIGEST_SIZE];
|
||||
size_t xres_len = 8;
|
||||
|
||||
uint8_t mac_s[OGS_MAC_S_LEN];
|
||||
|
||||
ogs_dbi_auth_info_t auth_info;
|
||||
uint8_t zero[OGS_RAND_LEN];
|
||||
int rv;
|
||||
uint32_t result_code = 0;
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_debug("[HSS] Authentication-Information-Request\n");
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_cpystrn(imsi_bcd, (char*)hdr->avp_value->os.data,
|
||||
ogs_min(hdr->avp_value->os.len, OGS_MAX_IMSI_BCD_LEN)+1);
|
||||
|
||||
rv = hss_db_auth_info(imsi_bcd, &auth_info);
|
||||
if (rv != OGS_OK) {
|
||||
result_code = OGS_DIAM_S6A_ERROR_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(zero, 0, sizeof(zero));
|
||||
if (memcmp(auth_info.rand, zero, OGS_RAND_LEN) == 0) {
|
||||
ogs_random(auth_info.rand, OGS_RAND_LEN);
|
||||
}
|
||||
|
||||
if (auth_info.use_opc)
|
||||
memcpy(opc, auth_info.opc, sizeof(opc));
|
||||
else
|
||||
milenage_opc(auth_info.k, auth_info.op, opc);
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_req_eutran_auth_info, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_avp_search_avp(
|
||||
avp, ogs_diam_s6a_re_synchronization_info, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
if (avpch) {
|
||||
ret = fd_msg_avp_hdr(avpch, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_auc_sqn(opc, auth_info.k,
|
||||
hdr->avp_value->os.data,
|
||||
hdr->avp_value->os.data + OGS_RAND_LEN,
|
||||
sqn, mac_s);
|
||||
if (memcmp(mac_s, hdr->avp_value->os.data +
|
||||
OGS_RAND_LEN + OGS_SQN_LEN, OGS_MAC_S_LEN) == 0) {
|
||||
ogs_random(auth_info.rand, OGS_RAND_LEN);
|
||||
auth_info.sqn = ogs_buffer_to_uint64(sqn, OGS_SQN_LEN);
|
||||
/* 33.102 C.3.4 Guide : IND + 1 */
|
||||
auth_info.sqn = (auth_info.sqn + 32 + 1) & OGS_MAX_SQN;
|
||||
} else {
|
||||
ogs_error("Re-synch MAC failed for IMSI:`%s`", imsi_bcd);
|
||||
ogs_log_print(OGS_LOG_ERROR, "MAC_S: ");
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, mac_s, OGS_MAC_S_LEN);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
(void*)(hdr->avp_value->os.data +
|
||||
OGS_RAND_LEN + OGS_SQN_LEN),
|
||||
OGS_MAC_S_LEN);
|
||||
ogs_log_print(OGS_LOG_ERROR, "SQN: ");
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, sqn, OGS_SQN_LEN);
|
||||
result_code = OGS_DIAM_S6A_AUTHENTICATION_DATA_UNAVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = hss_db_update_rand_and_sqn(imsi_bcd, auth_info.rand, auth_info.sqn);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot update rand and sqn for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_AUTHENTICATION_DATA_UNAVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = hss_db_increment_sqn(imsi_bcd);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot increment sqn for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_AUTHENTICATION_DATA_UNAVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_visited_plmn_id, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
#if 0 // TODO : check visited_plmn_id
|
||||
memcpy(visited_plmn_id, hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
#endif
|
||||
|
||||
milenage_generate(opc, auth_info.amf, auth_info.k,
|
||||
ogs_uint64_to_buffer(auth_info.sqn, OGS_SQN_LEN, sqn), auth_info.rand,
|
||||
autn, ik, ck, ak, xres, &xres_len);
|
||||
ogs_auc_kasme(ck, ik, hdr->avp_value->os.data, sqn, ak, kasme);
|
||||
|
||||
/* Set the Authentication-Info */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_authentication_info, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_e_utran_vector, 0, &avp_e_utran_vector);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_rand, 0, &avp_rand);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = auth_info.rand;
|
||||
val.os.len = OGS_KEY_LEN;
|
||||
ret = fd_msg_avp_setvalue(avp_rand, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_rand);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_xres, 0, &avp_xres);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = xres;
|
||||
val.os.len = xres_len;
|
||||
ret = fd_msg_avp_setvalue(avp_xres, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_xres);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_autn, 0, &avp_autn);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = autn;
|
||||
val.os.len = OGS_AUTN_LEN;
|
||||
ret = fd_msg_avp_setvalue(avp_autn, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_autn);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_kasme, 0, &avp_kasme);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = kasme;
|
||||
val.os.len = OGS_SHA256_DIGEST_SIZE;
|
||||
ret = fd_msg_avp_setvalue(avp_kasme, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_kasme);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_e_utran_vector);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
||||
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("[HSS] Authentication-Information-Answer\n");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback for incoming Update-Location-Request messages */
|
||||
static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int ret;
|
||||
struct msg *ans, *qry;
|
||||
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
ogs_s_nssai_t s_nssai;
|
||||
|
||||
int rv;
|
||||
uint32_t result_code = 0;
|
||||
ogs_subscription_data_t subscription_data;
|
||||
ogs_slice_data_t *slice_data = NULL;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_debug("[HSS] Update-Location-Request\n");
|
||||
|
||||
memset(&subscription_data, 0, sizeof(ogs_subscription_data_t));
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_cpystrn(imsi_bcd, (char*)hdr->avp_value->os.data,
|
||||
ogs_min(hdr->avp_value->os.len, OGS_MAX_IMSI_BCD_LEN)+1);
|
||||
|
||||
rv = hss_db_subscription_data(imsi_bcd, &subscription_data);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_ERROR_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_visited_plmn_id, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
#if 0 // TODO : check visited_plmn_id
|
||||
memcpy(visited_plmn_id, hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
#endif
|
||||
|
||||
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
||||
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the ULA Flags */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_ula_flags, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_DIAM_S6A_ULA_FLAGS_MME_REGISTERED_FOR_SMS;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_ulr_flags, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
if (!(hdr->avp_value->u32 & OGS_DIAM_S6A_ULR_SKIP_SUBSCRIBER_DATA)) {
|
||||
struct avp *avp_msisdn, *avp_a_msisdn;
|
||||
struct avp *avp_access_restriction_data;
|
||||
struct avp *avp_subscriber_status, *avp_network_access_mode;
|
||||
struct avp *avp_ambr, *avp_max_bandwidth_ul, *avp_max_bandwidth_dl;
|
||||
struct avp *avp_rau_tau_timer;
|
||||
|
||||
/* Set the APN Configuration Profile */
|
||||
struct avp *apn_configuration_profile;
|
||||
struct avp *context_identifier;
|
||||
struct avp *all_apn_configuration_included_indicator;
|
||||
|
||||
int i;
|
||||
|
||||
/* Set the Subscription Data */
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_subscription_data, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/*
|
||||
* TS29.328
|
||||
* 6.3.2 MSISDN AVP
|
||||
*
|
||||
* The MSISDN AVP is of type OctetString.
|
||||
* This AVP contains an MSISDN, in international number format
|
||||
* as described in ITU-T Rec E.164 [8], encoded as a TBCD-string,
|
||||
* i.e. digits from 0 through 9 are encoded 0000 to 1001;
|
||||
* 1111 is used as a filler when there is an odd number of digits;
|
||||
* bits 8 to 5 of octet n encode digit 2n;
|
||||
* bits 4 to 1 of octet n encode digit 2(n-1)+1.
|
||||
*/
|
||||
if (subscription_data.num_of_msisdn >= 1) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_msisdn, 0, &avp_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = subscription_data.msisdn[0].buf;
|
||||
val.os.len = subscription_data.msisdn[0].len;
|
||||
ret = fd_msg_avp_setvalue(avp_msisdn, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subscription_data.num_of_msisdn >= 2) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_a_msisdn, 0, &avp_a_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = subscription_data.msisdn[1].buf;
|
||||
val.os.len = subscription_data.msisdn[1].len;
|
||||
ret = fd_msg_avp_setvalue(avp_a_msisdn, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_a_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subscription_data.access_restriction_data) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_access_restriction_data, 0,
|
||||
&avp_access_restriction_data);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.access_restriction_data;
|
||||
ret = fd_msg_avp_setvalue( avp_access_restriction_data, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
||||
avp_access_restriction_data);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_subscriber_status, 0, &avp_subscriber_status);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.subscriber_status;
|
||||
ret = fd_msg_avp_setvalue(avp_subscriber_status, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_subscriber_status);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_network_access_mode, 0,
|
||||
&avp_network_access_mode);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.network_access_mode;
|
||||
ret = fd_msg_avp_setvalue(avp_network_access_mode, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_network_access_mode);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the AMBR */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_ambr, 0, &avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_max_bandwidth_ul, 0, &avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = subscription_data.ambr.uplink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_ul, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(
|
||||
avp_ambr, MSG_BRW_LAST_CHILD, avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_max_bandwidth_dl, 0, &avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = subscription_data.ambr.downlink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_dl, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(
|
||||
avp_ambr, MSG_BRW_LAST_CHILD, avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Subscribed RAU TAU Timer */
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_subscribed_rau_tau_timer, 0, &avp_rau_tau_timer);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.subscribed_rau_tau_timer * 60; /* seconds */
|
||||
ret = fd_msg_avp_setvalue(avp_rau_tau_timer, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_rau_tau_timer);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* For EPC, we'll use SST:1 */
|
||||
s_nssai.sst = 1;
|
||||
s_nssai.sd.v = OGS_S_NSSAI_NO_SD_VALUE;
|
||||
|
||||
slice_data = ogs_slice_find_by_s_nssai(
|
||||
subscription_data.slice, subscription_data.num_of_slice,
|
||||
&s_nssai);
|
||||
if (!slice_data) {
|
||||
ogs_error("[%s] Cannot find S-NSSAI", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_ERROR_UNKNOWN_EPS_SUBSCRIPTION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!slice_data->num_of_session) {
|
||||
ogs_error("[%s] No PDN", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_ERROR_UNKNOWN_EPS_SUBSCRIPTION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_apn_configuration_profile, 0,
|
||||
&apn_configuration_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_context_identifier, 0,
|
||||
&context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1; /* Context Identifier : 1 */
|
||||
ret = fd_msg_avp_setvalue(context_identifier, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration_profile,
|
||||
MSG_BRW_LAST_CHILD, context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_all_apn_configuration_included_indicator, 0,
|
||||
&all_apn_configuration_included_indicator);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 0;
|
||||
ret = fd_msg_avp_setvalue(
|
||||
all_apn_configuration_included_indicator, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration_profile, MSG_BRW_LAST_CHILD,
|
||||
all_apn_configuration_included_indicator);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
for (i = 0; i < slice_data->num_of_session; i++) {
|
||||
/* Set the APN Configuration */
|
||||
struct avp *apn_configuration, *context_identifier, *pdn_type;
|
||||
struct avp *served_party_ip_address, *service_selection;
|
||||
struct avp *eps_subscribed_qos_profile, *qos_class_identifier;
|
||||
struct avp *allocation_retention_priority, *priority_level;
|
||||
struct avp *pre_emption_capability, *pre_emption_vulnerability;
|
||||
struct avp *mip6_agent_info, *mip_home_agent_address;
|
||||
|
||||
ogs_session_t *session = &slice_data->session[i];
|
||||
ogs_assert(session);
|
||||
session->context_identifier = i+1;
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_apn_configuration, 0,
|
||||
&apn_configuration);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Context-Identifier */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_context_identifier, 0,
|
||||
&context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = session->context_identifier;
|
||||
ret = fd_msg_avp_setvalue(context_identifier, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set PDN-Type */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_pdn_type, 0, &pdn_type);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_PDU_SESSION_TYPE_TO_DIAMETER(session->session_type);
|
||||
ret = fd_msg_avp_setvalue(pdn_type, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, pdn_type);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Served-Party-IP-Address */
|
||||
if ((session->session_type == OGS_PDU_SESSION_TYPE_IPV4 ||
|
||||
session->session_type == OGS_PDU_SESSION_TYPE_IPV4V6) &&
|
||||
session->ue_ip.ipv4) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address,
|
||||
0, &served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = session->ue_ip.addr;
|
||||
ret = fd_msg_avp_value_encode(&sin, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD,
|
||||
served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if ((session->session_type == OGS_PDU_SESSION_TYPE_IPV6 ||
|
||||
session->session_type == OGS_PDU_SESSION_TYPE_IPV4V6) &&
|
||||
session->ue_ip.ipv6) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address,
|
||||
0, &served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
memcpy(sin6.sin6_addr.s6_addr,
|
||||
session->ue_ip.addr6, OGS_IPV6_LEN);
|
||||
ret = fd_msg_avp_value_encode(&sin6, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD,
|
||||
served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Set Service-Selection */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_service_selection, 0,
|
||||
&service_selection);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(session->name);
|
||||
val.os.data = (uint8_t *)session->name;
|
||||
val.os.len = strlen(session->name);
|
||||
ret = fd_msg_avp_setvalue(service_selection, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, service_selection);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the EPS Subscribed QoS Profile */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_eps_subscribed_qos_profile, 0,
|
||||
&eps_subscribed_qos_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_qos_class_identifier, 0,
|
||||
&qos_class_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = session->qos.index;
|
||||
ret = fd_msg_avp_setvalue(qos_class_identifier, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(eps_subscribed_qos_profile,
|
||||
MSG_BRW_LAST_CHILD, qos_class_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Allocation retention priority */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_allocation_retention_priority, 0,
|
||||
&allocation_retention_priority);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_priority_level, 0, &priority_level);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = session->qos.arp.priority_level;
|
||||
ret = fd_msg_avp_setvalue(priority_level, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(allocation_retention_priority,
|
||||
MSG_BRW_LAST_CHILD, priority_level);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_pre_emption_capability, 0,
|
||||
&pre_emption_capability);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_DISABLED;
|
||||
if (session->qos.arp.pre_emption_capability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_ENABLED;
|
||||
ret = fd_msg_avp_setvalue(pre_emption_capability, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(allocation_retention_priority,
|
||||
MSG_BRW_LAST_CHILD, pre_emption_capability);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_pre_emption_vulnerability, 0,
|
||||
&pre_emption_vulnerability);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_DISABLED;
|
||||
if (session->qos.arp.pre_emption_vulnerability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_ENABLED;
|
||||
ret = fd_msg_avp_setvalue(pre_emption_vulnerability, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(allocation_retention_priority,
|
||||
MSG_BRW_LAST_CHILD, pre_emption_vulnerability);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(eps_subscribed_qos_profile,
|
||||
MSG_BRW_LAST_CHILD, allocation_retention_priority);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, eps_subscribed_qos_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set MIP6-Agent-Info */
|
||||
if (session->smf_ip.ipv4 || session->smf_ip.ipv6) {
|
||||
ret = fd_msg_avp_new(ogs_diam_mip6_agent_info, 0,
|
||||
&mip6_agent_info);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
if (session->smf_ip.ipv4) {
|
||||
ret = fd_msg_avp_new(ogs_diam_mip_home_agent_address, 0,
|
||||
&mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = session->smf_ip.addr;
|
||||
ret = fd_msg_avp_value_encode (
|
||||
&sin, mip_home_agent_address );
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(mip6_agent_info,
|
||||
MSG_BRW_LAST_CHILD, mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (session->smf_ip.ipv6) {
|
||||
ret = fd_msg_avp_new(ogs_diam_mip_home_agent_address, 0,
|
||||
&mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
memcpy(sin6.sin6_addr.s6_addr, session->smf_ip.addr6,
|
||||
sizeof session->smf_ip.addr6);
|
||||
ret = fd_msg_avp_value_encode (
|
||||
&sin6, mip_home_agent_address );
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(mip6_agent_info,
|
||||
MSG_BRW_LAST_CHILD, mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, mip6_agent_info);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Set AMBR */
|
||||
if (session->ambr.downlink || session->ambr.uplink) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_ambr, 0, &avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_max_bandwidth_ul, 0,
|
||||
&avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = session->ambr.uplink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_ul, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
||||
avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_max_bandwidth_dl, 0,
|
||||
&avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = session->ambr.downlink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_dl, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
||||
avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration_profile,
|
||||
MSG_BRW_LAST_CHILD, apn_configuration);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
||||
apn_configuration_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("[HSS] Update-Location-Answer\n");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert( pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert( pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hss_fd_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct disp_when data;
|
||||
struct dict_object *s6a_app, *vnd;
|
||||
struct dict_vendor_data vnd_data;
|
||||
struct dict_application_data s6a_app_data;
|
||||
int rv;
|
||||
|
||||
ret = ogs_diam_init(FD_MODE_SERVER,
|
||||
rv = ogs_diam_init(FD_MODE_SERVER,
|
||||
hss_self()->diam_conf_path, hss_self()->diam_config);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(rv == 0);
|
||||
|
||||
vnd_data.vendor_id = 10415;
|
||||
vnd_data.vendor_name = (char *) "3GPP";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict,
|
||||
DICT_VENDOR, &vnd_data, NULL, &vnd);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
s6a_app_data.application_id = 16777251;
|
||||
s6a_app_data.application_name = (char *) "S6A";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict, DICT_APPLICATION,
|
||||
&s6a_app_data, NULL, &s6a_app);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_disp_app_support(s6a_app, vnd, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
ret = ogs_diam_s6a_init();
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.app = ogs_diam_s6a_application;
|
||||
|
||||
/* Fallback CB if command != unexpected message received */
|
||||
ret = fd_disp_register(hss_ogs_diam_s6a_fb_cb, DISP_HOW_APPID, &data, NULL,
|
||||
&hdl_s6a_fb);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for Authentication-Information-Request */
|
||||
data.command = ogs_diam_s6a_cmd_air;
|
||||
ret = fd_disp_register(hss_ogs_diam_s6a_air_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_s6a_air);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for Location-Update-Request */
|
||||
data.command = ogs_diam_s6a_cmd_ulr;
|
||||
ret = fd_disp_register(hss_ogs_diam_s6a_ulr_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_s6a_ulr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
ret = fd_disp_app_support(ogs_diam_s6a_application, ogs_diam_vendor, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
rv = hss_s6a_init();
|
||||
ogs_assert(rv == OGS_OK);
|
||||
rv = hss_cx_init();
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void hss_fd_final(void)
|
||||
{
|
||||
if (hdl_s6a_fb)
|
||||
(void) fd_disp_unregister(&hdl_s6a_fb, NULL);
|
||||
if (hdl_s6a_air)
|
||||
(void) fd_disp_unregister(&hdl_s6a_air, NULL);
|
||||
if (hdl_s6a_ulr)
|
||||
(void) fd_disp_unregister(&hdl_s6a_ulr, NULL);
|
||||
hss_s6a_final();
|
||||
hss_cx_final();
|
||||
|
||||
ogs_diam_final();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,11 @@ extern "C" {
|
|||
int hss_fd_init(void);
|
||||
void hss_fd_final(void);
|
||||
|
||||
int hss_s6a_init(void);
|
||||
void hss_s6a_final(void);
|
||||
int hss_cx_init(void);
|
||||
void hss_cx_final(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,828 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-crypt.h"
|
||||
|
||||
#include "hss-context.h"
|
||||
#include "hss-fd-path.h"
|
||||
|
||||
/* handler for fallback cb */
|
||||
static struct disp_hdl *hdl_s6a_fb = NULL;
|
||||
/* handler for Authentication-Information-Request cb */
|
||||
static struct disp_hdl *hdl_s6a_air = NULL;
|
||||
/* handler for Update-Location-Request cb */
|
||||
static struct disp_hdl *hdl_s6a_ulr = NULL;
|
||||
|
||||
/* Default callback for the application. */
|
||||
static int hss_ogs_diam_s6a_fb_cb(struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
/* This CB should never be called */
|
||||
ogs_warn("Unexpected message received!");
|
||||
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
/* Callback for incoming Authentication-Information-Request messages */
|
||||
static int hss_ogs_diam_s6a_air_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct msg *ans, *qry;
|
||||
struct avp *avpch;
|
||||
struct avp *avp_e_utran_vector, *avp_xres, *avp_kasme, *avp_rand, *avp_autn;
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
uint8_t opc[OGS_KEY_LEN];
|
||||
uint8_t sqn[OGS_SQN_LEN];
|
||||
uint8_t autn[OGS_AUTN_LEN];
|
||||
uint8_t ik[OGS_KEY_LEN];
|
||||
uint8_t ck[OGS_KEY_LEN];
|
||||
uint8_t ak[OGS_AK_LEN];
|
||||
uint8_t xres[OGS_MAX_RES_LEN];
|
||||
uint8_t kasme[OGS_SHA256_DIGEST_SIZE];
|
||||
size_t xres_len = 8;
|
||||
|
||||
uint8_t mac_s[OGS_MAC_S_LEN];
|
||||
|
||||
ogs_dbi_auth_info_t auth_info;
|
||||
uint8_t zero[OGS_RAND_LEN];
|
||||
int rv;
|
||||
uint32_t result_code = 0;
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_debug("Authentication-Information-Request");
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_cpystrn(imsi_bcd, (char*)hdr->avp_value->os.data,
|
||||
ogs_min(hdr->avp_value->os.len, OGS_MAX_IMSI_BCD_LEN)+1);
|
||||
|
||||
rv = hss_db_auth_info(imsi_bcd, &auth_info);
|
||||
if (rv != OGS_OK) {
|
||||
result_code = OGS_DIAM_S6A_ERROR_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(zero, 0, sizeof(zero));
|
||||
if (memcmp(auth_info.rand, zero, OGS_RAND_LEN) == 0) {
|
||||
ogs_random(auth_info.rand, OGS_RAND_LEN);
|
||||
}
|
||||
|
||||
if (auth_info.use_opc)
|
||||
memcpy(opc, auth_info.opc, sizeof(opc));
|
||||
else
|
||||
milenage_opc(auth_info.k, auth_info.op, opc);
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_req_eutran_auth_info, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_avp_search_avp(
|
||||
avp, ogs_diam_s6a_re_synchronization_info, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
if (avpch) {
|
||||
ret = fd_msg_avp_hdr(avpch, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_auc_sqn(opc, auth_info.k,
|
||||
hdr->avp_value->os.data,
|
||||
hdr->avp_value->os.data + OGS_RAND_LEN,
|
||||
sqn, mac_s);
|
||||
if (memcmp(mac_s, hdr->avp_value->os.data +
|
||||
OGS_RAND_LEN + OGS_SQN_LEN, OGS_MAC_S_LEN) == 0) {
|
||||
ogs_random(auth_info.rand, OGS_RAND_LEN);
|
||||
auth_info.sqn = ogs_buffer_to_uint64(sqn, OGS_SQN_LEN);
|
||||
/* 33.102 C.3.4 Guide : IND + 1 */
|
||||
auth_info.sqn = (auth_info.sqn + 32 + 1) & OGS_MAX_SQN;
|
||||
} else {
|
||||
ogs_error("Re-synch MAC failed for IMSI:`%s`", imsi_bcd);
|
||||
ogs_log_print(OGS_LOG_ERROR, "MAC_S: ");
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, mac_s, OGS_MAC_S_LEN);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
(void*)(hdr->avp_value->os.data +
|
||||
OGS_RAND_LEN + OGS_SQN_LEN),
|
||||
OGS_MAC_S_LEN);
|
||||
ogs_log_print(OGS_LOG_ERROR, "SQN: ");
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, sqn, OGS_SQN_LEN);
|
||||
result_code = OGS_DIAM_S6A_AUTHENTICATION_DATA_UNAVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = hss_db_update_sqn(imsi_bcd, auth_info.rand, auth_info.sqn);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot update rand and sqn for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_AUTHENTICATION_DATA_UNAVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = hss_db_increment_sqn(imsi_bcd);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot increment sqn for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_AUTHENTICATION_DATA_UNAVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_visited_plmn_id, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
#if 0 // TODO : check visited_plmn_id
|
||||
memcpy(visited_plmn_id, hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
#endif
|
||||
|
||||
milenage_generate(opc, auth_info.amf, auth_info.k,
|
||||
ogs_uint64_to_buffer(auth_info.sqn, OGS_SQN_LEN, sqn), auth_info.rand,
|
||||
autn, ik, ck, ak, xres, &xres_len);
|
||||
ogs_auc_kasme(ck, ik, hdr->avp_value->os.data, sqn, ak, kasme);
|
||||
|
||||
/* Set the Authentication-Info */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_authentication_info, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_e_utran_vector, 0, &avp_e_utran_vector);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_rand, 0, &avp_rand);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = auth_info.rand;
|
||||
val.os.len = OGS_KEY_LEN;
|
||||
ret = fd_msg_avp_setvalue(avp_rand, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_rand);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_xres, 0, &avp_xres);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = xres;
|
||||
val.os.len = xres_len;
|
||||
ret = fd_msg_avp_setvalue(avp_xres, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_xres);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_autn, 0, &avp_autn);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = autn;
|
||||
val.os.len = OGS_AUTN_LEN;
|
||||
ret = fd_msg_avp_setvalue(avp_autn, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_autn);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_kasme, 0, &avp_kasme);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = kasme;
|
||||
val.os.len = OGS_SHA256_DIGEST_SIZE;
|
||||
ret = fd_msg_avp_setvalue(avp_kasme, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_kasme);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_e_utran_vector);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
||||
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("Authentication-Information-Answer");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback for incoming Update-Location-Request messages */
|
||||
static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int ret;
|
||||
struct msg *ans, *qry;
|
||||
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
ogs_s_nssai_t s_nssai;
|
||||
|
||||
int rv;
|
||||
uint32_t result_code = 0;
|
||||
ogs_subscription_data_t subscription_data;
|
||||
ogs_slice_data_t *slice_data = NULL;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_debug("Update-Location-Request");
|
||||
|
||||
memset(&subscription_data, 0, sizeof(ogs_subscription_data_t));
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_cpystrn(imsi_bcd, (char*)hdr->avp_value->os.data,
|
||||
ogs_min(hdr->avp_value->os.len, OGS_MAX_IMSI_BCD_LEN)+1);
|
||||
|
||||
rv = hss_db_subscription_data(imsi_bcd, &subscription_data);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_ERROR_USER_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_visited_plmn_id, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
#if 0 // TODO : check visited_plmn_id
|
||||
memcpy(visited_plmn_id, hdr->avp_value->os.data, hdr->avp_value->os.len);
|
||||
#endif
|
||||
|
||||
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
||||
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the ULA Flags */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_ula_flags, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_DIAM_S6A_ULA_FLAGS_MME_REGISTERED_FOR_SMS;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_ulr_flags, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
if (!(hdr->avp_value->u32 & OGS_DIAM_S6A_ULR_SKIP_SUBSCRIBER_DATA)) {
|
||||
struct avp *avp_msisdn, *avp_a_msisdn;
|
||||
struct avp *avp_access_restriction_data;
|
||||
struct avp *avp_subscriber_status, *avp_network_access_mode;
|
||||
struct avp *avp_ambr, *avp_max_bandwidth_ul, *avp_max_bandwidth_dl;
|
||||
struct avp *avp_rau_tau_timer;
|
||||
|
||||
/* Set the APN Configuration Profile */
|
||||
struct avp *apn_configuration_profile;
|
||||
struct avp *context_identifier;
|
||||
struct avp *all_apn_configuration_included_indicator;
|
||||
|
||||
int i;
|
||||
|
||||
/* Set the Subscription Data */
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_subscription_data, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/*
|
||||
* TS29.328
|
||||
* 6.3.2 MSISDN AVP
|
||||
*
|
||||
* The MSISDN AVP is of type OctetString.
|
||||
* This AVP contains an MSISDN, in international number format
|
||||
* as described in ITU-T Rec E.164 [8], encoded as a TBCD-string,
|
||||
* i.e. digits from 0 through 9 are encoded 0000 to 1001;
|
||||
* 1111 is used as a filler when there is an odd number of digits;
|
||||
* bits 8 to 5 of octet n encode digit 2n;
|
||||
* bits 4 to 1 of octet n encode digit 2(n-1)+1.
|
||||
*/
|
||||
if (subscription_data.num_of_msisdn >= 1) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_msisdn, 0, &avp_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = subscription_data.msisdn[0].buf;
|
||||
val.os.len = subscription_data.msisdn[0].len;
|
||||
ret = fd_msg_avp_setvalue(avp_msisdn, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subscription_data.num_of_msisdn >= 2) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_a_msisdn, 0, &avp_a_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = subscription_data.msisdn[1].buf;
|
||||
val.os.len = subscription_data.msisdn[1].len;
|
||||
ret = fd_msg_avp_setvalue(avp_a_msisdn, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_a_msisdn);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subscription_data.access_restriction_data) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_access_restriction_data, 0,
|
||||
&avp_access_restriction_data);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.access_restriction_data;
|
||||
ret = fd_msg_avp_setvalue( avp_access_restriction_data, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
||||
avp_access_restriction_data);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_subscriber_status, 0, &avp_subscriber_status);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.subscriber_status;
|
||||
ret = fd_msg_avp_setvalue(avp_subscriber_status, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_subscriber_status);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_network_access_mode, 0,
|
||||
&avp_network_access_mode);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.network_access_mode;
|
||||
ret = fd_msg_avp_setvalue(avp_network_access_mode, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_network_access_mode);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the AMBR */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_ambr, 0, &avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_max_bandwidth_ul, 0, &avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = subscription_data.ambr.uplink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_ul, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(
|
||||
avp_ambr, MSG_BRW_LAST_CHILD, avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_max_bandwidth_dl, 0, &avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = subscription_data.ambr.downlink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_dl, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(
|
||||
avp_ambr, MSG_BRW_LAST_CHILD, avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Subscribed RAU TAU Timer */
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_subscribed_rau_tau_timer, 0, &avp_rau_tau_timer);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = subscription_data.subscribed_rau_tau_timer * 60; /* seconds */
|
||||
ret = fd_msg_avp_setvalue(avp_rau_tau_timer, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_rau_tau_timer);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* For EPC, we'll use SST:1 */
|
||||
s_nssai.sst = 1;
|
||||
s_nssai.sd.v = OGS_S_NSSAI_NO_SD_VALUE;
|
||||
|
||||
slice_data = ogs_slice_find_by_s_nssai(
|
||||
subscription_data.slice, subscription_data.num_of_slice,
|
||||
&s_nssai);
|
||||
if (!slice_data) {
|
||||
ogs_error("[%s] Cannot find S-NSSAI", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_ERROR_UNKNOWN_EPS_SUBSCRIPTION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!slice_data->num_of_session) {
|
||||
ogs_error("[%s] No PDN", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_ERROR_UNKNOWN_EPS_SUBSCRIPTION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_apn_configuration_profile, 0,
|
||||
&apn_configuration_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_context_identifier, 0,
|
||||
&context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1; /* Context Identifier : 1 */
|
||||
ret = fd_msg_avp_setvalue(context_identifier, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration_profile,
|
||||
MSG_BRW_LAST_CHILD, context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_all_apn_configuration_included_indicator, 0,
|
||||
&all_apn_configuration_included_indicator);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 0;
|
||||
ret = fd_msg_avp_setvalue(
|
||||
all_apn_configuration_included_indicator, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration_profile, MSG_BRW_LAST_CHILD,
|
||||
all_apn_configuration_included_indicator);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
for (i = 0; i < slice_data->num_of_session; i++) {
|
||||
/* Set the APN Configuration */
|
||||
struct avp *apn_configuration, *context_identifier, *pdn_type;
|
||||
struct avp *served_party_ip_address, *service_selection;
|
||||
struct avp *eps_subscribed_qos_profile, *qos_class_identifier;
|
||||
struct avp *allocation_retention_priority, *priority_level;
|
||||
struct avp *pre_emption_capability, *pre_emption_vulnerability;
|
||||
struct avp *mip6_agent_info, *mip_home_agent_address;
|
||||
|
||||
ogs_session_t *session = &slice_data->session[i];
|
||||
ogs_assert(session);
|
||||
session->context_identifier = i+1;
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_apn_configuration, 0,
|
||||
&apn_configuration);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Context-Identifier */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_context_identifier, 0,
|
||||
&context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = session->context_identifier;
|
||||
ret = fd_msg_avp_setvalue(context_identifier, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, context_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set PDN-Type */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_pdn_type, 0, &pdn_type);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_PDU_SESSION_TYPE_TO_DIAMETER(session->session_type);
|
||||
ret = fd_msg_avp_setvalue(pdn_type, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, pdn_type);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Served-Party-IP-Address */
|
||||
if ((session->session_type == OGS_PDU_SESSION_TYPE_IPV4 ||
|
||||
session->session_type == OGS_PDU_SESSION_TYPE_IPV4V6) &&
|
||||
session->ue_ip.ipv4) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address,
|
||||
0, &served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = session->ue_ip.addr;
|
||||
ret = fd_msg_avp_value_encode(&sin, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD,
|
||||
served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if ((session->session_type == OGS_PDU_SESSION_TYPE_IPV6 ||
|
||||
session->session_type == OGS_PDU_SESSION_TYPE_IPV4V6) &&
|
||||
session->ue_ip.ipv6) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_served_party_ip_address,
|
||||
0, &served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
memcpy(sin6.sin6_addr.s6_addr,
|
||||
session->ue_ip.addr6, OGS_IPV6_LEN);
|
||||
ret = fd_msg_avp_value_encode(&sin6, served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration, MSG_BRW_LAST_CHILD,
|
||||
served_party_ip_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Set Service-Selection */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_service_selection, 0,
|
||||
&service_selection);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(session->name);
|
||||
val.os.data = (uint8_t *)session->name;
|
||||
val.os.len = strlen(session->name);
|
||||
ret = fd_msg_avp_setvalue(service_selection, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, service_selection);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the EPS Subscribed QoS Profile */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_eps_subscribed_qos_profile, 0,
|
||||
&eps_subscribed_qos_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_qos_class_identifier, 0,
|
||||
&qos_class_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = session->qos.index;
|
||||
ret = fd_msg_avp_setvalue(qos_class_identifier, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(eps_subscribed_qos_profile,
|
||||
MSG_BRW_LAST_CHILD, qos_class_identifier);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Allocation retention priority */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_allocation_retention_priority, 0,
|
||||
&allocation_retention_priority);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_priority_level, 0, &priority_level);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = session->qos.arp.priority_level;
|
||||
ret = fd_msg_avp_setvalue(priority_level, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(allocation_retention_priority,
|
||||
MSG_BRW_LAST_CHILD, priority_level);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_pre_emption_capability, 0,
|
||||
&pre_emption_capability);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_DISABLED;
|
||||
if (session->qos.arp.pre_emption_capability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_ENABLED;
|
||||
ret = fd_msg_avp_setvalue(pre_emption_capability, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(allocation_retention_priority,
|
||||
MSG_BRW_LAST_CHILD, pre_emption_capability);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_pre_emption_vulnerability, 0,
|
||||
&pre_emption_vulnerability);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_DISABLED;
|
||||
if (session->qos.arp.pre_emption_vulnerability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
val.u32 = OGS_EPC_PRE_EMPTION_ENABLED;
|
||||
ret = fd_msg_avp_setvalue(pre_emption_vulnerability, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(allocation_retention_priority,
|
||||
MSG_BRW_LAST_CHILD, pre_emption_vulnerability);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(eps_subscribed_qos_profile,
|
||||
MSG_BRW_LAST_CHILD, allocation_retention_priority);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, eps_subscribed_qos_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set MIP6-Agent-Info */
|
||||
if (session->smf_ip.ipv4 || session->smf_ip.ipv6) {
|
||||
ret = fd_msg_avp_new(ogs_diam_mip6_agent_info, 0,
|
||||
&mip6_agent_info);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
if (session->smf_ip.ipv4) {
|
||||
ret = fd_msg_avp_new(ogs_diam_mip_home_agent_address, 0,
|
||||
&mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = session->smf_ip.addr;
|
||||
ret = fd_msg_avp_value_encode (
|
||||
&sin, mip_home_agent_address );
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(mip6_agent_info,
|
||||
MSG_BRW_LAST_CHILD, mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (session->smf_ip.ipv6) {
|
||||
ret = fd_msg_avp_new(ogs_diam_mip_home_agent_address, 0,
|
||||
&mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
memcpy(sin6.sin6_addr.s6_addr, session->smf_ip.addr6,
|
||||
sizeof session->smf_ip.addr6);
|
||||
ret = fd_msg_avp_value_encode (
|
||||
&sin6, mip_home_agent_address );
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(mip6_agent_info,
|
||||
MSG_BRW_LAST_CHILD, mip_home_agent_address);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, mip6_agent_info);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Set AMBR */
|
||||
if (session->ambr.downlink || session->ambr.uplink) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_ambr, 0, &avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_max_bandwidth_ul, 0,
|
||||
&avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = session->ambr.uplink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_ul, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
||||
avp_max_bandwidth_ul);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_max_bandwidth_dl, 0,
|
||||
&avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = session->ambr.downlink;
|
||||
ret = fd_msg_avp_setvalue(avp_max_bandwidth_dl, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
||||
avp_max_bandwidth_dl);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration,
|
||||
MSG_BRW_LAST_CHILD, avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_add(apn_configuration_profile,
|
||||
MSG_BRW_LAST_CHILD, apn_configuration);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
||||
apn_configuration_profile);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("Update-Location-Answer");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert( pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert( pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_subscription_data_free(&subscription_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hss_s6a_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct disp_when data;
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
ret = ogs_diam_s6a_init();
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.app = ogs_diam_s6a_application;
|
||||
|
||||
/* Fallback CB if command != unexpected message received */
|
||||
ret = fd_disp_register(hss_ogs_diam_s6a_fb_cb, DISP_HOW_APPID, &data, NULL,
|
||||
&hdl_s6a_fb);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for Authentication-Information-Request */
|
||||
data.command = ogs_diam_s6a_cmd_air;
|
||||
ret = fd_disp_register(hss_ogs_diam_s6a_air_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_s6a_air);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for Location-Update-Request */
|
||||
data.command = ogs_diam_s6a_cmd_ulr;
|
||||
ret = fd_disp_register(hss_ogs_diam_s6a_ulr_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_s6a_ulr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
ret = fd_disp_app_support(ogs_diam_s6a_application, ogs_diam_vendor, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void hss_s6a_final(void)
|
||||
{
|
||||
if (hdl_s6a_fb)
|
||||
(void) fd_disp_unregister(&hdl_s6a_fb, NULL);
|
||||
if (hdl_s6a_air)
|
||||
(void) fd_disp_unregister(&hdl_s6a_air, NULL);
|
||||
if (hdl_s6a_ulr)
|
||||
(void) fd_disp_unregister(&hdl_s6a_ulr, NULL);
|
||||
}
|
|
@ -18,19 +18,24 @@
|
|||
libhss_sources = files('''
|
||||
hss-context.h
|
||||
hss-fd-path.h
|
||||
|
||||
hss-init.c
|
||||
hss-context.c
|
||||
hss-s6a-path.c
|
||||
hss-cx-path.c
|
||||
hss-fd-path.c
|
||||
'''.split())
|
||||
|
||||
libhss = static_library('hss',
|
||||
sources : libhss_sources,
|
||||
dependencies : [libapp_dep, libcrypt_dep, libdbi_dep, libdiameter_s6a_dep],
|
||||
dependencies : [libapp_dep, libcrypt_dep, libdbi_dep,
|
||||
libdiameter_s6a_dep, libdiameter_cx_dep],
|
||||
install : false)
|
||||
|
||||
libhss_dep = declare_dependency(
|
||||
link_with : libhss,
|
||||
dependencies : [libapp_dep, libcrypt_dep, libdbi_dep, libdiameter_s6a_dep])
|
||||
dependencies : [libapp_dep, libcrypt_dep, libdbi_dep,
|
||||
libdiameter_s6a_dep, libdiameter_cx_dep])
|
||||
|
||||
hss_sources = files('''
|
||||
app-init.c
|
||||
|
|
|
@ -58,17 +58,17 @@ void mme_s6a_send_air(mme_ue_t *mme_ue,
|
|||
|
||||
/* Clear Security Context */
|
||||
CLEAR_SECURITY_CONTEXT(mme_ue);
|
||||
|
||||
|
||||
/* Create the random value to store with the session */
|
||||
sess_data = ogs_calloc(1, sizeof (*sess_data));
|
||||
ogs_assert(sess_data);
|
||||
|
||||
|
||||
sess_data->mme_ue = mme_ue;
|
||||
|
||||
|
||||
/* Create the request */
|
||||
ret = fd_msg_new(ogs_diam_s6a_cmd_air, MSGFL_ALLOC_ETEID, &req);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
|
||||
/* Create a new session */
|
||||
#define OGS_DIAM_S6A_APP_SID_OPT "app_s6a"
|
||||
ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_S6A_APP_SID_OPT,
|
||||
|
@ -89,7 +89,7 @@ void mme_s6a_send_air(mme_ue_t *mme_ue,
|
|||
/* Set Origin-Host & Origin-Realm */
|
||||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -99,12 +99,12 @@ void mme_s6a_send_air(mme_ue_t *mme_ue,
|
|||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
|
||||
/* Set the User-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)mme_ue->imsi_bcd;
|
||||
val.os.len = strlen(mme_ue->imsi_bcd);
|
||||
val.os.len = strlen(mme_ue->imsi_bcd);
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
|
@ -163,16 +163,16 @@ void mme_s6a_send_air(mme_ue_t *mme_ue,
|
|||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
* in real life we would not need it */
|
||||
svg = sess_data;
|
||||
|
||||
|
||||
/* Store this value in the session */
|
||||
ret = fd_sess_state_store(mme_s6a_reg, session, &sess_data);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(sess_data == 0);
|
||||
|
||||
|
||||
/* Send the request */
|
||||
ret = fd_msg_send(&req, mme_s6a_aia_cb, svg);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -455,15 +455,16 @@ void mme_s6a_send_ulr(mme_ue_t *mme_ue)
|
|||
ogs_assert(mme_ue);
|
||||
|
||||
ogs_debug("[MME] Update-Location-Request");
|
||||
|
||||
|
||||
/* Create the random value to store with the session */
|
||||
sess_data = ogs_calloc(1, sizeof(*sess_data));
|
||||
ogs_assert(sess_data);
|
||||
sess_data->mme_ue = mme_ue;
|
||||
|
||||
|
||||
/* Create the request */
|
||||
ret = fd_msg_new(ogs_diam_s6a_cmd_ulr, MSGFL_ALLOC_ETEID, &req);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
|
||||
/* Create a new session */
|
||||
#define OGS_DIAM_S6A_APP_SID_OPT "app_s6a"
|
||||
ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_S6A_APP_SID_OPT,
|
||||
|
@ -484,7 +485,7 @@ void mme_s6a_send_ulr(mme_ue_t *mme_ue)
|
|||
/* Set Origin-Host & Origin-Realm */
|
||||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -494,7 +495,7 @@ void mme_s6a_send_ulr(mme_ue_t *mme_ue)
|
|||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
|
||||
/* Set the User-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -576,16 +577,16 @@ void mme_s6a_send_ulr(mme_ue_t *mme_ue)
|
|||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
* in real life we would not need it */
|
||||
svg = sess_data;
|
||||
|
||||
|
||||
/* Store this value in the session */
|
||||
ret = fd_sess_state_store(mme_s6a_reg, session, &sess_data);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(sess_data == 0);
|
||||
|
||||
|
||||
/* Send the request */
|
||||
ret = fd_msg_send(&req, mme_s6a_ula_cb, svg);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -1113,12 +1114,12 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
|||
|
||||
/* Free the message */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) +
|
||||
dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) +
|
||||
((ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
if (ogs_diam_logger_self()->stats.nb_recv) {
|
||||
/* Ponderate in the avg */
|
||||
ogs_diam_logger_self()->stats.avg = (ogs_diam_logger_self()->stats.avg *
|
||||
ogs_diam_logger_self()->stats.nb_recv + dur) /
|
||||
ogs_diam_logger_self()->stats.avg = (ogs_diam_logger_self()->stats.avg *
|
||||
ogs_diam_logger_self()->stats.nb_recv + dur) /
|
||||
(ogs_diam_logger_self()->stats.nb_recv + 1);
|
||||
/* Min, max */
|
||||
if (dur < ogs_diam_logger_self()->stats.shortest)
|
||||
|
@ -1136,17 +1137,17 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
|||
ogs_diam_logger_self()->stats.nb_recv++;
|
||||
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
|
||||
/* Display how long it took */
|
||||
if (ts.tv_nsec > sess_data->ts.tv_nsec)
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec - sess_data->ts.tv_sec),
|
||||
(long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
else
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec + 1 - sess_data->ts.tv_sec),
|
||||
(long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
|
||||
|
||||
ret = fd_msg_free(*msg);
|
||||
ogs_assert(ret == 0);
|
||||
*msg = NULL;
|
||||
|
@ -1159,29 +1160,9 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
|||
int mme_fd_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct dict_object *s6a_app, *vnd;
|
||||
struct dict_vendor_data vnd_data;
|
||||
struct dict_application_data s6a_app_data;
|
||||
|
||||
ret = ogs_diam_init(FD_MODE_CLIENT,
|
||||
mme_self()->diam_conf_path, mme_self()->diam_config);
|
||||
ogs_assert(ret == OGS_OK);
|
||||
|
||||
vnd_data.vendor_id = 10415;
|
||||
vnd_data.vendor_name = (char *) "3GPP";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict,
|
||||
DICT_VENDOR, &vnd_data, NULL, &vnd);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
s6a_app_data.application_id = 16777251;
|
||||
s6a_app_data.application_name = (char *) "S6A";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict, DICT_APPLICATION,
|
||||
&s6a_app_data, NULL, &s6a_app);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_disp_app_support(s6a_app, vnd, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
|
@ -1189,13 +1170,12 @@ int mme_fd_init(void)
|
|||
ogs_assert(ret == OGS_OK);
|
||||
|
||||
/* Create handler for sessions */
|
||||
ret = fd_sess_handler_create(&mme_s6a_reg, &state_cleanup,
|
||||
NULL, NULL);
|
||||
ogs_assert(ret == OGS_OK);
|
||||
ret = fd_sess_handler_create(&mme_s6a_reg, &state_cleanup, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
ret = fd_disp_app_support(ogs_diam_s6a_application, ogs_diam_vendor, 1, 0);
|
||||
ogs_assert(ret == OGS_OK);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -289,7 +289,7 @@ int pcrf_db_qos_data(
|
|||
return rv;
|
||||
}
|
||||
|
||||
int pcrf_sess_set_ipv4(const void *key, uint8_t *sid)
|
||||
void pcrf_sess_set_ipv4(const void *key, uint8_t *sid)
|
||||
{
|
||||
ogs_assert(self.ip_hash);
|
||||
|
||||
|
@ -298,10 +298,8 @@ int pcrf_sess_set_ipv4(const void *key, uint8_t *sid)
|
|||
ogs_hash_set(self.ip_hash, key, OGS_IPV4_LEN, sid);
|
||||
|
||||
ogs_thread_mutex_unlock(&self.hash_lock);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
int pcrf_sess_set_ipv6(const void *key, uint8_t *sid)
|
||||
void pcrf_sess_set_ipv6(const void *key, uint8_t *sid)
|
||||
{
|
||||
ogs_assert(self.ip_hash);
|
||||
|
||||
|
@ -310,8 +308,6 @@ int pcrf_sess_set_ipv6(const void *key, uint8_t *sid)
|
|||
ogs_hash_set(self.ip_hash, key, OGS_IPV6_DEFAULT_PREFIX_LEN >> 3, sid);
|
||||
|
||||
ogs_thread_mutex_unlock(&self.hash_lock);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
uint8_t *pcrf_sess_find_by_ipv4(const void *key)
|
||||
|
|
|
@ -41,10 +41,10 @@ typedef struct pcrf_context_s {
|
|||
const char *diam_conf_path; /* PCRF Diameter conf path */
|
||||
ogs_diam_config_t *diam_config; /* PCRF Diameter config */
|
||||
|
||||
ogs_thread_mutex_t db_lock;
|
||||
ogs_thread_mutex_t db_lock;
|
||||
|
||||
ogs_hash_t *ip_hash; /* hash table for Gx Frame IPv4/IPv6 */
|
||||
ogs_thread_mutex_t hash_lock;
|
||||
ogs_hash_t *ip_hash; /* hash table for Gx Frame IPv4/IPv6 */
|
||||
ogs_thread_mutex_t hash_lock;
|
||||
} pcrf_context_t;
|
||||
|
||||
void pcrf_context_init(void);
|
||||
|
@ -56,8 +56,8 @@ int pcrf_context_parse_config(void);
|
|||
int pcrf_db_qos_data(char *imsi_bcd, char *apn,
|
||||
ogs_session_data_t *session_data);
|
||||
|
||||
int pcrf_sess_set_ipv4(const void *key, uint8_t *sid);
|
||||
int pcrf_sess_set_ipv6(const void *key, uint8_t *sid);
|
||||
void pcrf_sess_set_ipv4(const void *key, uint8_t *sid);
|
||||
void pcrf_sess_set_ipv6(const void *key, uint8_t *sid);
|
||||
uint8_t *pcrf_sess_find_by_ipv4(const void *key);
|
||||
uint8_t *pcrf_sess_find_by_ipv6(const void *key);
|
||||
|
||||
|
|
|
@ -22,39 +22,11 @@
|
|||
|
||||
int pcrf_fd_init(void)
|
||||
{
|
||||
int rv, ret;
|
||||
struct dict_object *gx_app, *rx_app, *vnd;
|
||||
struct dict_vendor_data vnd_data;
|
||||
struct dict_application_data gx_app_data, rx_app_data;
|
||||
int rv;
|
||||
|
||||
ret = ogs_diam_init(FD_MODE_CLIENT|FD_MODE_SERVER,
|
||||
rv = ogs_diam_init(FD_MODE_CLIENT|FD_MODE_SERVER,
|
||||
pcrf_self()->diam_conf_path, pcrf_self()->diam_config);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
vnd_data.vendor_id = 10415;
|
||||
vnd_data.vendor_name = (char *) "3GPP";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict,
|
||||
DICT_VENDOR, &vnd_data, NULL, &vnd);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
gx_app_data.application_id = 16777238;
|
||||
gx_app_data.application_name = (char *) "Gx";
|
||||
|
||||
rx_app_data.application_id = 16777236;
|
||||
rx_app_data.application_name = (char *) "Rx";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict, DICT_APPLICATION,
|
||||
&gx_app_data, NULL, &gx_app);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict, DICT_APPLICATION,
|
||||
&rx_app_data, NULL, &rx_app);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_disp_app_support(gx_app, vnd, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_disp_app_support(rx_app, vnd, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(rv == 0);
|
||||
|
||||
rv = pcrf_gx_init();
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
|
|
@ -931,16 +931,6 @@ int pcrf_gx_send_rar(
|
|||
/* Set Origin-Host & Origin-Realm */
|
||||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
|
@ -952,6 +942,16 @@ int pcrf_gx_send_rar(
|
|||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Application-Id AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_application_id, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
|
|
@ -501,16 +501,6 @@ int pcrf_rx_send_asr(uint8_t *rx_sid, uint32_t abort_cause)
|
|||
/* Set Origin-Host & Origin-Realm */
|
||||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
|
@ -522,6 +512,16 @@ int pcrf_rx_send_asr(uint8_t *rx_sid, uint32_t abort_cause)
|
|||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Application-Id AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_application_id, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
|
|
@ -1056,9 +1056,6 @@ int smf_fd_init(void)
|
|||
{
|
||||
int ret;
|
||||
struct disp_when data;
|
||||
struct dict_object *gx_app, *vnd;
|
||||
struct dict_vendor_data vnd_data;
|
||||
struct dict_application_data gx_app_data;
|
||||
|
||||
if (smf_self()->diam_conf_path == NULL &&
|
||||
(smf_self()->diam_config->cnf_diamid == NULL ||
|
||||
|
@ -1075,23 +1072,6 @@ int smf_fd_init(void)
|
|||
smf_self()->diam_conf_path, smf_self()->diam_config);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
vnd_data.vendor_id = 10415;
|
||||
vnd_data.vendor_name = (char *) "3GPP";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict,
|
||||
DICT_VENDOR, &vnd_data, NULL, &vnd);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
gx_app_data.application_id = 16777238;
|
||||
gx_app_data.application_name = (char *) "Gx";
|
||||
|
||||
ret = fd_dict_new(fd_g_config->cnf_dict, DICT_APPLICATION,
|
||||
&gx_app_data, NULL, &gx_app);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_disp_app_support(gx_app, vnd, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
ret = ogs_diam_gx_init();
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -1114,6 +1094,7 @@ int smf_fd_init(void)
|
|||
|
||||
/* Advertise the support for the application in the peer */
|
||||
ret = fd_disp_app_support(ogs_diam_gx_application, ogs_diam_vendor, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
|
|
@ -1535,6 +1535,10 @@ bson_t *test_db_new_ims(test_ue_t *test_ue)
|
|||
|
||||
doc = BCON_NEW(
|
||||
"imsi", BCON_UTF8(test_ue->imsi),
|
||||
"msisdn", "[",
|
||||
BCON_UTF8(TEST_MSISDN),
|
||||
BCON_UTF8(TEST_ADDITIONAL_MSISDN),
|
||||
"]",
|
||||
"ambr", "{",
|
||||
"downlink", "{",
|
||||
"value", BCON_INT32(1),
|
||||
|
|
|
@ -40,6 +40,9 @@ extern "C" {
|
|||
|
||||
#define MAX_NUM_OF_SERVED_GUAMI 8
|
||||
|
||||
#define TEST_MSISDN "491725670014"
|
||||
#define TEST_ADDITIONAL_MSISDN "491725670015"
|
||||
|
||||
typedef struct test_context_s {
|
||||
uint16_t ngap_port; /* Default NGAP Port */
|
||||
ogs_list_t ngap_list; /* AMF NGAP IPv4 Server List */
|
||||
|
|
|
@ -67,7 +67,8 @@ libtestcommon = static_library('testcomon',
|
|||
libngap_dep,
|
||||
libnas_eps_dep,
|
||||
libnas_5gs_dep,
|
||||
libdiameter_rx_dep],
|
||||
libdiameter_rx_dep,
|
||||
libdiameter_cx_dep],
|
||||
install : false)
|
||||
|
||||
libtestcommon_dep = declare_dependency(
|
||||
|
@ -83,4 +84,5 @@ libtestcommon_dep = declare_dependency(
|
|||
libngap_dep,
|
||||
libnas_eps_dep,
|
||||
libnas_5gs_dep,
|
||||
libdiameter_rx_dep])
|
||||
libdiameter_rx_dep,
|
||||
libdiameter_cx_dep])
|
||||
|
|
|
@ -25,6 +25,7 @@ abts_suite *test_bearer(abts_suite *suite);
|
|||
abts_suite *test_session(abts_suite *suite);
|
||||
abts_suite *test_rx(abts_suite *suite);
|
||||
abts_suite *test_video(abts_suite *suite);
|
||||
abts_suite *test_cx(abts_suite *suite);
|
||||
|
||||
const struct testlist {
|
||||
abts_suite *(*func)(abts_suite *suite);
|
||||
|
@ -33,6 +34,7 @@ const struct testlist {
|
|||
{test_session},
|
||||
{test_rx},
|
||||
{test_video},
|
||||
{test_cx},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test-common.h"
|
||||
#include "pcscf-fd-path.h"
|
||||
|
||||
static void test1_func(abts_case *tc, void *data)
|
||||
{
|
||||
int rv;
|
||||
ogs_socknode_t *s1ap;
|
||||
ogs_socknode_t *gtpu;
|
||||
ogs_pkbuf_t *emmbuf;
|
||||
ogs_pkbuf_t *esmbuf;
|
||||
ogs_pkbuf_t *sendbuf;
|
||||
ogs_pkbuf_t *recvbuf;
|
||||
ogs_s1ap_message_t message;
|
||||
|
||||
uint8_t *rx_sid = NULL;
|
||||
|
||||
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
|
||||
test_ue_t *test_ue = NULL;
|
||||
test_sess_t *sess = NULL;
|
||||
test_bearer_t *bearer = NULL;
|
||||
|
||||
uint32_t enb_ue_s1ap_id;
|
||||
uint64_t mme_ue_s1ap_id;
|
||||
|
||||
bson_t *doc = NULL;
|
||||
|
||||
/* Setup Test UE & Session Context */
|
||||
memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci));
|
||||
|
||||
mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI;
|
||||
mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI;
|
||||
mobile_identity_suci.routing_indicator1 = 0;
|
||||
mobile_identity_suci.routing_indicator2 = 0xf;
|
||||
mobile_identity_suci.routing_indicator3 = 0xf;
|
||||
mobile_identity_suci.routing_indicator4 = 0xf;
|
||||
mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME;
|
||||
mobile_identity_suci.home_network_pki_value = 0;
|
||||
mobile_identity_suci.scheme_output[0] = 0x10;
|
||||
mobile_identity_suci.scheme_output[1] = 0x32;
|
||||
mobile_identity_suci.scheme_output[2] = 0x54;
|
||||
mobile_identity_suci.scheme_output[3] = 0x86;
|
||||
mobile_identity_suci.scheme_output[4] = 0x91;
|
||||
|
||||
test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13);
|
||||
ogs_assert(test_ue);
|
||||
|
||||
test_ue->e_cgi.cell_id = 0x1079baf;
|
||||
test_ue->nas.ksi = 0;
|
||||
test_ue->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH;
|
||||
|
||||
#if 0 /* ipsec_reg.pcapng */
|
||||
test_ue->k_string = "8baf473f2f8fd09487cccbd7097c6862";
|
||||
test_ue->opc_string = "8E27B6AF0E692E750F32667A3B14605D";
|
||||
#else
|
||||
test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
|
||||
test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca";
|
||||
#endif
|
||||
|
||||
sess = test_sess_add_by_apn(test_ue, "internet");
|
||||
ogs_assert(sess);
|
||||
|
||||
/* eNB connects to MME */
|
||||
s1ap = tests1ap_client(AF_INET);
|
||||
ABTS_PTR_NOTNULL(tc, s1ap);
|
||||
|
||||
/* eNB connects to SGW */
|
||||
gtpu = test_gtpu_server(1, AF_INET);
|
||||
ABTS_PTR_NOTNULL(tc, gtpu);
|
||||
|
||||
/* Send S1-Setup Reqeust */
|
||||
sendbuf = test_s1ap_build_s1_setup_request(
|
||||
S1AP_ENB_ID_PR_macroENB_ID, 0x54f64);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive S1-Setup Response */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(NULL, recvbuf);
|
||||
|
||||
/********** Insert Subscriber in Database */
|
||||
doc = test_db_new_ims(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, doc);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc));
|
||||
|
||||
/* Send Attach Request */
|
||||
memset(&sess->pdn_connectivity_param,
|
||||
0, sizeof(sess->pdn_connectivity_param));
|
||||
sess->pdn_connectivity_param.eit = 1;
|
||||
esmbuf = testesm_build_pdn_connectivity_request(sess);
|
||||
ABTS_PTR_NOTNULL(tc, esmbuf);
|
||||
|
||||
memset(&test_ue->attach_request_param,
|
||||
0, sizeof(test_ue->attach_request_param));
|
||||
test_ue->attach_request_param.integrity_protected = 1;
|
||||
test_ue->attach_request_param.drx_parameter = 1;
|
||||
test_ue->attach_request_param.ms_network_capability = 1;
|
||||
test_ue->attach_request_param.tmsi_status = 1;
|
||||
test_ue->attach_request_param.mobile_station_classmark_2 = 1;
|
||||
test_ue->attach_request_param.ue_usage_setting = 1;
|
||||
emmbuf = testemm_build_attach_request(test_ue, esmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, emmbuf);
|
||||
|
||||
memset(&test_ue->initial_ue_param, 0, sizeof(test_ue->initial_ue_param));
|
||||
sendbuf = test_s1ap_build_initial_ue_message(
|
||||
test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Signalling, false);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Authentication Request */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Authentication response */
|
||||
emmbuf = testemm_build_authentication_response(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, emmbuf);
|
||||
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Security mode Command */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Security mode complete */
|
||||
test_ue->mobile_identity_imeisv_presence = true;
|
||||
emmbuf = testemm_build_security_mode_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, emmbuf);
|
||||
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive ESM Information Request */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send ESM Information Response */
|
||||
sess->esm_information_param.pco = 1;
|
||||
esmbuf = testesm_build_esm_information_response(sess);
|
||||
ABTS_PTR_NOTNULL(tc, esmbuf);
|
||||
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Initial Context Setup Request +
|
||||
* Attach Accept +
|
||||
* Activate Default Bearer Context Request */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send UE Capability Info Indication */
|
||||
sendbuf = tests1ap_build_ue_radio_capability_info_indication(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Initial Context Setup Response */
|
||||
sendbuf = test_s1ap_build_initial_context_setup_response(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Attach Complete + Activate default EPS bearer cotext accept */
|
||||
test_ue->nr_cgi.cell_id = 0x1234502;
|
||||
bearer = test_bearer_find_by_ue_ebi(test_ue, 5);
|
||||
ogs_assert(bearer);
|
||||
esmbuf = testesm_build_activate_default_eps_bearer_context_accept(
|
||||
bearer, false);
|
||||
ABTS_PTR_NOTNULL(tc, esmbuf);
|
||||
emmbuf = testemm_build_attach_complete(test_ue, esmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, emmbuf);
|
||||
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive EMM information */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive GTP-U ICMP Packet */
|
||||
recvbuf = test_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
|
||||
/* Send PDN Connectivity Request */
|
||||
sess = test_sess_add_by_apn(test_ue, "ims");
|
||||
ogs_assert(sess);
|
||||
sess->pti = 5;
|
||||
|
||||
sess->pdn_connectivity_param.integrity_protected = 1;
|
||||
sess->pdn_connectivity_param.ciphered = 1;
|
||||
sess->pdn_connectivity_param.apn = 1;
|
||||
sess->pdn_connectivity_param.pco = 1;
|
||||
esmbuf = testesm_build_pdn_connectivity_request(sess);
|
||||
ABTS_PTR_NOTNULL(tc, esmbuf);
|
||||
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive E-RAB Setup Request +
|
||||
* Activate default EPS bearer context request */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send E-RAB Setup Response */
|
||||
bearer = test_bearer_find_by_ue_ebi(test_ue, 6);
|
||||
ogs_assert(bearer);
|
||||
sendbuf = test_s1ap_build_e_rab_setup_response(bearer);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Activate default EPS bearer context accept */
|
||||
esmbuf = testesm_build_activate_default_eps_bearer_context_accept(
|
||||
bearer, true);
|
||||
ABTS_PTR_NOTNULL(tc, esmbuf);
|
||||
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive GTP-U ICMP Packet */
|
||||
recvbuf = test_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
|
||||
/* Send AA-Request */
|
||||
pcscf_rx_send_aar_audio(&rx_sid, sess,
|
||||
OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1);
|
||||
|
||||
/* Receive E-RAB Setup Request +
|
||||
* Activate dedicated EPS bearer context request */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send E-RAB Setup Response */
|
||||
bearer = test_bearer_find_by_ue_ebi(test_ue, 7);
|
||||
ogs_assert(bearer);
|
||||
sendbuf = test_s1ap_build_e_rab_setup_response(bearer);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Activate dedicated EPS bearer context accept */
|
||||
esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer);
|
||||
ABTS_PTR_NOTNULL(tc, esmbuf);
|
||||
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* DELAY is needed in dedicated EPS bearer */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive GTP-U ICMP Packet */
|
||||
recvbuf = test_gtpu_read(gtpu);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
|
||||
/* Send User-Authorization-Request */
|
||||
test_cx_send_uar(test_ue, 0);
|
||||
|
||||
/* DELAY for setup IMS */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Send UEContextReleaseRequest */
|
||||
sendbuf = test_s1ap_build_ue_context_release_request(test_ue,
|
||||
S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive UEContextReleaseCommand */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send UEContextReleaseComplete */
|
||||
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
ogs_msleep(300);
|
||||
|
||||
/********** Remove Subscriber in Database */
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
|
||||
|
||||
/* eNB disonncect from MME */
|
||||
testenb_s1ap_close(s1ap);
|
||||
|
||||
/* eNB disonncect from SGW */
|
||||
test_gtpu_close(gtpu);
|
||||
|
||||
test_ue_remove(test_ue);
|
||||
}
|
||||
|
||||
abts_suite *test_cx(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, test1_func, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,926 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-diameter-cx.h"
|
||||
|
||||
#include "test-common.h"
|
||||
#include "pcscf-fd-path.h"
|
||||
|
||||
static struct session_handler *test_cx_reg = NULL;
|
||||
|
||||
struct sess_state {
|
||||
test_ue_t *test_ue;
|
||||
|
||||
char *user_name;
|
||||
char *public_identity;
|
||||
|
||||
bool resync;
|
||||
|
||||
struct timespec ts; /* Time of sending the message */
|
||||
};
|
||||
|
||||
static struct disp_hdl *hdl_cx_fb = NULL;
|
||||
|
||||
static void test_cx_uaa_cb(void *data, struct msg **msg);
|
||||
|
||||
static void test_cx_send_mar(struct sess_state *sess_data);
|
||||
static void test_cx_maa_cb(void *data, struct msg **msg);
|
||||
|
||||
static void test_cx_send_sar(struct sess_state *sess_data);
|
||||
static void test_cx_saa_cb(void *data, struct msg **msg);
|
||||
|
||||
static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque)
|
||||
{
|
||||
if (sess_data->user_name)
|
||||
ogs_free(sess_data->user_name);
|
||||
if (sess_data->public_identity)
|
||||
ogs_free(sess_data->public_identity);
|
||||
|
||||
ogs_free(sess_data);
|
||||
}
|
||||
|
||||
static int test_cx_fb_cb(struct msg **msg, struct avp *avp,
|
||||
struct session *sess, void *opaque, enum disp_action *act)
|
||||
{
|
||||
/* This CB should never be called */
|
||||
ogs_warn("Unexpected message received!");
|
||||
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
void test_cx_send_uar(test_ue_t *test_ue, int id_type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct msg *req = NULL;
|
||||
|
||||
struct msg_hdr *msg_header = NULL;
|
||||
|
||||
struct session *session = NULL;
|
||||
struct sess_state *sess_data = NULL, *svg;
|
||||
|
||||
struct avp *avp = NULL;
|
||||
union avp_value val;
|
||||
|
||||
ogs_assert(test_ue);
|
||||
|
||||
ogs_debug("User-Authroization-Request");
|
||||
|
||||
/* Create the random value to store with the session */
|
||||
sess_data = ogs_calloc(1, sizeof (*sess_data));
|
||||
ogs_assert(sess_data);
|
||||
|
||||
sess_data->test_ue = test_ue;
|
||||
|
||||
/* Create the request */
|
||||
ret = fd_msg_new(ogs_diam_cx_cmd_uar, MSGFL_ALLOC_ETEID, &req);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_hdr(req, &msg_header);
|
||||
ogs_assert(ret == 0);
|
||||
msg_header->msg_appl = OGS_DIAM_CX_APPLICATION_ID;
|
||||
|
||||
#define OGS_DIAM_CX_APP_SID_OPT "app_cx"
|
||||
ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_CX_APP_SID_OPT,
|
||||
CONSTSTRLEN(OGS_DIAM_CX_APP_SID_OPT));
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
req, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
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 Origin-Host & Origin-Realm */
|
||||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = TEST_HSS_IDENTITY;
|
||||
val.os.len = strlen(TEST_HSS_IDENTITY);
|
||||
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 */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the User-Name AVP */
|
||||
if (sess_data->user_name)
|
||||
ogs_free(sess_data->user_name);
|
||||
sess_data->user_name =
|
||||
ogs_msprintf("%s@%s", test_ue->imsi, fd_g_config->cnf_diamrlm);
|
||||
ogs_assert(sess_data->user_name);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)sess_data->user_name;
|
||||
val.os.len = strlen(sess_data->user_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 Public-Identity AVP */
|
||||
if (sess_data->public_identity)
|
||||
ogs_free(sess_data->public_identity);
|
||||
sess_data->public_identity = ogs_msprintf("sip:%s@%s",
|
||||
test_ue->imsi, fd_g_config->cnf_diamrlm);
|
||||
ogs_assert(sess_data->public_identity);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_public_identity, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)sess_data->public_identity;
|
||||
val.os.len = strlen(sess_data->public_identity);
|
||||
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 Visited-Network-Identifier AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_visited_network_identifier, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
* in real life we would not need it */
|
||||
svg = sess_data;
|
||||
|
||||
/* Store this value in the session */
|
||||
ret = fd_sess_state_store(test_cx_reg, session, &sess_data);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(sess_data == 0);
|
||||
|
||||
/* Send the request */
|
||||
ret = fd_msg_send(&req, test_cx_uaa_cb, svg);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Increment the counter */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_sent++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
}
|
||||
|
||||
/* Callback for incoming User-Authorization-Answer messages */
|
||||
static void test_cx_uaa_cb(void *data, struct msg **msg)
|
||||
{
|
||||
int ret, new;
|
||||
|
||||
struct avp *avp, *avpch;
|
||||
struct avp_hdr *hdr;
|
||||
|
||||
unsigned long dur;
|
||||
int error = 0;
|
||||
|
||||
struct sess_state *sess_data = NULL;
|
||||
struct timespec ts;
|
||||
struct session *session;
|
||||
|
||||
test_ue_t *test_ue = NULL;
|
||||
|
||||
uint32_t result_code;
|
||||
uint32_t *err = NULL, *exp_err = NULL;
|
||||
|
||||
ogs_debug("User-Authroization-Answer");
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Search the session, retrieve its data */
|
||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
|
||||
ogs_expect_or_return(ret == 0);
|
||||
ogs_expect_or_return(new == 0);
|
||||
|
||||
ret = fd_sess_state_retrieve(test_cx_reg, session, &sess_data);
|
||||
ogs_expect_or_return(ret == 0);
|
||||
ogs_expect_or_return(sess_data);
|
||||
ogs_expect_or_return((void *)sess_data == data);
|
||||
|
||||
test_ue = sess_data->test_ue;
|
||||
ogs_assert(test_ue);
|
||||
|
||||
/* Value of Result Code */
|
||||
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
result_code = hdr->avp_value->i32;
|
||||
err = &result_code;
|
||||
ogs_debug(" Result Code: %d", hdr->avp_value->i32);
|
||||
} else {
|
||||
ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_avp_search_avp(avp,
|
||||
ogs_diam_experimental_result_code, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
if (avpch) {
|
||||
ret = fd_msg_avp_hdr(avpch, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
result_code = hdr->avp_value->i32;
|
||||
exp_err = &result_code;
|
||||
ogs_debug(" Experimental Result Code: %d", result_code);
|
||||
}
|
||||
} else {
|
||||
ogs_error("no Result-Code");
|
||||
error++;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_assert(!err && exp_err &&
|
||||
result_code == OGS_DIAM_CX_FIRST_REGISTRATION);
|
||||
|
||||
/* Free the message */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) +
|
||||
((ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
if (ogs_diam_logger_self()->stats.nb_recv) {
|
||||
/* Ponderate in the avg */
|
||||
ogs_diam_logger_self()->stats.avg = (ogs_diam_logger_self()->stats.avg *
|
||||
ogs_diam_logger_self()->stats.nb_recv + dur) /
|
||||
(ogs_diam_logger_self()->stats.nb_recv + 1);
|
||||
/* Min, max */
|
||||
if (dur < ogs_diam_logger_self()->stats.shortest)
|
||||
ogs_diam_logger_self()->stats.shortest = dur;
|
||||
if (dur > ogs_diam_logger_self()->stats.longest)
|
||||
ogs_diam_logger_self()->stats.longest = dur;
|
||||
} else {
|
||||
ogs_diam_logger_self()->stats.shortest = dur;
|
||||
ogs_diam_logger_self()->stats.longest = dur;
|
||||
ogs_diam_logger_self()->stats.avg = dur;
|
||||
}
|
||||
if (error)
|
||||
ogs_diam_logger_self()->stats.nb_errs++;
|
||||
else
|
||||
ogs_diam_logger_self()->stats.nb_recv++;
|
||||
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
/* Display how long it took */
|
||||
if (ts.tv_nsec > sess_data->ts.tv_nsec)
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec - sess_data->ts.tv_sec),
|
||||
(long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
else
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec + 1 - sess_data->ts.tv_sec),
|
||||
(long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
|
||||
ret = fd_msg_free(*msg);
|
||||
ogs_assert(ret == 0);
|
||||
*msg = NULL;
|
||||
|
||||
test_cx_send_mar(sess_data);
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_cx_send_mar(struct sess_state *sess_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct msg *req = NULL;
|
||||
|
||||
struct msg_hdr *msg_header = NULL;
|
||||
|
||||
struct session *session = NULL;
|
||||
struct sess_state *svg;
|
||||
|
||||
struct avp *avp = NULL, *avpch = NULL;
|
||||
union avp_value val;
|
||||
|
||||
test_ue_t *test_ue = NULL;
|
||||
|
||||
uint8_t resync[OGS_AUTS_LEN + OGS_RAND_LEN];
|
||||
|
||||
ogs_assert(sess_data);
|
||||
test_ue = sess_data->test_ue;
|
||||
ogs_assert(test_ue);
|
||||
|
||||
ogs_debug("Multimedia-Auth-Request");
|
||||
|
||||
/* Create the request */
|
||||
ret = fd_msg_new(ogs_diam_cx_cmd_mar, MSGFL_ALLOC_ETEID, &req);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_hdr(req, &msg_header);
|
||||
ogs_assert(ret == 0);
|
||||
msg_header->msg_appl = OGS_DIAM_CX_APPLICATION_ID;
|
||||
|
||||
#define OGS_DIAM_CX_APP_SID_OPT "app_cx"
|
||||
ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_CX_APP_SID_OPT,
|
||||
CONSTSTRLEN(OGS_DIAM_CX_APP_SID_OPT));
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
req, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
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 Origin-Host & Origin-Realm */
|
||||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = TEST_HSS_IDENTITY;
|
||||
val.os.len = strlen(TEST_HSS_IDENTITY);
|
||||
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 */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the User-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)sess_data->user_name;
|
||||
val.os.len = strlen(sess_data->user_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 Public-Identity AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_public_identity, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)sess_data->public_identity;
|
||||
val.os.len = strlen(sess_data->public_identity);
|
||||
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 SIP-Auth-Data-Item AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_auth_data_item, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
if (sess_data->resync == true) {
|
||||
uint8_t ak[OGS_AK_LEN];
|
||||
uint8_t sqn[OGS_SQN_LEN];
|
||||
uint8_t mac_s[OGS_MAC_S_LEN];
|
||||
uint8_t amf[2] = { 0, 0 };
|
||||
uint8_t auts[OGS_AUTS_LEN];
|
||||
|
||||
uint64_t sqn_ms;
|
||||
int i;
|
||||
|
||||
OGS_HEX(test_ue->k_string, strlen(test_ue->k_string), test_ue->k);
|
||||
OGS_HEX(test_ue->opc_string, strlen(test_ue->opc_string), test_ue->opc);
|
||||
|
||||
milenage_f2345(test_ue->opc, test_ue->k, test_ue->rand,
|
||||
NULL, NULL, NULL, NULL, ak);
|
||||
|
||||
sqn_ms = 0x11223344;
|
||||
ogs_uint64_to_buffer(sqn_ms, 6, sqn);
|
||||
milenage_f1(test_ue->opc, test_ue->k, test_ue->rand,
|
||||
sqn, amf, NULL, auts + OGS_SQN_LEN);
|
||||
for (i = 0; i < OGS_SQN_LEN; i++)
|
||||
auts[i] = sqn[i] ^ ak[i];
|
||||
|
||||
memset(resync, 0, sizeof resync);
|
||||
memcpy(resync, test_ue->rand, OGS_RAND_LEN);
|
||||
memcpy(resync+OGS_RAND_LEN, auts, OGS_AUTS_LEN);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_authorization, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.len = OGS_RAND_LEN+OGS_AUTS_LEN;
|
||||
val.os.data = resync;
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
} else {
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_authentication_scheme, 0, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)OGS_DIAM_CX_AUTH_SCHEME_UNKNOWN;
|
||||
val.os.len = strlen(OGS_DIAM_CX_AUTH_SCHEME_UNKNOWN);
|
||||
ret = fd_msg_avp_setvalue(avpch, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the SIP-Number-Auth-Items AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_sip_number_auth_items, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
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 Server-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_server_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (os0_t)fd_g_config->cnf_diamid;
|
||||
val.os.len = fd_g_config->cnf_diamid_len;
|
||||
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);
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
* in real life we would not need it */
|
||||
svg = sess_data;
|
||||
|
||||
/* Store this value in the session */
|
||||
ret = fd_sess_state_store(test_cx_reg, session, &sess_data);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(sess_data == 0);
|
||||
|
||||
/* Send the request */
|
||||
ret = fd_msg_send(&req, test_cx_maa_cb, svg);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Increment the counter */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_sent++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
}
|
||||
|
||||
/* Callback for incoming Multimedia-Auth-Answer messages */
|
||||
static void test_cx_maa_cb(void *data, struct msg **msg)
|
||||
{
|
||||
int ret, new;
|
||||
|
||||
struct avp *avp, *avpch;
|
||||
struct avp_hdr *hdr;
|
||||
|
||||
unsigned long dur;
|
||||
int error = 0;
|
||||
|
||||
struct sess_state *sess_data = NULL;
|
||||
struct timespec ts;
|
||||
struct session *session;
|
||||
|
||||
test_ue_t *test_ue = NULL;
|
||||
|
||||
uint32_t result_code;
|
||||
uint32_t *err = NULL, *exp_err = NULL;
|
||||
|
||||
ogs_debug("Multimedia-Auth-Answer");
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Search the session, retrieve its data */
|
||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
|
||||
ogs_expect_or_return(ret == 0);
|
||||
ogs_expect_or_return(new == 0);
|
||||
|
||||
ret = fd_sess_state_retrieve(test_cx_reg, session, &sess_data);
|
||||
ogs_expect_or_return(ret == 0);
|
||||
ogs_expect_or_return(sess_data);
|
||||
ogs_expect_or_return((void *)sess_data == data);
|
||||
|
||||
test_ue = sess_data->test_ue;
|
||||
ogs_assert(test_ue);
|
||||
|
||||
/* Value of Result Code */
|
||||
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
result_code = hdr->avp_value->i32;
|
||||
err = &result_code;
|
||||
ogs_debug(" Result Code: %d", hdr->avp_value->i32);
|
||||
} else {
|
||||
ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_avp_search_avp(avp,
|
||||
ogs_diam_experimental_result_code, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
if (avpch) {
|
||||
ret = fd_msg_avp_hdr(avpch, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
result_code = hdr->avp_value->i32;
|
||||
exp_err = &result_code;
|
||||
ogs_debug(" Experimental Result Code: %d", result_code);
|
||||
}
|
||||
} else {
|
||||
ogs_error("no Result-Code");
|
||||
error++;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_assert(err && !exp_err && result_code == ER_DIAMETER_SUCCESS);
|
||||
|
||||
/* Free the message */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) +
|
||||
((ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
if (ogs_diam_logger_self()->stats.nb_recv) {
|
||||
/* Ponderate in the avg */
|
||||
ogs_diam_logger_self()->stats.avg = (ogs_diam_logger_self()->stats.avg *
|
||||
ogs_diam_logger_self()->stats.nb_recv + dur) /
|
||||
(ogs_diam_logger_self()->stats.nb_recv + 1);
|
||||
/* Min, max */
|
||||
if (dur < ogs_diam_logger_self()->stats.shortest)
|
||||
ogs_diam_logger_self()->stats.shortest = dur;
|
||||
if (dur > ogs_diam_logger_self()->stats.longest)
|
||||
ogs_diam_logger_self()->stats.longest = dur;
|
||||
} else {
|
||||
ogs_diam_logger_self()->stats.shortest = dur;
|
||||
ogs_diam_logger_self()->stats.longest = dur;
|
||||
ogs_diam_logger_self()->stats.avg = dur;
|
||||
}
|
||||
if (error)
|
||||
ogs_diam_logger_self()->stats.nb_errs++;
|
||||
else
|
||||
ogs_diam_logger_self()->stats.nb_recv++;
|
||||
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
/* Display how long it took */
|
||||
if (ts.tv_nsec > sess_data->ts.tv_nsec)
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec - sess_data->ts.tv_sec),
|
||||
(long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
else
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec + 1 - sess_data->ts.tv_sec),
|
||||
(long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
|
||||
ret = fd_msg_free(*msg);
|
||||
ogs_assert(ret == 0);
|
||||
*msg = NULL;
|
||||
|
||||
if (sess_data->resync == true) {
|
||||
test_cx_send_sar(sess_data);
|
||||
} else {
|
||||
sess_data->resync = true;
|
||||
test_cx_send_mar(sess_data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_cx_send_sar(struct sess_state *sess_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct msg *req = NULL;
|
||||
|
||||
struct msg_hdr *msg_header = NULL;
|
||||
|
||||
struct session *session = NULL;
|
||||
struct sess_state *svg;
|
||||
|
||||
struct avp *avp = NULL, *avpch = NULL;
|
||||
union avp_value val;
|
||||
|
||||
test_ue_t *test_ue = NULL;
|
||||
|
||||
ogs_assert(sess_data);
|
||||
test_ue = sess_data->test_ue;
|
||||
ogs_assert(test_ue);
|
||||
|
||||
ogs_debug("Server-Assignment-Request");
|
||||
|
||||
/* Create the request */
|
||||
ret = fd_msg_new(ogs_diam_cx_cmd_sar, MSGFL_ALLOC_ETEID, &req);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_hdr(req, &msg_header);
|
||||
ogs_assert(ret == 0);
|
||||
msg_header->msg_appl = OGS_DIAM_CX_APPLICATION_ID;
|
||||
|
||||
#define OGS_DIAM_CX_APP_SID_OPT "app_cx"
|
||||
ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_CX_APP_SID_OPT,
|
||||
CONSTSTRLEN(OGS_DIAM_CX_APP_SID_OPT));
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
req, OGS_DIAM_CX_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
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 Origin-Host & Origin-Realm */
|
||||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = TEST_HSS_IDENTITY;
|
||||
val.os.len = strlen(TEST_HSS_IDENTITY);
|
||||
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 */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
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);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the User-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)sess_data->user_name;
|
||||
val.os.len = strlen(sess_data->user_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 Public-Identity AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_public_identity, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (uint8_t *)sess_data->public_identity;
|
||||
val.os.len = strlen(sess_data->public_identity);
|
||||
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 Server-Name AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_server_name, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = (os0_t)fd_g_config->cnf_diamid;
|
||||
val.os.len = fd_g_config->cnf_diamid_len;
|
||||
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 Server-Assignment-Type AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_server_assignment_type, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_DIAM_CX_SERVER_ASSIGNMENT_REGISTRATION;
|
||||
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 User-Data-Already-Avaiable AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_cx_user_data_already_available, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_DIAM_CX_USER_DATA_NOT_AVAILABLE;
|
||||
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);
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
* in real life we would not need it */
|
||||
svg = sess_data;
|
||||
|
||||
/* Store this value in the session */
|
||||
ret = fd_sess_state_store(test_cx_reg, session, &sess_data);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(sess_data == 0);
|
||||
|
||||
/* Send the request */
|
||||
ret = fd_msg_send(&req, test_cx_saa_cb, svg);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Increment the counter */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_sent++;
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
}
|
||||
|
||||
/* Callback for incoming Server-Assignment-Answer messages */
|
||||
static void test_cx_saa_cb(void *data, struct msg **msg)
|
||||
{
|
||||
int ret, new;
|
||||
|
||||
struct avp *avp, *avpch;
|
||||
struct avp_hdr *hdr;
|
||||
|
||||
unsigned long dur;
|
||||
int error = 0;
|
||||
|
||||
struct sess_state *sess_data = NULL;
|
||||
struct timespec ts;
|
||||
struct session *session;
|
||||
|
||||
test_ue_t *test_ue = NULL;
|
||||
|
||||
uint32_t result_code;
|
||||
uint32_t *err = NULL, *exp_err = NULL;
|
||||
|
||||
ogs_debug("Server-Assignment-Answer");
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Search the session, retrieve its data */
|
||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
|
||||
ogs_expect_or_return(ret == 0);
|
||||
ogs_expect_or_return(new == 0);
|
||||
|
||||
ret = fd_sess_state_retrieve(test_cx_reg, session, &sess_data);
|
||||
ogs_expect_or_return(ret == 0);
|
||||
ogs_expect_or_return(sess_data);
|
||||
ogs_expect_or_return((void *)sess_data == data);
|
||||
|
||||
test_ue = sess_data->test_ue;
|
||||
ogs_assert(test_ue);
|
||||
|
||||
/* Value of Result Code */
|
||||
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
result_code = hdr->avp_value->i32;
|
||||
err = &result_code;
|
||||
ogs_debug(" Result Code: %d", hdr->avp_value->i32);
|
||||
} else {
|
||||
ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_avp_search_avp(avp,
|
||||
ogs_diam_experimental_result_code, &avpch);
|
||||
ogs_assert(ret == 0);
|
||||
if (avpch) {
|
||||
ret = fd_msg_avp_hdr(avpch, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
result_code = hdr->avp_value->i32;
|
||||
exp_err = &result_code;
|
||||
ogs_debug(" Experimental Result Code: %d", result_code);
|
||||
}
|
||||
} else {
|
||||
ogs_error("no Result-Code");
|
||||
error++;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_assert(err && !exp_err && result_code == ER_DIAMETER_SUCCESS);
|
||||
|
||||
/* Free the message */
|
||||
ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) +
|
||||
((ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
if (ogs_diam_logger_self()->stats.nb_recv) {
|
||||
/* Ponderate in the avg */
|
||||
ogs_diam_logger_self()->stats.avg = (ogs_diam_logger_self()->stats.avg *
|
||||
ogs_diam_logger_self()->stats.nb_recv + dur) /
|
||||
(ogs_diam_logger_self()->stats.nb_recv + 1);
|
||||
/* Min, max */
|
||||
if (dur < ogs_diam_logger_self()->stats.shortest)
|
||||
ogs_diam_logger_self()->stats.shortest = dur;
|
||||
if (dur > ogs_diam_logger_self()->stats.longest)
|
||||
ogs_diam_logger_self()->stats.longest = dur;
|
||||
} else {
|
||||
ogs_diam_logger_self()->stats.shortest = dur;
|
||||
ogs_diam_logger_self()->stats.longest = dur;
|
||||
ogs_diam_logger_self()->stats.avg = dur;
|
||||
}
|
||||
if (error)
|
||||
ogs_diam_logger_self()->stats.nb_errs++;
|
||||
else
|
||||
ogs_diam_logger_self()->stats.nb_recv++;
|
||||
|
||||
ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
/* Display how long it took */
|
||||
if (ts.tv_nsec > sess_data->ts.tv_nsec)
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec - sess_data->ts.tv_sec),
|
||||
(long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
else
|
||||
ogs_trace("in %d.%06ld sec",
|
||||
(int)(ts.tv_sec + 1 - sess_data->ts.tv_sec),
|
||||
(long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
|
||||
ret = fd_msg_free(*msg);
|
||||
ogs_assert(ret == 0);
|
||||
*msg = NULL;
|
||||
|
||||
state_cleanup(sess_data, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
int test_cx_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct disp_when data;
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
ret = ogs_diam_cx_init();
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Create handler for sessions */
|
||||
ret = fd_sess_handler_create(&test_cx_reg, &state_cleanup, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Fallback CB if command != unexpected message received */
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.app = ogs_diam_cx_application;
|
||||
|
||||
ret = fd_disp_register(test_cx_fb_cb, DISP_HOW_APPID, &data, NULL,
|
||||
&hdl_cx_fb);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
ret = fd_disp_app_support(ogs_diam_cx_application, ogs_diam_vendor, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_cx_final(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fd_sess_handler_destroy(&test_cx_reg, NULL);
|
||||
ogs_assert(ret == OGS_OK);
|
||||
|
||||
if (hdl_cx_fb)
|
||||
(void) fd_disp_unregister(&hdl_cx_fb, NULL);
|
||||
}
|
|
@ -18,12 +18,14 @@
|
|||
testapp_volte_sources = files('''
|
||||
pcscf-fd-path.h
|
||||
pcscf-fd-path.c
|
||||
diameter-cx-path.c
|
||||
|
||||
abts-main.c
|
||||
bearer-test.c
|
||||
session-test.c
|
||||
rx-test.c
|
||||
video-test.c
|
||||
cx-test.c
|
||||
'''.split())
|
||||
|
||||
testapp_volte_exe = executable('volte',
|
||||
|
|
|
@ -58,7 +58,7 @@ static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque)
|
|||
ogs_free(sess_data);
|
||||
}
|
||||
|
||||
static int pcscf_rx_fb_cb(struct msg **msg, struct avp *avp,
|
||||
static int pcscf_rx_fb_cb(struct msg **msg, struct avp *avp,
|
||||
struct session *sess, void *opaque, enum disp_action *act)
|
||||
{
|
||||
/* This CB should never be called */
|
||||
|
@ -156,6 +156,16 @@ void pcscf_rx_send_aar_audio(uint8_t **rx_sid,
|
|||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = TEST_PCRF_IDENTITY;
|
||||
val.os.len = strlen(TEST_PCRF_IDENTITY);
|
||||
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 */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -643,6 +653,16 @@ void pcscf_rx_send_aar_video(uint8_t **rx_sid, test_sess_t *sess, int id_type)
|
|||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = TEST_PCRF_IDENTITY;
|
||||
val.os.len = strlen(TEST_PCRF_IDENTITY);
|
||||
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 */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -1311,6 +1331,16 @@ void pcscf_rx_send_aar_ctrl(uint8_t **rx_sid, test_sess_t *sess, int id_type)
|
|||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = TEST_PCRF_IDENTITY;
|
||||
val.os.len = strlen(TEST_PCRF_IDENTITY);
|
||||
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 */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -1881,6 +1911,16 @@ void pcscf_rx_send_str(uint8_t *rx_sid)
|
|||
ret = fd_msg_add_origin(req, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Destination-Host AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.os.data = TEST_PCRF_IDENTITY;
|
||||
val.os.len = strlen(TEST_PCRF_IDENTITY);
|
||||
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 */
|
||||
ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -2063,7 +2103,7 @@ void pcscf_diam_config(void)
|
|||
{
|
||||
memset(&diam_config, 0, sizeof(ogs_diam_config_t));
|
||||
|
||||
diam_config.cnf_diamid = "pcscf.localdomain";
|
||||
diam_config.cnf_diamid = "ims.localdomain";
|
||||
diam_config.cnf_diamrlm = "localdomain";
|
||||
diam_config.cnf_port = DIAMETER_PORT;
|
||||
diam_config.cnf_port_tls = DIAMETER_SECURE_PORT;
|
||||
|
@ -2093,7 +2133,10 @@ void pcscf_diam_config(void)
|
|||
FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_dcca_3gpp.fdx";
|
||||
diam_config.num_of_ext++;
|
||||
|
||||
diam_config.conn[diam_config.num_of_conn].identity = "pcrf.localdomain";
|
||||
diam_config.conn[diam_config.num_of_conn].identity = TEST_HSS_IDENTITY;
|
||||
diam_config.conn[diam_config.num_of_conn].addr = "127.0.0.8";
|
||||
diam_config.num_of_conn++;
|
||||
diam_config.conn[diam_config.num_of_conn].identity = TEST_PCRF_IDENTITY;
|
||||
diam_config.conn[diam_config.num_of_conn].addr = "127.0.0.9";
|
||||
diam_config.num_of_conn++;
|
||||
}
|
||||
|
@ -2108,6 +2151,8 @@ int pcscf_fd_init(void)
|
|||
ret = ogs_diam_init(FD_MODE_CLIENT, NULL, &diam_config);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
test_cx_init();
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
ret = ogs_diam_rx_init();
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -2148,5 +2193,7 @@ void pcscf_fd_final(void)
|
|||
if (hdl_rx_asr)
|
||||
(void) fd_disp_unregister(&hdl_rx_asr, NULL);
|
||||
|
||||
test_cx_final();
|
||||
|
||||
ogs_diam_final();
|
||||
}
|
||||
|
|
|
@ -26,15 +26,23 @@ extern "C" {
|
|||
|
||||
#include "ogs-diameter-rx.h"
|
||||
|
||||
#define TEST_HSS_IDENTITY "hss.localdomain"
|
||||
#define TEST_PCRF_IDENTITY "pcrf.localdomain"
|
||||
|
||||
int pcscf_fd_init(void);
|
||||
void pcscf_fd_final(void);
|
||||
|
||||
int test_cx_init(void);
|
||||
void test_cx_final(void);
|
||||
|
||||
void pcscf_rx_send_aar_audio(uint8_t **rx_sid,
|
||||
test_sess_t *sess, int id_type, int qos_type, int flow_type);
|
||||
void pcscf_rx_send_aar_video(uint8_t **rx_sid, test_sess_t *sess, int id_type);
|
||||
void pcscf_rx_send_aar_ctrl(uint8_t **rx_sid, test_sess_t *sess, int id_type);
|
||||
void pcscf_rx_send_str(uint8_t *rx_sid);
|
||||
|
||||
void test_cx_send_uar(test_ue_t *test_ue, int id_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "open5gs",
|
||||
"version": "2.2.1",
|
||||
"version": "2.2.6",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "open5gs",
|
||||
"version": "2.2.1",
|
||||
"version": "2.2.6",
|
||||
"description": "Open5gs",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/open5gs/open5gs/webui",
|
||||
|
|
|
@ -11,6 +11,8 @@ const Profile = new Schema({
|
|||
|
||||
title: { $type: String, required: true },
|
||||
|
||||
msisdn: [ String ],
|
||||
|
||||
security: {
|
||||
k: String,
|
||||
op: String,
|
||||
|
|
|
@ -11,6 +11,8 @@ const Subscriber = new Schema({
|
|||
|
||||
imsi: { $type: String, unique: true, required: true },
|
||||
|
||||
msisdn: [ String ],
|
||||
|
||||
security: {
|
||||
k: String,
|
||||
op: String,
|
||||
|
|
|
@ -9,11 +9,29 @@ const schema = {
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"type": "string",
|
||||
"title": "Title*",
|
||||
"required": true,
|
||||
"maxLength": 24
|
||||
},
|
||||
"msisdn": {
|
||||
"type": "array",
|
||||
"title": "",
|
||||
"maxItems": 2,
|
||||
"messages": {
|
||||
"maxItems": "2 MSISDN are supported"
|
||||
},
|
||||
"items": {
|
||||
"type": "string",
|
||||
"title": "MSISDN",
|
||||
"maxLength": 15,
|
||||
"required": true,
|
||||
"pattern": "^\\d+$",
|
||||
"messages": {
|
||||
"pattern": "Only digits are allowed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"title": "",
|
||||
"type": "object",
|
||||
|
@ -440,7 +458,11 @@ const uiSchema = {
|
|||
"title" : {
|
||||
classNames: "col-xs-12",
|
||||
},
|
||||
"msisdn" : {
|
||||
classNames: "col-xs-7",
|
||||
},
|
||||
"security" : {
|
||||
classNames: "col-xs-12",
|
||||
"k" : {
|
||||
classNames: "col-xs-7",
|
||||
},
|
||||
|
@ -455,6 +477,7 @@ const uiSchema = {
|
|||
},
|
||||
},
|
||||
"ambr" : {
|
||||
classNames: "col-xs-12",
|
||||
"downlink": {
|
||||
classNames: "col-xs-6",
|
||||
"value": {
|
||||
|
@ -475,6 +498,7 @@ const uiSchema = {
|
|||
}
|
||||
},
|
||||
"slice": {
|
||||
classNames: "col-xs-12",
|
||||
"items": {
|
||||
"sst": {
|
||||
classNames: "col-xs-3",
|
||||
|
@ -621,12 +645,12 @@ const uiSchema = {
|
|||
|
||||
class Edit extends Component {
|
||||
static propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
action: PropTypes.string,
|
||||
visible: PropTypes.bool,
|
||||
action: PropTypes.string,
|
||||
formData: PropTypes.object,
|
||||
isLoading: PropTypes.bool,
|
||||
validate: PropTypes.func,
|
||||
onHide: PropTypes.func,
|
||||
validate: PropTypes.func,
|
||||
onHide: PropTypes.func,
|
||||
onSubmit: PropTypes.func,
|
||||
onError: PropTypes.func
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import EditIcon from 'react-icons/lib/md/edit';
|
|||
import DeleteIcon from 'react-icons/lib/md/delete';
|
||||
import CloseIcon from 'react-icons/lib/md/close';
|
||||
|
||||
import PhoneIcon from 'react-icons/lib/md/phone';
|
||||
import SecurityIcon from 'react-icons/lib/md/security';
|
||||
import PdnIcon from 'react-icons/lib/md/cast';
|
||||
import KeyboardControlIcon from 'react-icons/lib/md/keyboard-control';
|
||||
|
@ -161,6 +162,7 @@ const Pdn = styled.div`
|
|||
const View = ({ visible, disableOnClickOutside, profile, onEdit, onDelete, onHide }) => {
|
||||
const _id = (profile || {})._id;
|
||||
const title = (profile || {}).title;
|
||||
const msisdn_list = ((profile || {}).msisdn || []);
|
||||
const security = ((profile || {}).security || {});
|
||||
const ambr = ((profile || {}).ambr || {});
|
||||
const slice_list = ((profile || {}).slice || []);
|
||||
|
@ -191,6 +193,21 @@ const View = ({ visible, disableOnClickOutside, profile, onEdit, onDelete, onHid
|
|||
<div className="header">
|
||||
Profile Configuration
|
||||
</div>
|
||||
{msisdn_list.length !== 0 &&
|
||||
<div className="body">
|
||||
<div className="left">
|
||||
<PhoneIcon/>
|
||||
</div>
|
||||
<div className="right">
|
||||
{msisdn_list.map((msisdn, index) =>
|
||||
<div key={index} className="data">
|
||||
{msisdn}
|
||||
<span style={{color:oc.gray[5]}}><KeyboardControlIcon/>MSISDN</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div className="body">
|
||||
<div className="left">
|
||||
<SecurityIcon/>
|
||||
|
|
|
@ -69,7 +69,10 @@ const fields = {
|
|||
};
|
||||
|
||||
function Label(props) {
|
||||
const { label, required, id } = props;
|
||||
// modified by acetcom
|
||||
// const { label, required, id } = props;
|
||||
const { label, id } = props;
|
||||
const required = 0;
|
||||
if (!label) {
|
||||
// See #312: Ensure compatibility with old versions of React.
|
||||
return <div />;
|
||||
|
@ -304,4 +307,4 @@ class Form extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default Form;
|
||||
export default Form;
|
||||
|
|
|
@ -11,7 +11,7 @@ const schema = {
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"imsi": {
|
||||
"type": "string",
|
||||
"type": "string",
|
||||
"title": "IMSI*",
|
||||
"required": true,
|
||||
"pattern": "^\\d+$",
|
||||
|
@ -20,6 +20,24 @@ const schema = {
|
|||
"pattern": "Only digits are allowed"
|
||||
}
|
||||
},
|
||||
"msisdn": {
|
||||
"type": "array",
|
||||
"title": "",
|
||||
"maxItems": 2,
|
||||
"messages": {
|
||||
"maxItems": "2 MSISDN are supported"
|
||||
},
|
||||
"items": {
|
||||
"type": "string",
|
||||
"title": "MSISDN",
|
||||
"maxLength": 15,
|
||||
"required": true,
|
||||
"pattern": "^\\d+$",
|
||||
"messages": {
|
||||
"pattern": "Only digits are allowed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"title": "",
|
||||
"type": "object",
|
||||
|
@ -446,7 +464,11 @@ const uiSchema = {
|
|||
"imsi" : {
|
||||
classNames: "col-xs-12",
|
||||
},
|
||||
"msisdn" : {
|
||||
classNames: "col-xs-7",
|
||||
},
|
||||
"security" : {
|
||||
classNames: "col-xs-12",
|
||||
"k" : {
|
||||
classNames: "col-xs-7",
|
||||
},
|
||||
|
@ -461,6 +483,7 @@ const uiSchema = {
|
|||
},
|
||||
},
|
||||
"ambr" : {
|
||||
classNames: "col-xs-12",
|
||||
"downlink": {
|
||||
classNames: "col-xs-6",
|
||||
"value": {
|
||||
|
@ -628,12 +651,12 @@ const uiSchema = {
|
|||
|
||||
class Edit extends Component {
|
||||
static propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
action: PropTypes.string,
|
||||
visible: PropTypes.bool,
|
||||
action: PropTypes.string,
|
||||
formData: PropTypes.object,
|
||||
isLoading: PropTypes.bool,
|
||||
validate: PropTypes.func,
|
||||
onHide: PropTypes.func,
|
||||
validate: PropTypes.func,
|
||||
onHide: PropTypes.func,
|
||||
onSubmit: PropTypes.func,
|
||||
onError: PropTypes.func
|
||||
}
|
||||
|
@ -679,7 +702,7 @@ class Edit extends Component {
|
|||
...schema,
|
||||
"properties": {
|
||||
profile: {
|
||||
type: "string",
|
||||
type: "string",
|
||||
title: "Profile*",
|
||||
enum: profiles.map(profile => profile._id),
|
||||
enumNames: profiles.map(profile => profile.title),
|
||||
|
|
|
@ -8,6 +8,7 @@ import EditIcon from 'react-icons/lib/md/edit';
|
|||
import DeleteIcon from 'react-icons/lib/md/delete';
|
||||
import CloseIcon from 'react-icons/lib/md/close';
|
||||
|
||||
import PhoneIcon from 'react-icons/lib/md/phone';
|
||||
import SecurityIcon from 'react-icons/lib/md/security';
|
||||
import PdnIcon from 'react-icons/lib/md/cast';
|
||||
import KeyboardControlIcon from 'react-icons/lib/md/keyboard-control';
|
||||
|
@ -160,6 +161,7 @@ const Pdn = styled.div`
|
|||
`
|
||||
const View = ({ visible, disableOnClickOutside, subscriber, onEdit, onDelete, onHide }) => {
|
||||
const imsi = (subscriber || {}).imsi;
|
||||
const msisdn_list = ((subscriber || {}).msisdn || []);
|
||||
const security = ((subscriber || {}).security || {});
|
||||
const ambr = ((subscriber || {}).ambr || {});
|
||||
const slice_list = ((subscriber || {}).slice || []);
|
||||
|
@ -190,6 +192,21 @@ const View = ({ visible, disableOnClickOutside, subscriber, onEdit, onDelete, on
|
|||
<div className="header">
|
||||
Subscriber Configuration
|
||||
</div>
|
||||
{msisdn_list.length !== 0 &&
|
||||
<div className="body">
|
||||
<div className="left">
|
||||
<PhoneIcon/>
|
||||
</div>
|
||||
<div className="right">
|
||||
{msisdn_list.map((msisdn, index) =>
|
||||
<div key={index} className="data">
|
||||
{msisdn}
|
||||
<span style={{color:oc.gray[5]}}><KeyboardControlIcon/>MSISDN</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div className="body">
|
||||
<div className="left">
|
||||
<SecurityIcon/>
|
||||
|
|
Loading…
Reference in New Issue