From dd535e8582955e61dfec4d4d8fab94e64b3649ab Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Thu, 18 Jul 2024 09:09:07 +0200 Subject: [PATCH] MT#58547 lcr_rate: use gw_id field from gw_uri_avp for load_peers() * merge lcr_rate patches * format code with kamailio clang definitions Change-Id: Ic20e9e535ca0f904b5f497468ddcf26abcb9fa2a (cherry picked from commit 8be5217b1f0c2b6359ca47e490b88fc4bbf1e758) (cherry picked from commit 294dbd880c05ed94e5ae8e44b6dfb0367cab3bd8) --- debian/patches/series | 1 - .../patches/sipwise/add_lcr_rate_module.patch | 260 ++++++++++-------- .../sipwise/fix_lcr_rate_wrong_id.patch | 67 ----- 3 files changed, 152 insertions(+), 176 deletions(-) delete mode 100644 debian/patches/sipwise/fix_lcr_rate_wrong_id.patch diff --git a/debian/patches/series b/debian/patches/series index a777d8c2b..3d2cff74c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -11,7 +11,6 @@ sipwise/parallel_build.patch ## New Modules sipwise/add_pcem_module.patch sipwise/add_lcr_rate_module.patch -sipwise/fix_lcr_rate_wrong_id.patch sipwise/add_tcap_module.patch sipwise/add_presence_dfks_module.patch sipwise/presence_dfks_null_ptr_fixes.patch diff --git a/debian/patches/sipwise/add_lcr_rate_module.patch b/debian/patches/sipwise/add_lcr_rate_module.patch index ce3b0ce44..8570ef320 100644 --- a/debian/patches/sipwise/add_lcr_rate_module.patch +++ b/debian/patches/sipwise/add_lcr_rate_module.patch @@ -7,8 +7,8 @@ Subject: add_lcr_rate_module src/core/mod_fix.c | 3 + src/core/mod_fix.h | 2 + src/modules/lcr_rate/Makefile | 9 + - src/modules/lcr_rate/lcr_rate_mod.c | 473 ++++++++++++++++++++++++++++++++++++ - 5 files changed, 494 insertions(+), 2 deletions(-) + src/modules/lcr_rate/lcr_rate_mod.c | 517 ++++++++++++++++++++++++++++++++++++ + 5 files changed, 538 insertions(+), 2 deletions(-) create mode 100644 src/modules/lcr_rate/Makefile create mode 100644 src/modules/lcr_rate/lcr_rate_mod.c @@ -97,10 +97,10 @@ index 0000000..9a3cee1 +include ../../Makefile.modules diff --git a/src/modules/lcr_rate/lcr_rate_mod.c b/src/modules/lcr_rate/lcr_rate_mod.c new file mode 100644 -index 0000000..f3a9ab2 +index 0000000..5670871 --- /dev/null +++ b/src/modules/lcr_rate/lcr_rate_mod.c -@@ -0,0 +1,473 @@ +@@ -0,0 +1,517 @@ +/* + * call rating for least cost routing module + * @@ -138,7 +138,8 @@ index 0000000..f3a9ab2 + +MODULE_VERSION + -+struct peer { ++struct peer ++{ + int valid; + unsigned int id; + double cost; @@ -151,10 +152,25 @@ index 0000000..f3a9ab2 +static int child_init(int rank); + +static int lcr_rate(sip_msg_t *msg, char *su, char *sq); -+static int lcr_get_prepaid_from_uuid(sip_msg_t *msg, char *uuid, char *avp, char *avp2); ++static int lcr_get_prepaid_from_uuid( ++ sip_msg_t *msg, char *uuid, char *avp, char *avp2); +static int lcr_get_prepaid_from_uuid2(sip_msg_t *msg, char *uuid, char *avp); +static int lcr_get_profile_id_from_uuid(sip_msg_t *msg, char *uuid, char *avp); + ++static char *gw_uri_avp_param; ++static int gw_uri_avp_type; ++static int_str gw_uri_avp; ++ ++static char *db_host; ++static unsigned int db_port; ++static char *db_user; ++static char *db_pass; ++static char *db_db; ++ ++static int swrate_done; ++static SWRATE *swrate_ptr; ++ ++/* clang-format off */ +static cmd_export_t cmds[] = { + {"lcr_rate", lcr_rate, 2, fixup_spve_spve, 0, + REQUEST_ROUTE | FAILURE_ROUTE}, @@ -167,16 +183,6 @@ index 0000000..f3a9ab2 + {0,} +}; + -+static char *gw_uri_avp_param; -+static int gw_uri_avp_type; -+static int_str gw_uri_avp; -+ -+static char *db_host; -+static unsigned int db_port; -+static char *db_user; -+static char *db_pass; -+static char *db_db; -+ +static param_export_t params[] = { + {"gw_uri_avp", STR_PARAM, &gw_uri_avp_param}, + {"db_host", STR_PARAM, &db_host}, @@ -187,9 +193,6 @@ index 0000000..f3a9ab2 + {0,}, +}; + -+static int swrate_done; -+static SWRATE *swrate_ptr; -+ +struct module_exports exports = { + "lcr_rate", /* module name */ + DEFAULT_DLFLAGS, /* dlopen flags */ @@ -202,13 +205,15 @@ index 0000000..f3a9ab2 + child_init, /* per-child init function */ + mod_destroy /* module destroy function */ +}; ++/* clang-format on */ + -+static int mod_init() { ++static int mod_init() ++{ + pv_spec_t avp_spec; + str s; + unsigned short avp_flags; + -+ if (!gw_uri_avp_param || !*gw_uri_avp_param) { ++ if(!gw_uri_avp_param || !*gw_uri_avp_param) { + LM_ERR("gw_uri_avp not set\n"); + return -1; + } @@ -216,12 +221,12 @@ index 0000000..f3a9ab2 + s.s = gw_uri_avp_param; + s.len = strlen(s.s); + -+ if (!pv_parse_spec(&s, &avp_spec) || avp_spec.type != PVT_AVP) { ++ if(!pv_parse_spec(&s, &avp_spec) || avp_spec.type != PVT_AVP) { + LM_ERR("malformed or non AVP definition <%s>\n", gw_uri_avp_param); + return -1; + } + -+ if (pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags)) { ++ if(pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags)) { + LM_ERR("invalid AVP definition <%s>\n", gw_uri_avp_param); + return -1; + } @@ -230,21 +235,25 @@ index 0000000..f3a9ab2 + return 0; +} + -+static int child_init(int rank) { ++static int child_init(int rank) ++{ + return 0; +} + -+static void mod_destroy() { -+ ; ++static void mod_destroy() ++{ ++ return; +} + -+static int check_swrate_init() { -+ if (swrate_done) ++static int check_swrate_init() ++{ ++ if(swrate_done) + return 0; -+ swrate_ptr = swrate_new(db_host, db_port, db_db, db_user, db_pass, NULL, 0, 1, 0); -+ if (!swrate_ptr || !swrate_new_ok(swrate_ptr)) { ++ swrate_ptr = swrate_new( ++ db_host, db_port, db_db, db_user, db_pass, NULL, 0, 1, 0); ++ if(!swrate_ptr || !swrate_new_ok(swrate_ptr)) { + LM_ERR("failed to initialized libswrate\n"); -+ if (swrate_ptr) ++ if(swrate_ptr) + swrate_free(swrate_ptr); + return -1; + } @@ -252,37 +261,39 @@ index 0000000..f3a9ab2 + return 0; +} + -+static struct peer *load_peers(int *num, char *src_user, char *src_domain, char *dst_user, char *dst_domain) { ++static struct peer *load_peers(int *num, char *src_user, char *src_domain, ++ char *dst_user, char *dst_domain) ++{ + struct usr_avp *avp; + int_str val; + struct peer *ret, *j; -+ int len, i; ++ int len, i, k; + char *c; + str s; + swr_rate_t rate; + time_t now; + -+ LM_DBG("loading peers for user <%s>@<%s> -> <%s>@<%s> from avp\n", -+ src_user, src_domain, dst_user, dst_domain); ++ LM_DBG("loading peers for user <%s>@<%s> -> <%s>@<%s> from avp\n", src_user, ++ src_domain, dst_user, dst_domain); + + len = 4; + ret = pkg_malloc(len * sizeof(*ret)); -+ if (!ret) { ++ if(!ret) { + LM_ERR("out of pkg memory\n"); + return NULL; + } + i = 0; + time(&now); + -+ while (1) { ++ while(1) { + avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &val, 0); -+ if (!avp) ++ if(!avp) + break; + -+ if (i == len) { ++ if(i == len) { + len <<= 1; + j = pkg_realloc(ret, len * sizeof(*ret)); -+ if (!j) { ++ if(!j) { + pkg_free(ret); + LM_ERR("out of pkg memory\n"); + return NULL; @@ -295,22 +306,47 @@ index 0000000..f3a9ab2 + + j->s.len = val.s.len; + j->s.s = pkg_malloc(val.s.len); -+ if (!j->s.s) { ++ if(!j->s.s) { + pkg_free(ret); + LM_ERR("out of pkg memory\n"); + return NULL; + } + memcpy(j->s.s, val.s.s, val.s.len); -+ c = memrchr(j->s.s, '|', val.s.len); -+ if (!c) { -+ LM_ERR("separator not found in string <%.*s>\n", val.s.len, j->s.s); -+ goto next; ++ ++ /* lcr gw fields: ++ * 0: gw index ++ * 1: scheme ++ * 2: strip ++ * 3: prefix ++ * 4: tag ++ * 5: ip adr ++ * 6: hostname ++ * 7: port ++ * 8: params ++ * 9: transport ++ * 10: flags ++ * 11: rule id ++ * 12: gw id ++ */ ++ c = j->s.s; ++ for(k = 0; k < 12; k++) { ++ c = memchr(c, '|', val.s.len - (c - j->s.s)); ++ if(!c) { ++ LM_ERR("separator not found in string <%.*s> (field #%i)\n", ++ val.s.len, j->s.s, k); ++ goto next; ++ } ++ c++; + } + -+ c++; + s.s = c; -+ s.len = val.s.len - (c - j->s.s); -+ if (str2int(&s, &j->id)) { ++ ++ /* find terminator */ ++ c = memchr(c, '|', val.s.len - (c - j->s.s)); ++ if(!c) ++ c = j->s.s + val.s.len; ++ s.len = c - s.s; ++ if(str2int(&s, &j->id)) { + LM_ERR("could not convert string <%.*s> to int\n", s.len, s.s); + goto next; + } @@ -318,17 +354,18 @@ index 0000000..f3a9ab2 + LM_DBG("finding rate for peer %u\n", j->id); + j->weight = i; + -+ if (swrate_get_peer_ab_rate(&rate, swrate_ptr, j->id, src_user, -+ src_domain, dst_user, dst_domain, now)) { -+ LM_ERR("failed to get rate for call, peer id %u, user <%s>@<%s> -> <%s>@<%s>\n", -+ j->id, src_user, src_domain, dst_user, dst_domain); ++ if(swrate_get_peer_ab_rate(&rate, swrate_ptr, j->id, src_user, ++ src_domain, dst_user, dst_domain, now)) { ++ LM_ERR("failed to get rate for call, peer id %u, user <%s>@<%s> -> " ++ "<%s>@<%s>\n", ++ j->id, src_user, src_domain, dst_user, dst_domain); + goto next; + } + j->cost = rate.init_rate; + j->valid = 1; + LM_DBG("cost is %f\n", j->cost); + -+next: ++ next: + destroy_avp(avp); + i++; + } @@ -337,37 +374,39 @@ index 0000000..f3a9ab2 + return ret; +} + -+static int peers_cmp(const void *aa, const void *bb) { ++static int peers_cmp(const void *aa, const void *bb) ++{ + const struct peer *a = aa, *b = bb; + -+ if (a->valid && !b->valid) ++ if(a->valid && !b->valid) + return 1; -+ if (!a->valid && b->valid) ++ if(!a->valid && b->valid) + return -1; -+ if (!a->valid && !b->valid) ++ if(!a->valid && !b->valid) + return 0; + -+ if (a->cost < b->cost) ++ if(a->cost < b->cost) + return 1; -+ if (a->cost > b->cost) ++ if(a->cost > b->cost) + return -1; + -+ if (a->weight < b->weight) ++ if(a->weight < b->weight) + return 1; -+ if (a->weight > b->weight) ++ if(a->weight > b->weight) + return -1; + + return 0; +} + -+static int save_peers(struct peer *peers, int num) { ++static int save_peers(struct peer *peers, int num) ++{ + int i; + int_str val; + -+ for (i = 0; i < num; i++) { ++ for(i = 0; i < num; i++) { + LM_DBG("adding back peer %u\n", peers[i].id); + val.s = peers[i].s; -+ if (add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val)) ++ if(add_avp(gw_uri_avp_type | AVP_VAL_STR, gw_uri_avp, val)) + LM_ERR("add_avp failed\n"); + pkg_free(val.s.s); + } @@ -376,35 +415,37 @@ index 0000000..f3a9ab2 + return 0; +} + -+static void extract_ud(str *s, char **user, char **at, char **domain) { ++static void extract_ud(str *s, char **user, char **at, char **domain) ++{ + *user = *at = *domain = NULL; -+ if (!s || !s->s || !*s->s) ++ if(!s || !s->s || !*s->s) + return; + *user = s->s; + *at = strchr(*user, '@'); -+ if (!*at) ++ if(!*at) + return; + **at = '\0'; + *domain = *at + 1; -+ if (!**domain) ++ if(!**domain) + *domain = NULL; +} + -+static int lcr_rate(sip_msg_t *msg, char *su, char *sq) { ++static int lcr_rate(sip_msg_t *msg, char *su, char *sq) ++{ + struct peer *peers; + int num_peers, ret; + str src, dst; + char *src_user, *src_at, *src_domain; + char *dst_user, *dst_at, *dst_domain; + -+ if (check_swrate_init()) ++ if(check_swrate_init()) + return -1; + -+ if (fixup_get_svalue(msg, (gparam_t *) su, &src)) { ++ if(fixup_get_svalue(msg, (gparam_t *)su, &src)) { + LM_ERR("failed to get user parameter\n"); + return -1; + } -+ if (fixup_get_svalue(msg, (gparam_t *) sq, &dst)) { ++ if(fixup_get_svalue(msg, (gparam_t *)sq, &dst)) { + LM_ERR("failed to get domain parameter\n"); + return -1; + } @@ -414,17 +455,17 @@ index 0000000..f3a9ab2 + + peers = load_peers(&num_peers, src_user, src_domain, dst_user, dst_domain); + -+ if (*src_at) ++ if(*src_at) + *src_at = '@'; -+ if (*dst_at) ++ if(*dst_at) + *dst_at = '@'; + -+ if (!peers) ++ if(!peers) + return -1; + qsort(peers, num_peers, sizeof(*peers), peers_cmp); + + ret = 1; -+ if (!num_peers || (!peers[0].valid && !peers[num_peers - 1].valid)) { ++ if(!num_peers || (!peers[0].valid && !peers[num_peers - 1].valid)) { + LM_ERR("no peers with valid ratings found\n"); + ret = -1; + } @@ -434,26 +475,24 @@ index 0000000..f3a9ab2 + return ret; +} + -+static int get_avp(unsigned short *avp_type, int_str *avp_name, char *avp_s) { ++static int get_avp(unsigned short *avp_type, int_str *avp_name, char *avp_s) ++{ + pv_spec_t *avp_spec = NULL; + str *avp; + -+ avp = (str *) avp_s; ++ avp = (str *)avp_s; + -+ if (pv_locate_name(avp) != avp->len) -+ { ++ if(pv_locate_name(avp) != avp->len) { + LM_ERR("invalid AVP parameter\n"); + return -1; + } + -+ if (((avp_spec = pv_cache_get(avp)) == NULL) -+ || avp_spec->type!=PVT_AVP) { ++ if(((avp_spec = pv_cache_get(avp)) == NULL) || avp_spec->type != PVT_AVP) { + LM_ERR("malformed or non AVP %s AVP definition\n", avp->s); + return -1; + } + -+ if(pv_get_avp_name(0, &avp_spec->pvp, avp_name, avp_type)!=0) -+ { ++ if(pv_get_avp_name(0, &avp_spec->pvp, avp_name, avp_type) != 0) { + LM_ERR("[%s]- invalid AVP definition\n", avp->s); + return -1; + } @@ -461,21 +500,23 @@ index 0000000..f3a9ab2 + return 0; +} + -+static int get_profile_from_uuid(swr_profile_t *prof, sip_msg_t *msg, char *uuid_s) { ++static int get_profile_from_uuid( ++ swr_profile_t *prof, sip_msg_t *msg, char *uuid_s) ++{ + char *pc, *ip; + str uuid; + -+ if (check_swrate_init()) ++ if(check_swrate_init()) + return -1; + + // validate parameters + -+ if (get_str_fparam(&uuid, msg, (fparam_t *) uuid_s)) { ++ if(get_str_fparam(&uuid, msg, (fparam_t *)uuid_s)) { + LM_ERR("unable to extract uuid parameter\n"); + return -1; + } + -+ if (!uuid.s || !*uuid.s) { ++ if(!uuid.s || !*uuid.s) { + LM_ERR("empty uuid parameter\n"); + return -1; + } @@ -483,14 +524,15 @@ index 0000000..f3a9ab2 + // split up "uuid;ip" + + pc = strchr(uuid.s, ';'); -+ if (!pc) ++ if(!pc) + ip = NULL; + else { + *pc = 0; -+ ip = pc+1; ++ ip = pc + 1; + } + -+ if (swrate_get_subscriber_billing_profile(prof, swrate_ptr, time(NULL), uuid.s, ip)) { ++ if(swrate_get_subscriber_billing_profile( ++ prof, swrate_ptr, time(NULL), uuid.s, ip)) { + LM_ERR("swrate call returned error\n"); + return -1; + } @@ -498,11 +540,14 @@ index 0000000..f3a9ab2 + return 0; +} + -+static int lcr_get_prepaid_from_uuid2(sip_msg_t *msg, char *uuid_s, char *avp_s) { ++static int lcr_get_prepaid_from_uuid2(sip_msg_t *msg, char *uuid_s, char *avp_s) ++{ + return lcr_get_prepaid_from_uuid(msg, uuid_s, avp_s, NULL); +} + -+static int lcr_get_prepaid_from_uuid(sip_msg_t *msg, char *uuid_s, char *avp_s, char *avp2_s) { ++static int lcr_get_prepaid_from_uuid( ++ sip_msg_t *msg, char *uuid_s, char *avp_s, char *avp2_s) ++{ + swr_profile_t *prof; + unsigned short avp_type = 0; + int_str avp_val; @@ -512,33 +557,31 @@ index 0000000..f3a9ab2 + int_str avp2_name; + + prof = swrate_profile_new(); -+ if (!prof) ++ if(!prof) + return -1; + -+ if (get_profile_from_uuid(prof, msg, uuid_s)) ++ if(get_profile_from_uuid(prof, msg, uuid_s)) + goto err; -+ if (get_avp(&avp_type, &avp_name, avp_s)) ++ if(get_avp(&avp_type, &avp_name, avp_s)) + goto err; -+ if (avp2_s) { -+ if (get_avp(&avp2_type, &avp2_name, avp2_s)) ++ if(avp2_s) { ++ if(get_avp(&avp2_type, &avp2_name, avp2_s)) + goto err; + } + + avp_val.s.s = prof->prepaid ? "1" : "0"; + avp_val.s.len = 1; + -+ if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) -+ { ++ if(add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) { + LM_ERR("Failed to add result avp"); + goto err; + } + -+ if (avp2_s) { ++ if(avp2_s) { + avp2_val.s.s = prof->prepaid_library; + avp2_val.s.len = strlen(prof->prepaid_library); + -+ if (add_avp(AVP_VAL_STR | avp2_type, avp2_name, avp2_val) != 0) -+ { ++ if(add_avp(AVP_VAL_STR | avp2_type, avp2_name, avp2_val) != 0) { + LM_ERR("Failed to add result avp"); + goto err; + } @@ -553,21 +596,22 @@ index 0000000..f3a9ab2 + return -1; +} + -+static int lcr_get_profile_id_from_uuid(sip_msg_t *msg, char *uuid_s, char *avp_s) { ++static int lcr_get_profile_id_from_uuid( ++ sip_msg_t *msg, char *uuid_s, char *avp_s) ++{ + swr_profile_t prof; + unsigned short avp_type = 0; + int_str avp_val; + int_str avp_name; + -+ if (get_profile_from_uuid(&prof, msg, uuid_s)) ++ if(get_profile_from_uuid(&prof, msg, uuid_s)) + return -1; -+ if (get_avp(&avp_type, &avp_name, avp_s)) ++ if(get_avp(&avp_type, &avp_name, avp_s)) + return -1; + + avp_val.s.s = int2str(prof.profile_id, &avp_val.s.len); + -+ if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) -+ { ++ if(add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) { + LM_ERR("Failed to add result avp"); + return -1; + } diff --git a/debian/patches/sipwise/fix_lcr_rate_wrong_id.patch b/debian/patches/sipwise/fix_lcr_rate_wrong_id.patch deleted file mode 100644 index 3d3a477a6..000000000 --- a/debian/patches/sipwise/fix_lcr_rate_wrong_id.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: Sipwise Development Team -Date: Thu, 26 Mar 2020 10:06:46 +0100 -Subject: fix_lcr_rate_wrong_id - ---- - src/modules/lcr_rate/lcr_rate_mod.c | 38 ++++++++++++++++++++++++++++++------- - 1 file changed, 31 insertions(+), 7 deletions(-) - -diff --git a/src/modules/lcr_rate/lcr_rate_mod.c b/src/modules/lcr_rate/lcr_rate_mod.c -index f3a9ab2..f35e577 100644 ---- a/src/modules/lcr_rate/lcr_rate_mod.c -+++ b/src/modules/lcr_rate/lcr_rate_mod.c -@@ -153,7 +153,7 @@ static struct peer *load_peers(int *num, char *src_user, char *src_domain, char - struct usr_avp *avp; - int_str val; - struct peer *ret, *j; -- int len, i; -+ int len, i, k; - char *c; - str s; - swr_rate_t rate; -@@ -198,15 +198,39 @@ static struct peer *load_peers(int *num, char *src_user, char *src_domain, char - return NULL; - } - memcpy(j->s.s, val.s.s, val.s.len); -- c = memrchr(j->s.s, '|', val.s.len); -- if (!c) { -- LM_ERR("separator not found in string <%.*s>\n", val.s.len, j->s.s); -- goto next; -+ -+ /* lcr gw fields: -+ * 0: gw index -+ * 1: scheme -+ * 2: strip -+ * 3: prefix -+ * 4: tag -+ * 5: ip adr -+ * 6: hostname -+ * 7: port -+ * 8: params -+ * 9: transport -+ * 10: flags -+ * 11: rule id -+ */ -+ c = j->s.s; -+ for (k = 0; k < 10; k++) { -+ c = memchr(c, '|', val.s.len - (c - j->s.s)); -+ if (!c) { -+ LM_ERR("separator not found in string <%.*s> (field #%i)\n", -+ val.s.len, j->s.s, k); -+ goto next; -+ } -+ c++; - } - -- c++; - s.s = c; -- s.len = val.s.len - (c - j->s.s); -+ -+ /* find terminator */ -+ c = memchr(c, '|', val.s.len - (c - j->s.s)); -+ if (!c) -+ c = j->s.s + val.s.len; -+ s.len = c - s.s; - if (str2int(&s, &j->id)) { - LM_ERR("could not convert string <%.*s> to int\n", s.len, s.s); - goto next;