mirror of https://github.com/sipwise/kamailio.git
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.
290 lines
9.3 KiB
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 */
|