implement RE matching against request URI

3.1_post-ngcp-2.5
Richard Fuchs 13 years ago
parent 2ae869ea18
commit f23a449aa3

@ -38,7 +38,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 stopper)
pcre *from_uri_re, unsigned short request_uri_len,
char *request_uri, pcre *request_uri_re,
unsigned short stopper)
{
struct rule_info *rule;
str prefix_str;
@ -48,6 +50,7 @@ int rule_hash_table_insert(struct rule_info **hash_table,
if (rule == NULL) {
LM_ERR("Cannot allocate memory for rule hash table entry\n");
if (from_uri_re) shm_free(from_uri_re);
if (request_uri_re) shm_free(request_uri_re);
return 0;
}
memset(rule, 0, sizeof(struct rule_info));
@ -63,6 +66,12 @@ int rule_hash_table_insert(struct rule_info **hash_table,
(rule->from_uri)[from_uri_len] = '\0';
rule->from_uri_re = from_uri_re;
}
rule->request_uri_len = request_uri_len;
if (request_uri_len) {
memcpy(rule->request_uri, request_uri, request_uri_len);
(rule->request_uri)[request_uri_len] = '\0';
rule->request_uri_re = request_uri_re;
}
rule->stopper = stopper;
rule->targets = (struct target *)NULL;
@ -73,9 +82,9 @@ int rule_hash_table_insert(struct rule_info **hash_table,
rule->next = hash_table[hash_val];
hash_table[hash_val] = rule;
LM_DBG("inserted rule <%u>, prefix <%.*s>, from_uri <%.*s>, stopper <%u>, "
LM_DBG("inserted rule <%u>, prefix <%.*s>, from_uri <%.*s>, request_uri <%.*s>, stopper <%u>, "
"into index <%u>\n",
rule_id, prefix_len, prefix, from_uri_len, from_uri, stopper,
rule_id, prefix_len, prefix, from_uri_len, from_uri, request_uri_len, request_uri, stopper,
hash_val);
return 1;
@ -177,6 +186,8 @@ void rule_hash_table_contents_free(struct rule_info **hash_table)
if (r->from_uri_re) {
shm_free(r->from_uri_re);
}
if (r->request_uri_re)
shm_free(r->request_uri_re);
t = r->targets;
while (t) {
next_t = t->next;

@ -36,7 +36,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 stopper);
pcre *from_uri_re, unsigned short request_uri_len,
char *request_uri, pcre *request_uri_re,
unsigned short stopper);
int rule_hash_table_insert_target(struct rule_info **hash_table,
struct gw_info *gws,

@ -90,7 +90,7 @@ MODULE_VERSION
/*
* versions of database tables required by the module.
*/
#define LCR_RULE_TABLE_VERSION 1
#define LCR_RULE_TABLE_VERSION 2
#define LCR_RULE_TARGET_TABLE_VERSION 1
#define LCR_GW_TABLE_VERSION 1
@ -104,6 +104,7 @@ MODULE_VERSION
#define LCR_ID_COL "lcr_id"
#define PREFIX_COL "prefix"
#define FROM_URI_COL "from_uri"
#define REQUEST_URI_COL "request_uri"
#define STOPPER_COL "stopper"
#define ENABLED_COL "enabled"
#define RULE_ID_COL "rule_id"
@ -164,6 +165,7 @@ static str id_col = str_init(ID_COL);
static str lcr_id_col = str_init(LCR_ID_COL);
static str prefix_col = str_init(PREFIX_COL);
static str from_uri_col = str_init(FROM_URI_COL);
static str request_uri_col = str_init(REQUEST_URI_COL);
static str stopper_col = str_init(STOPPER_COL);
static str enabled_col = str_init(ENABLED_COL);
static str rule_id_col = str_init(RULE_ID_COL);
@ -294,6 +296,7 @@ static param_export_t params[] = {
{"id_column", STR_PARAM, &id_col.s},
{"prefix_column", STR_PARAM, &prefix_col.s},
{"from_uri_column", STR_PARAM, &from_uri_col.s},
{"request_uri_column", STR_PARAM, &request_uri_col.s},
{"stopper_column", STR_PARAM, &stopper_col.s},
{"enabled_column", STR_PARAM, &enabled_col.s},
{"rule_id_column", STR_PARAM, &rule_id_col.s},
@ -416,6 +419,7 @@ static int mod_init(void)
lcr_id_col.len = strlen(lcr_id_col.s);
prefix_col.len = strlen(prefix_col.s);
from_uri_col.len = strlen(from_uri_col.s);
request_uri_col.len = strlen(request_uri_col.s);
stopper_col.len = strlen(stopper_col.s);
enabled_col.len = strlen(enabled_col.s);
rule_id_col.len = strlen(rule_id_col.s);
@ -895,21 +899,21 @@ int reload_tables()
unsigned int i, n, lcr_id, rule_id, gw_id, gw_name_len, port, strip,
tag_len, prefix_len, from_uri_len, stopper, enabled, flags, gw_cnt,
hostname_len, params_len, defunct_until, null_gw_ip_addr, priority,
weight, tmp;
request_uri_len, weight, tmp;
struct in_addr in_addr;
struct ip_addr ip_addr, *ip_p;
uri_type scheme;
uri_transport transport;
char *gw_name, *hostname, *tag, *prefix, *from_uri, *params;
char *gw_name, *hostname, *tag, *prefix, *from_uri, *params, *request_uri;
db1_res_t* res = NULL;
db_row_t* row;
db_key_t key_cols[1];
db_op_t op[1];
db_val_t vals[1];
db_key_t gw_cols[12];
db_key_t rule_cols[5];
db_key_t rule_cols[6];
db_key_t target_cols[4];
pcre *from_uri_re;
pcre *from_uri_re, *request_uri_re;
struct gw_info *gws, *gw_pt_tmp;
struct rule_info **rules, **rule_pt_tmp;
str ip_string;
@ -924,6 +928,7 @@ int reload_tables()
rule_cols[2] = &from_uri_col;
rule_cols[3] = &stopper_col;
rule_cols[4] = &enabled_col;
rule_cols[5] = &request_uri_col;
gw_cols[0] = &gw_name_col;
gw_cols[1] = &ip_addr_col;
@ -943,7 +948,7 @@ int reload_tables()
target_cols[2] = &priority_col;
target_cols[3] = &weight_col;
from_uri_re = 0;
request_uri_re = from_uri_re = 0;
if (lcr_db_init(&db_url) < 0) {
LM_ERR("unable to open database connection\n");
@ -964,7 +969,7 @@ int reload_tables()
VAL_INT(vals) = lcr_id;
if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 5, 0, 0)
if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, 0)
< 0) {
LM_ERR("db query on lcr_rule table failed\n");
goto err;
@ -974,7 +979,7 @@ int reload_tables()
goto err;
}
} else {
if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 5, 0, &res)
if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, &res)
< 0) {
LM_ERR("db query on lcr_rule table failed\n");
goto err;
@ -982,13 +987,13 @@ int reload_tables()
}
n = 0;
from_uri_re = 0;
request_uri_re = from_uri_re = 0;
do {
LM_DBG("loading, cycle %d with <%d> rows", n++, RES_ROW_N(res));
for (i = 0; i < RES_ROW_N(res); i++) {
from_uri_re = 0;
request_uri_re = from_uri_re = 0;
row = RES_ROWS(res) + i;
if ((VAL_NULL(ROW_VALUES(row)) == 1) ||
@ -1070,9 +1075,37 @@ int reload_tables()
from_uri_re = 0;
}
if (VAL_NULL(ROW_VALUES(row) + 5) == 1) {
request_uri_len = 0;
request_uri = 0;
} else {
if (VAL_TYPE(ROW_VALUES(row) + 5) != DB1_STRING) {
LM_ERR("lcr rule <%u> request_uri is not string\n",
rule_id);
goto err;
}
request_uri = (char *)VAL_STRING(ROW_VALUES(row) + 5);
request_uri_len = strlen(from_uri);
}
if (request_uri_len > MAX_URI_LEN) {
LM_ERR("lcr rule <%u> request_uri is too long\n", rule_id);
goto err;
}
if (request_uri_len > 0) {
request_uri_re = reg_ex_comp(request_uri);
if (request_uri_re == 0) {
LM_ERR("failed to compile lcr rule <%u> request_uri "
"<%s>\n", rule_id, request_uri);
goto err;
}
} else {
request_uri_re = 0;
}
if (!rule_hash_table_insert(rules, lcr_id, rule_id, prefix_len,
prefix, from_uri_len, from_uri,
from_uri_re, stopper) ||
from_uri_re, request_uri_len,
request_uri, request_uri_re, stopper) ||
!prefix_len_insert(rules, prefix_len)) {
goto err;
}
@ -1703,7 +1736,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
static int load_gws(struct sip_msg* _m, fparam_t *_lcr_id,
pv_spec_t* _from_uri)
{
str ruri_user, from_uri;
str ruri_user, from_uri, *request_uri;
int i, j, lcr_id;
unsigned int gw_index, now, dex;
int_str val;
@ -1749,6 +1782,7 @@ static int load_gws(struct sip_msg* _m, fparam_t *_lcr_id,
return -1;
}
ruri_user = _m->parsed_uri.user;
request_uri = GET_RURI(_m);
/*
* Find lcr entries that match based on prefix and from_uri and collect
@ -1774,34 +1808,43 @@ static int load_gws(struct sip_msg* _m, fparam_t *_lcr_id,
rule = rule_hash_table_lookup(rules, pl->prefix_len, ruri_user.s);
while (rule) {
/* Match prefix */
if ((rule->prefix_len == pl->prefix_len) &&
(strncmp(rule->prefix, ruri_user.s, pl->prefix_len) == 0)) {
/* 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)) {
/* Load gws associated with this rule */
t = rule->targets;
while (t) {
/* If this gw is defunct, skip it */
if (gws[t->gw_index].defunct_until > now) goto skip_gw;
matched_gws[gw_index].gw_index = t->gw_index;
matched_gws[gw_index].prefix_len = pl->prefix_len;
matched_gws[gw_index].priority = t->priority;
matched_gws[gw_index].weight = t->weight *
(rand() >> 8);
matched_gws[gw_index].duplicate = 0;
LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n",
gw_index, t->gw_index, pl->prefix_len,
t->priority, matched_gws[gw_index].weight);
gw_index++;
skip_gw:
t = t->next;
}
/* Do not look further if this matching rule was stopper */
if (rule->stopper == 1) goto done;
}
if ((rule->prefix_len != pl->prefix_len) ||
(strncmp(rule->prefix, ruri_user.s, pl->prefix_len)))
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))
goto next;
/* 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))
goto next;
/* Load gws associated with this rule */
t = rule->targets;
while (t) {
/* If this gw is defunct, skip it */
if (gws[t->gw_index].defunct_until > now) goto skip_gw;
matched_gws[gw_index].gw_index = t->gw_index;
matched_gws[gw_index].prefix_len = pl->prefix_len;
matched_gws[gw_index].priority = t->priority;
matched_gws[gw_index].weight = t->weight *
(rand() >> 8);
matched_gws[gw_index].duplicate = 0;
LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n",
gw_index, t->gw_index, pl->prefix_len,
t->priority, matched_gws[gw_index].weight);
gw_index++;
skip_gw:
t = t->next;
}
/* Do not look further if this matching rule was stopper */
if (rule->stopper == 1) goto done;
next:
rule = rule->next;
}
pl = pl->next;

@ -62,6 +62,9 @@ struct rule_info {
char from_uri[MAX_URI_LEN + 1];
unsigned short from_uri_len;
pcre *from_uri_re;
char request_uri[MAX_URI_LEN + 1];
unsigned short request_uri_len;
pcre *request_uri_re;
unsigned short stopper;
unsigned int enabled;
struct target *targets;

Loading…
Cancel
Save