From 99b2cfaf4151968a62099880928563a64ccdeddc Mon Sep 17 00:00:00 2001 From: Christoph Valentin Date: Tue, 9 Apr 2019 21:31:19 +0200 Subject: [PATCH] ims_isc: add-on for third-party registration - The feature is a add-on to third party registration in S-CSCF - The feature assumes two new flags in HSS database, where additional to the "Service Info XML" an "insertRegisterRequest" flag or an "insertRegisterRepsonse" flag can be set. These flags are sent with the SAR/SAA exchange to the S-CSCF, where the new feature does a prioritization: If Service Info present -> add service info to body of 3rd Party REGISTER Request else if insertRegisterRequest -> add original REGISTER request to body of 3rd Party REGISTER request else if insertRegisterResponse -> add original REGISTER response to body of 3rd Party REGISTER request else -> add no body to 3rd Party REGISTER request. - Multipart Body is not supported. - More info about the insertRegisterRequest and insertRegisterResponse flags can be found in applicable 3GPP standards. --- src/modules/ims_isc/checker.c | 2 + src/modules/ims_isc/checker.h | 2 + src/modules/ims_isc/doc/ims_isc_admin.xml | 8 ++ src/modules/ims_isc/third_party_reg.c | 106 +++++++++++++++++++--- src/modules/ims_isc/third_party_reg.h | 18 +++- 5 files changed, 119 insertions(+), 17 deletions(-) diff --git a/src/modules/ims_isc/checker.c b/src/modules/ims_isc/checker.c index f02cf98babc..07381c79abc 100644 --- a/src/modules/ims_isc/checker.c +++ b/src/modules/ims_isc/checker.c @@ -393,6 +393,8 @@ static inline isc_match* isc_new_match(ims_filter_criteria *fc, int index) { fc->application_server.service_info.len); } r->index = index; + r->include_register_request = fc->application_server.include_register_request; + r->include_register_response = fc->application_server.include_register_response; return r; } diff --git a/src/modules/ims_isc/checker.h b/src/modules/ims_isc/checker.h index f35636ceab3..24a5ec96a75 100644 --- a/src/modules/ims_isc/checker.h +++ b/src/modules/ims_isc/checker.h @@ -68,6 +68,8 @@ typedef struct { char default_handling; /**< handling to apply on failure to contact the AS */ str service_info; /**< additional service information */ int index; /**< index of the matching IFC */ + int include_register_request; /**< additional flag from the HSS */ + int include_register_response; /**< additional flag from the HSS */ } isc_match; diff --git a/src/modules/ims_isc/doc/ims_isc_admin.xml b/src/modules/ims_isc/doc/ims_isc_admin.xml index 311a25b921f..1c19ab2e979 100644 --- a/src/modules/ims_isc/doc/ims_isc_admin.xml +++ b/src/modules/ims_isc/doc/ims_isc_admin.xml @@ -163,6 +163,14 @@ modparam("ims_isc", "add_p_served_user", 1) A positive return code (1) means that the REGISTER message has matched to Initial Filter Criteria and is armed for routing. + This function handles also the Service Info (if sent by the + HSS), the InsertRegisterRequest flag (if sent by the HSS) or the + InsertRegisterResponse flag (if sent by the HSS). Either the Service + Info OR the original REGISTER request OR the original REGISTER + response is added to the body of the REGISTER message, before it is + forwarded to the relevant Application Server. Multipart body is not + supported in this case. + Meaning of the parameters is as follows: diff --git a/src/modules/ims_isc/third_party_reg.c b/src/modules/ims_isc/third_party_reg.c index b07773efa89..41877fd5150 100644 --- a/src/modules/ims_isc/third_party_reg.c +++ b/src/modules/ims_isc/third_party_reg.c @@ -44,6 +44,7 @@ */ #include "third_party_reg.h" +#include "../../core/msg_translator.h" usrloc_api_t isc_ulb;/*!< Structure containing pointers to usrloc functions*/ @@ -204,7 +205,7 @@ int build_p_associated_uri(ims_subscription* s) { return 0; } - +static str reg_resp_200OK = {"OK", 2}; /** * Handle third party registration @@ -286,7 +287,24 @@ int isc_third_party_reg(struct sip_msg *msg, isc_match *m, isc_mark *mark, udoma r.pvni = pvni; r.pani = pani; r.cv = cv; - r.service_info = m->service_info; + if (m->service_info.s && m->service_info.len) { + r.body.content_type = CT_SERVICE_INFO; + r.body.content = m->service_info; + } else if (m->include_register_request) { + r.body.content_type = CT_REGISTER_REQ; + r.body.content.s = msg->first_line.u.request.method.s; + r.body.content.len = msg->len; + } else if (m->include_register_response) { + struct bookmark dummy_bm; + r.body.content_type = CT_REGISTER_RESP; + r.body.content.s = build_res_buf_from_sip_req(200, ®_resp_200OK, 0, msg, (unsigned int*)&r.body.content.len, &dummy_bm); + if (!r.body.content.s) { + LM_DBG("response building failed for body of third party register request"); + r.body.content_type = CT_NONE; + } + } else { + r.body.content_type = CT_NONE; + } r.path = path; if (expires <= 0) @@ -324,6 +342,13 @@ static str comma = {",", 1}; static str path_mine_s = {"<", 1}; static str path_mine_e = {";lr>", 4}; +static str content_type_s = {"Content-Type: ", 14}; +static str content_type_e = {"\r\n", 2}; + +static str ct_service_info = {"application/3gpp-ims+xml", 24}; +static str ct_register_req = {"message/sip", 11}; +static str ct_register_resp = {"message/sip", 11}; + static str body_s = {"", 36}; static str body_e = {"", 26}; @@ -371,6 +396,20 @@ int r_send_third_party_reg(r_third_party_registration *r, int expires) { h.len += pauri.len; } + if (r->body.content_type == CT_SERVICE_INFO) { + h.len += content_type_s.len; + h.len += ct_service_info.len; + h.len += content_type_e.len; + } else if (r->body.content_type == CT_REGISTER_REQ) { + h.len += content_type_s.len; + h.len += ct_register_req.len; + h.len += content_type_e.len; + } else if (r->body.content_type == CT_REGISTER_RESP) { + h.len += content_type_s.len; + h.len += ct_register_resp.len; + h.len += content_type_e.len; + } + h.s = pkg_malloc(h.len); if (!h.s) { LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", h.len); @@ -423,20 +462,53 @@ int r_send_third_party_reg(r_third_party_registration *r, int expires) { if (p_associated_uri.data_len > 0) { STR_APPEND(h, pauri); } - LM_DBG("SRV INFO:<%.*s>\n", r->service_info.len, r->service_info.s); - if (r->service_info.len) { - b.len = body_s.len + r->service_info.len + body_e.len; - b.s = pkg_malloc(b.len); - if (!b.s) { - LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", b.len); - b.len = 0; - return 0; + LM_DBG("BODY TYPE(3rd PARTY REGISTER):<%d>\n", r->body.content_type); + if (r->body.content_type != CT_NONE) { + if (r->body.content_type == CT_SERVICE_INFO) { + LM_ERR("BODY (3rd PARTY REGISTER) \"SI\": <%.*s>\n", r->body.content.len, r->body.content.s); + b.len = body_s.len + r->body.content.len + body_e.len; + b.s = pkg_malloc(b.len); + if (!b.s) { + LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", b.len); + b.len = 0; + goto error; + } + b.len = 0; + STR_APPEND(b, body_s); + STR_APPEND(b, r->body.content); + STR_APPEND(b, body_e); + STR_APPEND(h, content_type_s); + STR_APPEND(h, ct_service_info); + STR_APPEND(h, content_type_e); + } else if (r->body.content_type == CT_REGISTER_REQ) { + LM_ERR("BODY (3rd PARTY REGISTER) \"REQ\": <%.*s>\n", r->body.content.len, r->body.content.s); + b.len = r->body.content.len; + b.s = pkg_malloc(b.len); + if (!b.s) { + LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", b.len); + b.len = 0; + goto error; + } + b.len = 0; + STR_APPEND(b, r->body.content); + STR_APPEND(h, content_type_s); + STR_APPEND(h, ct_register_req); + STR_APPEND(h, content_type_e); + } else if (r->body.content_type == CT_REGISTER_RESP) { + LM_ERR("BODY (3rd PARTY REGISTER) \"RESP\": <%.*s>\n", r->body.content.len, r->body.content.s); + b.len = r->body.content.len; + b.s = pkg_malloc(b.len); + if (!b.s) { + LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", b.len); + b.len = 0; + goto error; + } + b.len = 0; + STR_APPEND(b, r->body.content); + STR_APPEND(h, content_type_s); + STR_APPEND(h, ct_register_resp); + STR_APPEND(h, content_type_e); } - - b.len = 0; - STR_APPEND(b, body_s); - STR_APPEND(b, r->service_info); - STR_APPEND(b, body_e); } set_uac_req(&req, &method, &h, &b, 0, @@ -450,6 +522,8 @@ int r_send_third_party_reg(r_third_party_registration *r, int expires) { pkg_free(h.s); if (b.s) pkg_free(b.s); + if (r->body.content_type == CT_REGISTER_RESP) + pkg_free(r->body.content.s); return 1; error: @@ -457,6 +531,8 @@ int r_send_third_party_reg(r_third_party_registration *r, int expires) { pkg_free(h.s); if (b.s) pkg_free(b.s); + if (r->body.content_type == CT_REGISTER_RESP) + pkg_free(r->body.content.s); return 0; } diff --git a/src/modules/ims_isc/third_party_reg.h b/src/modules/ims_isc/third_party_reg.h index 66d21ee5bff..d2762c919e2 100644 --- a/src/modules/ims_isc/third_party_reg.h +++ b/src/modules/ims_isc/third_party_reg.h @@ -63,6 +63,20 @@ extern int isc_expires_grace; /**< expires value to add to the expires in the to prevent expiration in AS */ extern struct tm_binds isc_tmb; /**< Structure with pointers to tm funcs */ + +#define CT_NONE 0 +#define CT_SERVICE_INFO 1 +#define CT_REGISTER_REQ 2 +#define CT_REGISTER_RESP 3 + +/** one (part of a) body for the reg event notification structure */ +/** Currently we restrict the usage of multipart bodies */ +typedef struct body { + char content_type; /* Content-Type header for (one part of the) body*/ + str content; /* Content of (one part of the) body */ +} body_t; + + /** reg event notification structure */ typedef struct _r_third_party_reg { str req_uri; /* AS sip uri: */ @@ -71,8 +85,8 @@ typedef struct _r_third_party_reg { str pvni; /* Visited network id */ str pani; /* Access Network info */ str cv; /* Charging vector */ - str service_info; /* Service info body */ - str path; /* Path header */ + body_t body; /* The body */ + str path; /* Path header */ } r_third_party_registration; int isc_third_party_reg(struct sip_msg *msg, isc_match *m, isc_mark *mark, udomain_t* d);