From 41c26235b597e258a7256c9ff5b2c2064b80238c Mon Sep 17 00:00:00 2001 From: Fabricio Santolin da Silva Date: Thu, 24 Feb 2022 17:19:10 +0100 Subject: [PATCH] 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 --- debian/patches/series | 3 + .../pv_headers-fix-build-warning.patch | 33 ++ ...headers-remove_specific_header_value.patch | 289 ++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 debian/patches/sipwise/pv_headers-fix-build-warning.patch create mode 100644 debian/patches/upstream/pv-headers-remove_specific_header_value.patch diff --git a/debian/patches/series b/debian/patches/series index b77fbb2d6..7f620734d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -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 ### + diff --git a/debian/patches/sipwise/pv_headers-fix-build-warning.patch b/debian/patches/sipwise/pv_headers-fix-build-warning.patch new file mode 100644 index 000000000..af5659c0a --- /dev/null +++ b/debian/patches/sipwise/pv_headers-fix-build-warning.patch @@ -0,0 +1,33 @@ +From: Victor Seva +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); diff --git a/debian/patches/upstream/pv-headers-remove_specific_header_value.patch b/debian/patches/upstream/pv-headers-remove_specific_header_value.patch new file mode 100644 index 000000000..db9892885 --- /dev/null +++ b/debian/patches/upstream/pv-headers-remove_specific_header_value.patch @@ -0,0 +1,289 @@ +From 7a3f71e7ce6b63fe1c32853c30d785bc9c1f2236 Mon Sep 17 00:00:00 2001 +From: Fabricio Santolin da Silva + +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 @@ + +
+ +- \ ++ + + Functions +
+@@ -128,4 +128,37 @@ + pvh_collect_headers() or with auto_msg parameter enabled. + +
++
++ ++ <function moreinfo="none">pvh_value_exists(hname, hparameter)</function> ++ ++ ++ Checks if the parameter hparameter is present in the header hname from XAVP. ++ ++ ++ This function can be used from ANY_ROUTE but only after ++ pvh_collect_headers() have been called or with auto_msg parameter enabled. ++ +
++
++ ++ <function moreinfo="none">pvh_remove_header_param(hname, hparameter)</function> ++ ++ ++ Removes an existing parameter hparameter in the header hname from the XAVP. ++ ++ ++ If there are multiple headers, only the one containing the parameter will be modified. ++ ++ ++ The parameter can be located in any position (begining, middle or end) of the list of parameters. ++ ++ ++ If the parameter is the only one present, the header will be removed. ++ ++ ++ This function can be used from ANY_ROUTE but only after ++ pvh_collect_headers() have been called or with auto_msg parameter enabled. ++ ++
++
+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 @@ + vseva@sipwise.com + Sipwise GmbH + ++ ++ Fabricio ++ Santolin da Silva ++ fabricio.santolin-da-silva@al-enterprise.com ++ Alcatel-Lucent Enterprise ++ + + + 2018 +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 */