TT#159750 Add support to remove a specific value from a header

Previously, to remove a parameter from a header it was needed to create a complex method on the configuration file for each header/parameter. This modification moves this complexity to the 'pv_headers' module.

Two new functions:
  * pvh_header_param_exists
  * pvh_remove_header_param

Both functions take as parameters the name of the header and the name of the parameter.

It returns '-1' if the combination header/parameter:
  - is not found (pvh_header_param_exists)
  - couldn't be removed (pvh_remove_header_param).

Examples (proxy configuration):

if (pvh_header_param_exists("Supported", "100rel"))
{
  // "100rel" is present on the "Supported" header
}

if (pvh_remove_header_param("Supported", "100rel"))
{
  // "100rel" removed from header "Supported"
}

Change-Id: I2a95bcb54bf21d64cbf2c6f894b76e9f3cc7bdbc
mr11.0
Fabricio Santolin da Silva 4 years ago committed by Victor Seva
parent 239867b6b2
commit 41c26235b5

@ -37,6 +37,7 @@ upstream/tmx-use-trimmed-call-id-value-for-hashing.patch
upstream/topos_redis-contact-on-A-side-is-never-updated-on-di.patch
upstream/db_redis-clean-previous-connection-before-trying-to-.patch
upstream/pv-headers-ignore-skip-header-config-on-clone_branch.patch
upstream/pv-headers-remove_specific_header_value.patch
# https://github.com/kamailio/kamailio/pull/979
# collides with our changes to pua_dialoginfo
sipwise/Revert-pua_dialoginfo-disable-publish-notifications-.patch
@ -68,6 +69,7 @@ sipwise/db_redis_sscan_fix_empty_key.patch
sipwise/kamctl-TMPDIR-config.patch
### active development
sipwise/lcr-stopper_mode-parameter.patch
sipwise/pv_headers-fix-build-warning.patch
#
### Don't just put stuff in any order
### use gbp pq import/export tooling to help maintain patches
@ -85,3 +87,4 @@ sipwise/lcr-stopper_mode-parameter.patch
## git checkout -- debian/
### git commit + git-review as usual
###

@ -0,0 +1,33 @@
From: Victor Seva <vseva@sipwise.com>
Date: Tue, 12 Apr 2022 13:36:34 +0200
Subject: pv_headers: fix build warning
pvh_func.c:392:35: warning: division 'sizeof (char *) / sizeof (char)'
pvh_func.c:407:66: warning: division 'sizeof (char *) / sizeof (char)'
---
src/modules/pv_headers/pvh_func.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/modules/pv_headers/pvh_func.c b/src/modules/pv_headers/pvh_func.c
index 4ca72d2..c2a3f98 100644
--- a/src/modules/pv_headers/pvh_func.c
+++ b/src/modules/pv_headers/pvh_func.c
@@ -389,8 +389,7 @@ int pvh_remove_header_param(struct sip_msg *msg, int idx, str *hname, str *eleme
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;
+ int maxSize = elements->len;
if (result == NULL || t == NULL)
{
@@ -404,7 +403,7 @@ int pvh_remove_header_param(struct sip_msg *msg, int idx, str *hname, str *eleme
token = strtok_r(t, ", ", &next_token);
while(token)
{
- int notTarget = strncmp(token, toRemove->s, sizeof(toRemove->s)/sizeof(char));
+ int notTarget = strncmp(token, toRemove->s, toRemove->len);
if (notTarget)
{
int n = snprintf(result + offset, maxSize - offset, "%s", token);

@ -0,0 +1,289 @@
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 */
Loading…
Cancel
Save