From e8db6bfa32231a1b1f57b12267ce56d4cfa4f304 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Mon, 23 Dec 2019 19:54:02 +0100 Subject: [PATCH 01/26] Handling Data too long for column 'record_route' error --- utils/kamctl/mysql/ims_usrloc_scscf-create.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/kamctl/mysql/ims_usrloc_scscf-create.sql b/utils/kamctl/mysql/ims_usrloc_scscf-create.sql index ae7bd93a545..21c816c34e9 100644 --- a/utils/kamctl/mysql/ims_usrloc_scscf-create.sql +++ b/utils/kamctl/mysql/ims_usrloc_scscf-create.sql @@ -49,7 +49,7 @@ CREATE TABLE `subscriber` ( `call_id` varchar(50) NOT NULL, `from_tag` varchar(50) NOT NULL, `to_tag` varchar(50) NOT NULL, - `record_route` varchar(50) NOT NULL, + `record_route` TEXT NOT NULL, `sockinfo_str` varchar(50) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `watcher_uri` (`event`,`watcher_contact`,`presentity_uri`) From 7bf484f984b87aacfe05445d837edc31012937cb Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Thu, 13 Feb 2020 15:56:24 +0100 Subject: [PATCH 02/26] Fix Rx_AAR_Register when EPC is behind a NAT This commit fixes the Rx AAR failure due to wrong IP address in Framed IP address field of Rx AAR message when EPC is behind a NAT. The fix is to use via host and port for Framed IP address rathen than received source ip and port. --- src/modules/ims_qos/ims_qos_mod.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/modules/ims_qos/ims_qos_mod.c b/src/modules/ims_qos/ims_qos_mod.c index bcf8266853a..4bd622f8e22 100644 --- a/src/modules/ims_qos/ims_qos_mod.c +++ b/src/modules/ims_qos/ims_qos_mod.c @@ -1300,8 +1300,12 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char* } //we use the received IP address for the framed_ip_address - recv_ip.s = ip_addr2a(&msg->rcv.src_ip); - recv_ip.len = strlen(ip_addr2a(&msg->rcv.src_ip)); + memset(&recv_ip, 0, sizeof(str)); + char buff[IP_ADDR_MAX_STR_SIZE]; + memcpy(&buff, vb->host.s, vb->host.len); + buff[vb->host.len]=0; + recv_ip.s = buff; + recv_ip.len = strlen(buff); ip_version = check_ip_version(recv_ip); if (!ip_version) { @@ -1309,8 +1313,8 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char* goto error; } - recv_port = msg->rcv.src_port; - recv_proto = msg->rcv.proto; + recv_port = via_port; + recv_proto = via_proto; LM_DBG("Message received IP address is: [%.*s]\n", recv_ip.len, recv_ip.s); LM_DBG("Message via is [%d://%.*s:%d]\n", vb->proto, vb->host.len, vb->host.s, via_port); From 77570e1919cef2efa455a4be356cde8e675d295f Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Wed, 15 Apr 2020 10:12:36 +0200 Subject: [PATCH 03/26] Introduce a function to destroy IPSec based on Contact and Received IP and Port The default ipsec_destroy cannot be used to used destroy IPSec in any route and needed to be used exactly after all the de-registration process was complete. But, as per the kamailio P-CSCF config script, ipsec_destroy was used in reply route of NATPING, which didn't have any idea about SIP Register message used for de-registration. Thus, resulting in IPSec not being destroyed even after de-registration was complete. The newly introduced function ipsec_destroy_by_contact takes domain, contact, received host and received port in order to determine the exact UE's IPSec tunnel to destroy. --- src/modules/ims_ipsec_pcscf/cmd.c | 56 +++++++++++++++ src/modules/ims_ipsec_pcscf/cmd.h | 1 + .../ims_ipsec_pcscf/ims_ipsec_pcscf_mod.c | 71 +++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 0651d4226f5..bc467b89a28 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -998,6 +998,62 @@ int ipsec_destroy(struct sip_msg* m, udomain_t* d) return ret; } +int ipsec_destroy_by_contact(udomain_t* _d, str * uri, str * received_host, int received_port) { + + pcontact_t* pcontact = NULL; + int ret = IPSEC_CMD_FAIL; // FAIL by default + + pcontact_info_t search_ci; + memset(&search_ci, 0, sizeof(struct pcontact_info)); + + sip_uri_t contact_uri; + if (parse_uri(uri->s, uri->len, &contact_uri) != 0) { + LM_WARN("Failed to parse aor [%.*s]\n", uri->len, uri->s); + return ret; + } + + search_ci.received_host.s = received_host->s; + search_ci.received_host.len = received_host->len; + search_ci.received_port = received_port; + search_ci.received_proto = contact_uri.proto? contact_uri.proto : PROTO_UDP; + search_ci.searchflag = SEARCH_RECEIVED; + search_ci.via_host.s = received_host->s; + search_ci.via_host.len = received_host->len; + search_ci.via_port = received_port; + search_ci.via_prot = search_ci.received_proto; + search_ci.aor.s = uri->s; + search_ci.aor.len = uri->len; + search_ci.reg_state = PCONTACT_ANY; + + if (ul.get_pcontact(_d, &search_ci, &pcontact, 0) != 0 || pcontact==NULL) { + LM_ERR("Contact doesn't exist\n"); + return ret; + } + + /* Lock this record while working with the data: */ + ul.lock_udomain(_d, &pcontact->via_host, pcontact->via_port, pcontact->via_proto); + + if(pcontact->security_temp == NULL) { + LM_ERR("No security parameters found in contact\n"); + goto cleanup; + } + + //get security parameters + if(pcontact->security_temp->type != SECURITY_IPSEC ) { + LM_ERR("Unsupported security type: %d\n", pcontact->security_temp->type); + goto cleanup; + } + + destroy_ipsec_tunnel(search_ci.received_host, pcontact->security_temp->data.ipsec, pcontact->contact_port); + + ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit + +cleanup: + /* Unlock domain */ + ul.unlock_udomain(_d, &pcontact->via_host, pcontact->via_port, pcontact->via_proto); + return ret; +} + int ipsec_reconfig() { if(ul.get_number_of_contacts() != 0){ diff --git a/src/modules/ims_ipsec_pcscf/cmd.h b/src/modules/ims_ipsec_pcscf/cmd.h index 122330dbb80..680fb2eeeb1 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.h +++ b/src/modules/ims_ipsec_pcscf/cmd.h @@ -68,5 +68,6 @@ int ipsec_destroy(struct sip_msg* m, udomain_t* d); int ipsec_cleanall(); int ipsec_reconfig(); void ipsec_on_expire(pcontact_t* c, int type, void* param); +int ipsec_destroy_by_contact(udomain_t* _d, str * uri, str * received_host, int received_port); #endif /* IPSEC_CMD_H */ diff --git a/src/modules/ims_ipsec_pcscf/ims_ipsec_pcscf_mod.c b/src/modules/ims_ipsec_pcscf/ims_ipsec_pcscf_mod.c index b2a19f332ec..be5f1babdfd 100644 --- a/src/modules/ims_ipsec_pcscf/ims_ipsec_pcscf_mod.c +++ b/src/modules/ims_ipsec_pcscf/ims_ipsec_pcscf_mod.c @@ -57,12 +57,15 @@ static void mod_destroy(void); static int w_create(struct sip_msg* _m, char* _d, char* _cflags); static int w_forward(struct sip_msg* _m, char* _d, char* _cflags); static int w_destroy(struct sip_msg* _m, char* _d, char* _cflags); +static int w_destroy_by_contact(struct sip_msg* _m, char* _d, char* _aor, char* _received_host, char* _received_port, char* _cflags); /*! \brief Fixup functions */ static int domain_fixup(void** param, int param_no); static int save_fixup2(void** param, int param_no); static int free_uint_fixup(void** param, int param_no); +static int unregister_fixup(void ** param, int param_no); + extern int bind_ipsec_pcscf(usrloc_api_t* api); int init_flag = 0; @@ -76,6 +79,7 @@ static cmd_export_t cmds[] = { {"ipsec_forward", (cmd_function)w_forward, 1, save_fixup2, 0, REQUEST_ROUTE | ONREPLY_ROUTE }, {"ipsec_forward", (cmd_function)w_forward, 2, save_fixup2, free_uint_fixup, REQUEST_ROUTE | ONREPLY_ROUTE }, {"ipsec_destroy", (cmd_function)w_destroy, 1, save_fixup2, 0, REQUEST_ROUTE | ONREPLY_ROUTE }, + {"ipsec_destroy_by_contact", (cmd_function)w_destroy_by_contact, 4, unregister_fixup, 0, ANY_ROUTE}, {"bind_ims_ipsec_pcscf", (cmd_function)bind_ipsec_pcscf, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -401,6 +405,32 @@ static int save_fixup2(void** param, int param_no) return 0; } +static int unregister_fixup(void ** param, int param_no) { + if (param_no == 1) { + return domain_fixup(param,param_no); + } else { + pv_elem_t *model=NULL; + str s; + + /* convert to str */ + s.s = (char*)*param; + s.len = strlen(s.s); + + model = NULL; + if(s.len==0) { + LM_ERR("no param!\n"); + return E_CFG; + } + if(pv_parse_format(&s, &model)<0 || model==NULL) { + LM_ERR("wrong format [%s]!\n", s.s); + return E_CFG; + } + *param = (void*)model; + return 0; + } + return E_CFG; +} + /*! \brief * Wrapper to ipsec functions @@ -425,3 +455,44 @@ static int w_destroy(struct sip_msg* _m, char* _d, char* _cflags) { return ipsec_destroy(_m, (udomain_t*)_d); } + +static int w_destroy_by_contact(struct sip_msg* _m, char* _d, char* _aor, char* _received_host, char* _received_port, char* _cflags) +{ + pv_elem_t *model; + str aor; + str received_host; + str received_port; + int port = 0; + + if ((_aor == NULL) || (_received_host == NULL) || (_received_port == NULL)) { + LM_ERR("error - bad parameters\n"); + return -1; + } + + model = (pv_elem_t*)_aor; + if (pv_printf_s(_m, model, &aor)<0) { + LM_ERR("error - cannot print the format\n"); + return -1; + } + LM_DBG("URI: %.*s\n", aor.len, aor.s); + + model = (pv_elem_t*)_received_host; + if (pv_printf_s(_m, model, &received_host)<0) { + LM_ERR("error - cannot print the format\n"); + return -1; + } + LM_DBG("Received-Host: %.*s\n", received_host.len, received_host.s); + + model = (pv_elem_t*)_received_port; + if (pv_printf_s(_m, model, &received_port)<0) { + LM_ERR("error - cannot print the format\n"); + return -1; + } + LM_DBG("Received-Port: %.*s\n", received_port.len, received_port.s); + if (str2sint(&received_port, &port) != 0) { + LM_ERR("error - cannot convert %.*s to an int!\n", received_port.len, received_port.s); + return -1; + } + + return ipsec_destroy_by_contact((udomain_t*)_d, &aor, &received_host, port); +} From 77a8f79a43950a437dde5072f3cb20eaadd08677 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Thu, 16 Apr 2020 12:00:30 +0200 Subject: [PATCH 04/26] Fixes for populating AOR in order to search for contact This commit handles extraction of AOR from Contact/R-URI having ;alias/;phone-context fields respectively --- src/modules/ims_ipsec_pcscf/cmd.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index bc467b89a28..7b4b7a79c06 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -146,6 +146,8 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * struct via_body* vb = NULL; struct sip_msg* req = NULL; char* srcip = NULL; + str aor; + int i = 0; if(!ci) { LM_ERR("called with null ptr\n"); @@ -170,9 +172,17 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * ci->via_host = uri.host; ci->via_port = uri.port_no ? uri.port_no : 5060; ci->via_prot = 0; - ci->aor = m->first_line.u.request.uri; + //ci->aor = m->first_line.u.request.uri; ci->searchflag = SEARCH_NORMAL; + aor.s = pkg_malloc(m->first_line.u.request.uri.len); + if (aor.s == NULL) { + LM_ERR("memory allocation failure\n"); + return -1; + } + memcpy(aor.s, m->first_line.u.request.uri.s, m->first_line.u.request.uri.len); + aor.len = m->first_line.u.request.uri.len; + if(ci->via_host.s == NULL || ci->via_host.len == 0){ // no host included in RURI vb = cscf_get_ue_via(m); @@ -267,9 +277,17 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * ci->via_host = vb->host; ci->via_port = vb->port; ci->via_prot = vb->proto; - ci->aor = cb->contacts->uri; + //ci->aor = cb->contacts->uri; ci->searchflag = SEARCH_RECEIVED; + aor.s = pkg_malloc(cb->contacts->uri.len); + if (aor.s == NULL) { + LM_ERR("memory allocation failure\n"); + return -1; + } + memcpy(aor.s, cb->contacts->uri.s, cb->contacts->uri.len); + aor.len = cb->contacts->uri.len; + if((srcip = pkg_malloc(50)) == NULL) { LM_ERR("Error allocating memory for source IP address\n"); return -1; @@ -285,6 +303,15 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * return -1; } + for (i = 4; i < aor.len; i++) + if (aor.s[i] == ';') { + aor.len = i; + break; + } + + LM_DBG("AOR <%.*s>\n", aor.len, aor.s); + ci->aor = aor; + LM_DBG("SIP %s fill contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", m->first_line.type == SIP_REQUEST ? "REQUEST" : "REPLY", ci->aor.len, ci->aor.s, ci->via_prot, ci->via_host.len, ci->via_host.s, ci->via_port, From 251c082e52c33094b05997484a897d17e72843b9 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Tue, 21 Apr 2020 10:44:53 +0200 Subject: [PATCH 05/26] Add q value to Security-Server header for IPSec --- src/modules/ims_ipsec_pcscf/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 7b4b7a79c06..0b2352fcedd 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -645,7 +645,7 @@ int add_security_server_header(struct sip_msg* m, ipsec_t* s) char sec_hdr_buf[1024]; memset(sec_hdr_buf, 0, sizeof(sec_hdr_buf)); sec_header->len = snprintf(sec_hdr_buf, sizeof(sec_hdr_buf) - 1, - "Security-Server: ipsec-3gpp;prot=esp;mod=trans;spi-c=%d;spi-s=%d;port-c=%d;port-s=%d;alg=%.*s;ealg=%.*s\r\n", + "Security-Server: ipsec-3gpp;q=0.1;prot=esp;mod=trans;spi-c=%d;spi-s=%d;port-c=%d;port-s=%d;alg=%.*s;ealg=%.*s\r\n", s->spi_pc, s->spi_ps, s->port_pc, s->port_ps, s->r_alg.len, s->r_alg.s, s->r_ealg.len, s->r_ealg.s From c7b2ca9ddbad0e9270f39a7210718fd63e320ff1 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Fri, 29 May 2020 10:01:59 +0200 Subject: [PATCH 06/26] Set DLG to mobile originating for Rx AAR Register This fixes the flow description for Rx AAR Register request --- src/modules/ims_qos/rx_aar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/ims_qos/rx_aar.c b/src/modules/ims_qos/rx_aar.c index dbc2aebaeb6..d06169109c1 100644 --- a/src/modules/ims_qos/rx_aar.c +++ b/src/modules/ims_qos/rx_aar.c @@ -1038,7 +1038,7 @@ int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, saved_transactio &port_from, ip_version == AF_INET ? &af_signaling_ip : &af_signaling_ip6, &port_to, &flow_protocol, &raw_stream, - &raw_stream, DLG_MOBILE_REGISTER, AVP_EPC_Flow_Usage_AF_Signaling); + &raw_stream, DLG_MOBILE_ORIGINATING, AVP_EPC_Flow_Usage_AF_Signaling); /* Add specific action AVP's */ rx_add_specific_action_avp(aar, 1); // CHARGING_CORRELATION_EXCHANGE From 73aa78d3de9700411439bc4949ecaef538bdf6d2 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Thu, 27 Aug 2020 22:28:44 +0200 Subject: [PATCH 07/26] IPSec fixes --- src/modules/ims_ipsec_pcscf/cmd.c | 68 +++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 0b2352fcedd..3142c31f57d 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -725,13 +725,71 @@ int ipsec_create(struct sip_msg* m, udomain_t* d, int _cflags) ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); - ipsec_t* s = pcontact->security_temp->data.ipsec; + //ipsec_t* s = pcontact->security_temp->data.ipsec; + ipsec_t* s = NULL; + security_t* sec_params = NULL; - // for initial Registration use a new P-CSCF server port - if(update_contact_ipsec_params(s, m, NULL) != 0) { + // Parse security parameters from the REGISTER request and get some data for the tunnels + if((sec_params = cscf_get_security(req)) == NULL) { + LM_CRIT("No security parameters in REGISTER request\n"); goto cleanup; } + if (sec_params->data.ipsec->port_uc != pcontact->security_temp->data.ipsec->port_uc || + sec_params->data.ipsec->port_us != pcontact->security_temp->data.ipsec->port_us || + sec_params->data.ipsec->spi_uc != pcontact->security_temp->data.ipsec->spi_uc || + sec_params->data.ipsec->spi_us != pcontact->security_temp->data.ipsec->spi_us) { + + // Backup the Proxy Server port + ipsec_t ipsec_ps; + ipsec_ps.port_ps = pcontact->security_temp->data.ipsec->port_ps; + + if(pcontact->security_temp->sec_header.s) + shm_free(pcontact->security_temp->sec_header.s); + + if(pcontact->security_temp->data.ipsec){ + if(pcontact->security_temp->data.ipsec->ealg.s) + shm_free(pcontact->security_temp->data.ipsec->ealg.s); + if(pcontact->security_temp->data.ipsec->r_ealg.s) + shm_free(pcontact->security_temp->data.ipsec->r_ealg.s); + if(pcontact->security_temp->data.ipsec->ck.s) + shm_free(pcontact->security_temp->data.ipsec->ck.s); + if(pcontact->security_temp->data.ipsec->alg.s) + shm_free(pcontact->security_temp->data.ipsec->alg.s); + if(pcontact->security_temp->data.ipsec->r_alg.s) + shm_free(pcontact->security_temp->data.ipsec->r_alg.s); + if(pcontact->security_temp->data.ipsec->ik.s) + shm_free(pcontact->security_temp->data.ipsec->ik.s); + if(pcontact->security_temp->data.ipsec->prot.s) + shm_free(pcontact->security_temp->data.ipsec->prot.s); + if(pcontact->security_temp->data.ipsec->mod.s) + shm_free(pcontact->security_temp->data.ipsec->mod.s); + + shm_free(pcontact->security_temp->data.ipsec); + } + shm_free(pcontact->security_temp); + + if(ul.update_temp_security(d, sec_params->type, sec_params, pcontact) != 0){ + LM_ERR("Error updating temp security\n"); + goto cleanup; + } + + s = pcontact->security_temp->data.ipsec; + + // Restore the backed up Proxy Server port + if(update_contact_ipsec_params(s, m, &ipsec_ps) != 0) { + goto cleanup; + } + } else { + + s = pcontact->security_temp->data.ipsec; + + // for initial Registration use a new P-CSCF server port + if(update_contact_ipsec_params(s, m, NULL) != 0) { + goto cleanup; + } + } + if(create_ipsec_tunnel(&req->rcv.src_ip, s) != 0){ goto cleanup; } @@ -1014,6 +1072,8 @@ int ipsec_destroy(struct sip_msg* m, udomain_t* d) destroy_ipsec_tunnel(ci.received_host, pcontact->security_temp->data.ipsec, pcontact->contact_port); + ipsec_reconfig(); + ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: @@ -1073,6 +1133,8 @@ int ipsec_destroy_by_contact(udomain_t* _d, str * uri, str * received_host, int destroy_ipsec_tunnel(search_ci.received_host, pcontact->security_temp->data.ipsec, pcontact->contact_port); + ipsec_reconfig(); + ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: From 3ea8605eacb1e49b896ba65ad006332effbfc610 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Mon, 31 Aug 2020 08:44:03 +0200 Subject: [PATCH 08/26] Handle deletion of redundant IPSec tunnels which arise in SQN mismatch scenario --- src/modules/ims_ipsec_pcscf/cmd.c | 58 +++++++++++++++++++------------ 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 3142c31f57d..364025df774 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -398,17 +398,22 @@ static int update_contact_ipsec_params(ipsec_t* s, const struct sip_msg* m, ipse return -1; } - if((s->port_pc = acquire_cport()) == 0){ - LM_ERR("No free client port for IPSEC tunnel creation\n"); - shm_free(s->ck.s); - s->ck.s = NULL; s->ck.len = 0; - shm_free(s->ik.s); - s->ik.s = NULL; s->ik.len = 0; + // use the same P-CSCF client port if it is present + if(s_old){ + s->port_pc = s_old->port_pc; + }else{ + if((s->port_pc = acquire_cport()) == 0){ + LM_ERR("No free client port for IPSEC tunnel creation\n"); + shm_free(s->ck.s); + s->ck.s = NULL; s->ck.len = 0; + shm_free(s->ik.s); + s->ik.s = NULL; s->ik.len = 0; - release_spi(s->spi_pc); - release_spi(s->spi_ps); - return -1; - } + release_spi(s->spi_pc); + release_spi(s->spi_ps); + return -1; + } + } // use the same P-CSCF server port if it is present if(s_old){ @@ -491,7 +496,7 @@ static int create_ipsec_tunnel(const struct ip_addr *remote_addr, ipsec_t* s) return 0; } -static int destroy_ipsec_tunnel(str remote_addr, ipsec_t* s, unsigned short received_port) +static int destroy_ipsec_tunnel(str remote_addr, ipsec_t* s, unsigned short received_port, int release_proxy_ports) { struct mnl_socket* sock = init_mnl_socket(); if (sock == NULL) { @@ -538,9 +543,11 @@ static int destroy_ipsec_tunnel(str remote_addr, ipsec_t* s, unsigned short rece release_spi(s->spi_pc); release_spi(s->spi_ps); - // Release the client and the server ports - release_cport(s->port_pc); - release_sport(s->port_ps); + if (release_proxy_ports) { + // Release the client and the server ports + release_cport(s->port_pc); + release_sport(s->port_ps); + } close_mnl_socket(sock); return 0; @@ -565,7 +572,7 @@ void ipsec_on_expire(struct pcontact *c, int type, void *param) return; } - destroy_ipsec_tunnel(c->received_host, c->security_temp->data.ipsec, c->contact_port); + destroy_ipsec_tunnel(c->received_host, c->security_temp->data.ipsec, c->contact_port, 1); } int add_supported_secagree_header(struct sip_msg* m) @@ -740,9 +747,14 @@ int ipsec_create(struct sip_msg* m, udomain_t* d, int _cflags) sec_params->data.ipsec->spi_uc != pcontact->security_temp->data.ipsec->spi_uc || sec_params->data.ipsec->spi_us != pcontact->security_temp->data.ipsec->spi_us) { - // Backup the Proxy Server port + // Backup the Proxy Server and Client port - we re-use them ipsec_t ipsec_ps; ipsec_ps.port_ps = pcontact->security_temp->data.ipsec->port_ps; + ipsec_ps.port_pc = pcontact->security_temp->data.ipsec->port_pc; + + // Destroy privously existing IPSec tunnels but dont release proxy ports + destroy_ipsec_tunnel(ci.received_host, + pcontact->security_temp->data.ipsec, pcontact->contact_port, 0); if(pcontact->security_temp->sec_header.s) shm_free(pcontact->security_temp->sec_header.s); @@ -776,7 +788,7 @@ int ipsec_create(struct sip_msg* m, udomain_t* d, int _cflags) s = pcontact->security_temp->data.ipsec; - // Restore the backed up Proxy Server port + // Restore the backed up Proxy Server and Client port if(update_contact_ipsec_params(s, m, &ipsec_ps) != 0) { goto cleanup; } @@ -834,6 +846,10 @@ int ipsec_create(struct sip_msg* m, udomain_t* d, int _cflags) goto cleanup; } + // Restore Proxy Server and Client port + req_sec_params->data.ipsec->port_ps = pcontact->security_temp->data.ipsec->port_ps; + req_sec_params->data.ipsec->port_pc = pcontact->security_temp->data.ipsec->port_pc; + if(create_ipsec_tunnel(&req->rcv.src_ip, req_sec_params->data.ipsec) != 0){ goto cleanup; } @@ -1070,9 +1086,7 @@ int ipsec_destroy(struct sip_msg* m, udomain_t* d) goto cleanup; } - destroy_ipsec_tunnel(ci.received_host, pcontact->security_temp->data.ipsec, pcontact->contact_port); - - ipsec_reconfig(); + destroy_ipsec_tunnel(ci.received_host, pcontact->security_temp->data.ipsec, pcontact->contact_port, 1); ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit @@ -1131,9 +1145,7 @@ int ipsec_destroy_by_contact(udomain_t* _d, str * uri, str * received_host, int goto cleanup; } - destroy_ipsec_tunnel(search_ci.received_host, pcontact->security_temp->data.ipsec, pcontact->contact_port); - - ipsec_reconfig(); + destroy_ipsec_tunnel(search_ci.received_host, pcontact->security_temp->data.ipsec, pcontact->contact_port, 1); ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit From a30a342ad8c30100b3f48ff508782947ee1a21a1 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Thu, 8 Oct 2020 14:33:06 +0200 Subject: [PATCH 09/26] IPSec forward fixes for SIP messages changing from TCP to UDP Applies for Non-REGISTER SIP messages only: This commit fixes the issue wherein the SIP messages sent from UE to PCSCF over TCP which gets changed to UDP while traversing through PCSCF to the other end UE doesnt get ESP encapsulated through IPSec tunnel. --- src/modules/ims_ipsec_pcscf/cmd.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 364025df774..5e5977dae84 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -955,6 +955,9 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // for Reply get the dest proto from the received request dst_proto = req->rcv.proto; + // As per ETSI TS 133 203 V11.2.0, 7.1 Security association parameters + // https://tools.ietf.org/html/rfc3261#section-18 + // for Reply and TCP sends from P-CSCF server port, for Reply and UDP sends from P-CSCF client port src_port = dst_proto == PROTO_TCP ? s->port_ps : s->port_pc; @@ -968,8 +971,12 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) dst_port = s->port_us; } }else{ - // for Request get the dest proto from the saved contact - dst_proto = pcontact->received_proto; + if (req->first_line.u.request.method_value == METHOD_REGISTER) { + // for Request get the dest proto from the saved contact + dst_proto = pcontact->received_proto; + } else { + dst_proto = m->rcv.proto; + } // for Request sends from P-CSCF client port src_port = s->port_pc; From 565664b1b9c42dfb94656d2a2fff703d01a184aa Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Thu, 12 Nov 2020 10:10:21 +0100 Subject: [PATCH 10/26] Fix for broken In-Dialog requests/replies --- src/modules/ims_ipsec_pcscf/cmd.c | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 5e5977dae84..f66fcb3e098 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -491,6 +491,28 @@ static int create_ipsec_tunnel(const struct ip_addr *remote_addr, ipsec_t* s) add_sa (sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, s->ck, s->ik, s->r_alg, s->r_ealg); add_policy(sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, IPSEC_POLICY_DIRECTION_IN); + /* Fix for some broken In-Dialog routing */ + + // SA5 UE client to P-CSCF client + // src adrr dst addr src port dst port + add_sa (sock, remote_addr, ipsec_addr, s->port_uc, s->port_pc, s->spi_ps, s->ck, s->ik, s->r_alg, s->r_ealg); + add_policy(sock, remote_addr, ipsec_addr, s->port_uc, s->port_pc, s->spi_ps, IPSEC_POLICY_DIRECTION_IN); + + // SA6 P-CSCF client to UE client + // src adrr dst addr src port dst port + add_sa (sock, ipsec_addr, remote_addr, s->port_pc, s->port_uc, s->spi_us, s->ck, s->ik, s->r_alg, s->r_ealg); + add_policy(sock, ipsec_addr, remote_addr, s->port_pc, s->port_uc, s->spi_us, IPSEC_POLICY_DIRECTION_OUT); + + // SA7 P-CSCF server to UE server + // src adrr dst addr src port dst port + add_sa (sock, ipsec_addr, remote_addr, s->port_ps, s->port_us, s->spi_uc, s->ck, s->ik, s->r_alg, s->r_ealg); + add_policy(sock, ipsec_addr, remote_addr, s->port_ps, s->port_us, s->spi_uc, IPSEC_POLICY_DIRECTION_OUT); + + // SA8 UE server to P-CSCF server + // src adrr dst addr src port dst port + add_sa (sock, remote_addr, ipsec_addr, s->port_us, s->port_ps, s->spi_pc, s->ck, s->ik, s->r_alg, s->r_ealg); + add_policy(sock, remote_addr, ipsec_addr, s->port_us, s->port_ps, s->spi_pc, IPSEC_POLICY_DIRECTION_IN); + close_mnl_socket(sock); return 0; @@ -539,6 +561,24 @@ static int destroy_ipsec_tunnel(str remote_addr, ipsec_t* s, unsigned short rece remove_sa (sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, ip_addr.af); remove_policy(sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, ip_addr.af, IPSEC_POLICY_DIRECTION_IN); + /* Fix for some broken In-Dialog routing */ + + // SA5 UE client to P-CSCF client + remove_sa (sock, remote_addr, ipsec_addr, s->port_uc, s->port_pc, s->spi_ps, ip_addr.af); + remove_policy(sock, remote_addr, ipsec_addr, s->port_uc, s->port_pc, s->spi_ps, ip_addr.af, IPSEC_POLICY_DIRECTION_IN); + + // SA6 P-CSCF client to UE client + remove_sa (sock, ipsec_addr, remote_addr, s->port_pc, s->port_uc, s->spi_us, ip_addr.af); + remove_policy(sock, ipsec_addr, remote_addr, s->port_pc, s->port_uc, s->spi_us, ip_addr.af, IPSEC_POLICY_DIRECTION_OUT); + + // SA7 P-CSCF server to UE server + remove_sa (sock, ipsec_addr, remote_addr, s->port_ps, s->port_us, s->spi_uc, ip_addr.af); + remove_policy(sock, ipsec_addr, remote_addr, s->port_ps, s->port_us, s->spi_uc, ip_addr.af, IPSEC_POLICY_DIRECTION_OUT); + + // SA8 UE server to P-CSCF server + remove_sa (sock, remote_addr, ipsec_addr, s->port_us, s->port_ps, s->spi_pc, ip_addr.af); + remove_policy(sock, remote_addr, ipsec_addr, s->port_us, s->port_ps, s->spi_pc, ip_addr.af, IPSEC_POLICY_DIRECTION_IN); + // Release SPIs release_spi(s->spi_pc); release_spi(s->spi_ps); From 7c8f3f9720d06a4de0f05bff046bcd75897c67a0 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Mon, 16 Nov 2020 09:32:15 +0100 Subject: [PATCH 11/26] Improve contact lookup for an IMPU --- .../ims_usrloc_scscf/contact_dlg_handlers.c | 74 +++++++++++++------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/src/modules/ims_usrloc_scscf/contact_dlg_handlers.c b/src/modules/ims_usrloc_scscf/contact_dlg_handlers.c index e4c5a2a130f..e9241a17d34 100644 --- a/src/modules/ims_usrloc_scscf/contact_dlg_handlers.c +++ b/src/modules/ims_usrloc_scscf/contact_dlg_handlers.c @@ -44,35 +44,65 @@ void contact_dlg_create_handler(struct dlg_cell* dlg, int cb_types, struct dlg_c * @return 0 on success, anything else on failure */ static inline int find_contact_from_impu(impurecord_t* impu, str* search_aor, ucontact_t** scontact) { - impu_contact_t *impucontact; - short i_searchlen; + impu_contact_t *impucontact; + short i_searchlen, c_searchlen, alias_searchlen; char *s_term; + char *c_term; + char *alias_term; if (!search_aor) return 1; - + LM_DBG("Looking for contact [%.*s] for IMPU [%.*s]\n", search_aor->len, search_aor->s, impu->public_identity.len, impu->public_identity.s); + + /* Filter out sip: and anything before @ from search URI */ + s_term = strstr(search_aor->s, "@"); + if (!s_term) { + s_term = strstr(search_aor->s, ":"); + } + s_term += 1; + if (s_term-search_aor->s >= search_aor->len) { + goto error; + } + i_searchlen = search_aor->len - (s_term-search_aor->s); + + /* Compare the entire contact including alias, if not until alias IP */ + alias_term = strstr(s_term, "~"); + if (!alias_term) { + alias_searchlen = i_searchlen; + } else { + alias_term += 1; + alias_searchlen = alias_term - s_term; + } - s_term = memchr(search_aor->s,'@',search_aor->len); - if (!s_term) - { - LM_DBG("Malformed contact...bailing search\n"); - return 1; - } - i_searchlen = s_term - search_aor->s; - - impucontact = impu->linked_contacts.head; - + impucontact = impu->linked_contacts.head; + while (impucontact) { - if (impucontact->contact && impucontact->contact->aor.s[i_searchlen] == '@' - && (memcmp(impucontact->contact->aor.s, search_aor->s, i_searchlen) == 0)) { - *scontact = impucontact->contact; - return 0; - } - if (impucontact->contact) - LM_DBG("Skipping %.*s\n", impucontact->contact->aor.len, impucontact->contact->aor.s); - impucontact = impucontact->next; - } + + if (impucontact->contact) { + + c_term = strstr(impucontact->contact->c.s, "@"); + if (!c_term) { + c_term = strstr(impucontact->contact->c.s, ":"); + } + c_term += 1; + c_searchlen = impucontact->contact->c.len - (c_term-impucontact->contact->c.s); + + LM_DBG("Comparing [%.*s] and [%.*s]\n", i_searchlen, s_term, c_searchlen, c_term); + LM_DBG("Comparing [%.*s] and [%.*s]\n", alias_searchlen, s_term, c_searchlen, c_term); + if ((strncmp(c_term, s_term, i_searchlen) == 0) || + (strncmp(c_term, s_term, alias_searchlen) == 0)) { + *scontact = impucontact->contact; + return 0; + } + } + if (impucontact->contact) + LM_DBG("Skipping %.*s\n", impucontact->contact->c.len, impucontact->contact->c.s); + impucontact = impucontact->next; + } + +error: + LM_DBG("Malformed contact...bailing search\n"); return 1; } From 2d251a8340f2cdc95c775a7a95e44ad8a1bd37a0 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Sat, 12 Dec 2020 08:04:21 +0100 Subject: [PATCH 12/26] IPSec crash fix --- src/modules/ims_ipsec_pcscf/cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index f66fcb3e098..93c23158f5e 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -931,7 +931,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) if(m->first_line.type == SIP_REPLY) { // Get request from reply t = tmb.t_gett(); - if (!t) { + if (!t || t == (void*) -1) { LM_ERR("Error getting transaction\n"); return ret; } @@ -1063,7 +1063,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // Update dst_info in message if(m->first_line.type == SIP_REPLY) { struct cell *t = tmb.t_gett(); - if (!t) { + if (!t || t == (void*) -1) { LM_ERR("Error getting transaction\n"); goto cleanup; } From e1498a0301c36afffd2ef9dbef8a0c0a51f02cf6 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Wed, 16 Dec 2020 15:23:02 +0100 Subject: [PATCH 13/26] Fix request message contact parsing --- src/modules/ims_ipsec_pcscf/cmd.c | 37 ++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 93c23158f5e..9beb60f943c 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -82,6 +82,24 @@ extern struct tm_binds tmb; #define IPSEC_CREATE_DELETE_UNUSED_TUNNELS 0x01 /* if set - delete unused tunnels before every registration */ +static int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst) +{ + dst->id = src->id; + dst->rcv = src->rcv; + dst->set_global_address = src->set_global_address; + dst->set_global_port = src->set_global_port; + dst->flags = src->flags; + dst->fwd_send_flags = src->fwd_send_flags; + dst->rpl_send_flags = src->rpl_send_flags; + dst->force_send_socket = src->force_send_socket; + + if (parse_msg(dst->buf, dst->len, dst) != 0) { + LM_ERR("parse msg failed\n"); + return -1; + } + return 0; +} + int bind_ipsec_pcscf(ipsec_pcscf_api_t* api) { if(!api){ LM_ERR("invalid parameter value\n"); @@ -261,7 +279,24 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * req = t->uas.request; - cb = cscf_parse_contacts(req); + /* Do not use t->uas.request for getting contacts - it has garbage */ + struct sip_msg req_msg; + memset(&req_msg, 0, sizeof(struct sip_msg)); + req_msg.buf = + (char*) pkg_malloc((t->uas.request->len + 1) * sizeof(char)); + memcpy(req_msg.buf, t->uas.request->buf, t->uas.request->len); + req_msg.buf[t->uas.request->len] = '\0'; + req_msg.len = t->uas.request->len; + if (pv_t_copy_msg(t->uas.request, &req_msg) != 0) { + pkg_free(req_msg.buf); + req_msg.buf = NULL; + return -1; + } + if (req_msg.contact && ((contact_body_t *) req_msg.contact->parsed)) { + free_contact((contact_body_t **) &req_msg.contact->parsed); + } + + cb = cscf_parse_contacts(&req_msg); if (!cb || (!cb->contacts)) { LM_ERR("Reply No contact headers\n"); return -1; From 551e91fb5414cc73a49c03fc0fbfd47dffb4484d Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Fri, 29 Jan 2021 19:06:43 +0100 Subject: [PATCH 14/26] Fix for CER not containing Host-IP-Address AVP --- src/modules/cdp/peerstatemachine.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/modules/cdp/peerstatemachine.c b/src/modules/cdp/peerstatemachine.c index a4520d797d1..eb875831d33 100644 --- a/src/modules/cdp/peerstatemachine.c +++ b/src/modules/cdp/peerstatemachine.c @@ -128,8 +128,10 @@ int sm_process(peer *p,peer_event_t event,AAAMessage *msg,int peer_locked,int so case Wait_Conn_Ack: switch(event){ case I_Rcv_Conn_Ack: - I_Snd_CER(p); p->state = Wait_I_CEA; + I_Snd_CER(p); + if (p->state == Closed) + sm_process(p, Start, 0, 1, 0); break; case I_Rcv_Conn_NAck: Cleanup(p,p->I_sock); @@ -624,15 +626,23 @@ void I_Snd_CER(peer *p) } addr_u ; socklen_t addrlen; char x[18]; + int ret = 0; cer = AAANewMessage(Code_CE,0,0,0); if (!cer) return; cer->hopbyhopId = next_hopbyhop(); cer->endtoendId = next_endtoend(); addrlen = sizeof(addr_u); - if (getsockname(p->I_sock,&(addr_u.addr), &addrlen) == -1) { + if ((ret = getsockname(p->I_sock,&(addr_u.addr), &addrlen)) == -1) { LM_ERR("I_Snd_CER(): Error on finding local host address > %s\n",strerror(errno)); - }else{ + + Cleanup(p,p->I_sock); + p->state = Closed; + AAAFreeMessage(&cer); + return; + } + + if (ret != -1) { switch(addr_u.addr.sa_family){ case AF_INET: set_2bytes(x,1); From 301fa8da79c619dc5d7f7da83d973cf106ce633c Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Sat, 10 Apr 2021 20:14:41 +0200 Subject: [PATCH 15/26] Reuse IPSec ports but remove SA and Policies --- src/modules/ims_ipsec_pcscf/cmd.c | 9 ++-- src/modules/ims_ipsec_pcscf/port_gen.c | 63 ++++++++++++++------------ 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 9beb60f943c..d879f38e0a8 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -461,7 +461,7 @@ static int update_contact_ipsec_params(ipsec_t* s, const struct sip_msg* m, ipse shm_free(s->ik.s); s->ik.s = NULL; s->ik.len = 0; - release_cport(s->port_pc); + // release_cport(s->port_pc); release_spi(s->spi_pc); release_spi(s->spi_ps); @@ -620,8 +620,9 @@ static int destroy_ipsec_tunnel(str remote_addr, ipsec_t* s, unsigned short rece if (release_proxy_ports) { // Release the client and the server ports - release_cport(s->port_pc); - release_sport(s->port_ps); + // Do not release proxy IPSec ports at all just remove SA and Policies + // release_cport(s->port_pc); + // release_sport(s->port_ps); } close_mnl_socket(sock); @@ -1244,7 +1245,7 @@ int ipsec_reconfig() } clean_spi_list(); - clean_port_lists(); + // clean_port_lists(); LM_DBG("Clean all ipsec tunnels\n"); diff --git a/src/modules/ims_ipsec_pcscf/port_gen.c b/src/modules/ims_ipsec_pcscf/port_gen.c index d722eefd2be..a841ce33580 100644 --- a/src/modules/ims_ipsec_pcscf/port_gen.c +++ b/src/modules/ims_ipsec_pcscf/port_gen.c @@ -93,34 +93,41 @@ uint32_t acquire_port(spi_list_t* used_ports, pthread_mutex_t* port_mut, uint32_ return ret; } - while(1){ - if(spi_in_list(used_ports, *port_val) == 0) { - ret = *port_val; - (*port_val)++; - - if(*port_val >= max_port) { //reached the top of the range - reset - *port_val = min_port; - } - - break; - } - - (*port_val)++; //the current server port is not available - increment - - if(*port_val >= max_port) { //reached the top of the range - reset - *port_val = min_port; - } - - if(*port_val == initial_val) { //there are no free server ports - pthread_mutex_unlock(port_mut); - return ret; - } - } - - // found unused server port - add it to the used list - if(spi_add(used_ports, ret) != 0) { - ret = 0; - } + if(*port_val >= max_port) { //reached the top of the range - reset + *port_val = min_port; + } + ret = *port_val; + (*port_val)++; + + // The below code is commented because we want to re-use the ports but with different SA and Policies + // while(1){ + // if(spi_in_list(used_ports, *port_val) == 0) { + // ret = *port_val; + // (*port_val)++; + + // if(*port_val >= max_port) { //reached the top of the range - reset + // *port_val = min_port; + // } + + // break; + // } + + // (*port_val)++; //the current server port is not available - increment + + // if(*port_val >= max_port) { //reached the top of the range - reset + // *port_val = min_port; + // } + + // if(*port_val == initial_val) { //there are no free server ports + // pthread_mutex_unlock(port_mut); + // return ret; + // } + // } + + // // found unused server port - add it to the used list + // if(spi_add(used_ports, ret) != 0) { + // ret = 0; + // } pthread_mutex_unlock(port_mut); return ret; From c8768538345681fa41a2bc6272892231a96f3fec Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Thu, 15 Apr 2021 18:17:38 +0200 Subject: [PATCH 16/26] Handle IPSec registration corner case where first SIP REGISTER does not have VIA port as 5060 --- src/modules/ims_ipsec_pcscf/cmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index d879f38e0a8..d832de89b08 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -803,7 +803,9 @@ int ipsec_create(struct sip_msg* m, udomain_t* d, int _cflags) struct sip_msg* req = t->uas.request; // Update contacts only for initial registration, for re-registration the existing contacts shouldn't be updated. - if(ci.via_port == SIP_PORT){ + if((ci.via_port == SIP_PORT) || + (pcontact->security_temp->data.ipsec->port_ps == 0 && + pcontact->security_temp->data.ipsec->port_pc == 0)){ LM_DBG("Registration for contact with AOR [%.*s], VIA [%d://%.*s:%d], received_host [%d://%.*s:%d]\n", ci.aor.len, ci.aor.s, ci.via_prot, ci.via_host.len, ci.via_host.s, ci.via_port, ci.received_proto, ci.received_host.len, ci.received_host.s, ci.received_port); From 700e7d29d824027121b940b7460aad33b37f7ab5 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Thu, 29 Apr 2021 18:21:43 +0200 Subject: [PATCH 17/26] Fix for covnersion as per this comment - https://github.com/kamailio/kamailio/issues/1173#issuecomment-315198949 --- src/modules/siputils/checks.c | 387 +++++++++++++++++++++++++++------- 1 file changed, 310 insertions(+), 77 deletions(-) diff --git a/src/modules/siputils/checks.c b/src/modules/siputils/checks.c index 1bfaae23300..ca2bb49db58 100644 --- a/src/modules/siputils/checks.c +++ b/src/modules/siputils/checks.c @@ -575,89 +575,322 @@ int w_uri_param_rm(struct sip_msg* _msg, char* _param, char* _str2) * tel URI. Returns -1, if conversion failed. Takes SIP URI hostpart from * second parameter and (if needed) writes the result to third paramater. */ -int tel2sip(struct sip_msg* _msg, char* _uri, char* _hostpart, char* _res) -{ - str uri, hostpart, tel_uri, sip_uri; - char *at; - int i, j, in_tel_parameters = 0; - pv_spec_t *res; - pv_value_t res_val; - - /* get parameters */ - if (get_str_fparam(&uri, _msg, (fparam_t*)_uri) < 0) { - LM_ERR("failed to get uri value\n"); - return -1; - } - if (get_str_fparam(&hostpart, _msg, (fparam_t*)_hostpart) < 0) { - LM_ERR("failed to get hostpart value\n"); - return -1; - } - res = (pv_spec_t *)_res; - - /* check if anything needs to be done */ - if (uri.len < 4) return 2; - if (strncasecmp(uri.s, "tel:", 4) != 0) return 2; - - /* reserve memory for clean tel uri */ - tel_uri.s = pkg_malloc(uri.len+1); - if (tel_uri.s == 0) { - LM_ERR("no more pkg memory\n"); - return -1; - } - - /* Remove visual separators before converting to SIP URI. Don't remove - * visual separators in TEL URI parameters (after the first ";") */ - for (i=0, j=0; i < uri.len; i++) { - if (in_tel_parameters == 0) { - if (uri.s[i] == ';') - in_tel_parameters = 1; - } - if (in_tel_parameters == 0) { - if ((uri.s[i] != '-') && (uri.s[i] != '.') && - (uri.s[i] != '(') && (uri.s[i] != ')')) - tel_uri.s[j++] = tolower(uri.s[i]); - } else { - tel_uri.s[j++] = tolower(uri.s[i]); - } - } - tel_uri.s[j] = '\0'; - tel_uri.len = strlen(tel_uri.s); - - /* reserve memory for resulting sip uri */ - sip_uri.len = 4 + tel_uri.len - 4 + 1 + hostpart.len + 1 + 10; - sip_uri.s = pkg_malloc(sip_uri.len+1); - if (sip_uri.s == 0) { - LM_ERR("no more pkg memory\n"); - pkg_free(tel_uri.s); - return -1; - } +// int tel2sip(struct sip_msg* _msg, char* _uri, char* _hostpart, char* _res) +// { +// str uri, hostpart, tel_uri, sip_uri; +// char *at; +// int i, j, in_tel_parameters = 0; +// pv_spec_t *res; +// pv_value_t res_val; + +// /* get parameters */ +// if (get_str_fparam(&uri, _msg, (fparam_t*)_uri) < 0) { +// LM_ERR("failed to get uri value\n"); +// return -1; +// } +// if (get_str_fparam(&hostpart, _msg, (fparam_t*)_hostpart) < 0) { +// LM_ERR("failed to get hostpart value\n"); +// return -1; +// } +// res = (pv_spec_t *)_res; + +// /* check if anything needs to be done */ +// if (uri.len < 4) return 2; +// if (strncasecmp(uri.s, "tel:", 4) != 0) return 2; + +// /* reserve memory for clean tel uri */ +// tel_uri.s = pkg_malloc(uri.len+1); +// if (tel_uri.s == 0) { +// LM_ERR("no more pkg memory\n"); +// return -1; +// } + +// /* Remove visual separators before converting to SIP URI. Don't remove +// * visual separators in TEL URI parameters (after the first ";") */ +// for (i=0, j=0; i < uri.len; i++) { +// if (in_tel_parameters == 0) { +// if (uri.s[i] == ';') +// in_tel_parameters = 1; +// } +// if (in_tel_parameters == 0) { +// if ((uri.s[i] != '-') && (uri.s[i] != '.') && +// (uri.s[i] != '(') && (uri.s[i] != ')')) +// tel_uri.s[j++] = tolower(uri.s[i]); +// } else { +// tel_uri.s[j++] = tolower(uri.s[i]); +// } +// } +// tel_uri.s[j] = '\0'; +// tel_uri.len = strlen(tel_uri.s); + +// /* reserve memory for resulting sip uri */ +// sip_uri.len = 4 + tel_uri.len - 4 + 1 + hostpart.len + 1 + 10; +// sip_uri.s = pkg_malloc(sip_uri.len+1); +// if (sip_uri.s == 0) { +// LM_ERR("no more pkg memory\n"); +// pkg_free(tel_uri.s); +// return -1; +// } + +// /* create resulting sip uri */ +// at = sip_uri.s; +// append_str(at, "sip:", 4); +// append_str(at, tel_uri.s + 4, tel_uri.len - 4); +// append_chr(at, '@'); +// append_str(at, hostpart.s, hostpart.len); +// append_chr(at, ';'); +// append_str(at, "user=phone", 10); + +// /* tel_uri is not needed anymore */ +// pkg_free(tel_uri.s); + +// /* set result pv value and write sip uri to result pv */ +// res_val.rs = sip_uri; +// res_val.flags = PV_VAL_STR; +// if (res->setf(_msg, &res->pvp, (int)EQ_T, &res_val) != 0) { +// LM_ERR("failed to set result pvar\n"); +// pkg_free(sip_uri.s); +// return -1; +// } + +// /* free allocated pkg memory and return */ +// pkg_free(sip_uri.s); +// return 1; +// } - /* create resulting sip uri */ - at = sip_uri.s; - append_str(at, "sip:", 4); - append_str(at, tel_uri.s + 4, tel_uri.len - 4); - append_chr(at, '@'); - append_str(at, hostpart.s, hostpart.len); - append_chr(at, ';'); - append_str(at, "user=phone", 10); +/* + * Compare function to sort tel: uri options acording to standard + * before inserting into sip: uri + * + * See "RFC 3261 SIP: Session Initiation Protocol June 2002" + * 19.1.6 Relating SIP URIs and tel URLs + */ +typedef struct +{ + char *name; + char *value; +} tel_param_t; +#define MAX_TEL_PARAMS (10) - /* tel_uri is not needed anymore */ - pkg_free(tel_uri.s); +int compare_tel_options(const void *v1, const void *v2) +{ + tel_param_t *p1 = (tel_param_t *) v1; + tel_param_t *p2 = (tel_param_t *) v2; + + if (0 == strcasecmp(p1->name, "isdn-subaddress")) + { + return -1; + } + else if (0 == strcasecmp(p2->name, "isdn-subaddress")) + { + return 1; + } + else if (0 == strcasecmp(p1->name, "post-dial")) + { + return -1; + } + else if (0 == strcasecmp(p2->name, "post-dial")) + { + return 1; + } + else + { + return strcasecmp(p1->name, p2->name); + } +} - /* set result pv value and write sip uri to result pv */ - res_val.rs = sip_uri; - res_val.flags = PV_VAL_STR; - if (res->setf(_msg, &res->pvp, (int)EQ_T, &res_val) != 0) { - LM_ERR("failed to set result pvar\n"); - pkg_free(sip_uri.s); - return -1; - } +/* + * Remove visual separators from the phone number + * Assume it has been validated as a number containing + * ONLY leading '+', digits, and visual separators. + */ +static void remove_visual_separators_from_phone(char *p) +{ + char *p2; + p2 = p; + while (*p != '\0') + { + /* Skip all visual separators */ + while ((*p != '\0') && ((*p == '.') || (*p == '-') || (*p == '(') || (*p == ')'))) + { + p++; + } + *p2 = *p; /* Until the first visual separator, these both point to the same place. */ + /* but, more efficient to just do it than an if statement each time. */ + /* If we arrived at a terminator in the inner loop, time to exit */ + if (*p == '\0') return; + /* Now we increment both pointers. */ + p++; + p2++; + } + *p2 = '\0'; /* Make sure that the string is terminated after the last valid digit. */ +} - /* free allocated pkg memory and return */ - pkg_free(sip_uri.s); - return 1; +/* + * Check if this is a phone number. + * Assume possible leading '+' + * Assume separators '.', '-', '(', or ')' could be present. + */ +static int is_number(const char *p) +{ + if (*p == '+') p++; + while (*p != '\0') + { + if ((!isdigit(*p)) && (*p != '.') && (*p != '-') && (*p != '(') && (*p != ')')) return 0; + p++; + } + return 1; } +/* + * Converts URI, if it is tel URI, to SIP URI. Returns 1, if + * conversion succeeded or if no conversion was needed, i.e., URI was not + * tel URI. Returns -1, if conversion failed. Takes SIP URI hostpart from + * second parameter and (if needed) writes the result to third parameter. + * This one attempts to be standards compliant and sort tel: uri parameters + * copied to the sip: uri in the manner defined in the standard. It also + * deletes the "phone-context" parameter if it is a domain, and, takes visual + * separators from the "phone-context" parameter if it is a telephone number. + */ +int tel2sip(struct sip_msg* _msg, char* _uri, char* _hostpart, char* _res) +{ + str uri, hostpart, tel_uri, sip_uri; + char *at; + int i, j, in_tel_parameters = 0; + pv_spec_t *res; + pv_value_t res_val; + + /* get parameters */ + if (get_str_fparam(&uri, _msg, (fparam_t*)_uri) < 0) { + LM_ERR("failed to get uri value\n"); + } + if (get_str_fparam(&hostpart, _msg, (fparam_t*)_hostpart) < 0) { + LM_ERR("failed to get hostpart value\n"); + } + res = (pv_spec_t *)_res; + + /* check if anything needs to be done */ + if (uri.len < 4) return 1; + if (strncasecmp(uri.s, "tel:", 4) != 0) return 1; + + /* reserve memory for clean tel uri */ + tel_uri.s = pkg_malloc(uri.len+1); + if (tel_uri.s == 0) { + LM_ERR("no more pkg memory\n"); + return -1; + } + + /* Remove visual separators before converting to SIP URI. Don't remove + * visual separators in TEL URI parameters (after the first ";") */ + for (i=0, j=0; i < uri.len; i++) { + if (in_tel_parameters == 0) { + if (uri.s[i] == ';') + in_tel_parameters = 1; + } + if (in_tel_parameters == 0) { + if ((uri.s[i] != '-') && (uri.s[i] != '.') && + (uri.s[i] != '(') && (uri.s[i] != ')')) + tel_uri.s[j++] = tolower(uri.s[i]); + } else { + tel_uri.s[j++] = tolower(uri.s[i]); + } + } + tel_uri.s[j] = '\0'; + tel_uri.len = strlen(tel_uri.s); + + /*** Start Code to sort tel: params *******/ + tel_param_t params[MAX_TEL_PARAMS]; + char *tmp_ptr = tel_uri.s + 4; // skip tel: + + int n_tel_params = 0; + for (int i=0; i < MAX_TEL_PARAMS; i++) + { + tmp_ptr = strchr(tmp_ptr, ';'); + if (tmp_ptr == NULL) + { + break; + } + *tmp_ptr = '\0'; + tmp_ptr++; + n_tel_params++; + params[i].name = tmp_ptr; + } + for (int i=0; i < n_tel_params; i++) + { + tmp_ptr = strchr(params[i].name, '='); + if (tmp_ptr == NULL) + { + params[i].value = ""; + } + else + { + *tmp_ptr = '\0'; + tmp_ptr++; + params[i].value = tmp_ptr; + } + if ((0 == strcasecmp(params[i].name, "phone-context")) && (is_number(params[i].value))) + { + remove_visual_separators_from_phone(params[i].value); + } + + } + if (n_tel_params > 1) + { + qsort(¶ms[0], n_tel_params, sizeof(tel_param_t), compare_tel_options); + } + /*** End Code to sort tel: params ******/ + + /* reserve memory for resulting sip uri */ + sip_uri.len = 4 + tel_uri.len - 4 + 1 + hostpart.len + 1 + 10; + sip_uri.s = pkg_malloc(sip_uri.len+1); + if (sip_uri.s == 0) { + LM_ERR("no more pkg memory\n"); + pkg_free(tel_uri.s); + return -1; + } + + /* create resulting sip uri */ + at = sip_uri.s; + append_str(at, "sip:", 4); + /** Original code tel: parameters NOT sorted + append_str(at, tel_uri.s + 4, tel_uri.len - 4); + *****/ + /***** Start Changed Code for sorted tel: parameters ****/ + append_str(at, tel_uri.s + 4, strlen(tel_uri.s + 4)); /* This string was terminated after the number */ + /** Now we need to insert sorted tel: parameters **/ + for (int i=0; i < n_tel_params; i++) + { + /* If the phone context is a domain, it has already been extracted and is in the "host part" */ + if ((0 != strcasecmp(params[i].name, "phone-context")) || (is_number(params[i].value))) + { + append_chr(at, ';'); + append_str(at, params[i].name, strlen(params[i].name)); + append_chr(at, '='); + append_str(at, params[i].value, strlen(params[i].value)); + } + } + /***** End Changed Code for sort tel: parameters ****/ + append_chr(at, '@'); + append_str(at, hostpart.s, hostpart.len); + append_chr(at, ';'); + append_str(at, "user=phone", 10); + + /* tel_uri is not needed anymore */ + pkg_free(tel_uri.s); + + /* set result pv value and write sip uri to result pv */ + res_val.rs = sip_uri; + res_val.flags = PV_VAL_STR; + if (res->setf(_msg, &res->pvp, (int)EQ_T, &res_val) != 0) { + LM_ERR("failed to set result pvar\n"); + pkg_free(sip_uri.s); + return -1; + } + + /* free allocated pkg memory and return */ + pkg_free(sip_uri.s); + return 1; +} /* * Check if parameter is an e164 number. From 908e04ab52d98e8ca2e90898694376f3f9973276 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Tue, 4 May 2021 17:06:50 +0200 Subject: [PATCH 18/26] Do not crash if the conversion fails --- src/modules/siputils/checks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/siputils/checks.c b/src/modules/siputils/checks.c index ca2bb49db58..f290de1b5a5 100644 --- a/src/modules/siputils/checks.c +++ b/src/modules/siputils/checks.c @@ -763,9 +763,11 @@ int tel2sip(struct sip_msg* _msg, char* _uri, char* _hostpart, char* _res) /* get parameters */ if (get_str_fparam(&uri, _msg, (fparam_t*)_uri) < 0) { LM_ERR("failed to get uri value\n"); + return -1; } if (get_str_fparam(&hostpart, _msg, (fparam_t*)_hostpart) < 0) { LM_ERR("failed to get hostpart value\n"); + return -1; } res = (pv_spec_t *)_res; From ed5b7423fc0a7cb1feb84e902a4a5f31fa8ca484 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Mon, 10 May 2021 07:51:10 +0200 Subject: [PATCH 19/26] Delay pcontact delete by 10 seconds --- src/modules/ims_registrar_pcscf/save.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/modules/ims_registrar_pcscf/save.c b/src/modules/ims_registrar_pcscf/save.c index b33a596cd2d..20266229e74 100644 --- a/src/modules/ims_registrar_pcscf/save.c +++ b/src/modules/ims_registrar_pcscf/save.c @@ -218,8 +218,13 @@ static inline int update_contacts(struct sip_msg *req,struct sip_msg *rpl, udoma LM_DBG("contact already exists and is in state (%d) : [%s]\n",pcontact->reg_state, reg_state_to_string(pcontact->reg_state)); if ((expires-local_time_now)<=0) { //remove contact - de-register LM_DBG("This is a de-registration for contact <%.*s>\n", c->uri.len, c->uri.s); - if (ul.delete_pcontact(_d, pcontact) != 0) { - LM_ERR("failed to delete pcscf contact <%.*s>\n", c->uri.len, c->uri.s); + // if (ul.delete_pcontact(_d, pcontact) != 0) { + // LM_ERR("failed to delete pcscf contact <%.*s>\n", c->uri.len, c->uri.s); + // } + // Rather than delete update the pcontact with expire value of 10 seconds + ci.expires = local_time_now + 10; + if (ul.update_pcontact(_d, &ci, pcontact) != 0) { + LM_DBG("failed to update pcscf contact on de-register\n"); } //TODO_LATEST replace above } else { //update contact From 88b3e9ac627cdb5b21cc343bbfe90f2c4a72a1be Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Wed, 12 May 2021 14:46:12 +0200 Subject: [PATCH 20/26] Delay pcontact delete by 10 seconds upon REGINFO enabled --- src/modules/ims_registrar_pcscf/notify.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/modules/ims_registrar_pcscf/notify.c b/src/modules/ims_registrar_pcscf/notify.c index ca5391c7c1a..e046a9b4c68 100644 --- a/src/modules/ims_registrar_pcscf/notify.c +++ b/src/modules/ims_registrar_pcscf/notify.c @@ -203,8 +203,13 @@ int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_st if (contact_state == STATE_TERMINATED) { //delete contact LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s); - if (ul.delete_pcontact(_d, pcontact) != 0) { - LM_DBG("failed to delete pcscf contact <%.*s> - not a problem this may have been removed by de registration", contact_uri.len, contact_uri.s); + // if (ul.delete_pcontact(_d, pcontact) != 0) { + // LM_DBG("failed to delete pcscf contact <%.*s> - not a problem this may have been removed by de registration", contact_uri.len, contact_uri.s); + // } + // Rather than delete update the pcontact with expire value of 10 seconds + ci.expires = local_time_now + 10; + if (ul.update_pcontact(_d, &ci, pcontact) != 0) { + LM_DBG("failed to update pcscf contact on de-register\n"); } /*TODO_LATEST - put this back */ } else {//state is active From 4846b1be16b496e040de2d40b61b269c63bff78f Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Mon, 7 Jun 2021 14:01:54 +0200 Subject: [PATCH 21/26] IPSec fixes --- src/modules/ims_ipsec_pcscf/cmd.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index d832de89b08..7336c361bff 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -963,6 +963,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) unsigned short dst_port = 0; unsigned short src_port = 0; ip_addr_t via_host; + struct via_body *vb; struct sip_msg* req = NULL; struct cell *t = NULL; @@ -1028,10 +1029,11 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) m->dst_uri.len = 0; } + vb = cscf_get_last_via(m); + char buf[1024]; if(m->first_line.type == SIP_REPLY){ - // for Reply get the dest proto from the received request - dst_proto = req->rcv.proto; + dst_proto = vb ? vb->proto : req->rcv.proto; // As per ETSI TS 133 203 V11.2.0, 7.1 Security association parameters // https://tools.ietf.org/html/rfc3261#section-18 @@ -1053,7 +1055,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // for Request get the dest proto from the saved contact dst_proto = pcontact->received_proto; } else { - dst_proto = m->rcv.proto; + dst_proto = vb ? vb->proto : m->rcv.proto; } // for Request sends from P-CSCF client port @@ -1063,7 +1065,14 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) dst_port = s->port_us; } - int buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d", ci.via_host.len, ci.via_host.s, dst_port); + int buf_len = 0; + if (dst_proto == PROTO_TCP) { + buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d;transport=tcp", ci.via_host.len, ci.via_host.s, dst_port); + } else if (dst_proto == PROTO_TLS) { + buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d;transport=tls", ci.via_host.len, ci.via_host.s, dst_port); + } else { + buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d", ci.via_host.len, ci.via_host.s, dst_port); + } if((m->dst_uri.s = pkg_malloc(buf_len + 1)) == NULL) { LM_ERR("Error allocating memory for dst_uri\n"); @@ -1108,7 +1117,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) t->uas.response.dst = dst_info; } - LM_DBG("Destination changed to [%d://%.*s], from [%d:%d]\n", dst_info.proto, m->dst_uri.len, m->dst_uri.s, + LM_INFO("Destination changed to [%d://%.*s], from [%d:%d]\n", dst_info.proto, m->dst_uri.len, m->dst_uri.s, dst_info.send_sock->proto, dst_info.send_sock->port_no); ret = IPSEC_CMD_SUCCESS; // all good, return SUCCESS From 16f98a438753f2645d6b8a0166f60e71cf41afdf Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Tue, 22 Jun 2021 10:51:35 +0200 Subject: [PATCH 22/26] Try for TCP if UDP fails --- src/modules/ims_ipsec_pcscf/cmd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 7336c361bff..6e7b5e804ca 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -1065,6 +1065,13 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) dst_port = s->port_us; } + // Try for send socket + struct socket_info * client_sock = grep_sock_info(via_host.af == AF_INET ? &ipsec_listen_addr : &ipsec_listen_addr6, src_port, dst_proto); + if(!client_sock && dst_proto == PROTO_UDP) { + LM_ERR("UDP socket not found for IPSec forward, trying for TCP\n"); + dst_proto = PROTO_TCP; + } + int buf_len = 0; if (dst_proto == PROTO_TCP) { buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d;transport=tcp", ci.via_host.len, ci.via_host.s, dst_port); @@ -1084,7 +1091,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) m->dst_uri.s[m->dst_uri.len] = '\0'; // Set send socket - struct socket_info * client_sock = grep_sock_info(via_host.af == AF_INET ? &ipsec_listen_addr : &ipsec_listen_addr6, src_port, dst_proto); + client_sock = grep_sock_info(via_host.af == AF_INET ? &ipsec_listen_addr : &ipsec_listen_addr6, src_port, dst_proto); if(!client_sock) { LM_ERR("Error calling grep_sock_info() for ipsec client port\n"); goto cleanup; From d9a76eccbecb7113332d018726009f36a1638cfd Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Mon, 10 Jan 2022 11:34:03 +0100 Subject: [PATCH 23/26] Fix In-Dialog request forwarding based on destination URI transport Force send socket Fix string presence check --- src/modules/ims_ipsec_pcscf/cmd.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 6e7b5e804ca..a84ffe26a55 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -1023,12 +1023,6 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // from URI //int uri_len = 4 /* strlen("sip:") */ + ci.via_host.len + 5 /* max len of port number */ ; - if(m->dst_uri.s) { - pkg_free(m->dst_uri.s); - m->dst_uri.s = NULL; - m->dst_uri.len = 0; - } - vb = cscf_get_last_via(m); char buf[1024]; @@ -1055,7 +1049,14 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // for Request get the dest proto from the saved contact dst_proto = pcontact->received_proto; } else { - dst_proto = vb ? vb->proto : m->rcv.proto; + if (strstr(m->dst_uri.s, ";transport=tcp") != NULL) { + dst_proto = PROTO_TCP; + } else if (strstr( + m->dst_uri.s, ";transport=tls") != NULL) { + dst_proto = PROTO_TLS; + } else { + dst_proto = m->rcv.proto; + } } // for Request sends from P-CSCF client port @@ -1081,6 +1082,12 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d", ci.via_host.len, ci.via_host.s, dst_port); } + if(m->dst_uri.s) { + pkg_free(m->dst_uri.s); + m->dst_uri.s = NULL; + m->dst_uri.len = 0; + } + if((m->dst_uri.s = pkg_malloc(buf_len + 1)) == NULL) { LM_ERR("Error allocating memory for dst_uri\n"); goto cleanup; @@ -1101,10 +1108,15 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // Set destination info struct dest_info dst_info; dst_info.send_sock = client_sock; +#if 1 if(m->first_line.type == SIP_REQUEST && (_cflags & IPSEC_SEND_FORCE_SOCKET)){ dst_info.send_flags.f |= SND_F_FORCE_SOCKET; m->fwd_send_flags.f |= SND_F_FORCE_SOCKET; } +#else + // commit c08ae85661b35a93bf98d8112982e5fcf7ff1ae8 from https://github.com/herlesupreeth/kamailio + set_force_socket(m, client_sock); +#endif #ifdef USE_DNS_FAILOVER if (!uri2dst(NULL, &dst_info, m, &m->dst_uri, dst_proto)) { #else From 1fd4ec6cf2d8b523eb9dd36fafd0034f0d41d69c Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Wed, 9 Feb 2022 15:16:07 +0100 Subject: [PATCH 24/26] Handle IPSec forwarding scenarios when contact header is absent --- src/modules/ims_ipsec_pcscf/cmd.c | 36 ++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index a84ffe26a55..c4c26dc30a0 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -164,7 +164,7 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * struct via_body* vb = NULL; struct sip_msg* req = NULL; char* srcip = NULL; - str aor; + str aor, f_uri; int i = 0; if(!ci) { @@ -298,13 +298,18 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * cb = cscf_parse_contacts(&req_msg); if (!cb || (!cb->contacts)) { - LM_ERR("Reply No contact headers\n"); - return -1; + LM_ERR("Reply No contact headers. Will try with request's From URI\n"); + if (!cscf_get_from_uri(&req_msg, &f_uri)) { + LM_INFO("From URI in request <%.*s>\n", f_uri.len, f_uri.s); + pkg_free(req_msg.buf); + return -1; + } } vb = cscf_get_ue_via(m); if (!vb) { LM_ERR("Reply No via body headers\n"); + pkg_free(req_msg.buf); return -1; } @@ -315,13 +320,14 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * //ci->aor = cb->contacts->uri; ci->searchflag = SEARCH_RECEIVED; - aor.s = pkg_malloc(cb->contacts->uri.len); + aor.s = pkg_malloc((cb && cb->contacts) ? cb->contacts->uri.len : f_uri.len); if (aor.s == NULL) { LM_ERR("memory allocation failure\n"); + pkg_free(req_msg.buf); return -1; } - memcpy(aor.s, cb->contacts->uri.s, cb->contacts->uri.len); - aor.len = cb->contacts->uri.len; + memcpy(aor.s, (cb && cb->contacts) ? cb->contacts->uri.s : f_uri.s, (cb && cb->contacts) ? cb->contacts->uri.len : f_uri.len); + aor.len = (cb && cb->contacts) ? cb->contacts->uri.len : f_uri.len; if((srcip = pkg_malloc(50)) == NULL) { LM_ERR("Error allocating memory for source IP address\n"); @@ -332,6 +338,8 @@ static int fill_contact(struct pcontact_info* ci, struct sip_msg* m, tm_cell_t * ci->received_host.s = srcip; ci->received_port = req->rcv.src_port; ci->received_proto = req->rcv.proto; + + pkg_free(req_msg.buf); } else { LM_ERR("Unknown first line type: %d\n", m->first_line.type); @@ -1033,10 +1041,19 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // https://tools.ietf.org/html/rfc3261#section-18 // for Reply and TCP sends from P-CSCF server port, for Reply and UDP sends from P-CSCF client port - src_port = dst_proto == PROTO_TCP ? s->port_ps : s->port_pc; + // src_port = dst_proto == PROTO_TCP ? s->port_ps : s->port_pc; // for Reply and TCP sends to UE client port, for Reply and UDP sends to UE server port - dst_port = dst_proto == PROTO_TCP ? s->port_uc : s->port_us; + // dst_port = dst_proto == PROTO_TCP ? s->port_uc : s->port_us; + + // From P-CSCF client port + src_port = s->port_pc; + + if (vb && ((vb->port == s->port_uc) || (vb->port == s->port_us))) { + dst_port = vb->port; + } else { + dst_port = s->port_us; + } // Check send socket struct socket_info * client_sock = grep_sock_info(via_host.af == AF_INET ? &ipsec_listen_addr : &ipsec_listen_addr6, src_port, dst_proto); @@ -1051,8 +1068,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) } else { if (strstr(m->dst_uri.s, ";transport=tcp") != NULL) { dst_proto = PROTO_TCP; - } else if (strstr( - m->dst_uri.s, ";transport=tls") != NULL) { + } else if (strstr(m->dst_uri.s, ";transport=tls") != NULL) { dst_proto = PROTO_TLS; } else { dst_proto = m->rcv.proto; From 8b62618ca11a379eed6c4a5ec6cfc3518bb402a4 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Fri, 9 Dec 2022 15:05:24 +0100 Subject: [PATCH 25/26] For SIP reply send via request received port when TCP --- src/modules/ims_ipsec_pcscf/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index c4c26dc30a0..93e74867d60 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -1047,7 +1047,7 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // dst_port = dst_proto == PROTO_TCP ? s->port_uc : s->port_us; // From P-CSCF client port - src_port = s->port_pc; + src_port = dst_proto == PROTO_TCP ? req->rcv.dst_port : s->port_pc; if (vb && ((vb->port == s->port_uc) || (vb->port == s->port_us))) { dst_port = vb->port; From 9a0e3df6df3775d59a9aaea887aa8e33c82b97e9 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Mon, 12 Dec 2022 13:23:30 +0100 Subject: [PATCH 26/26] Set destination port same as received source port in request --- src/modules/ims_ipsec_pcscf/cmd.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index 93e74867d60..f920ab166f7 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -1046,13 +1046,17 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // for Reply and TCP sends to UE client port, for Reply and UDP sends to UE server port // dst_port = dst_proto == PROTO_TCP ? s->port_uc : s->port_us; - // From P-CSCF client port - src_port = dst_proto == PROTO_TCP ? req->rcv.dst_port : s->port_pc; - - if (vb && ((vb->port == s->port_uc) || (vb->port == s->port_us))) { - dst_port = vb->port; + // From Reply and TCP send via the same ports Request was recevied. + if (dst_proto == PROTO_TCP) { + src_port = req->rcv.dst_port; + dst_port = req->rcv.src_port; } else { - dst_port = s->port_us; + src_port = s->port_pc; + if (vb && ((vb->port == s->port_uc) || (vb->port == s->port_us))) { + dst_port = vb->port; + } else { + dst_port = s->port_us; + } } // Check send socket