lcr: pcre2 migration
authorVictor Seva <linuxmaniac@torreviejawireless.org>
Mon, 21 Aug 2023 11:30:36 +0000 (13:30 +0200)
committerVictor Seva <vseva@debian.org>
Fri, 29 Sep 2023 14:40:26 +0000 (15:40 +0100)
Gbp-Pq: Topic upstream
Gbp-Pq: Name lcr-pcre2-migration.patch

src/modules/lcr/Makefile
src/modules/lcr/hash.c
src/modules/lcr/hash.h
src/modules/lcr/lcr_mod.c
src/modules/lcr/lcr_mod.h

index 56be2e3a7418c02202a8651e1b35b13d311795d9..ad82bf6bc687c692a46362bfa1e505e1cabf0a28 100644 (file)
@@ -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)
index d49fb666af6608299fc40a2b218300600c1b36f2..1546f1daf11f813d73608d6d98dc2eaf052773be 100644 (file)
@@ -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,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;
index 2ed741ef41a8a8049c789fc8410ffbfd253e564b..62a844839bbc90bef6fcee5f779d5af6ffd3cce4 100644 (file)
@@ -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,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,
index be945fb8af88d5cbc0dd1ef01bf2de69573813cd..c28f31817b3abd9aec9ca96a102a38c53d24408f 100644 (file)
@@ -43,7 +43,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <arpa/inet.h>
-#include <pcre.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
 #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
  */
@@ -376,6 +380,17 @@ struct module_exports exports = {
 };
 /* clang-format on */
 
+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;
+}
+
 static int lcr_db_init(const str *db_url)
 {
        if(lcr_dbf.init == 0) {
@@ -698,7 +713,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(
@@ -774,6 +797,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;
 }
@@ -789,7 +818,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();
 }
 
@@ -870,33 +904,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;
 }
 
@@ -1405,7 +1438,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;
 
@@ -2122,11 +2155,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;
@@ -2171,11 +2205,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)
@@ -2209,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;
                        }
 
@@ -2275,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;
@@ -2336,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 */
@@ -2372,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 */
index 421fe68f507a6b10b82033f62e045448729eb541..0255241c0645cad35a9334599cafc1df8fea5dc0 100644 (file)
@@ -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 <stdio.h>
-#include <pcre.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
 #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;