Răsfoiți Sursa

ims_ipsec_pcscf: new 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.
Supreeth Herle 1 an în urmă
părinte
comite
279454ff8d

+ 63 - 0
src/modules/ims_ipsec_pcscf/cmd.c

@@ -1097,6 +1097,69 @@ cleanup:
 	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) {
+		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) {

+ 2 - 0
src/modules/ims_ipsec_pcscf/cmd.h

@@ -69,5 +69,7 @@ int ipsec_destroy(struct sip_msg *m, udomain_t *d, str *uri);
 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 */

+ 74 - 0
src/modules/ims_ipsec_pcscf/ims_ipsec_pcscf_mod.c

@@ -58,12 +58,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 *_aor);
+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);
+static int unregister2_fixup(void **param, int param_no);
 
 extern int bind_ipsec_pcscf(usrloc_api_t *api);
 
@@ -87,6 +90,7 @@ static cmd_export_t cmds[] = {
 		0, REQUEST_ROUTE | ONREPLY_ROUTE },
 	{"ipsec_destroy", (cmd_function)w_destroy, 2, unregister_fixup,
 		0, ANY_ROUTE },
+	{"ipsec_destroy_by_contact", (cmd_function)w_destroy_by_contact, 4, unregister2_fixup, 0, ANY_ROUTE},
 	{"bind_ims_ipsec_pcscf", (cmd_function)bind_ipsec_pcscf, 1, 0,
 		0, 0},
 	{0, 0, 0, 0, 0, 0}
@@ -465,6 +469,32 @@ static int unregister_fixup(void **param, int param_no)
 	return E_CFG;
 }
 
+static int unregister2_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
@@ -500,3 +530,47 @@ static int w_destroy(struct sip_msg *_m, char *_d, char *_aor)
 	}
 	return ipsec_destroy(_m, (udomain_t *)_d, NULL);
 }
+
+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);
+}