You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/debian/patches/upstream/pv-headers-remove_specific_...

290 lines
9.3 KiB

From 7a3f71e7ce6b63fe1c32853c30d785bc9c1f2236 Mon Sep 17 00:00:00 2001
From: Fabricio Santolin da Silva
<fabricio.santolin-da-silva@al-enterprise.com>
Date: Wed, 30 Mar 2022 16:42:41 +0200
Subject: [PATCH] pv_headers: Add support to remove a specific value from a
header
- To be used with headers containing values separated by commas
- pvh_header_param_exists() check if the value is present to a given header
- pvh_remove_header_param() remove the value from the given header or the entire header if no other value is present
---
src/modules/pv_headers/doc/functions.xml | 35 +++++++-
src/modules/pv_headers/doc/pv_headers.xml | 6 ++
src/modules/pv_headers/pv_headers.c | 61 ++++++++++++++
src/modules/pv_headers/pvh_func.c | 97 +++++++++++++++++++++++
src/modules/pv_headers/pvh_func.h | 2 +
5 files changed, 200 insertions(+), 1 deletion(-)
diff --git a/src/modules/pv_headers/doc/functions.xml b/src/modules/pv_headers/doc/functions.xml
index ef7f133779..e0d38d47ea 100644
--- a/src/modules/pv_headers/doc/functions.xml
+++ b/src/modules/pv_headers/doc/functions.xml
@@ -11,7 +11,7 @@
<section id="pv_headers.funtions" xmlns:xi="http://www.w3.org/2001/XInclude">
<sectioninfo>
- </sectioninfo>\
+ </sectioninfo>
<title>Functions</title>
<section id="pv_headers.f.pvh_collect_headers">
@@ -128,4 +128,37 @@
pvh_collect_headers()</link> or with <quote>auto_msg</quote> parameter enabled.
</para>
</section>
+ <section id="pv_headers.f.pvh_header_param_exists">
+ <title>
+ <function moreinfo="none">pvh_value_exists(hname, hparameter)</function>
+ </title>
+ <para>
+ Checks if the parameter <quote>hparameter</quote> is present in the header <quote>hname</quote> from XAVP.
+ </para>
+ <para>
+ This function can be used from ANY_ROUTE but only after <link linked="pv_headers.f.pvh_collect_headers">
+ pvh_collect_headers()</link> have been called or with <quote>auto_msg</quote> parameter enabled.
+ </para>
</section>
+ <section id="pv_headers.f.pvh_remove_header_param">
+ <title>
+ <function moreinfo="none">pvh_remove_header_param(hname, hparameter)</function>
+ </title>
+ <para>
+ Removes an existing parameter <quote>hparameter</quote> in the header <quote>hname</quote> from the XAVP.
+ </para>
+ <para>
+ If there are multiple headers, only the one containing the parameter will be modified.
+ </para>
+ <para>
+ The parameter can be located in any position (begining, middle or end) of the list of parameters.
+ </para>
+ <para>
+ If the parameter is the only one present, the header will be removed.
+ </para>
+ <para>
+ This function can be used from ANY_ROUTE but only after <link linked="pv_headers.f.pvh_collect_headers">
+ pvh_collect_headers()</link> have been called or with <quote>auto_msg</quote> parameter enabled.
+ </para>
+ </section>
+</section>
diff --git a/src/modules/pv_headers/doc/pv_headers.xml b/src/modules/pv_headers/doc/pv_headers.xml
index a5211b9288..47d40e1ae9 100644
--- a/src/modules/pv_headers/doc/pv_headers.xml
+++ b/src/modules/pv_headers/doc/pv_headers.xml
@@ -26,6 +26,12 @@
<email>vseva@sipwise.com</email>
<affiliation><orgname>Sipwise GmbH</orgname></affiliation>
</editor>
+ <editor>
+ <firstname>Fabricio</firstname>
+ <surname>Santolin da Silva</surname>
+ <email>fabricio.santolin-da-silva@al-enterprise.com</email>
+ <affiliation><orgname>Alcatel-Lucent Enterprise</orgname></affiliation>
+ </editor>
</authorgroup>
<copyright>
<year>2018</year>
diff --git a/src/modules/pv_headers/pv_headers.c b/src/modules/pv_headers/pv_headers.c
index 6dfac3d18b..be43bb29f4 100644
--- a/src/modules/pv_headers/pv_headers.c
+++ b/src/modules/pv_headers/pv_headers.c
@@ -205,6 +205,53 @@ static int w_pvh_remove_header(
return pvh_remove_header(msg, &hname, indx);
}
+static int w_pvh_header_param_exists(
+ struct sip_msg *msg, char *p1, char *p2)
+{
+ str hname = STR_NULL;
+ str value = STR_NULL;
+
+ if(fixup_get_svalue(msg, (gparam_p)p1, &hname) < 0)
+ return -1;
+
+ if(p2 && fixup_get_svalue(msg, (gparam_p)p2, &value) < 0)
+ return -1;
+
+ return pvh_header_param_exists(msg, &hname, &value);
+}
+
+static int w_pvh_remove_header_param(struct sip_msg *msg, char *p1, char *p2)
+{
+ int ret = -1;
+ int idx = 0;
+ str hname = STR_NULL;
+ str value = STR_NULL;
+ sr_xavp_t *avi=NULL;
+ char tt[header_name_size];
+ str br_xname = {tt, header_name_size};
+
+ if(fixup_get_svalue(msg, (gparam_p)p1, &hname) < 0)
+ return -1;
+
+ if(p2 && fixup_get_svalue(msg, (gparam_p)p2, &value) < 0)
+ return -1;
+
+ pvh_get_branch_xname(msg, &xavi_name, &br_xname);
+
+ avi = xavi_get_child(&br_xname, &hname);
+
+ while(avi)
+ {
+ if (avi->val.type == SR_XTYPE_STR && avi->val.v.s.s != NULL && _strnstr(avi->val.v.s.s, value.s, avi->val.v.s.len) != NULL) {
+ ret = pvh_remove_header_param(msg, idx, &hname, &avi->val.v.s, &value) && ret;
+ }
+ idx++;
+ avi = xavi_get_next(avi);
+ }
+
+ return ret;
+}
+
/* clang-format off */
static cmd_export_t cmds[] = {
{"pvh_collect_headers", (cmd_function)w_pvh_collect_headers, 0, 0, 0,
@@ -225,6 +272,10 @@ static cmd_export_t cmds[] = {
fixup_spve_null, fixup_free_spve_null, ANY_ROUTE},
{"pvh_remove_header", (cmd_function)w_pvh_remove_header, 2,
fixup_spve_spve, fixup_free_spve_spve, ANY_ROUTE},
+ {"pvh_header_param_exists", (cmd_function)w_pvh_header_param_exists, 2,
+ fixup_spve_spve, fixup_free_spve_spve, ANY_ROUTE},
+ {"pvh_remove_header_param", (cmd_function)w_pvh_remove_header_param, 2,
+ fixup_spve_spve, fixup_free_spve_spve, ANY_ROUTE},
{0, 0, 0, 0, 0, 0}
};
@@ -537,6 +588,16 @@ static sr_kemi_t pvh_kemi_exports[] = {
{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE}
},
+ { str_init("pv_headers"), str_init("pvh_header_param_exists"),
+ SR_KEMIP_INT, pvh_header_param_exists,
+ { SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
+ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE}
+ },
+ { str_init("pv_headers"), str_init("pvh_remove_header_param"),
+ SR_KEMIP_INT, pvh_remove_header_param,
+ { SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
+ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE}
+ },
{{0, 0}, {0, 0}, 0, NULL, {0, 0, 0, 0, 0, 0}}
};
/* clang-format on */
diff --git a/src/modules/pv_headers/pvh_func.c b/src/modules/pv_headers/pvh_func.c
index 01a7d3d211..4ca72d217d 100644
--- a/src/modules/pv_headers/pvh_func.c
+++ b/src/modules/pv_headers/pvh_func.c
@@ -357,3 +357,100 @@ int pvh_remove_header(struct sip_msg *msg, str *hname, int indx)
return 1;
}
+
+int pvh_header_param_exists(struct sip_msg *msg, str *hname, str *hvalue)
+{
+ sr_xavp_t *avi=NULL;
+ char head_name[header_name_size];
+ str br_xname = {head_name, header_name_size};
+
+ avi = xavi_get(&xavi_name,NULL);
+ pvh_get_branch_xname(msg, &xavi_name, &br_xname);
+
+ avi = xavi_get_child(&br_xname, hname);
+
+ while(avi)
+ {
+ if (avi->val.type == SR_XTYPE_STR && avi->val.v.s.s != NULL && _strnstr(avi->val.v.s.s, hvalue->s, avi->val.v.s.len) != NULL)
+ {
+ return 1;
+ }
+ avi = xavi_get_next(avi);
+ }
+
+ return -1;
+}
+
+int pvh_remove_header_param(struct sip_msg *msg, int idx, str *hname, str *elements, str *toRemove)
+{
+ int offset = 0;
+ int ret = -1;
+ char *next_token;
+ char *token;
+ char *result = (char*)pkg_malloc(elements->len - toRemove->len);
+ char *t = (char*)pkg_malloc(elements->len);
+ int maxSize = sizeof(elements->s)/sizeof(char);
+ maxSize = maxSize < elements->len?elements->len:maxSize;
+
+ if (result == NULL || t == NULL)
+ {
+ PKG_MEM_ERROR;
+ goto clean;
+ }
+
+ snprintf(result, elements->len - toRemove->len, "%*s", elements->len - toRemove->len, "");
+ snprintf(t, elements->len+1, "%s", elements->s);
+
+ token = strtok_r(t, ", ", &next_token);
+ while(token)
+ {
+ int notTarget = strncmp(token, toRemove->s, sizeof(toRemove->s)/sizeof(char));
+ if (notTarget)
+ {
+ int n = snprintf(result + offset, maxSize - offset, "%s", token);
+ if (n < 0 || n >= maxSize - offset)
+ {
+ break;
+ }
+ offset += n;
+ }
+ token = strtok_r(NULL, ", ", &next_token);
+ if (token && notTarget && maxSize - offset - toRemove->len > 2)
+ {
+ int n = snprintf(result + offset, maxSize - offset, ", ");
+ if (n < 0 || n >= maxSize - offset)
+ {
+ break;
+ }
+ offset += n;
+ }
+ }
+
+ if (elements->len-toRemove->len > 0)
+ {
+ snprintf(elements->s, elements->len, "%*s", elements->len-toRemove->len, "");
+ snprintf(elements->s, (strlen(result)%elements->len)+1, "%s", result);
+ elements->len = strlen(result);
+ ret = 1;
+ }
+ else
+ {
+ ret = pvh_remove_header(msg, hname, idx);
+ }
+
+clean:
+
+ if(t != NULL)
+ {
+ pkg_free(t);
+ t = NULL;
+ }
+
+ if(result != NULL)
+ {
+ pkg_free(result);
+ result = NULL;
+ }
+
+ return ret;
+}
diff --git a/src/modules/pv_headers/pvh_func.h b/src/modules/pv_headers/pvh_func.h
index 6aaf5aa9f5..a4e0bfad3e 100644
--- a/src/modules/pv_headers/pvh_func.h
+++ b/src/modules/pv_headers/pvh_func.h
@@ -38,5 +38,7 @@ int pvh_check_header(struct sip_msg *msg, str *hname);
int pvh_append_header(struct sip_msg *msg, str *hname, str *hvalue);
int pvh_modify_header(struct sip_msg *msg, str *hname, str *hvalue, int indx);
int pvh_remove_header(struct sip_msg *msg, str *hname, int indx);
+int pvh_header_param_exists(struct sip_msg *msg, str *hname, str *hvalue);
+int pvh_remove_header_param(struct sip_msg *msg, int idx, str *hname, str *elements, str *toRemove);
#endif /* PV_FUNC_H */