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);