From 5807a760ca593ecdbedcedf792db3794b53df00d Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Mon, 21 Aug 2023 13:30:36 +0200 Subject: [PATCH] lcr: pcre2 migration Gbp-Pq: Topic upstream Gbp-Pq: Name lcr-pcre2-migration.patch --- src/modules/lcr/Makefile | 12 +-- src/modules/lcr/hash.c | 16 ++-- src/modules/lcr/hash.h | 4 +- src/modules/lcr/lcr_mod.c | 168 +++++++++++++++++++++++++------------- src/modules/lcr/lcr_mod.h | 8 +- 5 files changed, 131 insertions(+), 77 deletions(-) diff --git a/src/modules/lcr/Makefile b/src/modules/lcr/Makefile index 56be2e3a..8b6bb222 100644 --- 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 - diff --git a/src/modules/lcr/hash.c b/src/modules/lcr/hash.c index 41a3b0b8..9d2f4633 100644 --- a/src/modules/lcr/hash.c +++ b/src/modules/lcr/hash.c @@ -36,9 +36,9 @@ /* 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 request_uri_len, char *request_uri, pcre2_code *request_uri_re, unsigned short stopper) { struct rule_info *rule; @@ -50,9 +50,9 @@ int rule_hash_table_insert(struct rule_info **hash_table, unsigned int lcr_id, 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_info **hash_table, unsigned int lcr_id, 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; } @@ -209,10 +209,10 @@ void rule_hash_table_contents_free(struct rule_info **hash_table) 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; diff --git a/src/modules/lcr/hash.h b/src/modules/lcr/hash.h index 7b29932b..62a84483 100644 --- a/src/modules/lcr/hash.h +++ b/src/modules/lcr/hash.h @@ -34,9 +34,9 @@ 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 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, diff --git a/src/modules/lcr/lcr_mod.c b/src/modules/lcr/lcr_mod.c index 1d5a1ff0..0abb6866 100644 --- a/src/modules/lcr/lcr_mod.c +++ b/src/modules/lcr/lcr_mod.c @@ -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_param = 0; /* 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 */ @@ -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; } @@ -875,33 +903,32 @@ static int comp_matched(const void *m1, const void *m2) /* 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; } @@ -1414,7 +1441,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 +2156,12 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws, 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 +2206,18 @@ int load_gws_dummy(int lcr_id, str *ruri_user, str *from_uri, str *request_uri, || 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 +2250,16 @@ int load_gws_dummy(int lcr_id, str *ruri_user, str *from_uri, str *request_uri, "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 +2323,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 +2385,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 +2429,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 */ diff --git a/src/modules/lcr/lcr_mod.h b/src/modules/lcr/lcr_mod.h index 421fe68f..0255241c 100644 --- 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; -- 2.30.2