diff --git a/net/kamailio/Makefile b/net/kamailio/Makefile index 4cff613..070f7b7 100644 --- a/net/kamailio/Makefile +++ b/net/kamailio/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=kamailio PKG_VERSION:=5.7.2 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL:=https://www.kamailio.org/pub/kamailio/$(PKG_VERSION)/src PKG_SOURCE:=kamailio-$(PKG_VERSION)_src.tar.gz @@ -521,7 +521,7 @@ $(eval $(call BuildKamailioModule,db_text,Text DB-backend,,,dbtext/kamailio)) $(eval $(call BuildKamailioModule,db_unixodbc,UnixODBC DB-backend,,+unixodbc)) $(eval $(call BuildKamailioModule,debugger,Interactive config file debugger,,)) $(eval $(call BuildKamailioModule,dialog,Dialog support,,+kamailio-mod-rr +kamailio-mod-tm)) -$(eval $(call BuildKamailioModule,dialplan,Dialplan management,,+libpcre)) +$(eval $(call BuildKamailioModule,dialplan,Dialplan management,,+libpcre2)) $(eval $(call BuildKamailioModule,dispatcher,Dispatcher,,)) $(eval $(call BuildKamailioModule,diversion,Diversion header insertion,,)) $(eval $(call BuildKamailioModule,dlgs,Track active calls in stateless mode,,)) @@ -562,7 +562,7 @@ $(eval $(call BuildKamailioModule,jsonrpcs,JSONRPC server over HTTP,,+libevent2) $(eval $(call BuildKamailioModule,keepalive,SIP keepalive monitoring,,+kamailio-mod-tm,,)) $(eval $(call BuildKamailioModule,kemix,KEMI extensions,,,)) $(eval $(call BuildKamailioModule,kex,Core extensions,,)) -$(eval $(call BuildKamailioModule,lcr,Least Cost Routing,,+kamailio-mod-tm +libpcre)) +$(eval $(call BuildKamailioModule,lcr,Least Cost Routing,,+kamailio-mod-tm +libpcre2)) $(eval $(call BuildKamailioModule,ldap,LDAP connector,,+libopenldap)) $(eval $(call BuildKamailioModule,log_custom,Logging to custom backends,,)) $(eval $(call BuildKamailioModule,lost,HELD and LOST routing,,+kamailio-mod-http-client,)) @@ -610,7 +610,7 @@ $(eval $(call BuildKamailioModule,pv,Pseudo-Variables,,)) $(eval $(call BuildKamailioModule,pv_headers,Flexible SIP header management,,)) $(eval $(call BuildKamailioModule,qos,QoS control,,+kamailio-mod-dialog)) $(eval $(call BuildKamailioModule,ratelimit,Traffic shapping,,)) -$(eval $(call BuildKamailioModule,regex,Regular Expression,,+libpcre)) +$(eval $(call BuildKamailioModule,regex,Regular Expression,,+libpcre2)) $(eval $(call BuildKamailioModule,registrar,SIP Registrar,,+kamailio-mod-usrloc)) $(eval $(call BuildKamailioModule,rls,Resource List Server,,+kamailio-mod-presence +kamailio-mod-pua +kamailio-mod-tm,)) $(eval $(call BuildKamailioModule,rr,Record-Route and Route,,)) diff --git a/net/kamailio/patches/010-dialplan-clang-format-for-coherent-indentation-and-c.patch b/net/kamailio/patches/010-dialplan-clang-format-for-coherent-indentation-and-c.patch new file mode 100644 index 0000000..3fa8a95 --- /dev/null +++ b/net/kamailio/patches/010-dialplan-clang-format-for-coherent-indentation-and-c.patch @@ -0,0 +1,2821 @@ +From 01d0d1de2c82db189c288a157932f4a3ba98970a Mon Sep 17 00:00:00 2001 +From: Victor Seva +Date: Wed, 17 May 2023 16:36:04 +0200 +Subject: [PATCH] dialplan: clang-format for coherent indentation and coding + style + +--- + src/modules/dialplan/dialplan.c | 522 +++++++++++++++----------------- + src/modules/dialplan/dialplan.h | 89 +++--- + src/modules/dialplan/dp_db.c | 364 +++++++++++----------- + src/modules/dialplan/dp_db.h | 38 +-- + src/modules/dialplan/dp_repl.c | 387 +++++++++++------------ + 5 files changed, 701 insertions(+), 699 deletions(-) + +--- a/src/modules/dialplan/dialplan.c ++++ b/src/modules/dialplan/dialplan.c +@@ -35,8 +35,6 @@ + */ + + +- +- + #include + #include + #include +@@ -67,18 +65,19 @@ static void mod_destroy(); + + static int dialplan_init_rpc(void); + +-static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2); +-static int dp_trans_fixup(void ** param, int param_no); +-static int dp_reload_f(struct sip_msg* msg); +-static int w_dp_replace(sip_msg_t* msg, char* pid, char* psrc, char* pdst); +-static int w_dp_match(sip_msg_t* msg, char* pid, char* psrc); +- +-static int ki_dp_translate(sip_msg_t* msg, int id, str *input, str *output); +-static int ki_dp_translate_id(sip_msg_t* msg, int id); +-static int ki_dp_translate_vars(sip_msg_t* msg, int id, str *input, str *output); ++static int dp_translate_f(struct sip_msg *msg, char *str1, char *str2); ++static int dp_trans_fixup(void **param, int param_no); ++static int dp_reload_f(struct sip_msg *msg); ++static int w_dp_replace(sip_msg_t *msg, char *pid, char *psrc, char *pdst); ++static int w_dp_match(sip_msg_t *msg, char *pid, char *psrc); ++ ++static int ki_dp_translate(sip_msg_t *msg, int id, str *input, str *output); ++static int ki_dp_translate_id(sip_msg_t *msg, int id); ++static int ki_dp_translate_vars( ++ sip_msg_t *msg, int id, str *input, str *output); + +-int dp_replace_fixup(void** param, int param_no); +-int dp_replace_fixup_free(void** param, int param_no); ++int dp_replace_fixup(void **param, int param_no); ++int dp_replace_fixup_free(void **param, int param_no); + + str dp_attr_pvar_s = STR_NULL; + pv_spec_t *dp_attr_pvar = NULL; +@@ -93,76 +92,69 @@ int dp_reload_delta = 5; + + static time_t *dp_rpc_reload_time = NULL; + +-static param_export_t mod_params[]={ +- { "db_url", PARAM_STR, &dp_db_url }, +- { "table_name", PARAM_STR, &dp_table_name }, +- { "dpid_col", PARAM_STR, &dpid_column }, +- { "pr_col", PARAM_STR, &pr_column }, +- { "match_op_col", PARAM_STR, &match_op_column }, +- { "match_exp_col", PARAM_STR, &match_exp_column }, +- { "match_len_col", PARAM_STR, &match_len_column }, +- { "subst_exp_col", PARAM_STR, &subst_exp_column }, +- { "repl_exp_col", PARAM_STR, &repl_exp_column }, +- { "attrs_col", PARAM_STR, &attrs_column }, +- { "attrs_pvar", PARAM_STR, &dp_attr_pvar_s }, +- { "fetch_rows", PARAM_INT, &dp_fetch_rows }, +- { "match_dynamic", PARAM_INT, &dp_match_dynamic }, +- { "append_branch", PARAM_INT, &dp_append_branch }, +- { "reload_delta", PARAM_INT, &dp_reload_delta }, +- {0,0,0} +-}; +- +-static cmd_export_t cmds[]={ +- {"dp_translate",(cmd_function)dp_translate_f, 2, dp_trans_fixup, 0, +- ANY_ROUTE}, +- {"dp_translate",(cmd_function)dp_translate_f, 1, dp_trans_fixup, 0, +- ANY_ROUTE}, +- {"dp_reload",(cmd_function)dp_reload_f, 0, 0, 0, +- ANY_ROUTE}, +- {"dp_match",(cmd_function)w_dp_match, 2, fixup_igp_spve, +- fixup_free_igp_spve, ANY_ROUTE}, +- {"dp_replace",(cmd_function)w_dp_replace, 3, dp_replace_fixup, +- dp_replace_fixup_free, ANY_ROUTE}, +- {0,0,0,0,0,0} +-}; +- +-struct module_exports exports= { +- "dialplan", /* module's name */ +- DEFAULT_DLFLAGS, /* dlopen flags */ +- cmds, /* exported functions */ +- mod_params, /* param exports */ +- 0, /* exported RPC functions */ +- 0, /* exported pseudo-variables */ +- 0, /* reply processing function */ +- mod_init, /* module initialization function */ +- child_init, /* per-child init function */ +- mod_destroy /* module destroy function */ ++static param_export_t mod_params[] = {{"db_url", PARAM_STR, &dp_db_url}, ++ {"table_name", PARAM_STR, &dp_table_name}, ++ {"dpid_col", PARAM_STR, &dpid_column}, ++ {"pr_col", PARAM_STR, &pr_column}, ++ {"match_op_col", PARAM_STR, &match_op_column}, ++ {"match_exp_col", PARAM_STR, &match_exp_column}, ++ {"match_len_col", PARAM_STR, &match_len_column}, ++ {"subst_exp_col", PARAM_STR, &subst_exp_column}, ++ {"repl_exp_col", PARAM_STR, &repl_exp_column}, ++ {"attrs_col", PARAM_STR, &attrs_column}, ++ {"attrs_pvar", PARAM_STR, &dp_attr_pvar_s}, ++ {"fetch_rows", PARAM_INT, &dp_fetch_rows}, ++ {"match_dynamic", PARAM_INT, &dp_match_dynamic}, ++ {"append_branch", PARAM_INT, &dp_append_branch}, ++ {"reload_delta", PARAM_INT, &dp_reload_delta}, {0, 0, 0}}; ++ ++static cmd_export_t cmds[] = {{"dp_translate", (cmd_function)dp_translate_f, 2, ++ dp_trans_fixup, 0, ANY_ROUTE}, ++ {"dp_translate", (cmd_function)dp_translate_f, 1, dp_trans_fixup, 0, ++ ANY_ROUTE}, ++ {"dp_reload", (cmd_function)dp_reload_f, 0, 0, 0, ANY_ROUTE}, ++ {"dp_match", (cmd_function)w_dp_match, 2, fixup_igp_spve, ++ fixup_free_igp_spve, ANY_ROUTE}, ++ {"dp_replace", (cmd_function)w_dp_replace, 3, dp_replace_fixup, ++ dp_replace_fixup_free, ANY_ROUTE}, ++ {0, 0, 0, 0, 0, 0}}; ++ ++struct module_exports exports = { ++ "dialplan", /* module's name */ ++ DEFAULT_DLFLAGS, /* dlopen flags */ ++ cmds, /* exported functions */ ++ mod_params, /* param exports */ ++ 0, /* exported RPC functions */ ++ 0, /* exported pseudo-variables */ ++ 0, /* reply processing function */ ++ mod_init, /* module initialization function */ ++ child_init, /* per-child init function */ ++ mod_destroy /* module destroy function */ + }; + + + static int mod_init(void) + { +- if(dialplan_init_rpc()!=0) +- { ++ if(dialplan_init_rpc() != 0) { + LM_ERR("failed to register RPC commands\n"); + return -1; + } + +- LM_DBG("db_url=%s/%d/%p\n", ZSW(dp_db_url.s), dp_db_url.len,dp_db_url.s); ++ LM_DBG("db_url=%s/%d/%p\n", ZSW(dp_db_url.s), dp_db_url.len, dp_db_url.s); + +- if(dp_attr_pvar_s.s && dp_attr_pvar_s.len>0) { ++ if(dp_attr_pvar_s.s && dp_attr_pvar_s.len > 0) { + dp_attr_pvar = pv_cache_get(&dp_attr_pvar_s); +- if( (dp_attr_pvar==NULL) || +- ((dp_attr_pvar->type != PVT_AVP) && +- (dp_attr_pvar->type != PVT_XAVP) && +- (dp_attr_pvar->type != PVT_SCRIPTVAR))) { ++ if((dp_attr_pvar == NULL) ++ || ((dp_attr_pvar->type != PVT_AVP) ++ && (dp_attr_pvar->type != PVT_XAVP) ++ && (dp_attr_pvar->type != PVT_SCRIPTVAR))) { + LM_ERR("invalid pvar name\n"); + return -1; + } + } + + dp_default_par2 = (dp_param_p)shm_malloc(sizeof(dp_param_t)); +- if(dp_default_par2 == NULL){ ++ if(dp_default_par2 == NULL) { + LM_ERR("no shm more memory\n"); + return -1; + } +@@ -171,22 +163,22 @@ static int mod_init(void) + /* emulate "$rU/$rU" as second parameter for dp_translate() */ + dp_default_param_s.len = strlen(dp_default_param_s.s); + dp_default_par2->v.sp[0] = pv_cache_get(&dp_default_param_s); +- if (dp_default_par2->v.sp[0]==NULL) { ++ if(dp_default_par2->v.sp[0] == NULL) { + LM_ERR("input pv is invalid\n"); + return -1; + } + + dp_default_param_s.len = strlen(dp_default_param_s.s); + dp_default_par2->v.sp[1] = pv_cache_get(&dp_default_param_s); +- if (dp_default_par2->v.sp[1]==NULL) { ++ if(dp_default_par2->v.sp[1] == NULL) { + LM_ERR("output pv is invalid\n"); + return -1; + } + +- if(dp_fetch_rows<=0) ++ if(dp_fetch_rows <= 0) + dp_fetch_rows = 1000; + +- if(dp_reload_delta<0) ++ if(dp_reload_delta < 0) + dp_reload_delta = 5; + + if(init_data() != 0) { +@@ -214,11 +206,11 @@ static int child_init(int rank) + static void mod_destroy(void) + { + /*destroy shared memory*/ +- if(dp_default_par2){ ++ if(dp_default_par2) { + shm_free(dp_default_par2); + dp_default_par2 = NULL; + } +- if(dp_rpc_reload_time!=NULL) { ++ if(dp_rpc_reload_time != NULL) { + shm_free(dp_rpc_reload_time); + dp_rpc_reload_time = 0; + } +@@ -226,20 +218,21 @@ static void mod_destroy(void) + } + + +-static int dp_get_ivalue(struct sip_msg* msg, dp_param_p dp, int *val) ++static int dp_get_ivalue(struct sip_msg *msg, dp_param_p dp, int *val) + { + pv_value_t value; + +- if(dp->type==DP_VAL_INT) { ++ if(dp->type == DP_VAL_INT) { + *val = dp->v.id; + LM_DBG("dpid is %d from constant argument\n", *val); + return 0; + } + +- LM_DBG("searching %d\n",dp->v.sp[0]->type); ++ LM_DBG("searching %d\n", dp->v.sp[0]->type); + +- if( pv_get_spec_value( msg, dp->v.sp[0], &value)!=0 +- || value.flags&(PV_VAL_NULL|PV_VAL_EMPTY) || !(value.flags&PV_VAL_INT)) { ++ if(pv_get_spec_value(msg, dp->v.sp[0], &value) != 0 ++ || value.flags & (PV_VAL_NULL | PV_VAL_EMPTY) ++ || !(value.flags & PV_VAL_INT)) { + LM_ERR("no AVP, XAVP or SCRIPTVAR found (error in scripts)\n"); + return -1; + } +@@ -249,14 +242,14 @@ static int dp_get_ivalue(struct sip_msg* + } + + +-static int dp_get_svalue(struct sip_msg * msg, pv_spec_t *spec, str* val) ++static int dp_get_svalue(struct sip_msg *msg, pv_spec_t *spec, str *val) + { + pv_value_t value; + + LM_DBG("searching %d \n", spec->type); + +- if ( pv_get_spec_value(msg,spec,&value)!=0 || value.flags&PV_VAL_NULL +- || value.flags&PV_VAL_EMPTY || !(value.flags&PV_VAL_STR)){ ++ if(pv_get_spec_value(msg, spec, &value) != 0 || value.flags & PV_VAL_NULL ++ || value.flags & PV_VAL_EMPTY || !(value.flags & PV_VAL_STR)) { + LM_ERR("no AVP, XAVP or SCRIPTVAR found (error in scripts)\n"); + return -1; + } +@@ -266,8 +259,8 @@ static int dp_get_svalue(struct sip_msg + } + + +-static int dp_update(struct sip_msg * msg, pv_spec_t * dest, +- str * repl, str * attrs) ++static int dp_update( ++ struct sip_msg *msg, pv_spec_t *dest, str *repl, str *attrs) + { + int no_change; + pv_value_t val; +@@ -275,16 +268,16 @@ static int dp_update(struct sip_msg * ms + memset(&val, 0, sizeof(pv_value_t)); + val.flags = PV_VAL_STR; + +- no_change = (dest==NULL) || (dest->type == PVT_NONE) +- || (!repl->s) || (!repl->len); ++ no_change = (dest == NULL) || (dest->type == PVT_NONE) || (!repl->s) ++ || (!repl->len); + +- if (no_change) ++ if(no_change) + goto set_attr_pvar; + + val.rs = *repl; + + if(dest->setf) { +- if(dest->setf(msg, &dest->pvp, (int)EQ_T, &val)<0) { ++ if(dest->setf(msg, &dest->pvp, (int)EQ_T, &val) < 0) { + LM_ERR("setting dst pseudo-variable failed\n"); + return -1; + } +@@ -292,7 +285,7 @@ static int dp_update(struct sip_msg * ms + LM_WARN("target variable is read only - skipping setting its value\n"); + } + +- if(dp_append_branch!=0) { ++ if(dp_append_branch != 0) { + if(is_route_type(FAILURE_ROUTE) + && (dest->type == PVT_RURI + || dest->type == PVT_RURI_USERNAME)) { +@@ -306,12 +299,11 @@ static int dp_update(struct sip_msg * ms + + set_attr_pvar: + +- if(dp_attr_pvar==NULL || attrs==NULL) ++ if(dp_attr_pvar == NULL || attrs == NULL) + return 0; + + val.rs = *attrs; +- if(dp_attr_pvar->setf(msg, &dp_attr_pvar->pvp, (int)EQ_T, &val)<0) +- { ++ if(dp_attr_pvar->setf(msg, &dp_attr_pvar->pvp, (int)EQ_T, &val) < 0) { + LM_ERR("setting attr pseudo-variable failed\n"); + return -1; + } +@@ -320,7 +312,7 @@ set_attr_pvar: + } + + +-static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2) ++static int dp_translate_f(struct sip_msg *msg, char *str1, char *str2) + { + int dpid; + str input, output; +@@ -332,59 +324,60 @@ static int dp_translate_f(struct sip_msg + return -1; + + /*verify first param's value*/ +- id_par = (dp_param_p) str1; +- if (dp_get_ivalue(msg, id_par, &dpid) != 0){ ++ id_par = (dp_param_p)str1; ++ if(dp_get_ivalue(msg, id_par, &dpid) != 0) { + LM_ERR("no dpid value\n"); + return -1; + } + +- if ((idp = select_dpid(dpid)) ==0 ){ ++ if((idp = select_dpid(dpid)) == 0) { + LM_DBG("no information available for dpid %i\n", dpid); + return -2; + } + +- repl_par = (str2!=NULL)? ((dp_param_p)str2):dp_default_par2; +- if (dp_get_svalue(msg, repl_par->v.sp[0], &input)!=0){ ++ repl_par = (str2 != NULL) ? ((dp_param_p)str2) : dp_default_par2; ++ if(dp_get_svalue(msg, repl_par->v.sp[0], &input) != 0) { + LM_ERR("invalid param 2\n"); + return -1; + } + + LM_DBG("input is %.*s\n", input.len, input.s); + +- outattrs = (!dp_attr_pvar)?NULL:&attrs; +- if (dp_translate_helper(msg, &input, &output, idp, outattrs)!=0) { ++ outattrs = (!dp_attr_pvar) ? NULL : &attrs; ++ if(dp_translate_helper(msg, &input, &output, idp, outattrs) != 0) { + LM_DBG("could not translate %.*s " +- "with dpid %i\n", input.len, input.s, idp->dp_id); ++ "with dpid %i\n", ++ input.len, input.s, idp->dp_id); + return -1; + } +- LM_DBG("input %.*s with dpid %i => output %.*s\n", +- input.len, input.s, idp->dp_id, output.len, output.s); ++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s, ++ idp->dp_id, output.len, output.s); + + /* set the output */ +- if (dp_update(msg, repl_par->v.sp[1], &output, outattrs) !=0){ ++ if(dp_update(msg, repl_par->v.sp[1], &output, outattrs) != 0) { + LM_ERR("cannot set the output\n"); + return -1; + } + + return 1; +- + } + +-#define verify_par_type(_par_no, _spec, _ret) \ +- do{\ +- if( ((_par_no == 1) \ +- && (_spec->type != PVT_AVP) && (_spec->type != PVT_XAVP) && \ +- (_spec->type!=PVT_SCRIPTVAR) )\ +- ||((_par_no == 2) \ +- && (_spec->type != PVT_AVP) && (_spec->type != PVT_XAVP) && \ +- (_spec->type!=PVT_SCRIPTVAR) \ +- && (_spec->type!=PVT_RURI) && (_spec->type!=PVT_RURI_USERNAME))){\ +- \ +- LM_ERR("Unsupported Parameter TYPE[%d]\n", _spec->type);\ +- _ret = E_UNSPEC; \ +- goto error; \ +- }\ +- }while(0); ++#define verify_par_type(_par_no, _spec, _ret) \ ++ do { \ ++ if(((_par_no == 1) && (_spec->type != PVT_AVP) \ ++ && (_spec->type != PVT_XAVP) \ ++ && (_spec->type != PVT_SCRIPTVAR)) \ ++ || ((_par_no == 2) && (_spec->type != PVT_AVP) \ ++ && (_spec->type != PVT_XAVP) \ ++ && (_spec->type != PVT_SCRIPTVAR) \ ++ && (_spec->type != PVT_RURI) \ ++ && (_spec->type != PVT_RURI_USERNAME))) { \ ++ \ ++ LM_ERR("Unsupported Parameter TYPE[%d]\n", _spec->type); \ ++ _ret = E_UNSPEC; \ ++ goto error; \ ++ } \ ++ } while(0); + + + /* first param: DPID: type: INT, AVP, XAVP, SVAR +@@ -392,19 +385,20 @@ static int dp_translate_f(struct sip_msg + * second param: DST type: RURI, RURI_USERNAME, AVP, XAVP, SVAR, N/A + * default value for the second param: $ru.user/$ru.user + */ +-static int dp_trans_fixup(void ** param, int param_no){ ++static int dp_trans_fixup(void **param, int param_no) ++{ + + int dpid; +- dp_param_p dp_par= NULL; +- char *p, *s=NULL; ++ dp_param_p dp_par = NULL; ++ char *p, *s = NULL; + str lstr; + int ret = E_INVALID_PARAMS; + +- if(param_no!=1 && param_no!=2) ++ if(param_no != 1 && param_no != 2) + return 0; + +- p = (char*)*param; +- if(!p || (*p == '\0')){ ++ p = (char *)*param; ++ if(!p || (*p == '\0')) { + LM_DBG("null param %i\n", param_no); + return E_CFG; + } +@@ -412,7 +406,7 @@ static int dp_trans_fixup(void ** param, + LM_DBG("param_no is %i\n", param_no); + + dp_par = (dp_param_p)pkg_malloc(sizeof(dp_param_t)); +- if(dp_par == NULL){ ++ if(dp_par == NULL) { + LM_ERR("no more pkg memory\n"); + return E_OUT_OF_MEM; + } +@@ -421,19 +415,21 @@ static int dp_trans_fixup(void ** param, + if(param_no == 1) { + if(*p != '$') { + dp_par->type = DP_VAL_INT; +- lstr.s = *param; lstr.len = strlen(*param); ++ lstr.s = *param; ++ lstr.len = strlen(*param); + if(str2sint(&lstr, &dpid) != 0) { +- LM_ERR("bad number <%s>\n",(char *)(*param)); ++ LM_ERR("bad number <%s>\n", (char *)(*param)); + ret = E_CFG; + goto error; + } + + dp_par->type = DP_VAL_INT; + dp_par->v.id = dpid; +- }else{ +- lstr.s = p; lstr.len = strlen(p); ++ } else { ++ lstr.s = p; ++ lstr.len = strlen(p); + dp_par->v.sp[0] = pv_cache_get(&lstr); +- if (dp_par->v.sp[0]==NULL) { ++ if(dp_par->v.sp[0] == NULL) { + goto error; + } + +@@ -442,30 +438,32 @@ static int dp_trans_fixup(void ** param, + } + } else { + +- if (((s = strchr(p, '/')) != 0) && (*(s+1)=='\0')) ++ if(((s = strchr(p, '/')) != 0) && (*(s + 1) == '\0')) + goto error; + +- if (s != 0) { +- *s = '\0'; s++; ++ if(s != 0) { ++ *s = '\0'; ++ s++; + } + +- lstr.s = p; lstr.len = strlen(p); ++ lstr.s = p; ++ lstr.len = strlen(p); + dp_par->v.sp[0] = pv_cache_get(&lstr); +- if(dp_par->v.sp[0]==NULL) { ++ if(dp_par->v.sp[0] == NULL) { + goto error; + } + +- if (s != 0) { +- lstr.s = s; lstr.len = strlen(s); ++ if(s != 0) { ++ lstr.s = s; ++ lstr.len = strlen(s); + dp_par->v.sp[1] = pv_cache_get(&lstr); +- if (dp_par->v.sp[1]==NULL) { ++ if(dp_par->v.sp[1] == NULL) { + goto error; + } + verify_par_type(param_no, dp_par->v.sp[1], ret); + } + + dp_par->type = DP_VAL_SPEC; +- + } + + *param = (void *)dp_par; +@@ -474,13 +472,14 @@ static int dp_trans_fixup(void ** param, + + error: + LM_ERR("failed to parse param %i\n", param_no); +- if(dp_par) pkg_free(dp_par); ++ if(dp_par) ++ pkg_free(dp_par); + + return ret; + } + +-static int dp_replace_helper(sip_msg_t *msg, int dpid, str *input, +- pv_spec_t *pvd) ++static int dp_replace_helper( ++ sip_msg_t *msg, int dpid, str *input, pv_spec_t *pvd) + { + dpl_id_p idp; + str tmp = STR_NULL; +@@ -488,25 +487,26 @@ static int dp_replace_helper(sip_msg_t * + str *output = NULL; + str *outattrs = NULL; + +- if ((idp = select_dpid(dpid)) ==0) { ++ if((idp = select_dpid(dpid)) == 0) { + LM_DBG("no information available for dpid %i\n", dpid); + return -2; + } + +- outattrs = (!dp_attr_pvar)?NULL:&attrs; +- output = (!pvd)?NULL:&tmp; +- if (dp_translate_helper(msg, input, output, idp, outattrs)!=0) { ++ outattrs = (!dp_attr_pvar) ? NULL : &attrs; ++ output = (!pvd) ? NULL : &tmp; ++ if(dp_translate_helper(msg, input, output, idp, outattrs) != 0) { + LM_DBG("could not translate %.*s " +- "with dpid %i\n", input->len, input->s, idp->dp_id); ++ "with dpid %i\n", ++ input->len, input->s, idp->dp_id); + return -1; + } +- if (output) { +- LM_DBG("input %.*s with dpid %i => output %.*s\n", +- input->len, input->s, idp->dp_id, output->len, output->s); ++ if(output) { ++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input->len, input->s, ++ idp->dp_id, output->len, output->s); + } + + /* set the output */ +- if (dp_update(msg, pvd, output, outattrs) !=0){ ++ if(dp_update(msg, pvd, output, outattrs) != 0) { + LM_ERR("cannot set the output\n"); + return -1; + } +@@ -514,31 +514,31 @@ static int dp_replace_helper(sip_msg_t * + return 1; + } + +-static int w_dp_replace(sip_msg_t* msg, char* pid, char* psrc, char* pdst) ++static int w_dp_replace(sip_msg_t *msg, char *pid, char *psrc, char *pdst) + { + int dpid = 1; + str src = STR_NULL; + pv_spec_t *pvd = NULL; + +- if(fixup_get_ivalue(msg, (gparam_t*)pid, &dpid)<0) { ++ if(fixup_get_ivalue(msg, (gparam_t *)pid, &dpid) < 0) { + LM_ERR("failed to get dialplan id value\n"); + return -1; + } +- if(fixup_get_svalue(msg, (gparam_t*)psrc, &src)<0) { ++ if(fixup_get_svalue(msg, (gparam_t *)psrc, &src) < 0) { + LM_ERR("failed to get src value\n"); + return -1; + } +- pvd = (pv_spec_t*)pdst; ++ pvd = (pv_spec_t *)pdst; + + return dp_replace_helper(msg, dpid, &src, pvd); + } + +-static int ki_dp_replace(sip_msg_t* msg, int dpid, str* src, str* dst) ++static int ki_dp_replace(sip_msg_t *msg, int dpid, str *src, str *dst) + { + pv_spec_t *pvd = NULL; + + pvd = pv_cache_get(dst); +- if(pvd==NULL) { ++ if(pvd == NULL) { + LM_ERR("cannot get pv spec for [%.*s]\n", dst->len, dst->s); + return -1; + } +@@ -546,16 +546,16 @@ static int ki_dp_replace(sip_msg_t* msg, + return dp_replace_helper(msg, dpid, src, pvd); + } + +-static int w_dp_match(sip_msg_t* msg, char* pid, char* psrc) ++static int w_dp_match(sip_msg_t *msg, char *pid, char *psrc) + { + int dpid = 1; + str src = STR_NULL; + +- if(fixup_get_ivalue(msg, (gparam_t*)pid, &dpid)<0) { ++ if(fixup_get_ivalue(msg, (gparam_t *)pid, &dpid) < 0) { + LM_ERR("failed to get dialplan id value\n"); + return -1; + } +- if(fixup_get_svalue(msg, (gparam_t*)psrc, &src)<0) { ++ if(fixup_get_svalue(msg, (gparam_t *)psrc, &src) < 0) { + LM_ERR("failed to get src value\n"); + return -1; + } +@@ -563,30 +563,30 @@ static int w_dp_match(sip_msg_t* msg, ch + return dp_replace_helper(msg, dpid, &src, NULL); + } + +-static int ki_dp_match(sip_msg_t* msg, int dpid, str* src) ++static int ki_dp_match(sip_msg_t *msg, int dpid, str *src) + { + return dp_replace_helper(msg, dpid, src, NULL); + } + +-int dp_replace_fixup(void** param, int param_no) ++int dp_replace_fixup(void **param, int param_no) + { +- if (param_no == 1) ++ if(param_no == 1) + return fixup_igp_null(param, param_no); +- else if (param_no == 2) ++ else if(param_no == 2) + return fixup_spve_all(param, param_no); +- else if (param_no == 3) ++ else if(param_no == 3) + return fixup_pvar_all(param, param_no); + return E_UNSPEC; + } + + +-int dp_replace_fixup_free(void** param, int param_no) ++int dp_replace_fixup_free(void **param, int param_no) + { +- if (param_no == 1) ++ if(param_no == 1) + return fixup_free_igp_null(param, param_no); +- else if (param_no == 2) ++ else if(param_no == 2) + return fixup_free_spve_all(param, param_no); +- else if (param_no == 3) ++ else if(param_no == 3) + return fixup_free_pvar_all(param, param_no); + return E_UNSPEC; + } +@@ -594,14 +594,14 @@ int dp_replace_fixup_free(void** param, + /** + * trigger reload of dialplan db records from config file + */ +-static int dp_reload_f(struct sip_msg* msg) ++static int dp_reload_f(struct sip_msg *msg) + { +- if (dp_connect_db() < 0) { ++ if(dp_connect_db() < 0) { + LM_ERR("failed to reload rules fron database (db connect)\n"); + return -1; + } + +- if(dp_load_db() != 0){ ++ if(dp_load_db() != 0) { + LM_ERR("failed to reload rules fron database (db load)\n"); + dp_disconnect_db(); + return -1; +@@ -614,35 +614,34 @@ static int dp_reload_f(struct sip_msg* m + } + + +-static const char* dialplan_rpc_reload_doc[2] = { +- "Reload dialplan table from database", +- 0 +-}; ++static const char *dialplan_rpc_reload_doc[2] = { ++ "Reload dialplan table from database", 0}; + + + /* + * RPC command to reload dialplan table + */ +-static void dialplan_rpc_reload(rpc_t* rpc, void* ctx) ++static void dialplan_rpc_reload(rpc_t *rpc, void *ctx) + { +- if(dp_rpc_reload_time==NULL) { ++ if(dp_rpc_reload_time == NULL) { + LM_ERR("not ready for reload\n"); + rpc->fault(ctx, 500, "Not ready for reload"); + return; + } +- if(*dp_rpc_reload_time!=0 && *dp_rpc_reload_time > time(NULL) - dp_reload_delta) { ++ if(*dp_rpc_reload_time != 0 ++ && *dp_rpc_reload_time > time(NULL) - dp_reload_delta) { + LM_ERR("ongoing reload\n"); + rpc->fault(ctx, 500, "ongoing reload"); + return; + } + *dp_rpc_reload_time = time(NULL); +- if (dp_connect_db() < 0) { ++ if(dp_connect_db() < 0) { + LM_ERR("failed to reload rules fron database (db connect)\n"); + rpc->fault(ctx, 500, "DB Connection Error"); + return; + } + +- if(dp_load_db() != 0){ ++ if(dp_load_db() != 0) { + LM_ERR("failed to reload rules fron database (db load)\n"); + dp_disconnect_db(); + rpc->fault(ctx, 500, "Dialplan Reload Failed"); +@@ -654,63 +653,55 @@ static void dialplan_rpc_reload(rpc_t* r + } + + +- +-static const char* dialplan_rpc_translate_doc[2] = { +- "Perform dialplan translation", +- 0 +-}; ++static const char *dialplan_rpc_translate_doc[2] = { ++ "Perform dialplan translation", 0}; + + + /* + * RPC command to perform dialplan translation + */ +-static void dialplan_rpc_translate(rpc_t* rpc, void* ctx) ++static void dialplan_rpc_translate(rpc_t *rpc, void *ctx) + { + dpl_id_p idp; + str input; + int dpid; +- str attrs = {"", 0}; ++ str attrs = {"", 0}; + str output = {0, 0}; +- void* th; ++ void *th; + +- if (rpc->scan(ctx, "dS", &dpid, &input) < 2) +- { ++ if(rpc->scan(ctx, "dS", &dpid, &input) < 2) { + rpc->fault(ctx, 500, "Invalid parameters"); + return; + } + +- if ((idp = select_dpid(dpid)) == 0 ){ ++ if((idp = select_dpid(dpid)) == 0) { + LM_ERR("no information available for dpid %i\n", dpid); + rpc->fault(ctx, 500, "Dialplan ID not matched"); + return; + } + +- if(input.s == NULL || input.len== 0) { ++ if(input.s == NULL || input.len == 0) { + LM_ERR("empty input parameter\n"); + rpc->fault(ctx, 500, "Empty input parameter"); + return; + } + +- LM_DBG("trying to translate %.*s with dpid %i\n", +- input.len, input.s, idp->dp_id); +- if (dp_translate_helper(NULL, &input, &output, idp, &attrs)!=0){ +- LM_DBG("could not translate %.*s with dpid %i\n", +- input.len, input.s, idp->dp_id); ++ LM_DBG("trying to translate %.*s with dpid %i\n", input.len, input.s, ++ idp->dp_id); ++ if(dp_translate_helper(NULL, &input, &output, idp, &attrs) != 0) { ++ LM_DBG("could not translate %.*s with dpid %i\n", input.len, input.s, ++ idp->dp_id); + rpc->fault(ctx, 500, "No translation"); + return; + } +- LM_DBG("input %.*s with dpid %i => output %.*s\n", +- input.len, input.s, idp->dp_id, output.len, output.s); ++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s, ++ idp->dp_id, output.len, output.s); + +- if (rpc->add(ctx, "{", &th) < 0) +- { ++ if(rpc->add(ctx, "{", &th) < 0) { + rpc->fault(ctx, 500, "Internal error creating rpc"); + return; + } +- if(rpc->struct_add(th, "SS", +- "Output", &output, +- "Attributes", &attrs)<0) +- { ++ if(rpc->struct_add(th, "SS", "Output", &output, "Attributes", &attrs) < 0) { + rpc->fault(ctx, 500, "Internal error creating rpc"); + return; + } +@@ -721,23 +712,22 @@ static void dialplan_rpc_translate(rpc_t + /* + * RPC command to dump dialplan + */ +-static void dialplan_rpc_dump(rpc_t* rpc, void* ctx) ++static void dialplan_rpc_dump(rpc_t *rpc, void *ctx) + { + dpl_id_p idp; + dpl_index_p indexp; + dpl_node_p rulep; + int dpid; +- void* th; +- void* ih; +- void* sh; ++ void *th; ++ void *ih; ++ void *sh; + +- if (rpc->scan(ctx, "d", &dpid) < 1) +- { ++ if(rpc->scan(ctx, "d", &dpid) < 1) { + rpc->fault(ctx, 500, "Missing parameter"); + return; + } + +- if ((idp = select_dpid(dpid)) == 0 ) { ++ if((idp = select_dpid(dpid)) == 0) { + LM_ERR("no information available for dpid %i\n", dpid); + rpc->fault(ctx, 500, "Dialplan ID not matched"); + return; +@@ -746,58 +736,49 @@ static void dialplan_rpc_dump(rpc_t* rpc + LM_DBG("trying to dump dpid %i\n", idp->dp_id); + + /* add entry node */ +- if (rpc->add(ctx, "{", &th) < 0) +- { ++ if(rpc->add(ctx, "{", &th) < 0) { + rpc->fault(ctx, 500, "Internal error root reply"); + return; + } + +- if(rpc->struct_add(th, "d[", +- "DPID", dpid, +- "ENTRIES", &ih)<0) +- { ++ if(rpc->struct_add(th, "d[", "DPID", dpid, "ENTRIES", &ih) < 0) { + rpc->fault(ctx, 500, "Internal error sets structure"); + return; + } + +- for(indexp=idp->first_index; indexp!=NULL;indexp=indexp->next) { ++ for(indexp = idp->first_index; indexp != NULL; indexp = indexp->next) { + LM_DBG("INDEX LEN: %i\n", indexp->len); +- for(rulep = indexp->first_rule; rulep!= NULL;rulep = rulep->next) { ++ for(rulep = indexp->first_rule; rulep != NULL; rulep = rulep->next) { + LM_DBG("DPID: %i PRIO : %i\n", rulep->dpid, rulep->pr); +- if (rpc->struct_add(ih, "{","ENTRY", &sh) < 0) +- { ++ if(rpc->struct_add(ih, "{", "ENTRY", &sh) < 0) { + rpc->fault(ctx, 500, "Internal error root reply"); + return; + } + +- if (rpc->struct_add(sh, "dd", "PRIO", rulep->pr, +- "MATCHOP", rulep->matchop)<0) +- { ++ if(rpc->struct_add( ++ sh, "dd", "PRIO", rulep->pr, "MATCHOP", rulep->matchop) ++ < 0) { + rpc->fault(ctx, 500, "Internal error adding prio"); + return; + } +- if (rpc->struct_add(sh, "s", "MATCHEXP", rulep->match_exp) < 0 ) +- { ++ if(rpc->struct_add(sh, "s", "MATCHEXP", rulep->match_exp) < 0) { + rpc->fault(ctx, 500, "Internal error adding match exp"); + return; + } +- if (rpc->struct_add(sh, "d", "MATCHLEN", rulep->matchlen) < 0 ) +- { +- rpc->fault(ctx, 500, "Internal error adding expression data and attribute"); ++ if(rpc->struct_add(sh, "d", "MATCHLEN", rulep->matchlen) < 0) { ++ rpc->fault(ctx, 500, ++ "Internal error adding expression data and attribute"); + return; + } +- if (rpc->struct_add(sh, "s", "SUBSTEXP", rulep->subst_exp) < 0 ) +- { ++ if(rpc->struct_add(sh, "s", "SUBSTEXP", rulep->subst_exp) < 0) { + rpc->fault(ctx, 500, "Internal error adding subst exp"); + return; + } +- if (rpc->struct_add(sh, "s", "REPLEXP", rulep->repl_exp) < 0 ) +- { ++ if(rpc->struct_add(sh, "s", "REPLEXP", rulep->repl_exp) < 0) { + rpc->fault(ctx, 500, "Internal error adding replace exp "); + return; + } +- if (rpc->struct_add(sh, "s", "ATTRS", rulep->attrs) < 0 ) +- { ++ if(rpc->struct_add(sh, "s", "ATTRS", rulep->attrs) < 0) { + rpc->fault(ctx, 500, "Internal error adding attribute"); + return; + } +@@ -807,26 +788,19 @@ static void dialplan_rpc_dump(rpc_t* rpc + return; + } + +-static const char* dialplan_rpc_dump_doc[2] = { +- "Dump dialplan content", +- 0 +-}; ++static const char *dialplan_rpc_dump_doc[2] = {"Dump dialplan content", 0}; + + + rpc_export_t dialplan_rpc_list[] = { +- {"dialplan.reload", dialplan_rpc_reload, +- dialplan_rpc_reload_doc, 0}, +- {"dialplan.translate", dialplan_rpc_translate, +- dialplan_rpc_translate_doc, 0}, +- {"dialplan.dump", dialplan_rpc_dump, +- dialplan_rpc_dump_doc, 0}, +- {0, 0, 0, 0} +-}; ++ {"dialplan.reload", dialplan_rpc_reload, dialplan_rpc_reload_doc, 0}, ++ {"dialplan.translate", dialplan_rpc_translate, ++ dialplan_rpc_translate_doc, 0}, ++ {"dialplan.dump", dialplan_rpc_dump, dialplan_rpc_dump_doc, 0}, ++ {0, 0, 0, 0}}; + + static int dialplan_init_rpc(void) + { +- if (rpc_register_array(dialplan_rpc_list)!=0) +- { ++ if(rpc_register_array(dialplan_rpc_list) != 0) { + LM_ERR("failed to register RPC commands\n"); + return -1; + } +@@ -863,20 +837,22 @@ static sr_kemi_t sr_kemi_dialplan_export + }; + /* clang-format on */ + +-static int ki_dp_translate(sip_msg_t* msg, int id, str *input_spv, str *output_spv) { ++static int ki_dp_translate( ++ sip_msg_t *msg, int id, str *input_spv, str *output_spv) ++{ + str input, output; + dpl_id_p idp; + str attrs, *outattrs; + pv_spec_t *pvs_i = NULL, *pvs_o = NULL; + +- if (!msg) ++ if(!msg) + return -1; + +- if (input_spv != NULL && (input_spv->s == NULL || input_spv->len <= 0)) { ++ if(input_spv != NULL && (input_spv->s == NULL || input_spv->len <= 0)) { + LM_ERR("invalid destination var name for input\n"); + return -1; + } +- if (output_spv != NULL && (output_spv->s == NULL || output_spv->len <= 0)) { ++ if(output_spv != NULL && (output_spv->s == NULL || output_spv->len <= 0)) { + LM_ERR("invalid destination var name for output\n"); + return -1; + } +@@ -892,56 +868,60 @@ static int ki_dp_translate(sip_msg_t* ms + pvs_o = pv_cache_get(output_spv); + } + +- if (pvs_i == NULL || pvs_o == NULL) { ++ if(pvs_i == NULL || pvs_o == NULL) { + LM_ERR("cannot get pv spec for input or output\n"); + return -1; + } + +- if ((pvs_i->type!=PVT_AVP && pvs_i->type!=PVT_XAVP && pvs_i->type!=PVT_SCRIPTVAR && +- pvs_i->type!=PVT_RURI && pvs_i->type!=PVT_RURI_USERNAME) || +- (pvs_o->type!=PVT_AVP && pvs_o->type!=PVT_XAVP && pvs_o->type!=PVT_SCRIPTVAR && +- pvs_o->type!=PVT_RURI && pvs_o->type!=PVT_RURI_USERNAME)) { ++ if((pvs_i->type != PVT_AVP && pvs_i->type != PVT_XAVP ++ && pvs_i->type != PVT_SCRIPTVAR && pvs_i->type != PVT_RURI ++ && pvs_i->type != PVT_RURI_USERNAME) ++ || (pvs_o->type != PVT_AVP && pvs_o->type != PVT_XAVP ++ && pvs_o->type != PVT_SCRIPTVAR && pvs_o->type != PVT_RURI ++ && pvs_o->type != PVT_RURI_USERNAME)) { + LM_ERR("type of pv error\n"); + return -1; + } + +- if ((idp = select_dpid(id)) ==0 ){ ++ if((idp = select_dpid(id)) == 0) { + LM_DBG("no information available for dpid %i\n", id); + return -2; + } + + /* get the input */ +- if (dp_get_svalue(msg, pvs_i, &input)!=0){ ++ if(dp_get_svalue(msg, pvs_i, &input) != 0) { + LM_ERR("invalid param 2\n"); + return -1; + } + + LM_DBG("input is %.*s\n", input.len, input.s); + +- outattrs = (!dp_attr_pvar)?NULL:&attrs; +- if (dp_translate_helper(msg, &input, &output, idp, outattrs)!=0) { ++ outattrs = (!dp_attr_pvar) ? NULL : &attrs; ++ if(dp_translate_helper(msg, &input, &output, idp, outattrs) != 0) { + LM_DBG("could not translate %.*s " +- "with dpid %i\n", input.len, input.s, idp->dp_id); ++ "with dpid %i\n", ++ input.len, input.s, idp->dp_id); + return -1; + } +- LM_DBG("input %.*s with dpid %i => output %.*s\n", +- input.len, input.s, idp->dp_id, output.len, output.s); ++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s, ++ idp->dp_id, output.len, output.s); + + /* set the output */ +- if (dp_update(msg, pvs_o, &output, outattrs) !=0){ ++ if(dp_update(msg, pvs_o, &output, outattrs) != 0) { + LM_ERR("cannot set the output\n"); + return -1; + } + + return 1; +- + } + +-static int ki_dp_translate_id(sip_msg_t* msg, int id) { ++static int ki_dp_translate_id(sip_msg_t *msg, int id) ++{ + return ki_dp_translate(msg, id, NULL, NULL); + } + +-static int ki_dp_translate_vars(sip_msg_t* msg, int id, str *input, str *output) { ++static int ki_dp_translate_vars(sip_msg_t *msg, int id, str *input, str *output) ++{ + return ki_dp_translate(msg, id, input, output); + } + +--- a/src/modules/dialplan/dialplan.h ++++ b/src/modules/dialplan/dialplan.h +@@ -34,59 +34,64 @@ + #include "../../core/pvar.h" + #include "../../core/parser/msg_parser.h" + +-#define DP_EQUAL_OP 0 +-#define DP_REGEX_OP 1 +-#define DP_FNMATCH_OP 2 +- +-#define MAX_REPLACE_WITH 10 +- +-#define DP_TFLAGS_PV_MATCH (1 << 0) +-#define DP_TFLAGS_PV_SUBST (1 << 1) +- +-typedef struct dpl_node { +- int dpid; /* dialplan id */ +- int pr; /* priority */ +- int matchop; /* matching operator */ +- int matchlen; /* matching value length */ +- str match_exp; /* match-first string */ +- str subst_exp; /* match string with subtitution groupping */ +- str repl_exp; /* replacement expression string */ +- pcre *match_comp; /* compiled matching expression */ +- pcre *subst_comp; /* compiled substitution expression */ ++#define DP_EQUAL_OP 0 ++#define DP_REGEX_OP 1 ++#define DP_FNMATCH_OP 2 ++ ++#define MAX_REPLACE_WITH 10 ++ ++#define DP_TFLAGS_PV_MATCH (1 << 0) ++#define DP_TFLAGS_PV_SUBST (1 << 1) ++ ++typedef struct dpl_node ++{ ++ int dpid; /* dialplan id */ ++ int pr; /* priority */ ++ int matchop; /* matching operator */ ++ int matchlen; /* matching value length */ ++ str match_exp; /* match-first string */ ++ str subst_exp; /* match string with subtitution groupping */ ++ str repl_exp; /* replacement expression string */ ++ pcre *match_comp; /* compiled matching expression */ ++ pcre *subst_comp; /* compiled substitution expression */ + struct subst_expr *repl_comp; /* compiled replacement */ +- str attrs; /* attributes string */ +- unsigned int tflags; /* flags for type of values for matching */ ++ str attrs; /* attributes string */ ++ unsigned int tflags; /* flags for type of values for matching */ + +- struct dpl_node * next; /* next rule */ ++ struct dpl_node *next; /* next rule */ + } dpl_node_t, *dpl_node_p; + + /*For every distinct length of a matching string*/ +-typedef struct dpl_index{ ++typedef struct dpl_index ++{ + int len; +- dpl_node_t * first_rule; +- dpl_node_t * last_rule; ++ dpl_node_t *first_rule; ++ dpl_node_t *last_rule; + +- struct dpl_index * next; +-}dpl_index_t, *dpl_index_p; ++ struct dpl_index *next; ++} dpl_index_t, *dpl_index_p; + + /*For every DPID*/ +-typedef struct dpl_id{ ++typedef struct dpl_id ++{ + int dp_id; +- dpl_index_t* first_index;/*fast access :rules with specific length*/ +- struct dpl_id * next; +-}dpl_id_t,*dpl_id_p; ++ dpl_index_t *first_index; /*fast access :rules with specific length*/ ++ struct dpl_id *next; ++} dpl_id_t, *dpl_id_p; + + +-#define DP_VAL_INT 0 +-#define DP_VAL_SPEC 1 ++#define DP_VAL_INT 0 ++#define DP_VAL_SPEC 1 + +-typedef struct dp_param{ ++typedef struct dp_param ++{ + int type; +- union { ++ union ++ { + int id; +- pv_spec_t* sp[2]; ++ pv_spec_t *sp[2]; + } v; +-}dp_param_t, *dp_param_p; ++} dp_param_t, *dp_param_p; + + int init_data(); + void destroy_data(); +@@ -94,12 +99,12 @@ int dp_load_db(); + + dpl_id_p select_dpid(int id); + +-struct subst_expr* repl_exp_parse(str subst); ++struct subst_expr *repl_exp_parse(str subst); + void repl_expr_free(struct subst_expr *se); +-int dp_translate_helper(sip_msg_t *msg, str *user_name, str *repl_user, +- dpl_id_p idp, str *); +-int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule, +- pcre *subst_comp, str *); ++int dp_translate_helper( ++ sip_msg_t *msg, str *user_name, str *repl_user, dpl_id_p idp, str *); ++int rule_translate( ++ sip_msg_t *msg, str *instr, dpl_node_t *rule, pcre *subst_comp, str *); + + pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype); + #endif +--- a/src/modules/dialplan/dp_db.c ++++ b/src/modules/dialplan/dp_db.c +@@ -37,45 +37,46 @@ + #include "dp_db.h" + #include "dialplan.h" + +-str dp_db_url = str_init(DEFAULT_RODB_URL); +-str dp_table_name = str_init(DP_TABLE_NAME); +-str dpid_column = str_init(DPID_COL); +-str pr_column = str_init(PR_COL); +-str match_op_column = str_init(MATCH_OP_COL); +-str match_exp_column= str_init(MATCH_EXP_COL); +-str match_len_column= str_init(MATCH_LEN_COL); +-str subst_exp_column= str_init(SUBST_EXP_COL); +-str repl_exp_column = str_init(REPL_EXP_COL); +-str attrs_column = str_init(ATTRS_COL); ++str dp_db_url = str_init(DEFAULT_RODB_URL); ++str dp_table_name = str_init(DP_TABLE_NAME); ++str dpid_column = str_init(DPID_COL); ++str pr_column = str_init(PR_COL); ++str match_op_column = str_init(MATCH_OP_COL); ++str match_exp_column = str_init(MATCH_EXP_COL); ++str match_len_column = str_init(MATCH_LEN_COL); ++str subst_exp_column = str_init(SUBST_EXP_COL); ++str repl_exp_column = str_init(REPL_EXP_COL); ++str attrs_column = str_init(ATTRS_COL); + + extern int dp_fetch_rows; + extern int dp_match_dynamic; + +-static db1_con_t* dp_db_handle = 0; /* database connection handle */ ++static db1_con_t *dp_db_handle = 0; /* database connection handle */ + static db_func_t dp_dbf; + +-#define GET_STR_VALUE(_res, _values, _index)\ +- do{\ +- if ( VAL_NULL((_values)+ (_index)) ) { \ +- LM_ERR(" values %d is NULL - not allowed\n",_index);\ +- (_res).s = 0; (_res).len = 0;\ +- goto err;\ +- } \ +- (_res).s = VAL_STR((_values)+ (_index)).s;\ +- (_res).len = strlen(VAL_STR((_values)+ (_index)).s);\ +- }while(0); ++#define GET_STR_VALUE(_res, _values, _index) \ ++ do { \ ++ if(VAL_NULL((_values) + (_index))) { \ ++ LM_ERR(" values %d is NULL - not allowed\n", _index); \ ++ (_res).s = 0; \ ++ (_res).len = 0; \ ++ goto err; \ ++ } \ ++ (_res).s = VAL_STR((_values) + (_index)).s; \ ++ (_res).len = strlen(VAL_STR((_values) + (_index)).s); \ ++ } while(0); + +-void destroy_rule(dpl_node_t * rule); ++void destroy_rule(dpl_node_t *rule); + void destroy_hash(int); + +-dpl_node_t * build_rule(db_val_t * values); ++dpl_node_t *build_rule(db_val_t *values); + int add_rule2hash(dpl_node_t *, int); + +-void list_rule(dpl_node_t * ); ++void list_rule(dpl_node_t *); + void list_hash(int h_index); + + +-static dpl_id_p* dp_rules_hash = NULL; ++static dpl_id_p *dp_rules_hash = NULL; + static int *dp_crt_idx = NULL; + static int *dp_next_idx = NULL; + +@@ -91,7 +92,7 @@ int dpl_check_pv(str *in) + str s; + int len; + +- if(in==NULL || in->s==NULL) ++ if(in == NULL || in->s == NULL) + return -1; + + LM_DBG("parsing [%.*s]\n", in->len, in->s); +@@ -101,26 +102,27 @@ int dpl_check_pv(str *in) + + p = in->s; + +- while(is_in_str(p,in)) +- { +- while(is_in_str(p,in) && *p!=PV_MARKER) ++ while(is_in_str(p, in)) { ++ while(is_in_str(p, in) && *p != PV_MARKER) + p++; +- if(*p == '\0' || !is_in_str(p,in)) ++ if(*p == '\0' || !is_in_str(p, in)) + break; + /* last char is $ ? */ +- if(!is_in_str(p+1, in)) ++ if(!is_in_str(p + 1, in)) + break; + s.s = p; +- s.len = in->s+in->len-p; ++ s.len = in->s + in->len - p; + len = 0; + spec = pv_spec_lookup(&s, &len); +- if(spec!=NULL) { ++ if(spec != NULL) { + /* found a variable */ + LM_DBG("string [%.*s] has variables\n", in->len, in->s); + return 0; + } +- if(len) p += len; +- else p++; ++ if(len) ++ p += len; ++ else ++ p++; + } + + /* not found */ +@@ -129,27 +131,28 @@ int dpl_check_pv(str *in) + + int init_db_data(void) + { +- if(!dp_table_name.s || dp_table_name.len<=0){ ++ if(!dp_table_name.s || dp_table_name.len <= 0) { + LM_ERR("invalid database table name\n"); + return -1; + } + + /* Find a database module */ +- if (db_bind_mod(&dp_db_url, &dp_dbf) < 0){ ++ if(db_bind_mod(&dp_db_url, &dp_dbf) < 0) { + LM_ERR("unable to bind to a database driver\n"); + return -1; + } + +- if(dp_connect_db() !=0) ++ if(dp_connect_db() != 0) + return -1; + +- if(db_check_table_version(&dp_dbf, dp_db_handle, &dp_table_name, +- DP_TABLE_VERSION) < 0) { ++ if(db_check_table_version( ++ &dp_dbf, dp_db_handle, &dp_table_name, DP_TABLE_VERSION) ++ < 0) { + DB_TABLE_VERSION_ERROR(dp_table_name); + goto error; + } + +- if(dp_load_db() != 0){ ++ if(dp_load_db() != 0) { + LM_ERR("failed to load database data\n"); + goto error; + } +@@ -166,17 +169,17 @@ error: + + int dp_connect_db(void) + { +- if (dp_dbf.init==0){ ++ if(dp_dbf.init == 0) { + LM_CRIT("null dp_dbf\n"); + return -1; + } + +- if(dp_db_handle){ ++ if(dp_db_handle) { + LM_CRIT("BUG: connection to database already open\n"); + return -1; + } + +- if ((dp_db_handle = dp_dbf.init(&dp_db_url)) == 0){ ++ if((dp_db_handle = dp_dbf.init(&dp_db_url)) == 0) { + LM_ERR("unable to connect to the database\n"); + return -1; + } +@@ -187,7 +190,7 @@ int dp_connect_db(void) + + void dp_disconnect_db(void) + { +- if(dp_db_handle){ ++ if(dp_db_handle) { + dp_dbf.close(dp_db_handle); + dp_db_handle = 0; + } +@@ -198,20 +201,20 @@ int init_data(void) + { + int *p; + +- dp_rules_hash = (dpl_id_p *)shm_malloc(2*sizeof(dpl_id_p)); ++ dp_rules_hash = (dpl_id_p *)shm_malloc(2 * sizeof(dpl_id_p)); + if(!dp_rules_hash) { + LM_ERR("out of shm memory\n"); + return -1; + } + dp_rules_hash[0] = dp_rules_hash[1] = 0; + +- p = (int *)shm_malloc(2*sizeof(int)); +- if(!p){ ++ p = (int *)shm_malloc(2 * sizeof(int)); ++ if(!p) { + LM_ERR("out of shm memory\n"); + return -1; + } + dp_crt_idx = p; +- dp_next_idx = p+1; ++ dp_next_idx = p + 1; + *dp_crt_idx = *dp_next_idx = 0; + + LM_DBG("trying to initialize data from db\n"); +@@ -224,7 +227,7 @@ int init_data(void) + + void destroy_data(void) + { +- if(dp_rules_hash){ ++ if(dp_rules_hash) { + destroy_hash(0); + destroy_hash(1); + shm_free(dp_rules_hash); +@@ -240,45 +243,46 @@ void destroy_data(void) + int dp_load_db(void) + { + int i, nr_rows; +- db1_res_t * res = 0; +- db_val_t * values; +- db_row_t * rows; +- db_key_t query_cols[DP_TABLE_COL_NO] = { +- &dpid_column, &pr_column, +- &match_op_column, &match_exp_column, &match_len_column, +- &subst_exp_column, &repl_exp_column, &attrs_column }; ++ db1_res_t *res = 0; ++ db_val_t *values; ++ db_row_t *rows; ++ db_key_t query_cols[DP_TABLE_COL_NO] = {&dpid_column, &pr_column, ++ &match_op_column, &match_exp_column, &match_len_column, ++ &subst_exp_column, &repl_exp_column, &attrs_column}; + + db_key_t order = &pr_column; + + dpl_node_t *rule; + + LM_DBG("init\n"); +- if( (*dp_crt_idx) != (*dp_next_idx)){ ++ if((*dp_crt_idx) != (*dp_next_idx)) { + LM_WARN("a load command already generated, aborting reload...\n"); + return 0; + } + +- if (dp_dbf.use_table(dp_db_handle, &dp_table_name) < 0){ ++ if(dp_dbf.use_table(dp_db_handle, &dp_table_name) < 0) { + LM_ERR("error in use_table %.*s\n", dp_table_name.len, dp_table_name.s); + return -1; + } + +- if (DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) { +- if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0, +- DP_TABLE_COL_NO, order, 0) < 0){ ++ if(DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) { ++ if(dp_dbf.query(dp_db_handle, 0, 0, 0, query_cols, 0, DP_TABLE_COL_NO, ++ order, 0) ++ < 0) { + LM_ERR("failed to query database!\n"); + return -1; + } +- if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows)<0) { ++ if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows) < 0) { + LM_ERR("failed to fetch\n"); +- if (res) ++ if(res) + dp_dbf.free_result(dp_db_handle, res); + return -1; + } + } else { + /*select the whole table and all the columns*/ +- if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0, +- DP_TABLE_COL_NO, order, &res) < 0){ ++ if(dp_dbf.query(dp_db_handle, 0, 0, 0, query_cols, 0, DP_TABLE_COL_NO, ++ order, &res) ++ < 0) { + LM_ERR("failed to query database\n"); + return -1; + } +@@ -286,38 +290,37 @@ int dp_load_db(void) + + nr_rows = RES_ROW_N(res); + +- *dp_next_idx = ((*dp_crt_idx) == 0)? 1:0; ++ *dp_next_idx = ((*dp_crt_idx) == 0) ? 1 : 0; + destroy_hash(*dp_next_idx); + +- if(nr_rows == 0){ ++ if(nr_rows == 0) { + LM_WARN("no data in the db\n"); + goto end; + } + + do { +- for(i=0; i0); ++ } while(RES_ROW_N(res) > 0); + + + end: +@@ -328,7 +331,8 @@ end: + return 0; + + err2: +- if(rule) destroy_rule(rule); ++ if(rule) ++ destroy_rule(rule); + destroy_hash(*dp_next_idx); + dp_dbf.free_result(dp_db_handle, res); + *dp_next_idx = *dp_crt_idx; +@@ -340,16 +344,17 @@ int dpl_str_to_shm(str src, str *dest, i + { + int mdup = 0; + +- if(src.len ==0 || src.s ==0) ++ if(src.len == 0 || src.s == 0) + return 0; + +- if(mterm!=0 && PV_MARKER=='$') { +- if(src.len>1 && src.s[src.len-1]=='$' && src.s[src.len-2]!='$') { ++ if(mterm != 0 && PV_MARKER == '$') { ++ if(src.len > 1 && src.s[src.len - 1] == '$' ++ && src.s[src.len - 2] != '$') { + mdup = 1; + } + } +- dest->s = (char*)shm_malloc((src.len+1+mdup) * sizeof(char)); +- if(!dest->s){ ++ dest->s = (char *)shm_malloc((src.len + 1 + mdup) * sizeof(char)); ++ if(!dest->s) { + LM_ERR("out of shm memory\n"); + return -1; + } +@@ -378,28 +383,28 @@ pcre *reg_ex_comp(const char *pattern, i + size_t size; + + re = pcre_compile(pattern, 0, &error, &err_offset, NULL); +- if (re == NULL) { +- LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n", +- pattern, err_offset, error); ++ if(re == NULL) { ++ LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n", pattern, ++ err_offset, error); + return (pcre *)0; + } + rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size); +- if (rc != 0) { ++ if(rc != 0) { + pcre_free(re); + LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n", + pattern, rc); + return (pcre *)0; + } + rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, cap_cnt); +- if (rc != 0) { ++ if(rc != 0) { + pcre_free(re); + LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n", + pattern, rc); + return (pcre *)0; + } +- if(mtype==0) { ++ if(mtype == 0) { + result = (pcre *)shm_malloc(size); +- if (result == NULL) { ++ if(result == NULL) { + pcre_free(re); + LM_ERR("not enough shared memory for compiled PCRE pattern\n"); + return (pcre *)0; +@@ -414,20 +419,20 @@ pcre *reg_ex_comp(const char *pattern, i + + + /*compile the expressions, and if ok, build the rule */ +-dpl_node_t * build_rule(db_val_t * values) ++dpl_node_t *build_rule(db_val_t *values) + { + pcre *match_comp, *subst_comp; + struct subst_expr *repl_comp; +- dpl_node_t * new_rule; ++ dpl_node_t *new_rule; + str match_exp, subst_exp, repl_exp, attrs; + int matchop; +- int cap_cnt=0; +- unsigned int tflags=0; ++ int cap_cnt = 0; ++ unsigned int tflags = 0; + +- matchop = VAL_INT(values+2); ++ matchop = VAL_INT(values + 2); + +- if((matchop != DP_REGEX_OP) && (matchop!=DP_EQUAL_OP) +- && (matchop!=DP_FNMATCH_OP)){ ++ if((matchop != DP_REGEX_OP) && (matchop != DP_EQUAL_OP) ++ && (matchop != DP_FNMATCH_OP)) { + LM_ERR("invalid value for match operator\n"); + return NULL; + } +@@ -437,15 +442,15 @@ dpl_node_t * build_rule(db_val_t * value + new_rule = 0; + + GET_STR_VALUE(match_exp, values, 3); +- if(matchop == DP_REGEX_OP){ +- if(unlikely(dp_match_dynamic==1)) { +- if(dpl_check_pv(&match_exp)==0) { ++ if(matchop == DP_REGEX_OP) { ++ if(unlikely(dp_match_dynamic == 1)) { ++ if(dpl_check_pv(&match_exp) == 0) { + tflags |= DP_TFLAGS_PV_MATCH; + } + } +- if(!(tflags&DP_TFLAGS_PV_MATCH)) { ++ if(!(tflags & DP_TFLAGS_PV_MATCH)) { + match_comp = reg_ex_comp(match_exp.s, &cap_cnt, 0); +- if(!match_comp){ ++ if(!match_comp) { + LM_ERR("failed to compile match expression %.*s\n", + match_exp.len, match_exp.s); + goto err; +@@ -454,9 +459,9 @@ dpl_node_t * build_rule(db_val_t * value + } + + GET_STR_VALUE(repl_exp, values, 6); +- if(repl_exp.len && repl_exp.s){ ++ if(repl_exp.len && repl_exp.s) { + repl_comp = repl_exp_parse(repl_exp); +- if(!repl_comp){ ++ if(!repl_comp) { + LM_ERR("failed to compile replacing expression %.*s\n", + repl_exp.len, repl_exp.s); + goto err; +@@ -465,20 +470,20 @@ dpl_node_t * build_rule(db_val_t * value + + cap_cnt = 0; + GET_STR_VALUE(subst_exp, values, 5); +- if(subst_exp.s && subst_exp.len){ +- if(unlikely(dp_match_dynamic==1)) { +- if(dpl_check_pv(&subst_exp)==0) { ++ if(subst_exp.s && subst_exp.len) { ++ if(unlikely(dp_match_dynamic == 1)) { ++ if(dpl_check_pv(&subst_exp) == 0) { + tflags |= DP_TFLAGS_PV_SUBST; + } + } +- if(!(tflags&DP_TFLAGS_PV_SUBST)) { ++ if(!(tflags & DP_TFLAGS_PV_SUBST)) { + subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt, 0); +- if(!subst_comp){ ++ if(!subst_comp) { + LM_ERR("failed to compile subst expression %.*s\n", + subst_exp.len, subst_exp.s); + goto err; + } +- if (cap_cnt > MAX_REPLACE_WITH) { ++ if(cap_cnt > MAX_REPLACE_WITH) { + LM_ERR("subst expression %.*s has too many sub-expressions\n", + subst_exp.len, subst_exp.s); + goto err; +@@ -486,72 +491,77 @@ dpl_node_t * build_rule(db_val_t * value + } + } + +- LM_DBG("building rule for [%d:%.*s/%.*s/%.*s]\n", matchop, +- match_exp.len, ZSW(match_exp.s), subst_exp.len, ZSW(subst_exp.s), +- repl_exp.len, ZSW(repl_exp.s)); +- if (!(tflags&(DP_TFLAGS_PV_SUBST|DP_TFLAGS_PV_MATCH)) && +- repl_comp && (cap_cnt < repl_comp->max_pmatch) && +- (repl_comp->max_pmatch != 0)) +- { ++ LM_DBG("building rule for [%d:%.*s/%.*s/%.*s]\n", matchop, match_exp.len, ++ ZSW(match_exp.s), subst_exp.len, ZSW(subst_exp.s), repl_exp.len, ++ ZSW(repl_exp.s)); ++ if(!(tflags & (DP_TFLAGS_PV_SUBST | DP_TFLAGS_PV_MATCH)) && repl_comp ++ && (cap_cnt < repl_comp->max_pmatch) ++ && (repl_comp->max_pmatch != 0)) { + LM_ERR("repl_exp %.*s refers to %d sub-expressions, but " +- "subst_exp %.*s has only %d\n", +- repl_exp.len, repl_exp.s, repl_comp->max_pmatch, +- subst_exp.len, subst_exp.s, cap_cnt); ++ "subst_exp %.*s has only %d\n", ++ repl_exp.len, repl_exp.s, repl_comp->max_pmatch, subst_exp.len, ++ subst_exp.s, cap_cnt); + goto err; + } + + new_rule = (dpl_node_t *)shm_malloc(sizeof(dpl_node_t)); +- if(!new_rule){ ++ if(!new_rule) { + LM_ERR("out of shm memory(new_rule)\n"); + goto err; + } + memset(new_rule, 0, sizeof(dpl_node_t)); + +- if(dpl_str_to_shm(match_exp, &new_rule->match_exp, +- tflags&DP_TFLAGS_PV_MATCH)!=0) ++ if(dpl_str_to_shm( ++ match_exp, &new_rule->match_exp, tflags & DP_TFLAGS_PV_MATCH) ++ != 0) + goto err; + +- if(dpl_str_to_shm(subst_exp, &new_rule->subst_exp, +- tflags&DP_TFLAGS_PV_SUBST)!=0) ++ if(dpl_str_to_shm( ++ subst_exp, &new_rule->subst_exp, tflags & DP_TFLAGS_PV_SUBST) ++ != 0) + goto err; + +- if(dpl_str_to_shm(repl_exp, &new_rule->repl_exp, 0)!=0) ++ if(dpl_str_to_shm(repl_exp, &new_rule->repl_exp, 0) != 0) + goto err; + + /*set the rest of the rule fields*/ +- new_rule->dpid = VAL_INT(values); +- new_rule->pr = VAL_INT(values+1); +- new_rule->matchlen = VAL_INT(values+4); +- new_rule->matchop = matchop; ++ new_rule->dpid = VAL_INT(values); ++ new_rule->pr = VAL_INT(values + 1); ++ new_rule->matchlen = VAL_INT(values + 4); ++ new_rule->matchop = matchop; + GET_STR_VALUE(attrs, values, 7); +- if(dpl_str_to_shm(attrs, &new_rule->attrs, 0)!=0) ++ if(dpl_str_to_shm(attrs, &new_rule->attrs, 0) != 0) + goto err; + + LM_DBG("attrs are: '%.*s'\n", new_rule->attrs.len, new_rule->attrs.s); + + new_rule->match_comp = match_comp; + new_rule->subst_comp = subst_comp; +- new_rule->repl_comp = repl_comp; +- new_rule->tflags = tflags; ++ new_rule->repl_comp = repl_comp; ++ new_rule->tflags = tflags; + + return new_rule; + + err: +- if(match_comp) shm_free(match_comp); +- if(subst_comp) shm_free(subst_comp); +- if(repl_comp) repl_expr_free(repl_comp); +- if(new_rule) destroy_rule(new_rule); ++ if(match_comp) ++ shm_free(match_comp); ++ if(subst_comp) ++ shm_free(subst_comp); ++ if(repl_comp) ++ repl_expr_free(repl_comp); ++ if(new_rule) ++ destroy_rule(new_rule); + return NULL; + } + + +-int add_rule2hash(dpl_node_t * rule, int h_index) ++int add_rule2hash(dpl_node_t *rule, int h_index) + { + dpl_id_p crt_idp, last_idp; + dpl_index_p indexp, last_indexp, new_indexp; + int new_id; + +- if(!dp_rules_hash){ ++ if(!dp_rules_hash) { + LM_ERR("data not allocated\n"); + return -1; + } +@@ -559,15 +569,15 @@ int add_rule2hash(dpl_node_t * rule, int + new_id = 0; + + /*search for the corresponding dpl_id*/ +- for(crt_idp = last_idp =dp_rules_hash[h_index]; crt_idp!= NULL; ++ for(crt_idp = last_idp = dp_rules_hash[h_index]; crt_idp != NULL; + last_idp = crt_idp, crt_idp = crt_idp->next) + if(crt_idp->dp_id == rule->dpid) + break; + + /*didn't find a dpl_id*/ +- if(!crt_idp){ +- crt_idp = (dpl_id_t*)shm_malloc(sizeof(dpl_id_t)); +- if(!crt_idp){ ++ if(!crt_idp) { ++ crt_idp = (dpl_id_t *)shm_malloc(sizeof(dpl_id_t)); ++ if(!crt_idp) { + LM_ERR("out of shm memory (crt_idp)\n"); + return -1; + } +@@ -578,11 +588,12 @@ int add_rule2hash(dpl_node_t * rule, int + } + + /*search for the corresponding dpl_index*/ +- for(indexp = last_indexp =crt_idp->first_index; indexp!=NULL; +- last_indexp = indexp, indexp = indexp->next){ ++ for(indexp = last_indexp = crt_idp->first_index; indexp != NULL; ++ last_indexp = indexp, indexp = indexp->next) { + if(indexp->len == rule->matchlen) + goto add_rule; +- if((rule->matchlen!=0)&&((indexp->len)?(indexp->len>rule->matchlen):1)) ++ if((rule->matchlen != 0) ++ && ((indexp->len) ? (indexp->len > rule->matchlen) : 1)) + goto add_index; + } + +@@ -590,18 +601,18 @@ add_index: + LM_DBG("new index , len %i\n", rule->matchlen); + + new_indexp = (dpl_index_t *)shm_malloc(sizeof(dpl_index_t)); +- if(!new_indexp){ ++ if(!new_indexp) { + LM_ERR("out of shm memory\n"); + goto err; + } +- memset(new_indexp , 0, sizeof(dpl_index_t)); ++ memset(new_indexp, 0, sizeof(dpl_index_t)); + new_indexp->next = indexp; + new_indexp->len = rule->matchlen; + + /*add as first index*/ +- if(last_indexp == indexp){ ++ if(last_indexp == indexp) { + crt_idp->first_index = new_indexp; +- }else{ ++ } else { + last_indexp->next = new_indexp; + } + +@@ -617,13 +628,13 @@ add_rule: + + indexp->last_rule = rule; + +- if(new_id){ ++ if(new_id) { + crt_idp->next = dp_rules_hash[h_index]; + dp_rules_hash[h_index] = crt_idp; + } + LM_DBG("added the rule id %i index %i pr %i next %p to the " +- "index with %i len\n", rule->dpid, rule->matchlen, +- rule->pr, rule->next, indexp->len); ++ "index with %i len\n", ++ rule->dpid, rule->matchlen, rule->pr, rule->next, indexp->len); + + return 0; + +@@ -643,24 +654,23 @@ void destroy_hash(int index) + if(!dp_rules_hash[index]) + return; + +- for(crt_idp = dp_rules_hash[index]; crt_idp != NULL;){ ++ for(crt_idp = dp_rules_hash[index]; crt_idp != NULL;) { + +- for(indexp = crt_idp->first_index; indexp != NULL;){ ++ for(indexp = crt_idp->first_index; indexp != NULL;) { + +- for(rulep = indexp->first_rule; rulep!= NULL;){ ++ for(rulep = indexp->first_rule; rulep != NULL;) { + + destroy_rule(rulep); + + indexp->first_rule = rulep->next; + shm_free(rulep); +- rulep=0; +- rulep= indexp->first_rule; ++ rulep = 0; ++ rulep = indexp->first_rule; + } +- crt_idp->first_index= indexp->next; ++ crt_idp->first_index = indexp->next; + shm_free(indexp); +- indexp=0; ++ indexp = 0; + indexp = crt_idp->first_index; +- + } + + dp_rules_hash[index] = crt_idp->next; +@@ -673,13 +683,13 @@ void destroy_hash(int index) + } + + +-void destroy_rule(dpl_node_t * rule){ ++void destroy_rule(dpl_node_t *rule) ++{ + + if(!rule) + return; + +- LM_DBG("destroying rule with priority %i\n", +- rule->pr); ++ LM_DBG("destroying rule with priority %i\n", rule->pr); + + if(rule->match_comp) + shm_free(rule->match_comp); +@@ -712,7 +722,7 @@ dpl_id_p select_dpid(int id) + if(!dp_rules_hash || !dp_crt_idx) + return NULL; + +- for(idp = dp_rules_hash[*dp_crt_idx]; idp!=NULL; idp = idp->next) ++ for(idp = dp_rules_hash[*dp_crt_idx]; idp != NULL; idp = idp->next) + if(idp->dp_id == id) + return idp; + +@@ -731,11 +741,14 @@ void list_hash(int h_index) + if(!dp_rules_hash[h_index]) + return; + +- for(crt_idp=dp_rules_hash[h_index]; crt_idp!=NULL; crt_idp = crt_idp->next){ ++ for(crt_idp = dp_rules_hash[h_index]; crt_idp != NULL; ++ crt_idp = crt_idp->next) { + LM_DBG("DPID: %i, pointer %p\n", crt_idp->dp_id, crt_idp); +- for(indexp=crt_idp->first_index; indexp!=NULL;indexp= indexp->next){ ++ for(indexp = crt_idp->first_index; indexp != NULL; ++ indexp = indexp->next) { + LM_DBG("INDEX LEN: %i\n", indexp->len); +- for(rulep = indexp->first_rule; rulep!= NULL;rulep = rulep->next){ ++ for(rulep = indexp->first_rule; rulep != NULL; ++ rulep = rulep->next) { + list_rule(rulep); + } + } +@@ -746,12 +759,9 @@ void list_hash(int h_index) + void list_rule(dpl_node_t *rule) + { + LM_DBG("RULE %p: pr %i next %p op %d tflags %u match_exp %.*s, " +- "subst_exp %.*s, repl_exp %.*s and attrs %.*s\n", rule, +- rule->pr, rule->next, +- rule->matchop, rule->tflags, +- rule->match_exp.len, ZSW(rule->match_exp.s), +- rule->subst_exp.len, ZSW(rule->subst_exp.s), +- rule->repl_exp.len, ZSW(rule->repl_exp.s), +- rule->attrs.len, ZSW(rule->attrs.s)); +- ++ "subst_exp %.*s, repl_exp %.*s and attrs %.*s\n", ++ rule, rule->pr, rule->next, rule->matchop, rule->tflags, ++ rule->match_exp.len, ZSW(rule->match_exp.s), rule->subst_exp.len, ++ ZSW(rule->subst_exp.s), rule->repl_exp.len, ZSW(rule->repl_exp.s), ++ rule->attrs.len, ZSW(rule->attrs.s)); + } +--- a/src/modules/dialplan/dp_db.h ++++ b/src/modules/dialplan/dp_db.h +@@ -32,30 +32,30 @@ + #include "../../core/str.h" + #include "../../lib/srdb1/db.h" + +-#define DP_TABLE_NAME "dialplan" +-#define DPID_COL "dpid" +-#define PR_COL "pr" +-#define MATCH_OP_COL "match_op" +-#define MATCH_EXP_COL "match_exp" +-#define MATCH_LEN_COL "match_len" +-#define SUBST_EXP_COL "subst_exp" +-#define REPL_EXP_COL "repl_exp" +-#define ATTRS_COL "attrs" ++#define DP_TABLE_NAME "dialplan" ++#define DPID_COL "dpid" ++#define PR_COL "pr" ++#define MATCH_OP_COL "match_op" ++#define MATCH_EXP_COL "match_exp" ++#define MATCH_LEN_COL "match_len" ++#define SUBST_EXP_COL "subst_exp" ++#define REPL_EXP_COL "repl_exp" ++#define ATTRS_COL "attrs" + + +-#define DP_TABLE_VERSION 2 +-#define DP_TABLE_COL_NO 8 ++#define DP_TABLE_VERSION 2 ++#define DP_TABLE_COL_NO 8 + + extern str dp_db_url; + extern str dp_table_name; +-extern str dpid_column; +-extern str pr_column; +-extern str match_op_column; +-extern str match_exp_column; +-extern str match_len_column; +-extern str subst_exp_column; +-extern str repl_exp_column; +-extern str attrs_column; ++extern str dpid_column; ++extern str pr_column; ++extern str match_op_column; ++extern str match_exp_column; ++extern str match_len_column; ++extern str subst_exp_column; ++extern str repl_exp_column; ++extern str attrs_column; + + int init_db_data(); + int dp_connect_db(); +--- a/src/modules/dialplan/dp_repl.c ++++ b/src/modules/dialplan/dp_repl.c +@@ -42,27 +42,28 @@ typedef struct dpl_dyn_pcre + int cnt; + str expr; + +- struct dpl_dyn_pcre * next; /* next rule */ ++ struct dpl_dyn_pcre *next; /* next rule */ + } dpl_dyn_pcre_t, *dpl_dyn_pcre_p; + +-static void dpl_get_avp_val(avp_t *avp, str *dst) { ++static void dpl_get_avp_val(avp_t *avp, str *dst) ++{ + avp_value_t val; + +- if (avp==0 || dst==0) return; ++ if(avp == 0 || dst == 0) ++ return; + + /* Warning! it uses static buffer from int2str !!! */ + + get_avp_val(avp, &val); +- if (avp->flags & AVP_VAL_STR) { ++ if(avp->flags & AVP_VAL_STR) { + *dst = val.s; +- } +- else { /* probably (!) number */ ++ } else { /* probably (!) number */ + dst->s = int2str(val.n, &dst->len); + } + } + + int dpl_dyn_printf_s(sip_msg_t *msg, const pv_elem_p elem, +- const pv_elem_p avp_elem, str *val, pv_elem_p *elem_prev, str *vexpr) ++ const pv_elem_p avp_elem, str *val, pv_elem_p *elem_prev, str *vexpr) + { + pv_elem_p e = NULL; + pv_elem_p t = NULL; +@@ -70,45 +71,52 @@ int dpl_dyn_printf_s(sip_msg_t *msg, con + str v = STR_NULL; + int ret = -1; + +- if(elem==NULL||avp_elem==NULL||elem_prev==NULL||vexpr==NULL) return -1; +- if(str_append(&(avp_elem->text), val, &s)<0) return -1; ++ if(elem == NULL || avp_elem == NULL || elem_prev == NULL || vexpr == NULL) ++ return -1; ++ if(str_append(&(avp_elem->text), val, &s) < 0) ++ return -1; + +- if(pv_parse_format(&s, &e)<0) { ++ if(pv_parse_format(&s, &e) < 0) { + LM_ERR("parsing expression: %.*s\n", s.len, s.s); + goto clean; + } +- if(*elem_prev==NULL && elem!=avp_elem) { ++ if(*elem_prev == NULL && elem != avp_elem) { + LM_DBG("search for elem_prev\n"); +- for(t=elem; t!=NULL; t=t->next) { +- if(t->next==avp_elem) { *elem_prev = t; ++ for(t = elem; t != NULL; t = t->next) { ++ if(t->next == avp_elem) { ++ *elem_prev = t; + LM_DBG("found!\n"); + } + } + } +- if(*elem_prev) (*elem_prev)->next = e; ++ if(*elem_prev) ++ (*elem_prev)->next = e; + e->next = avp_elem->next; +- if(pv_printf_s(msg, e, &v)<0){ ++ if(pv_printf_s(msg, e, &v) < 0) { + LM_ERR("cannot get avp pcre dynamic expression value\n"); + goto clean; + } + /* pv_printf_s uses pv_get_buffer() we do need to copy */ + vexpr->len = v.len; +- vexpr->s = pkg_malloc(sizeof(char)*(v.len+1)); +- if(vexpr->s==NULL) { ++ vexpr->s = pkg_malloc(sizeof(char) * (v.len + 1)); ++ if(vexpr->s == NULL) { + PKG_MEM_ERROR; + goto clean; + } + strcpy(vexpr->s, v.s); + ret = 0; + clean: +- if(s.s) pkg_free(s.s); +- if(e) pkg_free(e); +- if(*elem_prev) (*elem_prev)->next = avp_elem; ++ if(s.s) ++ pkg_free(s.s); ++ if(e) ++ pkg_free(e); ++ if(*elem_prev) ++ (*elem_prev)->next = avp_elem; + return ret; + } + + int dpl_get_avp_values(sip_msg_t *msg, const pv_elem_p elem, +- const pv_elem_p avp_elem, struct str_list **out) ++ const pv_elem_p avp_elem, struct str_list **out) + { + struct usr_avp *avp = NULL; + unsigned short name_type; +@@ -120,16 +128,17 @@ int dpl_get_avp_values(sip_msg_t *msg, c + pv_elem_p elem_prev = NULL; + struct str_list *tl = NULL; + +- if(elem==NULL||avp_elem==NULL||out==NULL||*out==NULL) { ++ if(elem == NULL || avp_elem == NULL || out == NULL || *out == NULL) { + LM_ERR("wrong parameters\n"); + return -1; + } +- if(pv_get_avp_name(msg, &(avp_elem->spec->pvp), &avp_name, &name_type)!=0) { ++ if(pv_get_avp_name(msg, &(avp_elem->spec->pvp), &avp_name, &name_type) ++ != 0) { + LM_ERR("invalid avp name\n"); + return -1; + } + avp = search_first_avp(name_type, avp_name, &avp_value, &state); +- if(avp==NULL) { ++ if(avp == NULL) { + LM_ERR("can't find first avp\n"); + return -1; + } +@@ -139,10 +148,10 @@ int dpl_get_avp_values(sip_msg_t *msg, c + /*LM_DBG("elem[%p] avp_elem[%p], elem_prev[%p] [%.*s]\n", + elem, avp_elem, elem_prev, tl->s.len, tl->s.s);*/ + sum = tl->s.len; +- while ((avp=search_next_avp(&state, &avp_value))!=0) { ++ while((avp = search_next_avp(&state, &avp_value)) != 0) { + dpl_get_avp_val(avp, &s); + dpl_dyn_printf_s(msg, elem, avp_elem, &s, &elem_prev, &ts); +- if(append_str_list(ts.s, ts.len, &tl, &sum)==NULL) { ++ if(append_str_list(ts.s, ts.len, &tl, &sum) == NULL) { + while(*out) { + tl = (*out)->next; + pkg_free(*out); +@@ -160,18 +169,20 @@ int dpl_get_avp_values(sip_msg_t *msg, c + int dpl_detect_avp_indx(const pv_elem_p elem, pv_elem_p *avp) + { + int num, num_avp_all; +- pv_elem_p e = elem;; +- if(elem==NULL||avp==NULL) return -1; ++ pv_elem_p e = elem; ++ ; ++ if(elem == NULL || avp == NULL) ++ return -1; + +- for(e=elem, num=num_avp_all=0; e!=NULL; e=e->next, num++) { +- if(e->spec!=NULL && e->spec->type==PVT_AVP && +- e->spec->pvp.pvi.type==PV_IDX_ITR) +- { ++ for(e = elem, num = num_avp_all = 0; e != NULL; e = e->next, num++) { ++ if(e->spec != NULL && e->spec->type == PVT_AVP ++ && e->spec->pvp.pvi.type == PV_IDX_ITR) { + *avp = e; + num_avp_all++; + } + } +- if(num_avp_all==1) return 1; /* just one avp_indx supported */ ++ if(num_avp_all == 1) ++ return 1; /* just one avp_indx supported */ + return 0; + } + +@@ -180,29 +191,29 @@ pcre *dpl_dyn_pcre_comp(sip_msg_t *msg, + pcre *re = NULL; + int ccnt = 0; + +- if(expr==NULL || expr->s==NULL || expr->len<=0 || +- vexpr==NULL || vexpr->s==NULL || vexpr->len<=0) ++ if(expr == NULL || expr->s == NULL || expr->len <= 0 || vexpr == NULL ++ || vexpr->s == NULL || vexpr->len <= 0) + return NULL; + + re = reg_ex_comp(vexpr->s, &ccnt, 1); + if(!re) { +- if(expr!=vexpr) ++ if(expr != vexpr) + LM_ERR("failed to compile pcre expression: %.*s (%.*s)\n", +- expr->len, expr->s, vexpr->len, vexpr->s); ++ expr->len, expr->s, vexpr->len, vexpr->s); + else +- LM_ERR("failed to compile pcre expression: %.*s\n", +- vexpr->len, vexpr->s); ++ LM_ERR("failed to compile pcre expression: %.*s\n", vexpr->len, ++ vexpr->s); + return NULL; + } + if(cap_cnt) { + *cap_cnt = ccnt; + } +- if(expr!=vexpr) +- LM_DBG("compiled dynamic pcre expression: %.*s (%.*s) %d\n", +- expr->len, expr->s, vexpr->len, vexpr->s, ccnt); ++ if(expr != vexpr) ++ LM_DBG("compiled dynamic pcre expression: %.*s (%.*s) %d\n", expr->len, ++ expr->s, vexpr->len, vexpr->s, ccnt); + else +- LM_DBG("compiled dynamic pcre expression: %.*s %d\n", +- vexpr->len, vexpr->s, ccnt); ++ LM_DBG("compiled dynamic pcre expression: %.*s %d\n", vexpr->len, ++ vexpr->s, ccnt); + return re; + } + +@@ -218,35 +229,33 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip + int cnt = 0; + str vexpr = STR_NULL; + +- if(expr==NULL || expr->s==NULL || expr->len<=0) +- { ++ if(expr == NULL || expr->s == NULL || expr->len <= 0) { + LM_ERR("wrong parameters\n"); + return NULL; + } + +- if(pv_parse_format(expr, &elem)<0) { +- LM_ERR("parsing pcre expression: %.*s\n", +- expr->len, expr->s); ++ if(pv_parse_format(expr, &elem) < 0) { ++ LM_ERR("parsing pcre expression: %.*s\n", expr->len, expr->s); + return NULL; + } + LM_DBG("parsed pcre expression: %.*s\n", expr->len, expr->s); + if(dpl_detect_avp_indx(elem, &avp_elem)) { + l = pkg_malloc(sizeof(struct str_list)); +- if(l==NULL) { ++ if(l == NULL) { + PKG_MEM_ERROR; + goto error; + } + memset(l, 0, sizeof(struct str_list)); +- if(dpl_get_avp_values(msg, elem, avp_elem, &l)<0) { ++ if(dpl_get_avp_values(msg, elem, avp_elem, &l) < 0) { + LM_ERR("can't get list of avp values\n"); + goto error; + } + t = l; + while(t) { + re = dpl_dyn_pcre_comp(msg, &(t->s), &(t->s), &cnt); +- if(re!=NULL) { ++ if(re != NULL) { + rt = pkg_malloc(sizeof(dpl_dyn_pcre_t)); +- if(rt==NULL) { ++ if(rt == NULL) { + PKG_MEM_ERROR; + goto error; + } +@@ -259,17 +268,16 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip + } + t = t->next; + } +- } +- else { +- if(pv_printf_s(msg, elem, &vexpr)<0){ ++ } else { ++ if(pv_printf_s(msg, elem, &vexpr) < 0) { + LM_ERR("cannot get pcre dynamic expression value: %.*s\n", + expr->len, expr->s); + goto error; + } + re = dpl_dyn_pcre_comp(msg, expr, &vexpr, &cnt); +- if(re!=NULL) { ++ if(re != NULL) { + rt = pkg_malloc(sizeof(dpl_dyn_pcre_t)); +- if(rt==NULL) { ++ if(rt == NULL) { + PKG_MEM_ERROR; + goto error; + } +@@ -285,15 +293,18 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip + error: + while(re_list) { + rt = re_list->next; +- if(re_list->re) pcre_free(re_list->re); ++ if(re_list->re) ++ pcre_free(re_list->re); + pkg_free(re_list); + re_list = rt; + } + clean: +- if(elem) pv_elem_free_all(elem); ++ if(elem) ++ pv_elem_free_all(elem); + while(l) { + t = l->next; +- if(l->s.s) pkg_free(l->s.s); ++ if(l->s.s) ++ pkg_free(l->s.s); + pkg_free(l); + l = t; + } +@@ -305,7 +316,7 @@ void repl_expr_free(struct subst_expr *s + if(!se) + return; + +- if(se->replacement.s){ ++ if(se->replacement.s) { + shm_free(se->replacement.s); + se->replacement.s = 0; + } +@@ -315,13 +326,13 @@ void repl_expr_free(struct subst_expr *s + } + + +-struct subst_expr* repl_exp_parse(str subst) ++struct subst_expr *repl_exp_parse(str subst) + { + struct replace_with rw[MAX_REPLACE_WITH]; + int rw_no; +- struct subst_expr * se; ++ struct subst_expr *se; + int replace_all; +- char * p, *end, *repl, *repl_end; ++ char *p, *end, *repl, *repl_end; + int max_pmatch, r; + str shms; + +@@ -329,7 +340,7 @@ struct subst_expr* repl_exp_parse(str su + replace_all = 0; + shms.s = NULL; + +- if (!(shms.s=shm_malloc((subst.len+1) * sizeof(char))) ){ ++ if(!(shms.s = shm_malloc((subst.len + 1) * sizeof(char)))) { + LM_ERR("out of shm memory\n"); + goto error; + } +@@ -342,39 +353,41 @@ struct subst_expr* repl_exp_parse(str su + rw_no = 0; + + repl = p; +- if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITHOUT_SEP))< 0) { ++ if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITHOUT_SEP)) < 0) { + LM_ERR("parse repl failed\n"); + goto error; + } + +- repl_end=p; ++ repl_end = p; + + /* construct the subst_expr structure */ +- se = shm_malloc(sizeof(struct subst_expr)+ +- ((rw_no)?(rw_no-1)*sizeof(struct replace_with):0)); ++ se = shm_malloc( ++ sizeof(struct subst_expr) ++ + ((rw_no) ? (rw_no - 1) * sizeof(struct replace_with) : 0)); + /* 1 replace_with structure is already included in subst_expr */ +- if (se==0){ ++ if(se == 0) { + LM_ERR("out of shm memory (subst_expr)\n"); + goto error; + } +- memset((void*)se, 0, sizeof(struct subst_expr)); ++ memset((void *)se, 0, sizeof(struct subst_expr)); + + se->replacement.s = shms.s; + shms.s = NULL; +- se->replacement.len=repl_end-repl; +- if(!rw_no){ ++ se->replacement.len = repl_end - repl; ++ if(!rw_no) { + replace_all = 1; + } + /* start copying */ + LM_DBG("replacement expression is [%.*s]\n", se->replacement.len, + se->replacement.s); +- se->re=0; +- se->replace_all=replace_all; +- se->n_escapes=rw_no; +- se->max_pmatch=max_pmatch; ++ se->re = 0; ++ se->replace_all = replace_all; ++ se->n_escapes = rw_no; ++ se->max_pmatch = max_pmatch; + + /*replace_with is a simple structure, no shm alloc needed*/ +- for (r=0; rreplace[r]=rw[r]; ++ for(r = 0; r < rw_no; r++) ++ se->replace[r] = rw[r]; + return se; + + error: +@@ -384,17 +397,17 @@ error: + } + + +-#define MAX_PHONE_NB_DIGITS 127 +-static char dp_output_buf[MAX_PHONE_NB_DIGITS+1]; ++#define MAX_PHONE_NB_DIGITS 127 ++static char dp_output_buf[MAX_PHONE_NB_DIGITS + 1]; + int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule, + pcre *subst_comp, str *result) + { + int repl_nb, offset, match_nb, rc, cap_cnt; + struct replace_with token; +- struct subst_expr * repl_comp; ++ struct subst_expr *repl_comp; + str match; + pv_value_t sv; +- str* uri; ++ str *uri; + int ovector[3 * (MAX_REPLACE_WITH + 1)]; + char *p; + int size; +@@ -404,53 +417,50 @@ int rule_translate(sip_msg_t *msg, str * + result->len = 0; + + repl_comp = rule->repl_comp; +- if(!repl_comp){ ++ if(!repl_comp) { + LM_DBG("null replacement\n"); + return 0; + } + +- if(subst_comp){ ++ if(subst_comp) { + /*just in case something went wrong at load time*/ +- rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT, +- &cap_cnt); +- if (rc != 0) { +- LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n", +- rc); ++ rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT, &cap_cnt); ++ if(rc != 0) { ++ LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n", rc); + return -1; + } +- if(repl_comp->max_pmatch > cap_cnt){ ++ if(repl_comp->max_pmatch > cap_cnt) { + LM_ERR("illegal access to %i-th subexpr of subst expr (max %d)\n", + repl_comp->max_pmatch, cap_cnt); + return -1; + } +- if (rule->tflags&DP_TFLAGS_PV_SUBST && (cap_cnt > MAX_REPLACE_WITH)) { ++ if(rule->tflags & DP_TFLAGS_PV_SUBST && (cap_cnt > MAX_REPLACE_WITH)) { + LM_ERR("subst expression %.*s has too many sub-expressions\n", +- rule->subst_exp.len, rule->subst_exp.s); ++ rule->subst_exp.len, rule->subst_exp.s); + return -1; + } + + /*search for the pattern from the compiled subst_exp*/ +- if (pcre_exec(subst_comp, NULL, instr->s, instr->len, +- 0, 0, ovector, 3 * (MAX_REPLACE_WITH + 1)) <= 0) { ++ if(pcre_exec(subst_comp, NULL, instr->s, instr->len, 0, 0, ovector, ++ 3 * (MAX_REPLACE_WITH + 1)) ++ <= 0) { + LM_DBG("the string %.*s matched " +- "the match_exp %.*s but not the subst_exp %.*s!\n", +- instr->len, instr->s, +- rule->match_exp.len, rule->match_exp.s, +- rule->subst_exp.len, rule->subst_exp.s); ++ "the match_exp %.*s but not the subst_exp %.*s!\n", ++ instr->len, instr->s, rule->match_exp.len, ++ rule->match_exp.s, rule->subst_exp.len, rule->subst_exp.s); + return -1; + } + } + + /*simply copy from the replacing string*/ +- if(!subst_comp || (repl_comp->n_escapes <=0)){ +- if(!repl_comp->replacement.s || repl_comp->replacement.len == 0){ ++ if(!subst_comp || (repl_comp->n_escapes <= 0)) { ++ if(!repl_comp->replacement.s || repl_comp->replacement.len == 0) { + LM_ERR("invalid replacing string\n"); + goto error; + } + LM_DBG("simply replace the string, subst_comp %p, n_escapes %i\n", + subst_comp, repl_comp->n_escapes); +- memcpy(result->s, repl_comp->replacement.s, +- repl_comp->replacement.len); ++ memcpy(result->s, repl_comp->replacement.s, repl_comp->replacement.len); + result->len = repl_comp->replacement.len; + result->s[result->len] = '\0'; + return 0; +@@ -458,91 +468,90 @@ int rule_translate(sip_msg_t *msg, str * + + /* offset- offset in the replacement string */ + result->len = repl_nb = offset = 0; +- p=repl_comp->replacement.s; ++ p = repl_comp->replacement.s; + +- while( repl_nb < repl_comp->n_escapes){ ++ while(repl_nb < repl_comp->n_escapes) { + + token = repl_comp->replace[repl_nb]; + +- if(offset< token.offset){ +- if((repl_comp->replacement.len < offset)|| +- (result->len + token.offset -offset >= MAX_PHONE_NB_DIGITS)){ ++ if(offset < token.offset) { ++ if((repl_comp->replacement.len < offset) ++ || (result->len + token.offset - offset ++ >= MAX_PHONE_NB_DIGITS)) { + LM_ERR("invalid length\n"); + goto error; + } + /*copy from the replacing string*/ + size = token.offset - offset; + memcpy(result->s + result->len, p + offset, size); +- LM_DBG("copying <%.*s> from replacing string\n", +- size, p + offset); ++ LM_DBG("copying <%.*s> from replacing string\n", size, p + offset); + result->len += size; + offset = token.offset; + } + + switch(token.type) { + case REPLACE_NMATCH: +- /*copy from the match subexpression*/ ++ /*copy from the match subexpression*/ + match_nb = token.u.nmatch * 2; +- match.s = instr->s + ovector[match_nb]; ++ match.s = instr->s + ovector[match_nb]; + match.len = ovector[match_nb + 1] - ovector[match_nb]; +- if(result->len + match.len >= MAX_PHONE_NB_DIGITS){ ++ if(result->len + match.len >= MAX_PHONE_NB_DIGITS) { + LM_ERR("overflow\n"); + goto error; + } + + memcpy(result->s + result->len, match.s, match.len); +- LM_DBG("copying match <%.*s> token size %d\n", +- match.len, match.s, token.size); ++ LM_DBG("copying match <%.*s> token size %d\n", match.len, ++ match.s, token.size); + result->len += match.len; + offset += token.size; + break; + case REPLACE_CHAR: +- if(result->len + 1>= MAX_PHONE_NB_DIGITS){ ++ if(result->len + 1 >= MAX_PHONE_NB_DIGITS) { + LM_ERR("overflow\n"); + goto error; + } + *(result->s + result->len) = token.u.c; +- LM_DBG("copying char <%c> token size %d\n", +- token.u.c, token.size); ++ LM_DBG("copying char <%c> token size %d\n", token.u.c, ++ token.size); + result->len++; + offset += token.size; + break; +- case REPLACE_URI: +- if ( msg== NULL || msg->first_line.type!=SIP_REQUEST){ ++ case REPLACE_URI: ++ if(msg == NULL || msg->first_line.type != SIP_REQUEST) { + LM_CRIT("uri substitution attempt on no request" + " message\n"); + break; /* ignore, we can continue */ + } +- uri= (msg->new_uri.s)?(&msg->new_uri): +- (&msg->first_line.u.request.uri); +- if(result->len+uri->len>=MAX_PHONE_NB_DIGITS){ ++ uri = (msg->new_uri.s) ? (&msg->new_uri) ++ : (&msg->first_line.u.request.uri); ++ if(result->len + uri->len >= MAX_PHONE_NB_DIGITS) { + LM_ERR("overflow\n"); + goto error; + } + memcpy(result->s + result->len, uri->s, uri->len); +- LM_DBG("copying uri <%.*s> token size %d\n", +- uri->len, uri->s, token.size); +- result->len+=uri->len; ++ LM_DBG("copying uri <%.*s> token size %d\n", uri->len, uri->s, ++ token.size); ++ result->len += uri->len; + offset += token.size; + break; + case REPLACE_SPEC: +- if (msg== NULL) { ++ if(msg == NULL) { + LM_DBG("replace spec attempted on no message\n"); + break; + } +- if (pv_get_spec_value(msg, &token.u.spec, &sv) != 0) { ++ if(pv_get_spec_value(msg, &token.u.spec, &sv) != 0) { + LM_CRIT("item substitution returned error\n"); + break; /* ignore, we can continue */ + } +- if(result->len+sv.rs.len>=MAX_PHONE_NB_DIGITS){ ++ if(result->len + sv.rs.len >= MAX_PHONE_NB_DIGITS) { + LM_ERR("rule_translate: overflow\n"); + goto error; + } +- memcpy(result->s + result->len, sv.rs.s, +- sv.rs.len); +- LM_DBG("copying pvar value <%.*s> token size %d\n", +- sv.rs.len, sv.rs.s, token.size); +- result->len+=sv.rs.len; ++ memcpy(result->s + result->len, sv.rs.s, sv.rs.len); ++ LM_DBG("copying pvar value <%.*s> token size %d\n", sv.rs.len, ++ sv.rs.s, token.size); ++ result->len += sv.rs.len; + offset += token.size; + break; + default: +@@ -552,12 +561,12 @@ int rule_translate(sip_msg_t *msg, str * + repl_nb++; + } + /* anything left? */ +- if( repl_nb && offset < repl_comp->replacement.len){ ++ if(repl_nb && offset < repl_comp->replacement.len) { + /*copy from the replacing string*/ + size = repl_comp->replacement.len - offset; + memcpy(result->s + result->len, p + offset, size); +- LM_DBG("copying leftover <%.*s> from replacing string\n", +- size, p + offset); ++ LM_DBG("copying leftover <%.*s> from replacing string\n", size, ++ p + offset); + result->len += size; + } + +@@ -570,10 +579,10 @@ error: + return -1; + } + +-#define DP_MAX_ATTRS_LEN 255 +-static char dp_attrs_buf[DP_MAX_ATTRS_LEN+1]; +-int dp_translate_helper(sip_msg_t *msg, str *input, str *output, dpl_id_p idp, +- str *attrs) ++#define DP_MAX_ATTRS_LEN 255 ++static char dp_attrs_buf[DP_MAX_ATTRS_LEN + 1]; ++int dp_translate_helper( ++ sip_msg_t *msg, str *input, str *output, dpl_id_p idp, str *attrs) + { + dpl_node_p rulep; + dpl_index_p indexp; +@@ -588,70 +597,70 @@ int dp_translate_helper(sip_msg_t *msg, + } + + user_len = input->len; +- for(indexp = idp->first_index; indexp!=NULL; indexp = indexp->next) +- if(!indexp->len || (indexp->len!=0 && indexp->len == user_len) ) ++ for(indexp = idp->first_index; indexp != NULL; indexp = indexp->next) ++ if(!indexp->len || (indexp->len != 0 && indexp->len == user_len)) + break; + +- if(!indexp || (indexp!= NULL && !indexp->first_rule)){ ++ if(!indexp || (indexp != NULL && !indexp->first_rule)) { + LM_DBG("no rule for len %i\n", input->len); + return -1; + } + + search_rule: +- for(rulep=indexp->first_rule; rulep!=NULL; rulep= rulep->next) { ++ for(rulep = indexp->first_rule; rulep != NULL; rulep = rulep->next) { + switch(rulep->matchop) { + + case DP_REGEX_OP: +- LM_DBG("regex operator testing over [%.*s]\n", +- input->len, input->s); +- if(rulep->tflags&DP_TFLAGS_PV_MATCH) { ++ LM_DBG("regex operator testing over [%.*s]\n", input->len, ++ input->s); ++ if(rulep->tflags & DP_TFLAGS_PV_MATCH) { + re_list = dpl_dynamic_pcre_list(msg, &rulep->match_exp); +- if(re_list==NULL) { ++ if(re_list == NULL) { + /* failed to compile dynamic pcre -- ignore */ + LM_DBG("failed to compile dynamic pcre[%.*s]\n", +- rulep->match_exp.len, rulep->match_exp.s); ++ rulep->match_exp.len, rulep->match_exp.s); + continue; + } + rez = -1; + do { +- if(rez<0) { +- rez = pcre_exec(re_list->re, NULL, input->s, input->len, +- 0, 0, NULL, 0); ++ if(rez < 0) { ++ rez = pcre_exec(re_list->re, NULL, input->s, ++ input->len, 0, 0, NULL, 0); + LM_DBG("match check: [%.*s] %d\n", +- re_list->expr.len, re_list->expr.s, rez); +- } +- else LM_DBG("match check skipped: [%.*s] %d\n", +- re_list->expr.len, re_list->expr.s, rez); ++ re_list->expr.len, re_list->expr.s, rez); ++ } else ++ LM_DBG("match check skipped: [%.*s] %d\n", ++ re_list->expr.len, re_list->expr.s, rez); + rt = re_list->next; + pcre_free(re_list->re); + pkg_free(re_list); + re_list = rt; + } while(re_list); + } else { +- rez = pcre_exec(rulep->match_comp, NULL, input->s, input->len, +- 0, 0, NULL, 0); ++ rez = pcre_exec(rulep->match_comp, NULL, input->s, ++ input->len, 0, 0, NULL, 0); + } + break; + + case DP_EQUAL_OP: + LM_DBG("equal operator testing\n"); +- if(rulep->match_exp.s==NULL ++ if(rulep->match_exp.s == NULL + || rulep->match_exp.len != input->len) { + rez = -1; + } else { + rez = strncmp(rulep->match_exp.s, input->s, input->len); +- rez = (rez==0)?0:-1; ++ rez = (rez == 0) ? 0 : -1; + } + break; + + case DP_FNMATCH_OP: + LM_DBG("fnmatch operator testing\n"); +- if(rulep->match_exp.s!=NULL) { ++ if(rulep->match_exp.s != NULL) { + b = input->s[input->len]; + input->s[input->len] = '\0'; + rez = fnmatch(rulep->match_exp.s, input->s, 0); + input->s[input->len] = b; +- rez = (rez==0)?0:-1; ++ rez = (rez == 0) ? 0 : -1; + } else { + rez = -1; + } +@@ -665,8 +674,8 @@ search_rule: + goto repl; + } + /*test the rules with len 0*/ +- if(indexp->len){ +- for(indexp = indexp->next; indexp!=NULL; indexp = indexp->next) ++ if(indexp->len) { ++ for(indexp = indexp->next; indexp != NULL; indexp = indexp->next) + if(!indexp->len) + break; + if(indexp) +@@ -677,63 +686,61 @@ search_rule: + return -1; + + repl: +- LM_DBG("found a matching rule %p: pr %i, match_exp %.*s\n", +- rulep, rulep->pr, rulep->match_exp.len, rulep->match_exp.s); ++ LM_DBG("found a matching rule %p: pr %i, match_exp %.*s\n", rulep, ++ rulep->pr, rulep->match_exp.len, rulep->match_exp.s); + + if(attrs) { + attrs->len = 0; + attrs->s = 0; +- if(rulep->attrs.len>0) { +- LM_DBG("the rule's attrs are %.*s\n", +- rulep->attrs.len, rulep->attrs.s); ++ if(rulep->attrs.len > 0) { ++ LM_DBG("the rule's attrs are %.*s\n", rulep->attrs.len, ++ rulep->attrs.s); + if(rulep->attrs.len >= DP_MAX_ATTRS_LEN) { + LM_ERR("out of memory for attributes\n"); + return -1; + } + attrs->s = dp_attrs_buf; +- memcpy(attrs->s, rulep->attrs.s, rulep->attrs.len*sizeof(char)); ++ memcpy(attrs->s, rulep->attrs.s, rulep->attrs.len * sizeof(char)); + attrs->len = rulep->attrs.len; + attrs->s[attrs->len] = '\0'; + +- LM_DBG("the copied attributes are: %.*s\n", +- attrs->len, attrs->s); ++ LM_DBG("the copied attributes are: %.*s\n", attrs->len, attrs->s); + } + } + if(!output) { + return 0; + } +- if(rulep->tflags&DP_TFLAGS_PV_SUBST) { ++ if(rulep->tflags & DP_TFLAGS_PV_SUBST) { + re_list = dpl_dynamic_pcre_list(msg, &rulep->subst_exp); +- if(re_list==NULL) { ++ if(re_list == NULL) { + /* failed to compile dynamic pcre -- ignore */ + LM_DBG("failed to compile dynamic pcre[%.*s]\n", +- rulep->subst_exp.len, rulep->subst_exp.s); ++ rulep->subst_exp.len, rulep->subst_exp.s); + return -1; + } + rez = -1; + do { +- if(rez<0) { ++ if(rez < 0) { + rez = rule_translate(msg, input, rulep, re_list->re, output); +- LM_DBG("subst check: [%.*s] %d\n", +- re_list->expr.len, re_list->expr.s, rez); +- } +- else LM_DBG("subst check skipped: [%.*s] %d\n", +- re_list->expr.len, re_list->expr.s, rez); ++ LM_DBG("subst check: [%.*s] %d\n", re_list->expr.len, ++ re_list->expr.s, rez); ++ } else ++ LM_DBG("subst check skipped: [%.*s] %d\n", re_list->expr.len, ++ re_list->expr.s, rez); + rt = re_list->next; + pcre_free(re_list->re); + pkg_free(re_list); + re_list = rt; + } while(re_list); +- if(rez<0) { ++ if(rez < 0) { + LM_ERR("the string %.*s matched " +- "the match_exp %.*s but not the subst_exp %.*s!\n", +- input->len, input->s, +- rulep->match_exp.len, rulep->match_exp.s, +- rulep->subst_exp.len, rulep->subst_exp.s); ++ "the match_exp %.*s but not the subst_exp %.*s!\n", ++ input->len, input->s, rulep->match_exp.len, ++ rulep->match_exp.s, rulep->subst_exp.len, ++ rulep->subst_exp.s); + } +- } +- else { +- if(rule_translate(msg, input, rulep, rulep->subst_comp, output)!=0){ ++ } else { ++ if(rule_translate(msg, input, rulep, rulep->subst_comp, output) != 0) { + LM_ERR("could not build the output\n"); + return -1; + } diff --git a/net/kamailio/patches/011-dialplan-migrate-to-pcre2.patch b/net/kamailio/patches/011-dialplan-migrate-to-pcre2.patch new file mode 100644 index 0000000..23eede0 --- /dev/null +++ b/net/kamailio/patches/011-dialplan-migrate-to-pcre2.patch @@ -0,0 +1,456 @@ +From 374227b15ff7fbed8660beb93d52da15dcb4ba9e Mon Sep 17 00:00:00 2001 +From: Victor Seva +Date: Mon, 21 Aug 2023 12:27:43 +0200 +Subject: [PATCH] dialplan: migrate to pcre2 + +--- + src/modules/dialplan/Makefile | 11 +--- + src/modules/dialplan/dialplan.c | 5 ++ + src/modules/dialplan/dialplan.h | 20 ++++--- + src/modules/dialplan/dp_db.c | 103 +++++++++++++++++++------------- + src/modules/dialplan/dp_repl.c | 56 +++++++++++------ + 5 files changed, 121 insertions(+), 74 deletions(-) + +--- a/src/modules/dialplan/Makefile ++++ b/src/modules/dialplan/Makefile +@@ -6,20 +6,15 @@ auto_gen= + NAME=dialplan.so + + ifeq ($(CROSS_COMPILE),) +-PCRE_BUILDER = $(shell \ +- if pkg-config --exists libcre; then \ +- echo 'pkg-config libpcre'; \ +- else \ +- which pcre-config; \ +- fi) ++PCRE_BUILDER = $(shell command -v pcre2-config) + endif + + ifeq ($(PCRE_BUILDER),) + PCREDEFS=-I$(LOCALBASE)/include +- PCRELIBS=-L$(LOCALBASE)/lib -lpcre ++ PCRELIBS=-L$(LOCALBASE)/lib -lpcre2-8 + else + PCREDEFS = $(shell $(PCRE_BUILDER) --cflags) +- PCRELIBS = $(shell $(PCRE_BUILDER) --libs) ++ PCRELIBS = $(shell $(PCRE_BUILDER) --libs8) + endif + DEFS+=$(PCREDEFS) + LIBS=$(PCRELIBS) +--- a/src/modules/dialplan/dialplan.c ++++ b/src/modules/dialplan/dialplan.c +@@ -5,6 +5,8 @@ + * + * Copyright (C) 2014 Olle E. Johansson, Edvina AB + * ++ * Copyright (C) 2023 Victor Seva ++ * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify +@@ -79,6 +81,9 @@ static int ki_dp_translate_vars( + int dp_replace_fixup(void **param, int param_no); + int dp_replace_fixup_free(void **param, int param_no); + ++pcre2_general_context *dpl_gctx = NULL; ++pcre2_compile_context *dpl_ctx = NULL; ++ + str dp_attr_pvar_s = STR_NULL; + pv_spec_t *dp_attr_pvar = NULL; + +--- a/src/modules/dialplan/dialplan.h ++++ b/src/modules/dialplan/dialplan.h +@@ -13,8 +13,8 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +@@ -30,7 +30,8 @@ + #ifndef _DP_DIALPLAN_H + #define _DP_DIALPLAN_H + +-#include ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + #include "../../core/pvar.h" + #include "../../core/parser/msg_parser.h" + +@@ -43,6 +44,9 @@ + #define DP_TFLAGS_PV_MATCH (1 << 0) + #define DP_TFLAGS_PV_SUBST (1 << 1) + ++extern pcre2_general_context *dpl_gctx; ++extern pcre2_compile_context *dpl_ctx; ++ + typedef struct dpl_node + { + int dpid; /* dialplan id */ +@@ -52,8 +56,8 @@ typedef struct dpl_node + str match_exp; /* match-first string */ + str subst_exp; /* match string with subtitution groupping */ + str repl_exp; /* replacement expression string */ +- pcre *match_comp; /* compiled matching expression */ +- pcre *subst_comp; /* compiled substitution expression */ ++ pcre2_code *match_comp; /* compiled matching expression */ ++ pcre2_code *subst_comp; /* compiled substitution expression */ + struct subst_expr *repl_comp; /* compiled replacement */ + str attrs; /* attributes string */ + unsigned int tflags; /* flags for type of values for matching */ +@@ -103,8 +107,8 @@ struct subst_expr *repl_exp_parse(str su + void repl_expr_free(struct subst_expr *se); + int dp_translate_helper( + sip_msg_t *msg, str *user_name, str *repl_user, dpl_id_p idp, str *); +-int rule_translate( +- sip_msg_t *msg, str *instr, dpl_node_t *rule, pcre *subst_comp, str *); ++int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule, ++ pcre2_code *subst_comp, str *); + +-pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype); ++pcre2_code *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype); + #endif +--- a/src/modules/dialplan/dp_db.c ++++ b/src/modules/dialplan/dp_db.c +@@ -196,11 +196,31 @@ void dp_disconnect_db(void) + } + } + ++static void *pcre2_malloc(size_t size, void *ext) ++{ ++ return shm_malloc(size); ++} ++ ++static void pcre2_free(void *ptr, void *ext) ++{ ++ shm_free(ptr); ++ ptr = NULL; ++} + + int init_data(void) + { + int *p; + ++ if((dpl_gctx = pcre2_general_context_create(pcre2_malloc, pcre2_free, NULL)) ++ == NULL) { ++ LM_ERR("pcre2 general context creation failed\n"); ++ return -1; ++ } ++ if((dpl_ctx = pcre2_compile_context_create(dpl_gctx)) == NULL) { ++ LM_ERR("pcre2 compile context creation failed\n"); ++ return -1; ++ } ++ + dp_rules_hash = (dpl_id_p *)shm_malloc(2 * sizeof(dpl_id_p)); + if(!dp_rules_hash) { + LM_ERR("out of shm memory\n"); +@@ -227,6 +247,14 @@ int init_data(void) + + void destroy_data(void) + { ++ if(dpl_ctx) { ++ pcre2_compile_context_free(dpl_ctx); ++ } ++ ++ if(dpl_gctx) { ++ pcre2_general_context_free(dpl_gctx); ++ } ++ + if(dp_rules_hash) { + destroy_hash(0); + destroy_hash(1); +@@ -373,55 +401,50 @@ int dpl_str_to_shm(str src, str *dest, i + + + /* Compile pcre pattern +- * if mtype==0 - return pointer to shm copy of result +- * if mtype==1 - return pcre pointer that has to be pcre_free() */ +-pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype) +-{ +- pcre *re, *result; +- const char *error; +- int rc, err_offset; +- size_t size; ++ * if mtype==0 - return pointer using shm ++ * if mtype==1 - return pcre2_code pointer that has to be pcre2_code_free() */ ++pcre2_code *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype) ++{ ++ pcre2_code *re; ++ int pcre_error_num = 0; ++ char pcre_error[128]; ++ size_t pcre_erroffset; ++ int rc; + +- re = pcre_compile(pattern, 0, &error, &err_offset, NULL); ++ re = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0, ++ &pcre_error_num, &pcre_erroffset, mtype == 0 ? dpl_ctx : NULL); + if(re == NULL) { +- LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n", pattern, +- err_offset, error); +- return (pcre *)0; +- } +- rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size); +- if(rc != 0) { +- pcre_free(re); +- LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n", +- pattern, rc); +- return (pcre *)0; ++ switch(pcre2_get_error_message( ++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) { ++ case PCRE2_ERROR_NOMEMORY: ++ snprintf(pcre_error, 128, ++ "unknown error[%d]: pcre2 error buffer too small", ++ pcre_error_num); ++ break; ++ case PCRE2_ERROR_BADDATA: ++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]", ++ pcre_error_num); ++ break; ++ } ++ LM_ERR("PCRE compilation of '%s' failed at offset %zu: %s\n", pattern, ++ pcre_erroffset, pcre_error); ++ return NULL; + } +- rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, cap_cnt); ++ rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, cap_cnt); + if(rc != 0) { +- pcre_free(re); ++ pcre2_code_free(re); + LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n", + pattern, rc); +- return (pcre *)0; +- } +- if(mtype == 0) { +- result = (pcre *)shm_malloc(size); +- if(result == NULL) { +- pcre_free(re); +- LM_ERR("not enough shared memory for compiled PCRE pattern\n"); +- return (pcre *)0; +- } +- memcpy(result, re, size); +- pcre_free(re); +- return result; +- } else { +- return re; ++ return NULL; + } ++ return re; + } + + + /*compile the expressions, and if ok, build the rule */ + dpl_node_t *build_rule(db_val_t *values) + { +- pcre *match_comp, *subst_comp; ++ pcre2_code *match_comp, *subst_comp; + struct subst_expr *repl_comp; + dpl_node_t *new_rule; + str match_exp, subst_exp, repl_exp, attrs; +@@ -544,9 +567,9 @@ dpl_node_t *build_rule(db_val_t *values) + + err: + if(match_comp) +- shm_free(match_comp); ++ pcre2_code_free(match_comp); + if(subst_comp) +- shm_free(subst_comp); ++ pcre2_code_free(subst_comp); + if(repl_comp) + repl_expr_free(repl_comp); + if(new_rule) +@@ -692,10 +715,10 @@ void destroy_rule(dpl_node_t *rule) + LM_DBG("destroying rule with priority %i\n", rule->pr); + + if(rule->match_comp) +- shm_free(rule->match_comp); ++ pcre2_code_free(rule->match_comp); + + if(rule->subst_comp) +- shm_free(rule->subst_comp); ++ pcre2_code_free(rule->subst_comp); + + /*destroy repl_exp*/ + if(rule->repl_comp) +--- a/src/modules/dialplan/dp_repl.c ++++ b/src/modules/dialplan/dp_repl.c +@@ -15,8 +15,8 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +@@ -38,7 +38,7 @@ + + typedef struct dpl_dyn_pcre + { +- pcre *re; ++ pcre2_code *re; + int cnt; + str expr; + +@@ -186,9 +186,10 @@ int dpl_detect_avp_indx(const pv_elem_p + return 0; + } + +-pcre *dpl_dyn_pcre_comp(sip_msg_t *msg, str *expr, str *vexpr, int *cap_cnt) ++pcre2_code *dpl_dyn_pcre_comp( ++ sip_msg_t *msg, str *expr, str *vexpr, int *cap_cnt) + { +- pcre *re = NULL; ++ pcre2_code *re = NULL; + int ccnt = 0; + + if(expr == NULL || expr->s == NULL || expr->len <= 0 || vexpr == NULL +@@ -225,7 +226,7 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip + dpl_dyn_pcre_p rt = NULL; + struct str_list *l = NULL; + struct str_list *t = NULL; +- pcre *re = NULL; ++ pcre2_code *re = NULL; + int cnt = 0; + str vexpr = STR_NULL; + +@@ -294,7 +295,7 @@ error: + while(re_list) { + rt = re_list->next; + if(re_list->re) +- pcre_free(re_list->re); ++ pcre2_code_free(re_list->re); + pkg_free(re_list); + re_list = rt; + } +@@ -400,15 +401,16 @@ error: + #define MAX_PHONE_NB_DIGITS 127 + static char dp_output_buf[MAX_PHONE_NB_DIGITS + 1]; + int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule, +- pcre *subst_comp, str *result) ++ pcre2_code *subst_comp, str *result) + { + int repl_nb, offset, match_nb, rc, cap_cnt; + struct replace_with token; + struct subst_expr *repl_comp; ++ pcre2_match_data *pcre_md = NULL; + str match; + pv_value_t sv; + str *uri; +- int ovector[3 * (MAX_REPLACE_WITH + 1)]; ++ PCRE2_SIZE *ovector = NULL; + char *p; + int size; + +@@ -424,7 +426,7 @@ int rule_translate(sip_msg_t *msg, str * + + if(subst_comp) { + /*just in case something went wrong at load time*/ +- rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT, &cap_cnt); ++ rc = pcre2_pattern_info(subst_comp, PCRE2_INFO_CAPTURECOUNT, &cap_cnt); + if(rc != 0) { + LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n", rc); + return -1; +@@ -441,15 +443,19 @@ int rule_translate(sip_msg_t *msg, str * + } + + /*search for the pattern from the compiled subst_exp*/ +- if(pcre_exec(subst_comp, NULL, instr->s, instr->len, 0, 0, ovector, +- 3 * (MAX_REPLACE_WITH + 1)) ++ pcre_md = pcre2_match_data_create_from_pattern(subst_comp, NULL); ++ if(pcre2_match(subst_comp, (PCRE2_SPTR)instr->s, (PCRE2_SIZE)instr->len, ++ 0, 0, pcre_md, NULL) + <= 0) { + LM_DBG("the string %.*s matched " + "the match_exp %.*s but not the subst_exp %.*s!\n", + instr->len, instr->s, rule->match_exp.len, + rule->match_exp.s, rule->subst_exp.len, rule->subst_exp.s); ++ if(pcre_md) ++ pcre2_match_data_free(pcre_md); + return -1; + } ++ ovector = pcre2_get_ovector_pointer(pcre_md); + } + + /*simply copy from the replacing string*/ +@@ -463,6 +469,8 @@ int rule_translate(sip_msg_t *msg, str * + memcpy(result->s, repl_comp->replacement.s, repl_comp->replacement.len); + result->len = repl_comp->replacement.len; + result->s[result->len] = '\0'; ++ if(pcre_md) ++ pcre2_match_data_free(pcre_md); + return 0; + } + +@@ -571,11 +579,15 @@ int rule_translate(sip_msg_t *msg, str * + } + + result->s[result->len] = '\0'; ++ if(pcre_md) ++ pcre2_match_data_free(pcre_md); + return 0; + + error: + result->s = 0; + result->len = 0; ++ if(pcre_md) ++ pcre2_match_data_free(pcre_md); + return -1; + } + +@@ -584,6 +596,7 @@ static char dp_attrs_buf[DP_MAX_ATTRS_LE + int dp_translate_helper( + sip_msg_t *msg, str *input, str *output, dpl_id_p idp, str *attrs) + { ++ pcre2_match_data *pcre_md = NULL; + dpl_node_p rulep; + dpl_index_p indexp; + int user_len, rez; +@@ -624,21 +637,28 @@ search_rule: + rez = -1; + do { + if(rez < 0) { +- rez = pcre_exec(re_list->re, NULL, input->s, +- input->len, 0, 0, NULL, 0); ++ pcre_md = pcre2_match_data_create_from_pattern( ++ re_list->re, NULL); ++ rez = pcre2_match(re_list->re, (PCRE2_SPTR)input->s, ++ (PCRE2_SIZE)input->len, 0, 0, pcre_md, ++ NULL); + LM_DBG("match check: [%.*s] %d\n", + re_list->expr.len, re_list->expr.s, rez); + } else + LM_DBG("match check skipped: [%.*s] %d\n", + re_list->expr.len, re_list->expr.s, rez); + rt = re_list->next; +- pcre_free(re_list->re); ++ pcre2_match_data_free(pcre_md); ++ pcre2_code_free(re_list->re); + pkg_free(re_list); + re_list = rt; + } while(re_list); + } else { +- rez = pcre_exec(rulep->match_comp, NULL, input->s, +- input->len, 0, 0, NULL, 0); ++ pcre_md = pcre2_match_data_create_from_pattern( ++ rulep->match_comp, NULL); ++ rez = pcre2_match(rulep->match_comp, (PCRE2_SPTR)input->s, ++ (PCRE2_SIZE)input->len, 0, 0, pcre_md, 0); ++ pcre2_match_data_free(pcre_md); + } + break; + +@@ -728,7 +748,7 @@ repl: + LM_DBG("subst check skipped: [%.*s] %d\n", re_list->expr.len, + re_list->expr.s, rez); + rt = re_list->next; +- pcre_free(re_list->re); ++ pcre2_code_free(re_list->re); + pkg_free(re_list); + re_list = rt; + } while(re_list); diff --git a/net/kamailio/patches/020-lcr-clang-format-for-coherent-indentation-and-coding.patch b/net/kamailio/patches/020-lcr-clang-format-for-coherent-indentation-and-coding.patch new file mode 100644 index 0000000..8a5447c --- /dev/null +++ b/net/kamailio/patches/020-lcr-clang-format-for-coherent-indentation-and-coding.patch @@ -0,0 +1,510 @@ +From ecc2c9e54fa8f24c1e96860c1f59b43f2e1e8b7a Mon Sep 17 00:00:00 2001 +From: Victor Seva +Date: Wed, 17 May 2023 16:36:55 +0200 +Subject: [PATCH] lcr: clang-format for coherent indentation and coding style + +--- + src/modules/lcr/lcr_mod.c | 125 +++++++++++++++++++++----------------- + src/modules/lcr/lcr_rpc.c | 65 ++++++++++---------- + 2 files changed, 102 insertions(+), 88 deletions(-) + +--- a/src/modules/lcr/lcr_mod.c ++++ b/src/modules/lcr/lcr_mod.c +@@ -259,7 +259,8 @@ static int inactivate_gw(struct sip_msg + static int defunct_gw(struct sip_msg *_m, char *_s1, char *_s2); + static int from_gw_1(struct sip_msg *_m, char *_s1, char *_s2); + static int from_gw_3(struct sip_msg *_m, char *_s1, char *_s2, char *_s3); +-static int from_gw_4(struct sip_msg *_m, char *_s1, char *_s2, char *_s3, char *_s4); ++static int from_gw_4( ++ struct sip_msg *_m, char *_s1, char *_s2, char *_s3, char *_s4); + static int from_any_gw_0(struct sip_msg *_m, char *_s1, char *_s2); + static int from_any_gw_2(struct sip_msg *_m, char *_s1, char *_s2); + static int from_any_gw_3(struct sip_msg *_m, char *_s1, char *_s2, char *_s3); +@@ -554,7 +555,8 @@ static int mod_init(void) + LM_ERR("malformed or non AVP definition <%s>\n", rule_id_avp_param); + return -1; + } +- if(pv_get_avp_name(0, &(avp_spec->pvp), &rule_id_avp, &avp_flags) != 0) { ++ if(pv_get_avp_name(0, &(avp_spec->pvp), &rule_id_avp, &avp_flags) ++ != 0) { + LM_ERR("invalid AVP definition <%s>\n", rule_id_avp_param); + return -1; + } +@@ -680,18 +682,21 @@ static int mod_init(void) + LM_ERR("unable to open database connection\n"); + return -1; + } +- if(db_check_table_version(&lcr_dbf, dbh, &lcr_rule_table, +- LCR_RULE_TABLE_VERSION) < 0) { ++ if(db_check_table_version( ++ &lcr_dbf, dbh, &lcr_rule_table, LCR_RULE_TABLE_VERSION) ++ < 0) { + DB_TABLE_VERSION_ERROR(lcr_rule_table); + goto dberror; + } + if(db_check_table_version(&lcr_dbf, dbh, &lcr_rule_target_table, +- LCR_RULE_TARGET_TABLE_VERSION) < 0) { ++ LCR_RULE_TARGET_TABLE_VERSION) ++ < 0) { + DB_TABLE_VERSION_ERROR(lcr_rule_target_table); + goto dberror; + } +- if (db_check_table_version(&lcr_dbf, dbh, &lcr_gw_table, +- LCR_GW_TABLE_VERSION) < 0) { ++ if(db_check_table_version( ++ &lcr_dbf, dbh, &lcr_gw_table, LCR_GW_TABLE_VERSION) ++ < 0) { + DB_TABLE_VERSION_ERROR(lcr_gw_table); + goto dberror; + } +@@ -923,20 +928,24 @@ static int comp_gws(const void *_g1, con + /* + * Compare a gateway using IP address and the src port + */ +-static struct gw_info * find_gateway_by_ip_and_port(struct gw_info * gw, struct gw_info * gws) { ++static struct gw_info *find_gateway_by_ip_and_port( ++ struct gw_info *gw, struct gw_info *gws) ++{ + int tmp = 0, gw_index = 0, i; + +- for (i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) { +- tmp = memcmp(gws[i].ip_addr.u.addr, gw->ip_addr.u.addr, gws[i].ip_addr.len); +- if (gws[i].ip_addr.af == gw->ip_addr.af && +- gws[i].ip_addr.len == gw->ip_addr.len && +- tmp == 0 && /* a comparison of the IP address value */ +- gws[i].port == gw->port) { +- gw_index = i; +- break; ++ for(i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) { ++ tmp = memcmp( ++ gws[i].ip_addr.u.addr, gw->ip_addr.u.addr, gws[i].ip_addr.len); ++ if(gws[i].ip_addr.af == gw->ip_addr.af ++ && gws[i].ip_addr.len == gw->ip_addr.len && tmp == 0 ++ && /* a comparison of the IP address value */ ++ gws[i].port == gw->port) { ++ gw_index = i; ++ break; + } + } +- if (gw_index != 0) return &(gws[gw_index]); ++ if(gw_index != 0) ++ return &(gws[gw_index]); + + return NULL; + } +@@ -1074,7 +1083,7 @@ static int insert_gws(db1_res_t *res, st + row = RES_ROWS(res) + i; + if((VAL_NULL(ROW_VALUES(row) + 12) == 1) + || ((VAL_TYPE(ROW_VALUES(row) + 12) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row) + 12) != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row) + 12) != DB1_UINT))) { + LM_ERR("lcr_gw id at row <%u> is null or not int\n", i); + return 0; + } +@@ -1501,8 +1510,7 @@ int reload_tables() + + if((VAL_NULL(ROW_VALUES(row)) == 1) + || ((VAL_TYPE(ROW_VALUES(row)) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row)) +- != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row)) != DB1_UINT))) { + LM_ERR("lcr rule id at row <%u> is null or not int\n", i); + goto err; + } +@@ -1544,8 +1552,8 @@ int reload_tables() + + if((VAL_NULL(ROW_VALUES(row) + 3) == 1) + || ((VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row) + 3) +- != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row) + 3) ++ != DB1_UINT))) { + LM_ERR("lcr rule <%u> stopper is NULL or not int\n", + rule_id); + goto err; +@@ -1558,8 +1566,8 @@ int reload_tables() + + if((VAL_NULL(ROW_VALUES(row) + 4) == 1) + || ((VAL_TYPE(ROW_VALUES(row) + 4) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row) + 4) +- != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row) + 4) ++ != DB1_UINT))) { + LM_ERR("lcr rule <%u> enabled is NULL or not int\n", + rule_id); + goto err; +@@ -1769,8 +1777,7 @@ int reload_tables() + row = RES_ROWS(res) + i; + if((VAL_NULL(ROW_VALUES(row)) == 1) + || ((VAL_TYPE(ROW_VALUES(row)) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row)) +- != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row)) != DB1_UINT))) { + LM_ERR("lcr_rule_target rule_id at row <%u> is null " + "or not int\n", + i); +@@ -1779,8 +1786,8 @@ int reload_tables() + rule_id = (unsigned int)VAL_INT(ROW_VALUES(row)); + if((VAL_NULL(ROW_VALUES(row) + 1) == 1) + || ((VAL_TYPE(ROW_VALUES(row) + 1) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row) + 1) +- != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row) + 1) ++ != DB1_UINT))) { + LM_ERR("lcr_rule_target gw_id at row <%u> is null " + "or not int\n", + i); +@@ -1789,8 +1796,8 @@ int reload_tables() + gw_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 1); + if((VAL_NULL(ROW_VALUES(row) + 2) == 1) + || ((VAL_TYPE(ROW_VALUES(row) + 2) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row) + 2) +- != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row) + 2) ++ != DB1_UINT))) { + LM_ERR("lcr_rule_target priority at row <%u> is null " + "or not int\n", + i); +@@ -1805,8 +1812,8 @@ int reload_tables() + } + if((VAL_NULL(ROW_VALUES(row) + 3) == 1) + || ((VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT) +- && (VAL_TYPE(ROW_VALUES(row) + 3) +- != DB1_UINT))) { ++ && (VAL_TYPE(ROW_VALUES(row) + 3) ++ != DB1_UINT))) { + LM_ERR("lcr_rule_target weight at row <%u> is null " + "or not int\n", + i); +@@ -2087,10 +2094,10 @@ void add_gws_into_avps(struct gw_info *g + if(5 /* gw_index */ + 5 /* scheme */ + 4 /* strip */ + prefix_len + + tag_len + 1 /* @ */ + + ((hostname_len > IP6_MAX_STR_SIZE + 2) +- ? hostname_len +- : IP6_MAX_STR_SIZE + 2) ++ ? hostname_len ++ : IP6_MAX_STR_SIZE + 2) + + 6 /* port */ + params_len /* params */ +- + 15 /* transport */ + 10 /* flags */ ++ + 15 /* transport */ + 10 /* flags */ + + 7 /* separators */ + + 10 /* rule_id */ + > MAX_URI_LEN) { +@@ -2174,7 +2181,7 @@ int load_gws_dummy(int lcr_id, str *ruri + if((rule->from_uri_len != 0) + && (pcre_exec(rule->from_uri_re, NULL, from_uri->s, + from_uri->len, 0, 0, NULL, 0) +- < 0)) ++ < 0)) + goto next; + + if((from_uri->len > 0) && (rule->mt_tvalue_len > 0)) { +@@ -2339,7 +2346,7 @@ static int ki_load_gws_furi( + if((rule->from_uri_len != 0) + && (pcre_exec(rule->from_uri_re, NULL, from_uri->s, + from_uri->len, 0, 0, NULL, 0) +- < 0)) { ++ < 0)) { + LM_DBG("from uri <%.*s> did not match to from regex <%.*s>\n", + from_uri->len, from_uri->s, rule->from_uri_len, + rule->from_uri); +@@ -2375,7 +2382,7 @@ static int ki_load_gws_furi( + if((rule->request_uri_len != 0) + && (pcre_exec(rule->request_uri_re, NULL, request_uri->s, + request_uri->len, 0, 0, NULL, 0) +- < 0)) { ++ < 0)) { + LM_DBG("request uri <%.*s> did not match to request regex " + "<%.*s>\n", + request_uri->len, request_uri->s, rule->request_uri_len, +@@ -2549,7 +2556,8 @@ static int generate_uris(struct sip_msg + return 0; /* No more gateways left */ + + decode_avp_value(gw_uri_val.s.s, gw_index, &scheme, &strip, &prefix, +- &tmp_tag, addr, &hostname, &port, ¶ms, &transport, flags, rule_id); ++ &tmp_tag, addr, &hostname, &port, ¶ms, &transport, flags, ++ rule_id); + + if(addr->af != 0) { + addr_str.s = ip_addr2a(addr); +@@ -2560,8 +2568,8 @@ static int generate_uris(struct sip_msg + + if(scheme.len + r_uri_user->len - strip + prefix.len + 1 /* @ */ + + ((hostname.len > IP6_MAX_STR_SIZE + 2) +- ? hostname.len +- : IP6_MAX_STR_SIZE + 2) ++ ? hostname.len ++ : IP6_MAX_STR_SIZE + 2) + + 1 /* : */ + port.len + params.len + transport.len + + 1 /* null */ + > MAX_URI_LEN) { +@@ -2992,7 +3000,7 @@ static int ki_next_gw(sip_msg_t *_m) + if(rule_id_avp_param) { + val.n = rule_id; + add_avp(rule_id_avp_type, rule_id_avp, val); +- LM_DBG("added rule_id_avp <%u>\n", (unsigned int)val.n); ++ LM_DBG("added rule_id_avp <%u>\n", (unsigned int)val.n); + } + + /* Add index of selected gw to defunct gw AVP */ +@@ -3018,7 +3026,8 @@ static int next_gw(struct sip_msg *_m, c + * Checks if request comes from ip address of a gateway + */ + static int do_from_gw(struct sip_msg *_m, unsigned int lcr_id, +- struct ip_addr *src_addr, uri_transport transport, unsigned int src_port) ++ struct ip_addr *src_addr, uri_transport transport, ++ unsigned int src_port) + { + struct gw_info *res, gw, *gws; + int_str val; +@@ -3032,18 +3041,20 @@ static int do_from_gw(struct sip_msg *_m + } + + gw.ip_addr = *src_addr; +- if (src_port != 0) { ++ if(src_port != 0) { + /* Search for gw based on its ip address and port */ + gw.port = src_port; + res = find_gateway_by_ip_and_port(&gw, gws); + } else { + /* Search for gw based on its ip address */ +- res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0], +- sizeof(struct gw_info), comp_gws); ++ res = (struct gw_info *)bsearch(&gw, &(gws[1]), ++ gws[0].ip_addr.u.addr32[0], sizeof(struct gw_info), comp_gws); + } + + /* Store tag and flags and return result */ +- if((res != NULL) && ((transport == PROTO_NONE) || (res->transport_code == transport))) { ++ if((res != NULL) ++ && ((transport == PROTO_NONE) ++ || (res->transport_code == transport))) { + LM_DBG("request came from gw\n"); + if(tag_avp_param) { + val.s.s = res->tag; +@@ -3178,8 +3189,8 @@ static int from_gw_3( + return ki_from_gw_addr_port(_m, lcr_id, &addr_str, transport, 0); + } + +-static int from_gw_4( +- struct sip_msg *_m, char *_lcr_id, char *_addr, char *_transport, char *_src_port) ++static int from_gw_4(struct sip_msg *_m, char *_lcr_id, char *_addr, ++ char *_transport, char *_src_port) + { + int lcr_id; + str addr_str; +@@ -3202,7 +3213,7 @@ static int from_gw_4( + LM_ERR("invalid transport parameter %s\n", _lcr_id); + return -1; + } +- tmp=0; ++ tmp = 0; + src_port = strtol(_src_port, &tmp, 10); + if((tmp == 0) || (*tmp) || (tmp == _src_port)) { + LM_ERR("invalid port parameter %s\n", _src_port); +@@ -3243,8 +3254,8 @@ static int from_any_gw_0(struct sip_msg + * Checks if request comes from ip address of a gateway taking source + * IP address, transport protocol and source port from parameters. + */ +-static int ki_from_any_gw_addr_port(sip_msg_t *_m, str *addr_str, int transport, +- int src_port) ++static int ki_from_any_gw_addr_port( ++ sip_msg_t *_m, str *addr_str, int transport, int src_port) + { + unsigned int i; + struct ip_addr *ip, src_addr; +@@ -3307,7 +3318,8 @@ static int from_any_gw_2(struct sip_msg + return ki_from_any_gw_addr_port(_m, &addr_str, transport, 0); + } + +-static int from_any_gw_3(struct sip_msg *_m, char *_addr, char *_transport, char *_src_port) ++static int from_any_gw_3( ++ struct sip_msg *_m, char *_addr, char *_transport, char *_src_port) + { + str addr_str; + uri_transport transport; +@@ -3323,7 +3335,7 @@ static int from_any_gw_3(struct sip_msg + LM_ERR("invalid transport parameter %s\n", _transport); + return -1; + } +- tmp=0; ++ tmp = 0; + src_port = strtol(_src_port, &tmp, 10); + if((tmp == 0) || (*tmp) || (tmp == _src_port)) { + LM_ERR("invalid port parameter %s\n", _src_port); +@@ -3355,8 +3367,9 @@ static int do_to_gw(struct sip_msg *_m, + sizeof(struct gw_info), comp_gws); + + /* Return result */ +- if((res != NULL) && ((transport == PROTO_NONE) +- || (res->transport_code == transport))) { ++ if((res != NULL) ++ && ((transport == PROTO_NONE) ++ || (res->transport_code == transport))) { + LM_DBG("request goes to gw\n"); + return 1; + } else { +--- a/src/modules/lcr/lcr_rpc.c ++++ b/src/modules/lcr/lcr_rpc.c +@@ -48,7 +48,8 @@ static void reload(rpc_t *rpc, void *c) + static const char *dump_gws_doc[2] = {"Dump the contents of lcr_gws table.", 0}; + + +-static void dump_gw(rpc_t *rpc, void *st, struct gw_info *gw, unsigned int gw_index, unsigned int lcr_id) ++static void dump_gw(rpc_t *rpc, void *st, struct gw_info *gw, ++ unsigned int gw_index, unsigned int lcr_id) + { + str scheme, gw_name, hostname, params, transport; + str prefix, tag; +@@ -72,14 +73,10 @@ static void dump_gw(rpc_t *rpc, void *st + break; + case AF_INET6: + rpc->struct_printf(st, "ip_addr", "%x:%x:%x:%x:%x:%x:%x:%x", +- gw->ip_addr.u.addr16[0], +- gw->ip_addr.u.addr16[1], +- gw->ip_addr.u.addr16[2], +- gw->ip_addr.u.addr16[3], +- gw->ip_addr.u.addr16[4], +- gw->ip_addr.u.addr16[5], +- gw->ip_addr.u.addr16[6], +- gw->ip_addr.u.addr16[7]); ++ gw->ip_addr.u.addr16[0], gw->ip_addr.u.addr16[1], ++ gw->ip_addr.u.addr16[2], gw->ip_addr.u.addr16[3], ++ gw->ip_addr.u.addr16[4], gw->ip_addr.u.addr16[5], ++ gw->ip_addr.u.addr16[6], gw->ip_addr.u.addr16[7]); + break; + case 0: + rpc->struct_add(st, "s", "ip_addr", "0.0.0.0"); +@@ -99,11 +96,10 @@ static void dump_gw(rpc_t *rpc, void *st + prefix.len = gw->prefix_len; + tag.s = gw->tag; + tag.len = gw->tag_len; +- start = int2strbuf( +- gw->defunct_until, &(buf[0]), INT2STR_MAX_LEN, &len); +- rpc->struct_add(st, "dSSdds", "strip", gw->strip, "prefix", +- &prefix, "tag", &tag, "flags", gw->flags, "state", +- gw->state, "defunct_until", start); ++ start = int2strbuf(gw->defunct_until, &(buf[0]), INT2STR_MAX_LEN, &len); ++ rpc->struct_add(st, "dSSdds", "strip", gw->strip, "prefix", &prefix, "tag", ++ &tag, "flags", gw->flags, "state", gw->state, "defunct_until", ++ start); + } + + static void dump_gws(rpc_t *rpc, void *c) +@@ -119,7 +115,7 @@ static void dump_gws(rpc_t *rpc, void *c + gws = gw_pt[j]; + + for(i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) { +- if (srec==NULL) { ++ if(srec == NULL) { + /* We create one array per lcr_id */ + if(rpc->add(c, "{", &rec) < 0) + return; +@@ -143,7 +139,7 @@ static void dump_rules(rpc_t *rpc, void + int i, j; + int _filter_by_prefix = 0; + int _lcr_id = 0; +- str _prefix = {NULL,0}; ++ str _prefix = {NULL, 0}; + struct rule_info **rules, *rule; + struct target *t; + void *rec = NULL; +@@ -151,29 +147,32 @@ static void dump_rules(rpc_t *rpc, void + void *st, *sst, *ssst; + str prefix, from_uri, request_uri; + +- if (rpc->scan(c, "d", &_lcr_id)>0) { +- if (rpc->scan(c, ".S", &_prefix)>0) { ++ if(rpc->scan(c, "d", &_lcr_id) > 0) { ++ if(rpc->scan(c, ".S", &_prefix) > 0) { + _filter_by_prefix = 1; + } + } + + for(j = 1; j <= lcr_count_param; j++) { + +- if (_lcr_id && _lcr_id!=j) continue; ++ if(_lcr_id && _lcr_id != j) ++ continue; + + rules = rule_pt[j]; + + for(i = 0; i < lcr_rule_hash_size_param; i++) { + rule = rules[i]; + while(rule) { +- if (_filter_by_prefix && _prefix.len && _prefix.s) { +- if (_prefix.len < rule->prefix_len || +- strncmp(_prefix.s, rule->prefix, rule->prefix_len)!=0) { ++ if(_filter_by_prefix && _prefix.len && _prefix.s) { ++ if(_prefix.len < rule->prefix_len ++ || strncmp(_prefix.s, rule->prefix, ++ rule->prefix_len) ++ != 0) { + rule = rule->next; + continue; + } + } +- if (srec==NULL) { ++ if(srec == NULL) { + /* We create one array per lcr_id */ + if(rpc->add(c, "{", &rec) < 0) + return; +@@ -192,11 +191,11 @@ static void dump_rules(rpc_t *rpc, void + rule->rule_id, "prefix", &prefix, "from_uri", &from_uri, + "request_uri", &request_uri, "stopper", rule->stopper); + t = rule->targets; +- if (t) { +- if (rpc->struct_add(st, "[", "gw", &sst) < 0) ++ if(t) { ++ if(rpc->struct_add(st, "[", "gw", &sst) < 0) + return; + while(t) { +- if (rpc->array_add(sst, "{", &ssst) < 0) ++ if(rpc->array_add(sst, "{", &ssst) < 0) + return; + rpc->struct_add(ssst, "ddd", "gw_index", t->gw_index, + "priority", t->priority, "weight", t->weight); +@@ -210,10 +209,10 @@ static void dump_rules(rpc_t *rpc, void + /* Mark the end of rule array */ + srec = NULL; + +- if (_filter_by_prefix) ++ if(_filter_by_prefix) + continue; + rule = rules[lcr_rule_hash_size_param]; +- if (rule) { ++ if(rule) { + if(rpc->struct_add(rec, "[", "prefix_len", &st) < 0) + return; + while(rule) { +@@ -222,7 +221,8 @@ static void dump_rules(rpc_t *rpc, void + } + } + } +- if (rec==NULL) rpc->fault(c, 404, "Empty reply"); ++ if(rec == NULL) ++ rpc->fault(c, 404, "Empty reply"); + } + + +@@ -269,8 +269,9 @@ static void load_gws(rpc_t *rpc, void *c + + ret = rpc->scan(c, "dS*SS", &lcr_id, &uri_user, &caller_uri, &request_uri); + if(ret == -1) { +- rpc->fault(c, 400, "parameter error; if using cli, remember to prefix " +- "numeric uri_user param value with 's:'"); ++ rpc->fault(c, 400, ++ "parameter error; if using cli, remember to prefix " ++ "numeric uri_user param value with 's:'"); + return; + } + +@@ -289,7 +290,7 @@ static void load_gws(rpc_t *rpc, void *c + + gws = gw_pt[lcr_id]; + for(j = 0; j < gw_count; j++) { +- if (rec==NULL) { ++ if(rec == NULL) { + if(rpc->add(c, "[", &rec) < 0) + return; + } diff --git a/net/kamailio/patches/021-lcr-typos.patch b/net/kamailio/patches/021-lcr-typos.patch new file mode 100644 index 0000000..4029f39 --- /dev/null +++ b/net/kamailio/patches/021-lcr-typos.patch @@ -0,0 +1,51 @@ +From 70a9ea2b1e5cceeaf050356e7baf00127a58567d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= + =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= +Date: Mon, 8 May 2023 13:13:49 +0200 +Subject: [PATCH] lcr: typos + +--- + src/modules/lcr/doc/lcr_admin.xml | 2 +- + src/modules/lcr/lcr_mod.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +--- a/src/modules/lcr/doc/lcr_admin.xml ++++ b/src/modules/lcr/doc/lcr_admin.xml +@@ -1641,7 +1641,7 @@ if (to_any_gw("192.55.66.2", 1)) { + + Causes lcr module to dump the contents of its + in-memory lcr_rule and lcr_rule_target tables. +- Rules can be filetered by lcr_id or lcr_id and prefix. ++ Rules can be filtered by lcr_id or lcr_id and prefix. + The filters are passed as optional parameters. + + Parameters: +--- a/src/modules/lcr/lcr_mod.c ++++ b/src/modules/lcr/lcr_mod.c +@@ -188,7 +188,7 @@ unsigned int lcr_gw_count_param = DEF_LC + /* can gws be defuncted */ + static unsigned int defunct_capability_param = 0; + +-/* dont strip or tag param */ ++/* don't strip or tag param */ + static int dont_strip_or_prefix_flag_param = -1; + + /* ping related params */ +@@ -846,7 +846,7 @@ static int comp_matched(const void *m1, + if(mi1->priority < mi2->priority) + return 1; + if(mi1->priority == mi2->priority) { +- /* Sort by randomized weigth */ ++ /* Sort by randomized weight */ + if(mi1->weight > mi2->weight) + return 1; + if(mi1->weight == mi2->weight) +@@ -863,7 +863,7 @@ static int comp_matched(const void *m1, + if(mi1->priority < mi2->priority) + return 1; + if(mi1->priority == mi2->priority) { +- /* Sort by randomized weigth */ ++ /* Sort by randomized weight */ + if(mi1->weight > mi2->weight) + return 1; + if(mi1->weight == mi2->weight) diff --git a/net/kamailio/patches/022-lcr-pcre2-migration.patch b/net/kamailio/patches/022-lcr-pcre2-migration.patch new file mode 100644 index 0000000..c894e3a --- /dev/null +++ b/net/kamailio/patches/022-lcr-pcre2-migration.patch @@ -0,0 +1,508 @@ +From e3e2c41e8c46a13bad18dd40fd9e3540020dd5eb Mon Sep 17 00:00:00 2001 +From: Victor Seva +Date: Mon, 21 Aug 2023 13:30:36 +0200 +Subject: [PATCH] lcr: pcre2 migration + +--- + src/modules/lcr/Makefile | 12 +-- + src/modules/lcr/hash.c | 24 ++--- + src/modules/lcr/hash.h | 10 +- + src/modules/lcr/lcr_mod.c | 187 +++++++++++++++++++++++++------------- + src/modules/lcr/lcr_mod.h | 8 +- + 5 files changed, 150 insertions(+), 91 deletions(-) + +--- a/src/modules/lcr/Makefile ++++ b/src/modules/lcr/Makefile +@@ -9,20 +9,15 @@ auto_gen= + NAME=lcr.so + + ifeq ($(CROSS_COMPILE),) +-PCRE_BUILDER = $(shell \ +- if pkg-config --exists libcre; then \ +- echo 'pkg-config libpcre'; \ +- else \ +- which pcre-config; \ +- fi) ++PCRE_BUILDER = $(shell command -v pcre2-config) + endif + + ifeq ($(PCRE_BUILDER),) + PCREDEFS=-I$(LOCALBASE)/include +- PCRELIBS=-L$(LOCALBASE)/lib -lpcre ++ PCRELIBS=-L$(LOCALBASE)/lib -lpcre2-8 + else + PCREDEFS = $(shell $(PCRE_BUILDER) --cflags) +- PCRELIBS = $(shell $(PCRE_BUILDER) --libs) ++ PCRELIBS = $(shell $(PCRE_BUILDER) --libs8) + endif + + DEFS+=$(PCREDEFS) +@@ -31,4 +26,3 @@ LIBS+=$(PCRELIBS) + SERLIBPATH=../../lib + SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1 + include ../../Makefile.modules +- +--- a/src/modules/lcr/hash.c ++++ b/src/modules/lcr/hash.c +@@ -15,8 +15,8 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@@ -36,10 +36,10 @@ + /* Add lcr entry into hash table */ + int rule_hash_table_insert(struct rule_info **hash_table, unsigned int lcr_id, + unsigned int rule_id, unsigned short prefix_len, char *prefix, +- unsigned short from_uri_len, char *from_uri, pcre *from_uri_re, ++ unsigned short from_uri_len, char *from_uri, pcre2_code *from_uri_re, + unsigned short mt_tvalue_len, char *mt_tvalue, +- unsigned short request_uri_len, char *request_uri, pcre *request_uri_re, +- unsigned short stopper) ++ unsigned short request_uri_len, char *request_uri, ++ pcre2_code *request_uri_re, unsigned short stopper) + { + struct rule_info *rule; + str prefix_str; +@@ -50,9 +50,9 @@ int rule_hash_table_insert(struct rule_i + if(rule == NULL) { + SHM_MEM_ERROR_FMT("for rule hash table entry\n"); + if(from_uri_re) +- shm_free(from_uri_re); ++ pcre2_code_free(from_uri_re); + if(request_uri_re) +- shm_free(request_uri_re); ++ pcre2_code_free(request_uri_re); + return 0; + } + memset(rule, 0, sizeof(struct rule_info)); +@@ -99,9 +99,9 @@ int rule_hash_table_insert(struct rule_i + if(rid == NULL) { + PKG_MEM_ERROR_FMT("for rule_id hash table entry\n"); + if(from_uri_re) +- shm_free(from_uri_re); ++ pcre2_code_free(from_uri_re); + if(request_uri_re) +- shm_free(request_uri_re); ++ pcre2_code_free(request_uri_re); + shm_free(rule); + return 0; + } +@@ -180,7 +180,7 @@ int rule_hash_table_insert_target(struct + } + + +-/* ++/* + * Return pointer to lcr hash table entry to which given prefix hashes to. + */ + struct rule_info *rule_hash_table_lookup( +@@ -209,10 +209,10 @@ void rule_hash_table_contents_free(struc + r = hash_table[i]; + while(r) { + if(r->from_uri_re) { +- shm_free(r->from_uri_re); ++ pcre2_code_free(r->from_uri_re); + } + if(r->request_uri_re) +- shm_free(r->request_uri_re); ++ pcre2_code_free(r->request_uri_re); + t = r->targets; + while(t) { + next_t = t->next; +--- a/src/modules/lcr/hash.h ++++ b/src/modules/lcr/hash.h +@@ -15,8 +15,8 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@@ -34,10 +34,10 @@ + + int rule_hash_table_insert(struct rule_info **hash_table, unsigned int lcr_id, + unsigned int rule_id, unsigned short prefix_len, char *prefix, +- unsigned short from_uri_len, char *from_uri, pcre *from_uri_re, ++ unsigned short from_uri_len, char *from_uri, pcre2_code *from_uri_re, + unsigned short mt_tvalue_len, char *mt_tvalue, +- unsigned short request_uri_len, char *request_uri, pcre *request_uri_re, +- unsigned short stopper); ++ unsigned short request_uri_len, char *request_uri, ++ pcre2_code *request_uri_re, unsigned short stopper); + + int rule_hash_table_insert_target(struct rule_info **hash_table, + struct gw_info *gws, unsigned int rule_id, unsigned int gw_id, +--- a/src/modules/lcr/lcr_mod.c ++++ b/src/modules/lcr/lcr_mod.c +@@ -16,8 +16,8 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +@@ -43,7 +43,8 @@ + #include + #include + #include +-#include ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + #include "../../core/locking.h" + #include "../../core/sr_module.h" + #include "../../core/dprint.h" +@@ -204,6 +205,9 @@ static unsigned int priority_ordering_pa + /* mtree tree name */ + str mtree_param = {"lcr", 3}; + ++static pcre2_general_context *lcr_gctx = NULL; ++static pcre2_compile_context *lcr_ctx = NULL; ++ + /* + * Other module types and variables + */ +@@ -364,7 +368,7 @@ static param_export_t params[] = { + * Module interface + */ + struct module_exports exports = { +- "lcr", ++ "lcr", + DEFAULT_DLFLAGS, /* dlopen flags */ + cmds, /* Exported functions */ + params, /* Exported parameters */ +@@ -422,6 +426,16 @@ static void lcr_db_close(void) + } + } + ++static void *pcre2_malloc(size_t size, void *ext) ++{ ++ return shm_malloc(size); ++} ++ ++static void pcre2_free(void *ptr, void *ext) ++{ ++ shm_free(ptr); ++ ptr = NULL; ++} + + /* + * Module initialization function that is called before the main process forks +@@ -703,7 +717,15 @@ static int mod_init(void) + lcr_db_close(); + + /* rule shared memory */ +- ++ if((lcr_gctx = pcre2_general_context_create(pcre2_malloc, pcre2_free, NULL)) ++ == NULL) { ++ LM_ERR("pcre2 general context creation failed\n"); ++ goto err; ++ } ++ if((lcr_ctx = pcre2_compile_context_create(lcr_gctx)) == NULL) { ++ LM_ERR("pcre2 compile context creation failed\n"); ++ goto err; ++ } + /* rule hash table pointer table */ + /* pointer at index 0 points to temp rule hash table */ + rule_pt = (struct rule_info ***)shm_malloc( +@@ -779,6 +801,12 @@ dberror: + lcr_db_close(); + + err: ++ if(lcr_ctx) { ++ pcre2_compile_context_free(lcr_ctx); ++ } ++ if(lcr_gctx) { ++ pcre2_general_context_free(lcr_gctx); ++ } + free_shared_memory(); + return -1; + } +@@ -794,7 +822,12 @@ static int child_init(int rank) + static void destroy(void) + { + lcr_db_close(); +- ++ if(lcr_ctx) { ++ pcre2_compile_context_free(lcr_ctx); ++ } ++ if(lcr_gctx) { ++ pcre2_general_context_free(lcr_gctx); ++ } + free_shared_memory(); + } + +@@ -875,33 +908,32 @@ static int comp_matched(const void *m1, + + + /* Compile pattern into shared memory and return pointer to it. */ +-static pcre *reg_ex_comp(const char *pattern) ++static pcre2_code *reg_ex_comp(const char *pattern) + { +- pcre *re, *result; +- const char *error; +- int rc, err_offset; +- size_t size; +- +- re = pcre_compile(pattern, 0, &error, &err_offset, NULL); +- if(re == NULL) { +- LM_ERR("pcre compilation of '%s' failed at offset %d: %s\n", pattern, +- err_offset, error); +- return (pcre *)0; +- } +- rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size); +- if(rc != 0) { +- LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n", +- pattern, rc); +- return (pcre *)0; +- } +- result = (pcre *)shm_malloc(size); ++ pcre2_code *result; ++ int pcre_error_num = 0; ++ char pcre_error[128]; ++ size_t pcre_erroffset; ++ ++ result = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0, ++ &pcre_error_num, &pcre_erroffset, lcr_ctx); + if(result == NULL) { +- pcre_free(re); +- SHM_MEM_ERROR_FMT("for compiled PCRE pattern\n"); +- return (pcre *)0; ++ switch(pcre2_get_error_message( ++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) { ++ case PCRE2_ERROR_NOMEMORY: ++ snprintf(pcre_error, 128, ++ "unknown error[%d]: pcre2 error buffer too small", ++ pcre_error_num); ++ break; ++ case PCRE2_ERROR_BADDATA: ++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]", ++ pcre_error_num); ++ break; ++ } ++ LM_ERR("pcre compilation of '%s' failed at offset %zu: %s\n", pattern, ++ pcre_erroffset, pcre_error); ++ return NULL; + } +- memcpy(result, re, size); +- pcre_free(re); + return result; + } + +@@ -950,7 +982,7 @@ static struct gw_info *find_gateway_by_i + return NULL; + } + +-/* ++/* + * Insert gw info into index i or gws table + */ + static int insert_gw(struct gw_info *gws, unsigned int i, unsigned int gw_id, +@@ -1024,7 +1056,7 @@ static int insert_gw(struct gw_info *gws + + + /* +- * Insert prefix_len into list pointed by last rule hash table entry ++ * Insert prefix_len into list pointed by last rule hash table entry + * if not there already. Keep list in decending prefix_len order. + */ + static int prefix_len_insert( +@@ -1414,7 +1446,7 @@ int reload_tables() + db_key_t gw_cols[13]; + db_key_t rule_cols[7]; + db_key_t target_cols[4]; +- pcre *from_uri_re, *request_uri_re; ++ pcre2_code *from_uri_re, *request_uri_re; + struct gw_info *gws, *gw_pt_tmp; + struct rule_info **rules, **rule_pt_tmp; + +@@ -2129,11 +2161,12 @@ void add_gws_into_avps(struct gw_info *g + int load_gws_dummy(int lcr_id, str *ruri_user, str *from_uri, str *request_uri, + unsigned int *gw_indexes) + { +- int i, j; ++ int i, j, rc; + unsigned int gw_index, now, dex; + struct rule_info **rules, *rule, *pl; + struct gw_info *gws; + struct target *t; ++ pcre2_match_data *pcre_md = NULL; + struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1]; + struct sip_uri furi; + struct usr_avp *avp; +@@ -2178,12 +2211,18 @@ int load_gws_dummy(int lcr_id, str *ruri + || strncmp(rule->prefix, ruri_user->s, pl->prefix_len)) + goto next; + +- if((rule->from_uri_len != 0) +- && (pcre_exec(rule->from_uri_re, NULL, from_uri->s, +- from_uri->len, 0, 0, NULL, 0) +- < 0)) +- goto next; +- ++ if(rule->from_uri_len != 0) { ++ pcre_md = pcre2_match_data_create_from_pattern( ++ rule->from_uri_re, NULL); ++ rc = pcre2_match(rule->from_uri_re, (PCRE2_SPTR)from_uri->s, ++ (PCRE2_SIZE)from_uri->len, 0, 0, pcre_md, NULL); ++ if(pcre_md) { ++ pcre2_match_data_free(pcre_md); ++ pcre_md = NULL; ++ } ++ if(rc < 0) ++ goto next; ++ } + if((from_uri->len > 0) && (rule->mt_tvalue_len > 0)) { + if(mtree_api.mt_match(&msg, &mtree_param, &(furi.user), 2) + == -1) { +@@ -2216,9 +2255,16 @@ int load_gws_dummy(int lcr_id, str *ruri + "param has not been given.\n"); + return -1; + } +- if(pcre_exec(rule->request_uri_re, NULL, request_uri->s, +- request_uri->len, 0, 0, NULL, 0) +- < 0) ++ pcre_md = pcre2_match_data_create_from_pattern( ++ rule->request_uri_re, NULL); ++ rc = pcre2_match(rule->request_uri_re, ++ (PCRE2_SPTR)request_uri->s, ++ (PCRE2_SIZE)request_uri->len, 0, 0, pcre_md, NULL); ++ if(pcre_md) { ++ pcre2_match_data_free(pcre_md); ++ pcre_md = NULL; ++ } ++ if(rc < 0) + goto next; + } + +@@ -2282,9 +2328,10 @@ static int ki_load_gws_furi( + sip_msg_t *_m, int lcr_id, str *ruri_user, str *from_uri) + { + str *request_uri; +- int i, j; ++ int i, j, rc; + unsigned int gw_index, now, dex; + int_str val; ++ pcre2_match_data *pcre_md = NULL; + struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1]; + struct rule_info **rules, *rule, *pl; + struct gw_info *gws; +@@ -2343,14 +2390,22 @@ static int ki_load_gws_furi( + goto next; + + /* Match from uri */ +- if((rule->from_uri_len != 0) +- && (pcre_exec(rule->from_uri_re, NULL, from_uri->s, +- from_uri->len, 0, 0, NULL, 0) +- < 0)) { +- LM_DBG("from uri <%.*s> did not match to from regex <%.*s>\n", +- from_uri->len, from_uri->s, rule->from_uri_len, +- rule->from_uri); +- goto next; ++ if(rule->from_uri_len != 0) { ++ pcre_md = pcre2_match_data_create_from_pattern( ++ rule->from_uri_re, NULL); ++ rc = pcre2_match(rule->from_uri_re, (PCRE2_SPTR)from_uri->s, ++ (PCRE2_SIZE)from_uri->len, 0, 0, pcre_md, NULL); ++ if(pcre_md) { ++ pcre2_match_data_free(pcre_md); ++ pcre_md = NULL; ++ } ++ if(rc < 0) { ++ LM_DBG("from uri <%.*s> did not match to from regex " ++ "<%.*s>\n", ++ from_uri->len, from_uri->s, rule->from_uri_len, ++ rule->from_uri); ++ goto next; ++ } + } + + /* Match from uri user */ +@@ -2379,15 +2434,23 @@ static int ki_load_gws_furi( + } + + /* Match request uri */ +- if((rule->request_uri_len != 0) +- && (pcre_exec(rule->request_uri_re, NULL, request_uri->s, +- request_uri->len, 0, 0, NULL, 0) +- < 0)) { +- LM_DBG("request uri <%.*s> did not match to request regex " +- "<%.*s>\n", +- request_uri->len, request_uri->s, rule->request_uri_len, +- rule->request_uri); +- goto next; ++ if(rule->request_uri_len != 0) { ++ pcre_md = pcre2_match_data_create_from_pattern( ++ rule->request_uri_re, NULL); ++ rc = pcre2_match(rule->request_uri_re, ++ (PCRE2_SPTR)request_uri->s, ++ (PCRE2_SIZE)request_uri->len, 0, 0, pcre_md, NULL); ++ if(pcre_md) { ++ pcre2_match_data_free(pcre_md); ++ pcre_md = NULL; ++ } ++ if(rc < 0) { ++ LM_DBG("request uri <%.*s> did not match to request regex " ++ "<%.*s>\n", ++ request_uri->len, request_uri->s, ++ rule->request_uri_len, rule->request_uri); ++ goto next; ++ } + } + + /* Load gws associated with this rule */ +@@ -3015,7 +3078,7 @@ static int ki_next_gw(sip_msg_t *_m) + } + + /** +- * ++ * + */ + static int next_gw(struct sip_msg *_m, char *_s1, char *_s2) + { +--- a/src/modules/lcr/lcr_mod.h ++++ b/src/modules/lcr/lcr_mod.h +@@ -2,6 +2,7 @@ + * Various lcr related constant, types, and external variables + * + * Copyright (C) 2005-2014 Juha Heinanen ++ * Copyright (C) 2023 Victor Seva + * + * This file is part of Kamailio, a free SIP server. + * +@@ -33,7 +34,8 @@ + #define LCR_MOD_H + + #include +-#include ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + #include "../../core/locking.h" + #include "../../core/parser/parse_uri.h" + #include "../../core/ip_addr.h" +@@ -60,10 +62,10 @@ struct rule_info + unsigned short from_uri_len; + char mt_tvalue[MAX_MT_TVALUE_LEN + 1]; + unsigned short mt_tvalue_len; +- pcre *from_uri_re; ++ pcre2_code *from_uri_re; + char request_uri[MAX_URI_LEN + 1]; + unsigned short request_uri_len; +- pcre *request_uri_re; ++ pcre2_code *request_uri_re; + unsigned short stopper; + unsigned int enabled; + struct target *targets; diff --git a/net/kamailio/patches/030-regex-clang-format-for-coherent-indentation-and-codi.patch b/net/kamailio/patches/030-regex-clang-format-for-coherent-indentation-and-codi.patch new file mode 100644 index 0000000..485fa69 --- /dev/null +++ b/net/kamailio/patches/030-regex-clang-format-for-coherent-indentation-and-codi.patch @@ -0,0 +1,715 @@ +From fb7c59cafceb35628d40c727dbfa2990335b922a Mon Sep 17 00:00:00 2001 +From: Victor Seva +Date: Wed, 17 May 2023 16:37:10 +0200 +Subject: [PATCH] regex: clang-format for coherent indentation and coding style + +--- + src/modules/regex/regex_mod.c | 313 ++++++++++++++++------------------ + 1 file changed, 150 insertions(+), 163 deletions(-) + +--- a/src/modules/regex/regex_mod.c ++++ b/src/modules/regex/regex_mod.c +@@ -49,9 +49,9 @@ MODULE_VERSION + #define START 0 + #define RELOAD 1 + +-#define FILE_MAX_LINE 500 /*!< Max line size in the file */ +-#define MAX_GROUPS 20 /*!< Max number of groups */ +-#define GROUP_MAX_SIZE 8192 /*!< Max size of a group */ ++#define FILE_MAX_LINE 500 /*!< Max line size in the file */ ++#define MAX_GROUPS 20 /*!< Max number of groups */ ++#define GROUP_MAX_SIZE 8192 /*!< Max size of a group */ + + + static int regex_init_rpc(void); +@@ -66,12 +66,12 @@ gen_lock_t *reload_lock; + * Module exported parameter variables + */ + static char *file; +-static int max_groups = MAX_GROUPS; +-static int group_max_size = GROUP_MAX_SIZE; +-static int pcre_caseless = 0; +-static int pcre_multiline = 0; +-static int pcre_dotall = 0; +-static int pcre_extended = 0; ++static int max_groups = MAX_GROUPS; ++static int group_max_size = GROUP_MAX_SIZE; ++static int pcre_caseless = 0; ++static int pcre_multiline = 0; ++static int pcre_dotall = 0; ++static int pcre_extended = 0; + + + /* +@@ -100,119 +100,117 @@ static void free_shared_memory(void); + /* + * Script functions + */ +-static int w_pcre_match(struct sip_msg* _msg, char* _s1, char* _s2); +-static int w_pcre_match_group(struct sip_msg* _msg, char* _s1, char* _s2); ++static int w_pcre_match(struct sip_msg *_msg, char *_s1, char *_s2); ++static int w_pcre_match_group(struct sip_msg *_msg, char *_s1, char *_s2); + + + /* + * Exported functions + */ +-static cmd_export_t cmds[] = +-{ +- { "pcre_match", (cmd_function)w_pcre_match, 2, fixup_spve_spve, 0, +- REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE }, +- { "pcre_match_group", (cmd_function)w_pcre_match_group, 2, fixup_spve_spve, 0, +- REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE }, +- { "pcre_match_group", (cmd_function)w_pcre_match_group, 1, fixup_spve_null, 0, +- REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE }, +- { 0, 0, 0, 0, 0, 0 } +-}; ++static cmd_export_t cmds[] = { ++ {"pcre_match", (cmd_function)w_pcre_match, 2, fixup_spve_spve, 0, ++ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE ++ | LOCAL_ROUTE}, ++ {"pcre_match_group", (cmd_function)w_pcre_match_group, 2, ++ fixup_spve_spve, 0, ++ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE ++ | LOCAL_ROUTE}, ++ {"pcre_match_group", (cmd_function)w_pcre_match_group, 1, ++ fixup_spve_null, 0, ++ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE ++ | LOCAL_ROUTE}, ++ {0, 0, 0, 0, 0, 0}}; + + + /* + * Exported parameters + */ +-static param_export_t params[] = { +- {"file", PARAM_STRING, &file }, +- {"max_groups", INT_PARAM, &max_groups }, +- {"group_max_size", INT_PARAM, &group_max_size }, +- {"pcre_caseless", INT_PARAM, &pcre_caseless }, +- {"pcre_multiline", INT_PARAM, &pcre_multiline }, +- {"pcre_dotall", INT_PARAM, &pcre_dotall }, +- {"pcre_extended", INT_PARAM, &pcre_extended }, +- {0, 0, 0} +-}; ++static param_export_t params[] = {{"file", PARAM_STRING, &file}, ++ {"max_groups", INT_PARAM, &max_groups}, ++ {"group_max_size", INT_PARAM, &group_max_size}, ++ {"pcre_caseless", INT_PARAM, &pcre_caseless}, ++ {"pcre_multiline", INT_PARAM, &pcre_multiline}, ++ {"pcre_dotall", INT_PARAM, &pcre_dotall}, ++ {"pcre_extended", INT_PARAM, &pcre_extended}, {0, 0, 0}}; + + + /* + * Module interface + */ + struct module_exports exports = { +- "regex", /*!< module name */ +- DEFAULT_DLFLAGS, /*!< dlopen flags */ +- cmds, /*!< exported functions */ +- params, /*!< exported parameters */ +- 0, /*!< exported RPC functions */ +- 0, /*!< exported pseudo-variables */ +- 0, /*!< response handling function */ +- mod_init, /*!< module initialization function */ +- 0, /*!< per-child init function */ +- destroy /*!< destroy function */ ++ "regex", /*!< module name */ ++ DEFAULT_DLFLAGS, /*!< dlopen flags */ ++ cmds, /*!< exported functions */ ++ params, /*!< exported parameters */ ++ 0, /*!< exported RPC functions */ ++ 0, /*!< exported pseudo-variables */ ++ 0, /*!< response handling function */ ++ mod_init, /*!< module initialization function */ ++ 0, /*!< per-child init function */ ++ destroy /*!< destroy function */ + }; + + +- + /*! \brief + * Init module function + */ + static int mod_init(void) + { +- if(regex_init_rpc()<0) +- { ++ if(regex_init_rpc() < 0) { + LM_ERR("failed to register RPC commands\n"); + return -1; + } + + /* Group matching feature */ +- if (file == NULL) { ++ if(file == NULL) { + LM_NOTICE("'file' parameter is not set, group matching disabled\n"); + } else { + /* Create and init the lock */ + reload_lock = lock_alloc(); +- if (reload_lock == NULL) { ++ if(reload_lock == NULL) { + LM_ERR("cannot allocate reload_lock\n"); + goto err; + } +- if (lock_init(reload_lock) == NULL) { ++ if(lock_init(reload_lock) == NULL) { + LM_ERR("cannot init the reload_lock\n"); + lock_dealloc(reload_lock); + goto err; + } + + /* PCRE options */ +- if (pcre_caseless != 0) { ++ if(pcre_caseless != 0) { + LM_DBG("PCRE CASELESS enabled\n"); + pcre_options = pcre_options | PCRE_CASELESS; + } +- if (pcre_multiline != 0) { ++ if(pcre_multiline != 0) { + LM_DBG("PCRE MULTILINE enabled\n"); + pcre_options = pcre_options | PCRE_MULTILINE; + } +- if (pcre_dotall != 0) { ++ if(pcre_dotall != 0) { + LM_DBG("PCRE DOTALL enabled\n"); + pcre_options = pcre_options | PCRE_DOTALL; + } +- if (pcre_extended != 0) { ++ if(pcre_extended != 0) { + LM_DBG("PCRE EXTENDED enabled\n"); + pcre_options = pcre_options | PCRE_EXTENDED; + } + LM_DBG("PCRE options: %i\n", pcre_options); + + /* Pointer to pcres */ +- if ((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) { ++ if((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) { + LM_ERR("no memory for pcres_addr\n"); + goto err; + } + + /* Integer containing the number of pcres */ +- if ((num_pcres = shm_malloc(sizeof(int))) == 0) { ++ if((num_pcres = shm_malloc(sizeof(int))) == 0) { + LM_ERR("no memory for num_pcres\n"); + goto err; + } + + /* Load the pcres */ + LM_DBG("loading pcres...\n"); +- if (load_pcres(START)) { ++ if(load_pcres(START)) { + LM_ERR("failed to load pcres\n"); + goto err; + } +@@ -251,21 +249,21 @@ static int load_pcres(int action) + /* Get the lock */ + lock_get(reload_lock); + +- if (!(f = fopen(file, "r"))) { ++ if(!(f = fopen(file, "r"))) { + LM_ERR("could not open file '%s'\n", file); + goto err; + } + + /* Array containing each pattern in the file */ +- if ((patterns = pkg_malloc(sizeof(char*) * max_groups)) == 0) { ++ if((patterns = pkg_malloc(sizeof(char *) * max_groups)) == 0) { + LM_ERR("no more memory for patterns\n"); + fclose(f); + goto err; + } +- memset(patterns, 0, sizeof(char*) * max_groups); ++ memset(patterns, 0, sizeof(char *) * max_groups); + +- for (i=0; i= max_groups) { ++ if(i >= max_groups) { + LM_ERR("max patterns exceeded\n"); + fclose(f); + goto err; +@@ -309,14 +308,14 @@ static int load_pcres(int action) + + llen = strlen(line); + /* Check if the patter size is too big (aprox) */ +- if (strlen(patterns[i]) + llen >= group_max_size - 4) { ++ if(strlen(patterns[i]) + llen >= group_max_size - 4) { + LM_ERR("pattern max file exceeded\n"); + fclose(f); + goto err; + } + + /* Append ')' at the end of the line */ +- if (line[llen - 1] == '\n') { ++ if(line[llen - 1] == '\n') { + line[llen - 1] = ')'; + line[llen] = '\n'; + line[llen + 1] = '\0'; +@@ -328,7 +327,7 @@ static int load_pcres(int action) + + /* Append '(' at the beginning of the line */ + llen = strlen(patterns[i]); +- memcpy(patterns[i]+llen, "(", 1); ++ memcpy(patterns[i] + llen, "(", 1); + llen++; + + /* Append the line to the current pattern (including the ending 0) */ +@@ -340,16 +339,16 @@ static int load_pcres(int action) + + fclose(f); + +- if(num_pcres_tmp==0) { ++ if(num_pcres_tmp == 0) { + LM_ERR("no expressions in the file\n"); + goto err; + } + + /* Fix the patterns */ +- for (i=0; i < num_pcres_tmp; i++) { ++ for(i = 0; i < num_pcres_tmp; i++) { + + /* Convert empty groups in unmatcheable regular expression ^$ */ +- if (strlen(patterns[i]) == 1) { ++ if(strlen(patterns[i]) == 1) { + patterns[i][0] = '^'; + patterns[i][1] = '$'; + patterns[i][2] = '\0'; +@@ -357,13 +356,13 @@ static int load_pcres(int action) + } + + /* Delete possible '\n' at the end of the pattern */ +- if (patterns[i][strlen(patterns[i])-1] == '\n') { +- patterns[i][strlen(patterns[i])-1] = '\0'; ++ if(patterns[i][strlen(patterns[i]) - 1] == '\n') { ++ patterns[i][strlen(patterns[i]) - 1] = '\0'; + } + + /* Replace '\n' with '|' (except at the end of the pattern) */ +- for (j=0; j < strlen(patterns[i]); j++) { +- if (patterns[i][j] == '\n' && j != strlen(patterns[i])-1) { ++ for(j = 0; j < strlen(patterns[i]); j++) { ++ if(patterns[i][j] == '\n' && j != strlen(patterns[i]) - 1) { + patterns[i][j] = '|'; + } + } +@@ -374,38 +373,38 @@ static int load_pcres(int action) + + /* Log the group patterns */ + LM_INFO("num groups = %d\n", num_pcres_tmp); +- for (i=0; i < num_pcres_tmp; i++) { +- LM_INFO("%s (size = %i)\n", i, patterns[i], +- i, (int)strlen(patterns[i])); ++ for(i = 0; i < num_pcres_tmp; i++) { ++ LM_INFO("%s (size = %i)\n", i, patterns[i], i, ++ (int)strlen(patterns[i])); + } + + /* Temporal pointer of pcres */ +- if ((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) { ++ if((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) { + LM_ERR("no more memory for pcres_tmp\n"); + goto err; + } +- for (i=0; is, pcre_options, &pcre_error, &pcre_erroffset, NULL); +- if (pcre_re == NULL) { ++ pcre_re = pcre_compile( ++ regex->s, pcre_options, &pcre_error, &pcre_erroffset, NULL); ++ if(pcre_re == NULL) { + LM_ERR("pcre_re compilation of '%s' failed at offset %d: %s\n", + regex->s, pcre_erroffset, pcre_error); + return -4; + } + +- pcre_rc = pcre_exec( +- pcre_re, /* the compiled pattern */ +- NULL, /* no extra data - we didn't study the pattern */ +- string->s, /* the matching string */ +- (int)(string->len), /* the length of the subject */ +- 0, /* start at offset 0 in the string */ +- 0, /* default options */ +- NULL, /* output vector for substring information */ +- 0); /* number of elements in the output vector */ ++ pcre_rc = pcre_exec(pcre_re, /* the compiled pattern */ ++ NULL, /* no extra data - we didn't study the pattern */ ++ string->s, /* the matching string */ ++ (int)(string->len), /* the length of the subject */ ++ 0, /* start at offset 0 in the string */ ++ 0, /* default options */ ++ NULL, /* output vector for substring information */ ++ 0); /* number of elements in the output vector */ + + /* Matching failed: handle error cases */ +- if (pcre_rc < 0) { ++ if(pcre_rc < 0) { + switch(pcre_rc) { + case PCRE_ERROR_NOMATCH: + LM_DBG("'%s' doesn't match '%s'\n", string->s, regex->s); +@@ -562,28 +561,26 @@ static int ki_pcre_match(sip_msg_t* msg, + } + + /*! \brief Return true if the argument matches the regular expression parameter */ +-static int w_pcre_match(struct sip_msg* _msg, char* _s1, char* _s2) ++static int w_pcre_match(struct sip_msg *_msg, char *_s1, char *_s2) + { + str string; + str regex; + +- if (_s1 == NULL) { ++ if(_s1 == NULL) { + LM_ERR("bad parameters\n"); + return -2; + } + +- if (_s2 == NULL) { ++ if(_s2 == NULL) { + LM_ERR("bad parameters\n"); + return -2; + } + +- if (fixup_get_svalue(_msg, (gparam_p)_s1, &string)) +- { ++ if(fixup_get_svalue(_msg, (gparam_p)_s1, &string)) { + LM_ERR("cannot print the format for string\n"); + return -3; + } +- if (fixup_get_svalue(_msg, (gparam_p)_s2, ®ex)) +- { ++ if(fixup_get_svalue(_msg, (gparam_p)_s2, ®ex)) { + LM_ERR("cannot print the format for regex\n"); + return -3; + } +@@ -592,17 +589,17 @@ static int w_pcre_match(struct sip_msg* + } + + /*! \brief Return true if the string argument matches the pattern group parameter */ +-static int ki_pcre_match_group(sip_msg_t* _msg, str* string, int num_pcre) ++static int ki_pcre_match_group(sip_msg_t *_msg, str *string, int num_pcre) + { + int pcre_rc; + + /* Check if group matching feature is enabled */ +- if (file == NULL) { ++ if(file == NULL) { + LM_ERR("group matching is disabled\n"); + return -2; + } + +- if (num_pcre >= *num_pcres) { ++ if(num_pcre >= *num_pcres) { + LM_ERR("invalid pcre index '%i', there are %i pcres\n", num_pcre, + *num_pcres); + return -4; +@@ -610,20 +607,19 @@ static int ki_pcre_match_group(sip_msg_t + + lock_get(reload_lock); + +- pcre_rc = pcre_exec( +- (*pcres_addr)[num_pcre], /* the compiled pattern */ +- NULL, /* no extra data - we didn't study the pattern */ +- string->s, /* the matching string */ +- (int)(string->len), /* the length of the subject */ +- 0, /* start at offset 0 in the string */ +- 0, /* default options */ +- NULL, /* output vector for substring information */ +- 0); /* number of elements in the output vector */ ++ pcre_rc = pcre_exec((*pcres_addr)[num_pcre], /* the compiled pattern */ ++ NULL, /* no extra data - we didn't study the pattern */ ++ string->s, /* the matching string */ ++ (int)(string->len), /* the length of the subject */ ++ 0, /* start at offset 0 in the string */ ++ 0, /* default options */ ++ NULL, /* output vector for substring information */ ++ 0); /* number of elements in the output vector */ + + lock_release(reload_lock); + + /* Matching failed: handle error cases */ +- if (pcre_rc < 0) { ++ if(pcre_rc < 0) { + switch(pcre_rc) { + case PCRE_ERROR_NOMATCH: + LM_DBG("'%s' doesn't match pcres[%i]\n", string->s, num_pcre); +@@ -640,29 +636,27 @@ static int ki_pcre_match_group(sip_msg_t + } + + /*! \brief Return true if the string argument matches the pattern group parameter */ +-static int w_pcre_match_group(struct sip_msg* _msg, char* _s1, char* _s2) ++static int w_pcre_match_group(struct sip_msg *_msg, char *_s1, char *_s2) + { + str string, group; + unsigned int num_pcre = 0; + +- if (_s1 == NULL) { ++ if(_s1 == NULL) { + LM_ERR("bad parameters\n"); + return -3; + } + +- if (_s2 == NULL) { ++ if(_s2 == NULL) { + num_pcre = 0; + } else { +- if (fixup_get_svalue(_msg, (gparam_p)_s2, &group)) +- { ++ if(fixup_get_svalue(_msg, (gparam_p)_s2, &group)) { + LM_ERR("cannot print the format for second param\n"); + return -5; + } + str2int(&group, &num_pcre); + } + +- if (fixup_get_svalue(_msg, (gparam_p)_s1, &string)) +- { ++ if(fixup_get_svalue(_msg, (gparam_p)_s1, &string)) { + LM_ERR("cannot print the format for first param\n"); + return -5; + } +@@ -676,42 +670,35 @@ static int w_pcre_match_group(struct sip + */ + + /*! \brief Reload pcres by reading the file again */ +-void regex_rpc_reload(rpc_t* rpc, void* ctx) ++void regex_rpc_reload(rpc_t *rpc, void *ctx) + { + /* Check if group matching feature is enabled */ +- if (file == NULL) { ++ if(file == NULL) { + LM_NOTICE("'file' parameter is not set, group matching disabled\n"); + rpc->fault(ctx, 500, "Group matching not enabled"); + return; + } + LM_INFO("reloading pcres...\n"); +- if (load_pcres(RELOAD)) { ++ if(load_pcres(RELOAD)) { + LM_ERR("failed to reload pcres\n"); + rpc->fault(ctx, 500, "Failed to reload"); + return; + } + LM_INFO("reload success\n"); +- + } + +-static const char* regex_rpc_reload_doc[2] = { +- "Reload regex file", +- 0 +-}; ++static const char *regex_rpc_reload_doc[2] = {"Reload regex file", 0}; + + rpc_export_t regex_rpc_cmds[] = { +- {"regex.reload", regex_rpc_reload, +- regex_rpc_reload_doc, 0}, +- {0, 0, 0, 0} +-}; ++ {"regex.reload", regex_rpc_reload, regex_rpc_reload_doc, 0}, ++ {0, 0, 0, 0}}; + + /** + * register RPC commands + */ + static int regex_init_rpc(void) + { +- if (rpc_register_array(regex_rpc_cmds)!=0) +- { ++ if(rpc_register_array(regex_rpc_cmds) != 0) { + LM_ERR("failed to register RPC commands\n"); + return -1; + } diff --git a/net/kamailio/patches/031-regex-typos.patch b/net/kamailio/patches/031-regex-typos.patch new file mode 100644 index 0000000..e08b413 --- /dev/null +++ b/net/kamailio/patches/031-regex-typos.patch @@ -0,0 +1,39 @@ +From 650b109dbcfe2c3083e09c987bae7ca39e4a19d2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= + =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= +Date: Wed, 21 Jun 2023 21:34:21 +0200 +Subject: [PATCH] regex: typos + +--- + src/modules/regex/regex_mod.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/src/modules/regex/regex_mod.c ++++ b/src/modules/regex/regex_mod.c +@@ -230,7 +230,7 @@ static void destroy(void) + } + + +-/*! \brief Convert the file content into regular expresions and store them in pcres */ ++/*! \brief Convert the file content into regular expressions and store them in pcres */ + static int load_pcres(int action) + { + int i, j; +@@ -307,7 +307,7 @@ static int load_pcres(int action) + } + + llen = strlen(line); +- /* Check if the patter size is too big (aprox) */ ++ /* Check if the pattern size is too big (approx) */ + if(strlen(patterns[i]) + llen >= group_max_size - 4) { + LM_ERR("pattern max file exceeded\n"); + fclose(f); +@@ -387,7 +387,7 @@ static int load_pcres(int action) + pcres_tmp[i] = NULL; + } + +- /* Compile the patters */ ++ /* Compile the patterns */ + for(i = 0; i < num_pcres_tmp; i++) { + + pcre_tmp = pcre_compile( diff --git a/net/kamailio/patches/032-regex-convert-to-memory-error-logging-helper.patch b/net/kamailio/patches/032-regex-convert-to-memory-error-logging-helper.patch new file mode 100644 index 0000000..573cc4e --- /dev/null +++ b/net/kamailio/patches/032-regex-convert-to-memory-error-logging-helper.patch @@ -0,0 +1,44 @@ +From 5c7de00bc0826cf739577010ba7b4882e83819cc Mon Sep 17 00:00:00 2001 +From: Victor Seva +Date: Wed, 9 Aug 2023 10:52:47 +0000 +Subject: [PATCH] regex: convert to memory error logging helper + +--- + src/modules/regex/regex_mod.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/src/modules/regex/regex_mod.c ++++ b/src/modules/regex/regex_mod.c +@@ -198,13 +198,13 @@ static int mod_init(void) + + /* Pointer to pcres */ + if((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) { +- LM_ERR("no memory for pcres_addr\n"); ++ SHM_MEM_ERROR; + goto err; + } + + /* Integer containing the number of pcres */ + if((num_pcres = shm_malloc(sizeof(int))) == 0) { +- LM_ERR("no memory for num_pcres\n"); ++ SHM_MEM_ERROR; + goto err; + } + +@@ -425,14 +425,14 @@ static int load_pcres(int action) + shm_free(pcres); + } + if((pcres = shm_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) { +- LM_ERR("no more memory for pcres\n"); ++ SHM_MEM_ERROR; + goto err; + } + memset(pcres, 0, sizeof(pcre *) * num_pcres_tmp); + for(i = 0; i < num_pcres_tmp; i++) { + pcre_rc = pcre_fullinfo(pcres_tmp[i], NULL, PCRE_INFO_SIZE, &pcre_size); + if((pcres[i] = shm_malloc(pcre_size)) == 0) { +- LM_ERR("no more memory for pcres[%i]\n", i); ++ SHM_MEM_ERROR; + goto err; + } + memcpy(pcres[i], pcres_tmp[i], pcre_size); diff --git a/net/kamailio/patches/033-regex-migration-to-pcre2.patch b/net/kamailio/patches/033-regex-migration-to-pcre2.patch new file mode 100644 index 0000000..957affa --- /dev/null +++ b/net/kamailio/patches/033-regex-migration-to-pcre2.patch @@ -0,0 +1,433 @@ +From 325c7a34fca74770a4351e00e27fcae75d57852e Mon Sep 17 00:00:00 2001 +From: Victor Seva +Date: Wed, 9 Aug 2023 10:48:41 +0000 +Subject: [PATCH] regex: migration to pcre2 + +--- + src/modules/regex/Makefile | 11 +- + src/modules/regex/regex_mod.c | 240 ++++++++++++++++++++++------------ + 2 files changed, 158 insertions(+), 93 deletions(-) + +--- a/src/modules/regex/Makefile ++++ b/src/modules/regex/Makefile +@@ -5,20 +5,15 @@ auto_gen= + NAME=regex.so + + ifeq ($(CROSS_COMPILE),) +-PCRE_BUILDER = $(shell \ +- if pkg-config --exists libcre; then \ +- echo 'pkg-config libpcre'; \ +- else \ +- which pcre-config; \ +- fi) ++PCRE_BUILDER = $(shell command -v pcre2-config) + endif + + ifeq ($(PCRE_BUILDER),) + PCREDEFS=-I$(LOCALBASE)/include +- PCRELIBS=-L$(LOCALBASE)/lib -lpcre ++ PCRELIBS=-L$(LOCALBASE)/lib -lpcre2-8 + else + PCREDEFS = $(shell $(PCRE_BUILDER) --cflags) +- PCRELIBS = $(shell $(PCRE_BUILDER) --libs) ++ PCRELIBS = $(shell $(PCRE_BUILDER) --libs8) + endif + + DEFS+=$(PCREDEFS) +--- a/src/modules/regex/regex_mod.c ++++ b/src/modules/regex/regex_mod.c +@@ -2,6 +2,7 @@ + * regex module - pcre operations + * + * Copyright (C) 2008 Iñaki Baz Castillo ++ * Copyright (C) 2023 Victor Seva + * + * This file is part of Kamailio, a free SIP server. + * +@@ -25,6 +26,7 @@ + * \file + * \brief REGEX :: Perl-compatible regular expressions using PCRE library + * Copyright (C) 2008 Iñaki Baz Castillo ++ * Copyright (C) 2023 Victor Seva + * \ingroup regex + */ + +@@ -32,7 +34,8 @@ + #include + #include + #include +-#include ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + #include "../../core/sr_module.h" + #include "../../core/dprint.h" + #include "../../core/pt.h" +@@ -77,8 +80,11 @@ static int pcre_extended = 0; + /* + * Module internal parameter variables + */ +-static pcre **pcres; +-static pcre ***pcres_addr; ++static pcre2_general_context *pcres_gctx = NULL; ++static pcre2_match_context *pcres_mctx = NULL; ++static pcre2_compile_context *pcres_ctx = NULL; ++static pcre2_code **pcres; ++static pcre2_code ***pcres_addr; + static int *num_pcres; + static int pcre_options = 0x00000000; + +@@ -151,6 +157,17 @@ struct module_exports exports = { + }; + + ++static void *pcre2_malloc(size_t size, void *ext) ++{ ++ return shm_malloc(size); ++} ++ ++static void pcre2_free(void *ptr, void *ext) ++{ ++ shm_free(ptr); ++ ptr = NULL; ++} ++ + /*! \brief + * Init module function + */ +@@ -180,24 +197,39 @@ static int mod_init(void) + /* PCRE options */ + if(pcre_caseless != 0) { + LM_DBG("PCRE CASELESS enabled\n"); +- pcre_options = pcre_options | PCRE_CASELESS; ++ pcre_options = pcre_options | PCRE2_CASELESS; + } + if(pcre_multiline != 0) { + LM_DBG("PCRE MULTILINE enabled\n"); +- pcre_options = pcre_options | PCRE_MULTILINE; ++ pcre_options = pcre_options | PCRE2_MULTILINE; + } + if(pcre_dotall != 0) { + LM_DBG("PCRE DOTALL enabled\n"); +- pcre_options = pcre_options | PCRE_DOTALL; ++ pcre_options = pcre_options | PCRE2_DOTALL; + } + if(pcre_extended != 0) { + LM_DBG("PCRE EXTENDED enabled\n"); +- pcre_options = pcre_options | PCRE_EXTENDED; ++ pcre_options = pcre_options | PCRE2_EXTENDED; + } + LM_DBG("PCRE options: %i\n", pcre_options); + ++ if((pcres_gctx = pcre2_general_context_create( ++ pcre2_malloc, pcre2_free, NULL)) ++ == NULL) { ++ LM_ERR("pcre2 general context creation failed\n"); ++ return -1; ++ } ++ if((pcres_ctx = pcre2_compile_context_create(pcres_gctx)) == NULL) { ++ LM_ERR("pcre2 compile context creation failed\n"); ++ return -1; ++ } ++ if((pcres_mctx = pcre2_match_context_create(pcres_gctx)) == NULL) { ++ LM_ERR("pcre2 match context creation failed\n"); ++ return -1; ++ } ++ + /* Pointer to pcres */ +- if((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) { ++ if((pcres_addr = shm_malloc(sizeof(pcre2_code **))) == 0) { + SHM_MEM_ERROR; + goto err; + } +@@ -227,6 +259,18 @@ err: + static void destroy(void) + { + free_shared_memory(); ++ ++ if(pcres_ctx) { ++ pcre2_compile_context_free(pcres_ctx); ++ } ++ ++ if(pcres_mctx) { ++ pcre2_match_context_free(pcres_mctx); ++ } ++ ++ if(pcres_gctx) { ++ pcre2_general_context_free(pcres_gctx); ++ } + } + + +@@ -237,13 +281,11 @@ static int load_pcres(int action) + FILE *f; + char line[FILE_MAX_LINE]; + char **patterns = NULL; +- pcre *pcre_tmp = NULL; +- size_t pcre_size; +- int pcre_rc; +- const char *pcre_error; +- int pcre_erroffset; ++ int pcre_error_num = 0; ++ char pcre_error[128]; ++ size_t pcre_erroffset; + int num_pcres_tmp = 0; +- pcre **pcres_tmp = NULL; ++ pcre2_code **pcres_tmp = NULL; + int llen; + + /* Get the lock */ +@@ -379,38 +421,34 @@ static int load_pcres(int action) + } + + /* Temporal pointer of pcres */ +- if((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) { ++ if((pcres_tmp = pkg_malloc(sizeof(pcre2_code *) * num_pcres_tmp)) == 0) { + LM_ERR("no more memory for pcres_tmp\n"); + goto err; + } +- for(i = 0; i < num_pcres_tmp; i++) { +- pcres_tmp[i] = NULL; +- } ++ memset(pcres_tmp, 0, sizeof(pcre2_code *) * num_pcres_tmp); + + /* Compile the patterns */ + for(i = 0; i < num_pcres_tmp; i++) { +- +- pcre_tmp = pcre_compile( +- patterns[i], pcre_options, &pcre_error, &pcre_erroffset, NULL); +- if(pcre_tmp == NULL) { +- LM_ERR("pcre_tmp compilation of '%s' failed at offset %d: %s\n", ++ pcres_tmp[i] = pcre2_compile((PCRE2_SPTR)patterns[i], ++ PCRE2_ZERO_TERMINATED, pcre_options, &pcre_error_num, ++ &pcre_erroffset, pcres_ctx); ++ if(pcres_tmp[i] == NULL) { ++ switch(pcre2_get_error_message( ++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) { ++ case PCRE2_ERROR_NOMEMORY: ++ snprintf(pcre_error, 128, ++ "unknown error[%d]: pcre2 error buffer too small", ++ pcre_error_num); ++ break; ++ case PCRE2_ERROR_BADDATA: ++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]", ++ pcre_error_num); ++ break; ++ } ++ LM_ERR("pcre_tmp compilation of '%s' failed at offset %zu: %s\n", + patterns[i], pcre_erroffset, pcre_error); + goto err; + } +- pcre_rc = pcre_fullinfo(pcre_tmp, NULL, PCRE_INFO_SIZE, &pcre_size); +- if(pcre_rc) { +- printf("pcre_fullinfo on compiled pattern[%i] yielded error: %d\n", +- i, pcre_rc); +- goto err; +- } +- +- if((pcres_tmp[i] = pkg_malloc(pcre_size)) == 0) { +- LM_ERR("no more memory for pcres_tmp[%i]\n", i); +- goto err; +- } +- +- memcpy(pcres_tmp[i], pcre_tmp, pcre_size); +- pcre_free(pcre_tmp); + pkg_free(patterns[i]); + patterns[i] = NULL; + } +@@ -419,31 +457,15 @@ static int load_pcres(int action) + if(action == RELOAD) { + for(i = 0; i < *num_pcres; i++) { /* Use the previous num_pcres value */ + if(pcres[i]) { +- shm_free(pcres[i]); ++ pcre2_code_free(pcres[i]); + } + } + shm_free(pcres); + } +- if((pcres = shm_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) { +- SHM_MEM_ERROR; +- goto err; +- } +- memset(pcres, 0, sizeof(pcre *) * num_pcres_tmp); +- for(i = 0; i < num_pcres_tmp; i++) { +- pcre_rc = pcre_fullinfo(pcres_tmp[i], NULL, PCRE_INFO_SIZE, &pcre_size); +- if((pcres[i] = shm_malloc(pcre_size)) == 0) { +- SHM_MEM_ERROR; +- goto err; +- } +- memcpy(pcres[i], pcres_tmp[i], pcre_size); +- } + *num_pcres = num_pcres_tmp; ++ *pcres = *pcres_tmp; + *pcres_addr = pcres; + +- /* Free used memory */ +- for(i = 0; i < num_pcres_tmp; i++) { +- pkg_free(pcres_tmp[i]); +- } + pkg_free(pcres_tmp); + /* Free allocated slots for unused patterns */ + for(i = num_pcres_tmp; i < max_groups; i++) { +@@ -466,7 +488,7 @@ err: + if(pcres_tmp) { + for(i = 0; i < num_pcres_tmp; i++) { + if(pcres_tmp[i]) { +- pkg_free(pcres_tmp[i]); ++ pcre2_code_free(pcres_tmp[i]); + } + } + pkg_free(pcres_tmp); +@@ -520,42 +542,73 @@ static void free_shared_memory(void) + /*! \brief Return true if the argument matches the regular expression parameter */ + static int ki_pcre_match(sip_msg_t *msg, str *string, str *regex) + { +- pcre *pcre_re = NULL; ++ pcre2_code *pcre_re = NULL; ++ pcre2_match_data *pcre_md = NULL; + int pcre_rc; +- const char *pcre_error; +- int pcre_erroffset; ++ int pcre_error_num = 0; ++ char pcre_error[128]; ++ size_t pcre_erroffset; + +- pcre_re = pcre_compile( +- regex->s, pcre_options, &pcre_error, &pcre_erroffset, NULL); ++ pcre_re = pcre2_compile((PCRE2_SPTR)regex->s, PCRE2_ZERO_TERMINATED, ++ pcre_options, &pcre_error_num, &pcre_erroffset, pcres_ctx); + if(pcre_re == NULL) { +- LM_ERR("pcre_re compilation of '%s' failed at offset %d: %s\n", ++ switch(pcre2_get_error_message( ++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) { ++ case PCRE2_ERROR_NOMEMORY: ++ snprintf(pcre_error, 128, ++ "unknown error[%d]: pcre2 error buffer too small", ++ pcre_error_num); ++ break; ++ case PCRE2_ERROR_BADDATA: ++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]", ++ pcre_error_num); ++ break; ++ } ++ LM_ERR("pcre_re compilation of '%s' failed at offset %zu: %s\n", + regex->s, pcre_erroffset, pcre_error); + return -4; + } + +- pcre_rc = pcre_exec(pcre_re, /* the compiled pattern */ +- NULL, /* no extra data - we didn't study the pattern */ +- string->s, /* the matching string */ +- (int)(string->len), /* the length of the subject */ +- 0, /* start at offset 0 in the string */ +- 0, /* default options */ +- NULL, /* output vector for substring information */ +- 0); /* number of elements in the output vector */ ++ pcre_md = pcre2_match_data_create_from_pattern(pcre_re, pcres_gctx); ++ pcre_rc = pcre2_match(pcre_re, /* the compiled pattern */ ++ (PCRE2_SPTR)string->s, /* the matching string */ ++ (PCRE2_SIZE)(string->len), /* the length of the subject */ ++ 0, /* start at offset 0 in the string */ ++ 0, /* default options */ ++ pcre_md, /* the match data block */ ++ pcres_mctx); /* a match context; NULL means use defaults */ + + /* Matching failed: handle error cases */ + if(pcre_rc < 0) { + switch(pcre_rc) { +- case PCRE_ERROR_NOMATCH: ++ case PCRE2_ERROR_NOMATCH: + LM_DBG("'%s' doesn't match '%s'\n", string->s, regex->s); + break; + default: +- LM_DBG("matching error '%d'\n", pcre_rc); ++ switch(pcre2_get_error_message( ++ pcre_rc, (PCRE2_UCHAR *)pcre_error, 128)) { ++ case PCRE2_ERROR_NOMEMORY: ++ snprintf(pcre_error, 128, ++ "unknown error[%d]: pcre2 error buffer too " ++ "small", ++ pcre_rc); ++ break; ++ case PCRE2_ERROR_BADDATA: ++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]", ++ pcre_rc); ++ break; ++ } ++ LM_ERR("matching error:'%s' failed[%d]\n", pcre_error, pcre_rc); + break; + } +- pcre_free(pcre_re); ++ if(pcre_md) ++ pcre2_match_data_free(pcre_md); ++ pcre2_code_free(pcre_re); + return -1; + } +- pcre_free(pcre_re); ++ if(pcre_md) ++ pcre2_match_data_free(pcre_md); ++ pcre2_code_free(pcre_re); + LM_DBG("'%s' matches '%s'\n", string->s, regex->s); + return 1; + } +@@ -592,6 +645,8 @@ static int w_pcre_match(struct sip_msg * + static int ki_pcre_match_group(sip_msg_t *_msg, str *string, int num_pcre) + { + int pcre_rc; ++ pcre2_match_data *pcre_md = NULL; ++ char pcre_error[128]; + + /* Check if group matching feature is enabled */ + if(file == NULL) { +@@ -606,26 +661,41 @@ static int ki_pcre_match_group(sip_msg_t + } + + lock_get(reload_lock); +- +- pcre_rc = pcre_exec((*pcres_addr)[num_pcre], /* the compiled pattern */ +- NULL, /* no extra data - we didn't study the pattern */ +- string->s, /* the matching string */ +- (int)(string->len), /* the length of the subject */ +- 0, /* start at offset 0 in the string */ +- 0, /* default options */ +- NULL, /* output vector for substring information */ +- 0); /* number of elements in the output vector */ ++ pcre_md = pcre2_match_data_create_from_pattern( ++ (*pcres_addr)[num_pcre], pcres_gctx); ++ pcre_rc = pcre2_match((*pcres_addr)[num_pcre], /* the compiled pattern */ ++ (PCRE2_SPTR)string->s, /* the matching string */ ++ (PCRE2_SIZE)(string->len), /* the length of the subject */ ++ 0, /* start at offset 0 in the string */ ++ 0, /* default options */ ++ pcre_md, /* the match data block */ ++ pcres_mctx); /* a match context; NULL means use defaults */ + + lock_release(reload_lock); ++ if(pcre_md) ++ pcre2_match_data_free(pcre_md); + + /* Matching failed: handle error cases */ + if(pcre_rc < 0) { + switch(pcre_rc) { +- case PCRE_ERROR_NOMATCH: ++ case PCRE2_ERROR_NOMATCH: + LM_DBG("'%s' doesn't match pcres[%i]\n", string->s, num_pcre); + break; + default: +- LM_DBG("matching error '%d'\n", pcre_rc); ++ switch(pcre2_get_error_message( ++ pcre_rc, (PCRE2_UCHAR *)pcre_error, 128)) { ++ case PCRE2_ERROR_NOMEMORY: ++ snprintf(pcre_error, 128, ++ "unknown error[%d]: pcre2 error buffer too " ++ "small", ++ pcre_rc); ++ break; ++ case PCRE2_ERROR_BADDATA: ++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]", ++ pcre_rc); ++ break; ++ } ++ LM_ERR("matching error:'%s' failed[%d]\n", pcre_error, pcre_rc); + break; + } + return -1;