telephony/net/kamailio/patches/022-lcr-pcre2-migration.patch
Christian Marangi ac4ad7f6fc
kamailio: backport and move to PCRE2
Backport merged patch and move package to PCRE2 as PCRE is EOL and won't
receive any security updates anymore.

Additional patch are backported to minimize changes to the backport
patches. Only patch 010 required adaptation due to a fix backported in
5.7 in the same place where the patch fixed some whitespace issue.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
2023-11-03 03:37:05 +01:00

509 lines
15 KiB
Diff

From e3e2c41e8c46a13bad18dd40fd9e3540020dd5eb Mon Sep 17 00:00:00 2001
From: Victor Seva <linuxmaniac@torreviejawireless.org>
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 <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_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 <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;