lcr: pcre2 migration
authorVictor Seva <linuxmaniac@torreviejawireless.org>
Mon, 21 Aug 2023 11:30:36 +0000 (13:30 +0200)
committerRaspbian forward porter <root@raspbian.org>
Sat, 10 Feb 2024 11:06:59 +0000 (11:06 +0000)
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..8b6bb2220456424114639d855650685560e8bce2 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)
@@ -31,4 +26,3 @@ LIBS+=$(PCRELIBS)
 SERLIBPATH=../../lib
 SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
 include ../../Makefile.modules
-
index 41a3b0b82485823c24e504943aa6f46f6d4d33b6..9d2f4633dcea6b35d05a2b4c5ca435d89f8b5973 100644 (file)
@@ -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 7b29932beae2c18ad6dd5e416bcf0ac78a72c6ca..62a844839bbc90bef6fcee5f779d5af6ffd3cce4 100644 (file)
@@ -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 1d5a1ff012df9015e705925378c1d1cf42ca1cd7..0abb68660afeb402a82fb35251a6f1b195db3328 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
  */
@@ -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 */
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;