00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <string.h>
00061 #include <arpa/inet.h>
00062 #include <pcre.h>
00063 #include "../../locking.h"
00064 #include "../../sr_module.h"
00065 #include "../../dprint.h"
00066 #include "../../ut.h"
00067 #include "../../error.h"
00068 #include "../../mem/mem.h"
00069 #include "../../mem/shm_mem.h"
00070 #include "../../lib/srdb1/db.h"
00071 #include "../../usr_avp.h"
00072 #include "../../parser/parse_from.h"
00073 #include "../../parser/msg_parser.h"
00074 #include "../../action.h"
00075 #include "../../qvalue.h"
00076 #include "../../dset.h"
00077 #include "../../ip_addr.h"
00078 #include "../../resolve.h"
00079 #include "../../mod_fix.h"
00080 #include "../../socket_info.h"
00081 #include "../../pvar.h"
00082 #include "../../mod_fix.h"
00083 #include "hash.h"
00084 #include "lcr_rpc.h"
00085 #include "../../rpc_lookup.h"
00086
00087 MODULE_VERSION
00088
00089
00090
00091
00092 #define LCR_RULE_TABLE_VERSION 2
00093 #define LCR_RULE_TARGET_TABLE_VERSION 1
00094 #define LCR_GW_TABLE_VERSION 2
00095
00096
00097
00098 #define LCR_RULE_TABLE "lcr_rule"
00099 #define LCR_RULE_TARGET_TABLE "lcr_rule_target"
00100 #define LCR_GW_TABLE "lcr_gw"
00101
00102 #define ID_COL "id"
00103 #define LCR_ID_COL "lcr_id"
00104 #define PREFIX_COL "prefix"
00105 #define FROM_URI_COL "from_uri"
00106 #define REQUEST_URI_COL "request_uri"
00107 #define STOPPER_COL "stopper"
00108 #define ENABLED_COL "enabled"
00109 #define RULE_ID_COL "rule_id"
00110 #define PRIORITY_COL "priority"
00111 #define GW_ID_COL "gw_id"
00112 #define WEIGHT_COL "weight"
00113 #define GW_NAME_COL "gw_name"
00114 #define IP_ADDR_COL "ip_addr"
00115 #define PORT_COL "port"
00116 #define URI_SCHEME_COL "uri_scheme"
00117 #define TRANSPORT_COL "transport"
00118 #define PARAMS_COL "params"
00119 #define HOSTNAME_COL "hostname"
00120 #define STRIP_COL "strip"
00121 #define PREFIX_COL "prefix"
00122 #define TAG_COL "tag"
00123 #define FLAGS_COL "flags"
00124 #define DEFUNCT_COL "defunct"
00125
00126
00127 #define DEF_LCR_COUNT 1
00128 #define DEF_LCR_RULE_HASH_SIZE 128
00129 #define DEF_LCR_GW_COUNT 128
00130 #define DEF_FETCH_ROWS 1024
00131
00132
00133
00134
00135
00136 struct matched_gw_info {
00137 unsigned short gw_index;
00138 unsigned short prefix_len;
00139 unsigned short priority;
00140 unsigned int weight;
00141 unsigned short duplicate;
00142 };
00143
00144
00145
00146
00147 static db1_con_t* dbh = 0;
00148 static db_func_t lcr_dbf;
00149
00150
00151
00152
00153 gen_lock_t *reload_lock;
00154
00155
00156
00157
00158
00159
00160 static str db_url = str_init(DEFAULT_RODB_URL);
00161 static str lcr_rule_table = str_init(LCR_RULE_TABLE);
00162 static str lcr_rule_target_table = str_init(LCR_RULE_TARGET_TABLE);
00163 static str lcr_gw_table = str_init(LCR_GW_TABLE);
00164 static str id_col = str_init(ID_COL);
00165 static str lcr_id_col = str_init(LCR_ID_COL);
00166 static str prefix_col = str_init(PREFIX_COL);
00167 static str from_uri_col = str_init(FROM_URI_COL);
00168 static str request_uri_col = str_init(REQUEST_URI_COL);
00169 static str stopper_col = str_init(STOPPER_COL);
00170 static str enabled_col = str_init(ENABLED_COL);
00171 static str rule_id_col = str_init(RULE_ID_COL);
00172 static str priority_col = str_init(PRIORITY_COL);
00173 static str gw_id_col = str_init(GW_ID_COL);
00174 static str weight_col = str_init(WEIGHT_COL);
00175 static str gw_name_col = str_init(GW_NAME_COL);
00176 static str ip_addr_col = str_init(IP_ADDR_COL);
00177 static str port_col = str_init(PORT_COL);
00178 static str uri_scheme_col = str_init(URI_SCHEME_COL);
00179 static str transport_col = str_init(TRANSPORT_COL);
00180 static str params_col = str_init(PARAMS_COL);
00181 static str hostname_col = str_init(HOSTNAME_COL);
00182 static str strip_col = str_init(STRIP_COL);
00183 static str tag_col = str_init(TAG_COL);
00184 static str flags_col = str_init(FLAGS_COL);
00185 static str defunct_col = str_init(DEFUNCT_COL);
00186
00187
00188 static int fetch_rows_param = DEF_FETCH_ROWS;
00189
00190
00191 static char *gw_uri_avp_param = NULL;
00192 static char *ruri_user_avp_param = NULL;
00193 static char *tag_avp_param = NULL;
00194 static char *flags_avp_param = NULL;
00195 static char *defunct_gw_avp_param = NULL;
00196 static char *lcr_id_avp_param = NULL;
00197
00198
00199 unsigned int lcr_count_param = DEF_LCR_COUNT;
00200
00201
00202 unsigned int lcr_rule_hash_size_param = DEF_LCR_RULE_HASH_SIZE;
00203
00204
00205 unsigned int lcr_gw_count_param = DEF_LCR_GW_COUNT;
00206
00207
00208 static unsigned int defunct_capability_param = 0;
00209
00210
00211 static int dont_strip_or_prefix_flag_param = -1;
00212
00213
00214
00215
00216
00217
00218 static int gw_uri_avp_type;
00219 static int_str gw_uri_avp;
00220 static int ruri_user_avp_type;
00221 static int_str ruri_user_avp;
00222 static int tag_avp_type;
00223 static int_str tag_avp;
00224 static int flags_avp_type;
00225 static int_str flags_avp;
00226 static int defunct_gw_avp_type;
00227 static int_str defunct_gw_avp;
00228 static int lcr_id_avp_type;
00229 static int_str lcr_id_avp;
00230
00231
00232 struct rule_info ***rule_pt = (struct rule_info ***)NULL;
00233
00234
00235 struct gw_info **gw_pt = (struct gw_info **)NULL;
00236
00237
00238 struct rule_id_info **rule_id_hash_table = (struct rule_id_info **)NULL;
00239
00240
00241
00242
00243 static void destroy(void);
00244 static int mod_init(void);
00245 static int child_init(int rank);
00246 static void free_shared_memory(void);
00247
00248 static int load_gws(struct sip_msg* _m, int argc, action_u_t argv[]);
00249 static int next_gw(struct sip_msg* _m, char* _s1, char* _s2);
00250 static int defunct_gw(struct sip_msg* _m, char* _s1, char* _s2);
00251 static int from_gw_1(struct sip_msg* _m, char* _s1, char* _s2);
00252 static int from_gw_3(struct sip_msg* _m, char* _s1, char* _s2, char* _s3);
00253 static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2);
00254 static int from_any_gw_2(struct sip_msg* _m, char* _s1, char* _s2);
00255 static int to_gw_1(struct sip_msg* _m, char* _s1, char* _s2);
00256 static int to_gw_3(struct sip_msg* _m, char* _s1, char* _s2, char* _s3);
00257 static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2);
00258 static int to_any_gw_2(struct sip_msg* _m, char* _s1, char* _s2);
00259
00260
00261
00262
00263 static cmd_export_t cmds[] = {
00264 {"load_gws", (cmd_function)load_gws, VAR_PARAM_NO, 0, 0,
00265 REQUEST_ROUTE | FAILURE_ROUTE},
00266 {"next_gw", (cmd_function)next_gw, 0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00267 {"defunct_gw", (cmd_function)defunct_gw, 1, 0, 0,
00268 REQUEST_ROUTE | FAILURE_ROUTE},
00269 {"from_gw", (cmd_function)from_gw_1, 1, 0, 0,
00270 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00271 {"from_gw", (cmd_function)from_gw_3, 3, 0, 0,
00272 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00273 {"from_any_gw", (cmd_function)from_any_gw_0, 0, 0, 0,
00274 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00275 {"from_any_gw", (cmd_function)from_any_gw_2, 2, 0, 0,
00276 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00277 {"to_gw", (cmd_function)to_gw_1, 1, 0, 0,
00278 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00279 {"to_gw", (cmd_function)to_gw_3, 3, 0, 0,
00280 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00281 {"to_any_gw", (cmd_function)to_any_gw_0, 0, 0, 0,
00282 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00283 {"to_any_gw", (cmd_function)to_any_gw_2, 2, 0, 0,
00284 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
00285 {0, 0, 0, 0, 0, 0}
00286 };
00287
00288
00289
00290
00291
00292 static param_export_t params[] = {
00293 {"db_url", STR_PARAM, &db_url.s},
00294 {"lcr_rule_table", STR_PARAM, &lcr_rule_table.s},
00295 {"lcr_rule_target_table", STR_PARAM, &lcr_rule_target_table.s},
00296 {"lcr_gw_table", STR_PARAM, &lcr_gw_table.s},
00297 {"lcr_id_column", STR_PARAM, &lcr_id_col.s},
00298 {"id_column", STR_PARAM, &id_col.s},
00299 {"prefix_column", STR_PARAM, &prefix_col.s},
00300 {"from_uri_column", STR_PARAM, &from_uri_col.s},
00301 {"request_uri_column", STR_PARAM, &request_uri_col.s},
00302 {"stopper_column", STR_PARAM, &stopper_col.s},
00303 {"enabled_column", STR_PARAM, &enabled_col.s},
00304 {"rule_id_column", STR_PARAM, &rule_id_col.s},
00305 {"priority_column", STR_PARAM, &priority_col.s},
00306 {"gw_id_column", STR_PARAM, &gw_id_col.s},
00307 {"weight_column", STR_PARAM, &weight_col.s},
00308 {"gw_name_column", STR_PARAM, &gw_name_col.s},
00309 {"ip_addr_column", STR_PARAM, &ip_addr_col.s},
00310 {"port_column", STR_PARAM, &port_col.s},
00311 {"uri_scheme_column", STR_PARAM, &uri_scheme_col.s},
00312 {"transport_column", STR_PARAM, &transport_col.s},
00313 {"params_column", STR_PARAM, ¶ms_col.s},
00314 {"hostname_column", STR_PARAM, &hostname_col.s},
00315 {"strip_column", STR_PARAM, &strip_col.s},
00316 {"prefix_column", STR_PARAM, &prefix_col.s},
00317 {"tag_column", STR_PARAM, &tag_col.s},
00318 {"flags_column", STR_PARAM, &flags_col.s},
00319 {"defunct_column", STR_PARAM, &defunct_col.s},
00320 {"gw_uri_avp", STR_PARAM, &gw_uri_avp_param},
00321 {"ruri_user_avp", STR_PARAM, &ruri_user_avp_param},
00322 {"tag_avp", STR_PARAM, &tag_avp_param},
00323 {"flags_avp", STR_PARAM, &flags_avp_param},
00324 {"defunct_capability", INT_PARAM, &defunct_capability_param},
00325 {"defunct_gw_avp", STR_PARAM, &defunct_gw_avp_param},
00326 {"lcr_id_avp", STR_PARAM, &lcr_id_avp_param},
00327 {"lcr_count", INT_PARAM, &lcr_count_param},
00328 {"lcr_rule_hash_size", INT_PARAM, &lcr_rule_hash_size_param},
00329 {"lcr_gw_count", INT_PARAM, &lcr_gw_count_param},
00330 {"dont_strip_or_prefix_flag",INT_PARAM, &dont_strip_or_prefix_flag_param},
00331 {"fetch_rows", INT_PARAM, &fetch_rows_param},
00332 {0, 0, 0}
00333 };
00334
00335
00336
00337
00338 struct module_exports exports = {
00339 "lcr",
00340 DEFAULT_DLFLAGS,
00341 cmds,
00342 params,
00343 0,
00344 0,
00345 0,
00346 0,
00347 mod_init,
00348 0,
00349 destroy,
00350 child_init
00351 };
00352
00353 static int lcr_db_init(const str* db_url)
00354 {
00355 if (lcr_dbf.init==0){
00356 LM_CRIT("null lcr_dbf\n");
00357 goto error;
00358 }
00359 if (dbh) {
00360 LM_ERR("database is already connected\n");
00361 goto error;
00362 }
00363 dbh=lcr_dbf.init(db_url);
00364 if (dbh==0){
00365 LM_ERR("unable to connect to the database\n");
00366 goto error;
00367 }
00368 return 0;
00369 error:
00370 return -1;
00371 }
00372
00373
00374
00375 static int lcr_db_bind(const str* db_url)
00376 {
00377 if (db_bind_mod(db_url, &lcr_dbf)<0){
00378 LM_ERR("unable to bind to the database module\n");
00379 return -1;
00380 }
00381
00382 if (!DB_CAPABILITY(lcr_dbf, DB_CAP_QUERY)) {
00383 LM_ERR("database module does not implement 'query' function\n");
00384 return -1;
00385 }
00386
00387 return 0;
00388 }
00389
00390
00391 static void lcr_db_close(void)
00392 {
00393 if (dbh && lcr_dbf.close){
00394 lcr_dbf.close(dbh);
00395 dbh=0;
00396 }
00397 }
00398
00399
00400
00401
00402
00403 static int mod_init(void)
00404 {
00405 pv_spec_t avp_spec;
00406 str s;
00407 unsigned short avp_flags;
00408 unsigned int i;
00409
00410
00411 if (rpc_register_array(lcr_rpc)!=0) {
00412 LM_ERR("failed to register RPC commands\n");
00413 return -1;
00414 }
00415
00416
00417 db_url.len = strlen(db_url.s);
00418 lcr_rule_table.len = strlen(lcr_rule_table.s);
00419 lcr_rule_target_table.len = strlen(lcr_rule_target_table.s);
00420 lcr_gw_table.len = strlen(lcr_gw_table.s);
00421 id_col.len = strlen(id_col.s);
00422 lcr_id_col.len = strlen(lcr_id_col.s);
00423 prefix_col.len = strlen(prefix_col.s);
00424 from_uri_col.len = strlen(from_uri_col.s);
00425 request_uri_col.len = strlen(request_uri_col.s);
00426 stopper_col.len = strlen(stopper_col.s);
00427 enabled_col.len = strlen(enabled_col.s);
00428 rule_id_col.len = strlen(rule_id_col.s);
00429 priority_col.len = strlen(priority_col.s);
00430 gw_id_col.len = strlen(gw_id_col.s);
00431 weight_col.len = strlen(weight_col.s);
00432 gw_name_col.len = strlen(gw_name_col.s);
00433 ip_addr_col.len = strlen(ip_addr_col.s);
00434 port_col.len = strlen(port_col.s);
00435 uri_scheme_col.len = strlen(uri_scheme_col.s);
00436 transport_col.len = strlen(transport_col.s);
00437 params_col.len = strlen(params_col.s);
00438 hostname_col.len = strlen(hostname_col.s);
00439 strip_col.len = strlen(strip_col.s);
00440 prefix_col.len = strlen(prefix_col.s);
00441 tag_col.len = strlen(tag_col.s);
00442 flags_col.len = strlen(flags_col.s);
00443 defunct_col.len = strlen(defunct_col.s);
00444
00445
00446 if (lcr_db_bind(&db_url)) {
00447 LM_ERR("no database module found\n");
00448 return -1;
00449 }
00450
00451
00452 if (lcr_count_param < 1) {
00453 LM_ERR("invalid lcr_count module parameter value <%d>\n",
00454 lcr_count_param);
00455 return -1;
00456 }
00457 if (lcr_rule_hash_size_param < 1) {
00458 LM_ERR("invalid lcr_rule_hash_size module parameter value <%d>\n",
00459 lcr_rule_hash_size_param);
00460 return -1;
00461 }
00462 if (lcr_gw_count_param < 1) {
00463 LM_ERR("invalid lcr_gw_count module parameter value <%d>\n",
00464 lcr_gw_count_param);
00465 return -1;
00466 }
00467 if ((dont_strip_or_prefix_flag_param != -1) &&
00468 !flag_in_range(dont_strip_or_prefix_flag_param)) {
00469 LM_ERR("invalid dont_strip_or_prefix_flag value <%d>\n",
00470 dont_strip_or_prefix_flag_param);
00471 return -1;
00472 }
00473
00474
00475
00476 if (gw_uri_avp_param && *gw_uri_avp_param) {
00477 s.s = gw_uri_avp_param; s.len = strlen(s.s);
00478 if (pv_parse_spec(&s, &avp_spec)==0
00479 || avp_spec.type!=PVT_AVP) {
00480 LM_ERR("malformed or non AVP definition <%s>\n", gw_uri_avp_param);
00481 return -1;
00482 }
00483
00484 if (pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags) != 0) {
00485 LM_ERR("invalid AVP definition <%s>\n", gw_uri_avp_param);
00486 return -1;
00487 }
00488 gw_uri_avp_type = avp_flags;
00489 } else {
00490 LM_ERR("AVP gw_uri_avp has not been defined\n");
00491 return -1;
00492 }
00493
00494 if (ruri_user_avp_param && *ruri_user_avp_param) {
00495 s.s = ruri_user_avp_param; s.len = strlen(s.s);
00496 if (pv_parse_spec(&s, &avp_spec)==0
00497 || avp_spec.type!=PVT_AVP) {
00498 LM_ERR("malformed or non AVP definition <%s>\n",
00499 ruri_user_avp_param);
00500 return -1;
00501 }
00502
00503 if (pv_get_avp_name(0, &(avp_spec.pvp), &ruri_user_avp, &avp_flags)
00504 != 0) {
00505 LM_ERR("invalid AVP definition <%s>\n", ruri_user_avp_param);
00506 return -1;
00507 }
00508 ruri_user_avp_type = avp_flags;
00509 } else {
00510 LM_ERR("AVP ruri_user_avp has not been defined\n");
00511 return -1;
00512 }
00513
00514 if (tag_avp_param) {
00515 s.s = tag_avp_param; s.len = strlen(s.s);
00516 if ((pv_parse_spec(&s, &avp_spec)==0) || (avp_spec.type!=PVT_AVP)) {
00517 LM_ERR("malformed or non AVP definition <%s>\n", tag_avp_param);
00518 return -1;
00519 }
00520 if (pv_get_avp_name(0, &(avp_spec.pvp), &tag_avp, &avp_flags) != 0) {
00521 LM_ERR("invalid AVP definition <%s>\n", tag_avp_param);
00522 return -1;
00523 }
00524 tag_avp_type = avp_flags | AVP_VAL_STR;
00525 }
00526
00527 if (flags_avp_param) {
00528 s.s = flags_avp_param; s.len = strlen(s.s);
00529 if ((pv_parse_spec(&s, &avp_spec)==0) || (avp_spec.type != PVT_AVP)) {
00530 LM_ERR("malformed or non AVP definition <%s>\n", flags_avp_param);
00531 return -1;
00532 }
00533 if (pv_get_avp_name(0, &(avp_spec.pvp), &flags_avp, &avp_flags) != 0) {
00534 LM_ERR("invalid AVP definition <%s>\n", flags_avp_param);
00535 return -1;
00536 }
00537 flags_avp_type = avp_flags;
00538 }
00539
00540 if (defunct_capability_param > 0) {
00541 if (defunct_gw_avp_param && *defunct_gw_avp_param) {
00542 s.s = defunct_gw_avp_param; s.len = strlen(s.s);
00543 if ((pv_parse_spec(&s, &avp_spec) == 0) ||
00544 (avp_spec.type != PVT_AVP)) {
00545 LM_ERR("malformed or non AVP definition <%s>\n",
00546 defunct_gw_avp_param);
00547 return -1;
00548 }
00549 if (pv_get_avp_name(0, &(avp_spec.pvp), &defunct_gw_avp,
00550 &avp_flags) != 0) {
00551 LM_ERR("invalid AVP definition <%s>\n", defunct_gw_avp_param);
00552 return -1;
00553 }
00554 defunct_gw_avp_type = avp_flags;
00555 } else {
00556 LM_ERR("AVP defunct_gw_avp has not been defined\n");
00557 return -1;
00558 }
00559 if (lcr_id_avp_param && *lcr_id_avp_param) {
00560 s.s = lcr_id_avp_param; s.len = strlen(s.s);
00561 if ((pv_parse_spec(&s, &avp_spec) == 0) ||
00562 (avp_spec.type != PVT_AVP)) {
00563 LM_ERR("malformed or non AVP definition <%s>\n",
00564 lcr_id_avp_param);
00565 return -1;
00566 }
00567 if (pv_get_avp_name(0, &(avp_spec.pvp), &lcr_id_avp,
00568 &avp_flags) != 0) {
00569 LM_ERR("invalid AVP definition <%s>\n", lcr_id_avp_param);
00570 return -1;
00571 }
00572 lcr_id_avp_type = avp_flags;
00573 } else {
00574 LM_ERR("AVP lcr_id_avp has not been defined\n");
00575 return -1;
00576 }
00577 }
00578
00579 if (fetch_rows_param < 1) {
00580 LM_ERR("invalid fetch_rows module parameter value <%d>\n",
00581 fetch_rows_param);
00582 return -1;
00583 }
00584
00585
00586 if (lcr_db_init(&db_url) < 0) {
00587 LM_ERR("unable to open database connection\n");
00588 return -1;
00589 }
00590 if ((db_check_table_version(&lcr_dbf, dbh, &lcr_rule_table,
00591 LCR_RULE_TABLE_VERSION) < 0) ||
00592 (db_check_table_version(&lcr_dbf, dbh, &lcr_rule_target_table,
00593 LCR_RULE_TARGET_TABLE_VERSION) < 0) ||
00594 (db_check_table_version(&lcr_dbf, dbh, &lcr_gw_table,
00595 LCR_GW_TABLE_VERSION) < 0)) {
00596 LM_ERR("error during table version check\n");
00597 lcr_db_close();
00598 goto err;
00599 }
00600 lcr_db_close();
00601
00602
00603
00604
00605
00606 rule_pt = (struct rule_info ***)shm_malloc(sizeof(struct rule_info **) *
00607 (lcr_count_param + 1));
00608 if (rule_pt == 0) {
00609 LM_ERR("no memory for rule hash table pointer table\n");
00610 goto err;
00611 }
00612 memset(rule_pt, 0, sizeof(struct rule_info **) * (lcr_count_param + 1));
00613
00614
00615
00616 for (i = 0; i <= lcr_count_param; i++) {
00617 rule_pt[i] = (struct rule_info **)
00618 shm_malloc(sizeof(struct rule_info *) *
00619 (lcr_rule_hash_size_param + 1));
00620 if (rule_pt[i] == 0) {
00621 LM_ERR("no memory for rules hash table\n");
00622 goto err;
00623 }
00624 memset(rule_pt[i], 0, sizeof(struct rule_info *) *
00625 (lcr_rule_hash_size_param + 1));
00626 }
00627
00628
00629
00630
00631 gw_pt = (struct gw_info **)shm_malloc(sizeof(struct gw_info *) *
00632 (lcr_count_param + 1));
00633 if (gw_pt == 0) {
00634 LM_ERR("no memory for gw table pointer table\n");
00635 goto err;
00636 }
00637 memset(gw_pt, 0, sizeof(struct gw_info *) * (lcr_count_param + 1));
00638
00639
00640
00641
00642
00643
00644 for (i = 0; i <= lcr_count_param; i++) {
00645 gw_pt[i] = (struct gw_info *)shm_malloc(sizeof(struct gw_info) *
00646 (lcr_gw_count_param + 1));
00647 if (gw_pt[i] == 0) {
00648 LM_ERR("no memory for gw table\n");
00649 goto err;
00650 }
00651 memset(gw_pt[i], 0, sizeof(struct gw_info *) *
00652 (lcr_gw_count_param + 1));
00653 }
00654
00655
00656 reload_lock = lock_alloc();
00657 if (reload_lock == NULL) {
00658 LM_ERR("cannot allocate reload_lock\n");
00659 goto err;
00660 }
00661 if (lock_init(reload_lock) == NULL) {
00662 LM_ERR("cannot init reload_lock\n");
00663 goto err;
00664 }
00665
00666
00667 lock_get(reload_lock);
00668 if (reload_tables() < 0) {
00669 lock_release(reload_lock);
00670 LM_CRIT("failed to reload lcr tables\n");
00671 goto err;
00672 }
00673 lock_release(reload_lock);
00674
00675 return 0;
00676
00677 err:
00678 free_shared_memory();
00679 return -1;
00680 }
00681
00682
00683
00684 static int child_init(int rank)
00685 {
00686 return 0;
00687 }
00688
00689
00690 static void destroy(void)
00691 {
00692 lcr_db_close();
00693
00694 free_shared_memory();
00695 }
00696
00697
00698
00699 static void free_shared_memory(void)
00700 {
00701 int i;
00702 for (i = 0; i <= lcr_count_param; i++) {
00703 if (rule_pt && rule_pt[i]) {
00704 rule_hash_table_contents_free(rule_pt[i]);
00705 shm_free(rule_pt[i]);
00706 rule_pt[i] = 0;
00707 }
00708 }
00709 if (rule_pt) {
00710 shm_free(rule_pt);
00711 rule_pt = 0;
00712 }
00713 for (i = 0; i <= lcr_count_param; i++) {
00714 if (gw_pt && gw_pt[i]) {
00715 shm_free(gw_pt[i]);
00716 gw_pt[i] = 0;
00717 }
00718 }
00719 if (gw_pt) {
00720 shm_free(gw_pt);
00721 gw_pt = 0;
00722 }
00723 if (reload_lock) {
00724 lock_destroy(reload_lock);
00725 lock_dealloc(reload_lock);
00726 reload_lock=0;
00727 }
00728 }
00729
00730
00731
00732
00733
00734 static int comp_matched(const void *m1, const void *m2)
00735 {
00736 struct matched_gw_info *mi1 = (struct matched_gw_info *) m1;
00737 struct matched_gw_info *mi2 = (struct matched_gw_info *) m2;
00738
00739
00740 if (mi1->prefix_len > mi2->prefix_len) return 1;
00741 if (mi1->prefix_len == mi2->prefix_len) {
00742
00743 if (mi1->priority < mi2->priority) return 1;
00744 if (mi1->priority == mi2->priority) {
00745
00746 if (mi1->weight > mi2->weight) return 1;
00747 if (mi1->weight == mi2->weight) return 0;
00748 return -1;
00749 }
00750 return -1;
00751 }
00752 return -1;
00753 }
00754
00755
00756
00757 static pcre *reg_ex_comp(const char *pattern)
00758 {
00759 pcre *re, *result;
00760 const char *error;
00761 int rc, size, err_offset;
00762
00763 re = pcre_compile(pattern, 0, &error, &err_offset, NULL);
00764 if (re == NULL) {
00765 LM_ERR("pcre compilation of '%s' failed at offset %d: %s\n",
00766 pattern, err_offset, error);
00767 return (pcre *)0;
00768 }
00769 rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
00770 if (rc != 0) {
00771 LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
00772 pattern, rc);
00773 return (pcre *)0;
00774 }
00775 result = (pcre *)shm_malloc(size);
00776 if (result == NULL) {
00777 pcre_free(re);
00778 LM_ERR("not enough shared memory for compiled PCRE pattern\n");
00779 return (pcre *)0;
00780 }
00781 memcpy(result, re, size);
00782 pcre_free(re);
00783 return result;
00784 }
00785
00786
00787
00788
00789
00790 static int comp_gws(const void *_g1, const void *_g2)
00791 {
00792 struct gw_info *g1 = (struct gw_info *)_g1;
00793 struct gw_info *g2 = (struct gw_info *)_g2;
00794
00795 if (g1->ip_addr.af < g2->ip_addr.af) return -1;
00796 if (g1->ip_addr.af > g2->ip_addr.af) return 1;
00797 if (g1->ip_addr.len < g2->ip_addr.len) return -1;
00798 if (g1->ip_addr.len > g2->ip_addr.len) return 1;
00799 return memcmp(g1->ip_addr.u.addr, g2->ip_addr.u.addr, g1->ip_addr.len);
00800 }
00801
00802
00803
00804
00805
00806 static int insert_gw(struct gw_info *gws, unsigned int i, unsigned int gw_id,
00807 char *gw_name, unsigned int gw_name_len,
00808 unsigned int scheme, struct ip_addr *ip_addr,
00809 unsigned int port, unsigned int transport,
00810 char *params, unsigned int params_len,
00811 char *hostname, unsigned int hostname_len,
00812 char *ip_string, unsigned int strip, char *prefix,
00813 unsigned int prefix_len, char *tag, unsigned int tag_len,
00814 unsigned int flags, unsigned int defunct_until)
00815 {
00816 gws[i].gw_id = gw_id;
00817 if (gw_name_len) memcpy(&(gws[i].gw_name[0]), gw_name, gw_name_len);
00818 gws[i].gw_name_len = gw_name_len;
00819 gws[i].scheme = scheme;
00820 gws[i].ip_addr = *ip_addr;
00821 gws[i].port = port;
00822 gws[i].transport = transport;
00823 if (params_len) memcpy(&(gws[i].params[0]), params, params_len);
00824 gws[i].params_len = params_len;
00825 if (hostname_len) memcpy(&(gws[i].hostname[0]), hostname, hostname_len);
00826 gws[i].hostname_len = hostname_len;
00827 gws[i].strip = strip;
00828 gws[i].prefix_len = prefix_len;
00829 if (prefix_len) memcpy(&(gws[i].prefix[0]), prefix, prefix_len);
00830 gws[i].tag_len = tag_len;
00831 if (tag_len) memcpy(&(gws[i].tag[0]), tag, tag_len);
00832 gws[i].flags = flags;
00833 gws[i].defunct_until = defunct_until;
00834 LM_DBG("inserted gw <%u, %.*s, %s, %u, %.*s> at index %u\n", gw_id,
00835 gw_name_len, gw_name, ip_string, port, hostname_len, hostname, i);
00836 return 1;
00837 }
00838
00839
00840
00841
00842
00843
00844 static int prefix_len_insert(struct rule_info **table,
00845 unsigned short prefix_len)
00846 {
00847 struct rule_info *lcr_rec, **previous, *this;
00848
00849 previous = &(table[lcr_rule_hash_size_param]);
00850 this = table[lcr_rule_hash_size_param];
00851
00852 while (this) {
00853 if (this->prefix_len == prefix_len)
00854 return 1;
00855 if (this->prefix_len < prefix_len) {
00856 lcr_rec = shm_malloc(sizeof(struct rule_info));
00857 if (lcr_rec == NULL) {
00858 LM_ERR("no shared memory for rule_info\n");
00859 return 0;
00860 }
00861 memset(lcr_rec, 0, sizeof(struct rule_info));
00862 lcr_rec->prefix_len = prefix_len;
00863 lcr_rec->next = this;
00864 *previous = lcr_rec;
00865 return 1;
00866 }
00867 previous = &(this->next);
00868 this = this->next;
00869 }
00870
00871 lcr_rec = shm_malloc(sizeof(struct rule_info));
00872 if (lcr_rec == NULL) {
00873 LM_ERR("no shared memory for rule_info\n");
00874 return 0;
00875 }
00876 memset(lcr_rec, 0, sizeof(struct rule_info));
00877 lcr_rec->prefix_len = prefix_len;
00878 lcr_rec->next = NULL;
00879 *previous = lcr_rec;
00880 return 1;
00881 }
00882
00883 static int insert_gws(db1_res_t *res, struct gw_info *gws,
00884 unsigned int *null_gw_ip_addr,
00885 unsigned int *gw_cnt)
00886 {
00887 unsigned int i, gw_id, defunct_until, gw_name_len, port, params_len,
00888 hostname_len, strip, prefix_len, tag_len, flags;
00889 char *gw_name, *params, *hostname, *prefix, *tag;
00890 db_row_t* row;
00891 struct in_addr in_addr;
00892 struct ip_addr ip_addr, *ip_p;
00893 str ip_string;
00894 uri_type scheme;
00895 uri_transport transport;
00896
00897 for (i = 0; i < RES_ROW_N(res); i++) {
00898 row = RES_ROWS(res) + i;
00899 if ((VAL_NULL(ROW_VALUES(row) + 12) == 1) ||
00900 (VAL_TYPE(ROW_VALUES(row) + 12) != DB1_INT)) {
00901 LM_ERR("lcr_gw id at row <%u> is null or not int\n", i);
00902 return 0;
00903 }
00904 gw_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 12);
00905 if (VAL_NULL(ROW_VALUES(row) + 11)) {
00906 defunct_until = 0;
00907 } else {
00908 if (VAL_TYPE(ROW_VALUES(row) + 11) != DB1_INT) {
00909 LM_ERR("lcr_gw defunct at row <%u> is not int\n", i);
00910 return 0;
00911 }
00912 defunct_until = (unsigned int)VAL_INT(ROW_VALUES(row) + 11);
00913 if (defunct_until > 4294967294UL) {
00914 LM_DBG("skipping disabled gw <%u>\n", gw_id);
00915 continue;
00916 }
00917 }
00918 if (!VAL_NULL(ROW_VALUES(row)) &&
00919 (VAL_TYPE(ROW_VALUES(row)) != DB1_STRING)) {
00920 LM_ERR("lcr_gw gw_name at row <%u> is not null or string\n", i);
00921 return 0;
00922 }
00923 if (VAL_NULL(ROW_VALUES(row))) {
00924 gw_name_len = 0;
00925 gw_name = (char *)0;
00926 } else {
00927 if (VAL_TYPE(ROW_VALUES(row)) != DB1_STRING) {
00928 LM_ERR("lcr_gw gw_name at row <%u> is not string\n", i);
00929 return 0;
00930 }
00931 gw_name = (char *)VAL_STRING(ROW_VALUES(row));
00932 gw_name_len = strlen(gw_name);
00933 }
00934 if (gw_name_len > MAX_NAME_LEN) {
00935 LM_ERR("lcr_gw gw_name <%u> at row <%u> it too long\n",
00936 gw_name_len, i);
00937 return 0;
00938 }
00939 if (!VAL_NULL(ROW_VALUES(row) + 1) &&
00940 (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_STRING)) {
00941 LM_ERR("lcr_gw ip_addr at row <%u> is not null or string\n",
00942 i);
00943 return 0;
00944 }
00945 if (VAL_NULL(ROW_VALUES(row) + 1)) {
00946 ip_string.s = (char *)0;
00947 ip_addr.af = 0;
00948 ip_addr.len = 0;
00949 *null_gw_ip_addr = 1;
00950 } else {
00951 ip_string.s = (char *)VAL_STRING(ROW_VALUES(row) + 1);
00952 ip_string.len = strlen(ip_string.s);
00953 if ((ip_p = str2ip(&ip_string))) {
00954
00955 ip_addr = *ip_p;
00956 }
00957 #ifdef USE_IPV6
00958 else if ((ip_p = str2ip6(&ip_string))) {
00959
00960 ip_addr = *ip_p;
00961 }
00962 #endif
00963 else if (inet_aton(ip_string.s, &in_addr) == 0) {
00964
00965 ip_addr.u.addr32[0] = in_addr.s_addr;
00966 ip_addr.af = AF_INET;
00967 ip_addr.len = 4;
00968 }
00969 else {
00970 LM_ERR("lcr_gw ip_addr <%s> at row <%u> is invalid\n",
00971 ip_string.s, i);
00972 return 0;
00973 }
00974 }
00975 if (VAL_NULL(ROW_VALUES(row) + 2)) {
00976 port = 0;
00977 } else {
00978 if (VAL_TYPE(ROW_VALUES(row) + 2) != DB1_INT) {
00979 LM_ERR("lcr_gw port at row <%u> is not int\n", i);
00980 return 0;
00981 }
00982 port = (unsigned int)VAL_INT(ROW_VALUES(row) + 2);
00983 }
00984 if (port > 65536) {
00985 LM_ERR("lcr_gw port <%d> at row <%u> is too large\n", port, i);
00986 return 0;
00987 }
00988 if (VAL_NULL(ROW_VALUES(row) + 3)) {
00989 scheme = SIP_URI_T;
00990 } else {
00991 if (VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT) {
00992 LM_ERR("lcr_gw uri scheme at row <%u> is not int\n", i);
00993 return 0;
00994 }
00995 scheme = (uri_type)VAL_INT(ROW_VALUES(row) + 3);
00996 }
00997 if ((scheme != SIP_URI_T) && (scheme != SIPS_URI_T)) {
00998 LM_ERR("lcr_gw has unknown or unsupported URI scheme <%u> at "
00999 "row <%u>\n", (unsigned int)scheme, i);
01000 return 0;
01001 }
01002 if (VAL_NULL(ROW_VALUES(row) + 4)) {
01003 transport = PROTO_NONE;
01004 } else {
01005 if (VAL_TYPE(ROW_VALUES(row) + 4) != DB1_INT) {
01006 LM_ERR("lcr_gw transport at row <%u> is not int\n", i);
01007 return 0;
01008 }
01009 transport = (uri_transport)VAL_INT(ROW_VALUES(row) + 4);
01010 }
01011 if ((transport != PROTO_UDP) && (transport != PROTO_TCP) &&
01012 (transport != PROTO_TLS) && (transport != PROTO_SCTP) &&
01013 (transport != PROTO_NONE)) {
01014 LM_ERR("lcr_gw has unknown or unsupported transport <%u> at "
01015 " row <%u>\n", (unsigned int)transport, i);
01016 return 0;
01017 }
01018 if ((scheme == SIPS_URI_T) && (transport == PROTO_UDP)) {
01019 LM_ERR("lcr_gw has wrong transport <%u> for SIPS URI "
01020 "scheme at row <%u>\n", transport, i);
01021 return 0;
01022 }
01023 if (VAL_NULL(ROW_VALUES(row) + 5)) {
01024 params_len = 0;
01025 params = (char *)0;
01026 } else {
01027 if (VAL_TYPE(ROW_VALUES(row) + 5) != DB1_STRING) {
01028 LM_ERR("lcr_gw params at row <%u> is not string\n", i);
01029 return 0;
01030 }
01031 params = (char *)VAL_STRING(ROW_VALUES(row) + 5);
01032 params_len = strlen(params);
01033 if ((params_len > 0) && (params[0] != ';')) {
01034 LM_ERR("lcr_gw params at row <%u> does not start "
01035 "with ';'\n", i);
01036 return 0;
01037 }
01038 }
01039 if (params_len > MAX_PARAMS_LEN) {
01040 LM_ERR("lcr_gw params length <%u> at row <%u> it too large\n",
01041 params_len, i);
01042 return 0;
01043 }
01044 if (VAL_NULL(ROW_VALUES(row) + 6)) {
01045 if (ip_string.s == 0) {
01046 LM_ERR("lcr_gw gw ip_addr and hostname are both null "
01047 "at row <%u>\n", i);
01048 return 0;
01049 }
01050 hostname_len = 0;
01051 hostname = (char *)0;
01052 } else {
01053 if (VAL_TYPE(ROW_VALUES(row) + 6) != DB1_STRING) {
01054 LM_ERR("hostname at row <%u> is not string\n", i);
01055 return 0;
01056 }
01057 hostname = (char *)VAL_STRING(ROW_VALUES(row) + 6);
01058 hostname_len = strlen(hostname);
01059 }
01060 if (hostname_len > MAX_HOST_LEN) {
01061 LM_ERR("lcr_gw hostname at row <%u> it too long\n", i);
01062 return 0;
01063 }
01064 if (VAL_NULL(ROW_VALUES(row) + 7)) {
01065 strip = 0;
01066 } else {
01067 if (VAL_TYPE(ROW_VALUES(row) + 7) != DB1_INT) {
01068 LM_ERR("lcr_gw strip count at row <%u> is not int\n", i);
01069 return 0;
01070 }
01071 strip = (unsigned int)VAL_INT(ROW_VALUES(row) + 7);
01072 }
01073 if (strip > MAX_USER_LEN) {
01074 LM_ERR("lcr_gw strip count <%u> at row <%u> it too large\n",
01075 strip, i);
01076 return 0;
01077 }
01078 if (VAL_NULL(ROW_VALUES(row) + 8)) {
01079 prefix_len = 0;
01080 prefix = (char *)0;
01081 } else {
01082 if (VAL_TYPE(ROW_VALUES(row) + 8) != DB1_STRING) {
01083 LM_ERR("lcr_gw prefix at row <%u> is not string\n", i);
01084 return 0;
01085 }
01086 prefix = (char *)VAL_STRING(ROW_VALUES(row) + 8);
01087 prefix_len = strlen(prefix);
01088 }
01089 if (prefix_len > MAX_PREFIX_LEN) {
01090 LM_ERR("lcr_gw prefix at row <%u> it too long\n", i);
01091 return 0;
01092 }
01093 if (VAL_NULL(ROW_VALUES(row) + 9)) {
01094 tag_len = 0;
01095 tag = (char *)0;
01096 } else {
01097 if (VAL_TYPE(ROW_VALUES(row) + 9) != DB1_STRING) {
01098 LM_ERR("lcr_gw tag at row <%u> is not string\n", i);
01099 return 0;
01100 }
01101 tag = (char *)VAL_STRING(ROW_VALUES(row) + 9);
01102 tag_len = strlen(tag);
01103 }
01104 if (tag_len > MAX_TAG_LEN) {
01105 LM_ERR("lcr_gw tag at row <%u> it too long\n", i);
01106 return 0;
01107 }
01108 if (VAL_NULL(ROW_VALUES(row) + 10)) {
01109 flags = 0;
01110 } else {
01111 if (VAL_TYPE(ROW_VALUES(row) + 10) != DB1_INT) {
01112 LM_ERR("lcr_gw flags at row <%u> is not int\n", i);
01113 return 0;
01114 }
01115 flags = (unsigned int)VAL_INT(ROW_VALUES(row) + 10);
01116 }
01117 (*gw_cnt)++;
01118 if (!insert_gw(gws, *gw_cnt, gw_id, gw_name, gw_name_len,
01119 scheme, &ip_addr, port,
01120 transport, params, params_len, hostname,
01121 hostname_len, ip_string.s, strip, prefix, prefix_len,
01122 tag, tag_len, flags, defunct_until)) {
01123 return 0;
01124 }
01125 }
01126 return 1;
01127 }
01128
01129
01130
01131
01132
01133
01134
01135 int reload_tables()
01136 {
01137 unsigned int i, n, lcr_id, rule_id, gw_id, from_uri_len, request_uri_len,
01138 stopper, prefix_len, enabled, gw_cnt, null_gw_ip_addr, priority,
01139 weight, tmp;
01140 char *prefix, *from_uri, *request_uri;
01141 db1_res_t* res = NULL;
01142 db_row_t* row;
01143 db_key_t key_cols[1];
01144 db_op_t op[1];
01145 db_val_t vals[1];
01146 db_key_t gw_cols[13];
01147 db_key_t rule_cols[6];
01148 db_key_t target_cols[4];
01149 pcre *from_uri_re, *request_uri_re;
01150 struct gw_info *gws, *gw_pt_tmp;
01151 struct rule_info **rules, **rule_pt_tmp;
01152
01153 key_cols[0] = &lcr_id_col;
01154 op[0] = OP_EQ;
01155 VAL_TYPE(vals) = DB1_INT;
01156 VAL_NULL(vals) = 0;
01157
01158 rule_cols[0] = &id_col;
01159 rule_cols[1] = &prefix_col;
01160 rule_cols[2] = &from_uri_col;
01161 rule_cols[3] = &stopper_col;
01162 rule_cols[4] = &enabled_col;
01163 rule_cols[5] = &request_uri_col;
01164
01165 gw_cols[0] = &gw_name_col;
01166 gw_cols[1] = &ip_addr_col;
01167 gw_cols[2] = &port_col;
01168 gw_cols[3] = &uri_scheme_col;
01169 gw_cols[4] = &transport_col;
01170 gw_cols[5] = ¶ms_col;
01171 gw_cols[6] = &hostname_col;
01172 gw_cols[7] = &strip_col;
01173 gw_cols[8] = &prefix_col;
01174 gw_cols[9] = &tag_col;
01175 gw_cols[10] = &flags_col;
01176 gw_cols[11] = &defunct_col;
01177 gw_cols[12] = &id_col;
01178
01179 target_cols[0] = &rule_id_col;
01180 target_cols[1] = &gw_id_col;
01181 target_cols[2] = &priority_col;
01182 target_cols[3] = &weight_col;
01183
01184 request_uri_re = from_uri_re = 0;
01185
01186 if (lcr_db_init(&db_url) < 0) {
01187 LM_ERR("unable to open database connection\n");
01188 return -1;
01189 }
01190
01191 rule_id_hash_table = pkg_malloc(sizeof(struct rule_id_info *) *
01192 lcr_rule_hash_size_param);
01193 if (!rule_id_hash_table) {
01194 LM_ERR("no pkg memory for rule_id hash table\n");
01195 goto err;
01196 }
01197 memset(rule_id_hash_table, 0, sizeof(struct rule_id_info *) *
01198 lcr_rule_hash_size_param);
01199
01200 for (lcr_id = 1; lcr_id <= lcr_count_param; lcr_id++) {
01201
01202
01203
01204 rules = rule_pt[0];
01205 rule_hash_table_contents_free(rules);
01206 rule_id_hash_table_contents_free();
01207
01208 if (lcr_dbf.use_table(dbh, &lcr_rule_table) < 0) {
01209 LM_ERR("error while trying to use lcr_rule table\n");
01210 goto err;
01211 }
01212
01213 VAL_INT(vals) = lcr_id;
01214 if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
01215 if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, 0)
01216 < 0) {
01217 LM_ERR("db query on lcr_rule table failed\n");
01218 goto err;
01219 }
01220 if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
01221 LM_ERR("failed to fetch rows from lcr_rule table\n");
01222 goto err;
01223 }
01224 } else {
01225 if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, &res)
01226 < 0) {
01227 LM_ERR("db query on lcr_rule table failed\n");
01228 goto err;
01229 }
01230 }
01231
01232 n = 0;
01233 request_uri_re = from_uri_re = 0;
01234
01235 do {
01236 LM_DBG("loading, cycle %d with <%d> rows", n++, RES_ROW_N(res));
01237 for (i = 0; i < RES_ROW_N(res); i++) {
01238
01239 request_uri_re = from_uri_re = 0;
01240 row = RES_ROWS(res) + i;
01241
01242 if ((VAL_NULL(ROW_VALUES(row)) == 1) ||
01243 (VAL_TYPE(ROW_VALUES(row)) != DB1_INT)) {
01244 LM_ERR("lcr rule id at row <%u> is null or not int\n", i);
01245 goto err;
01246 }
01247 rule_id = (unsigned int)VAL_INT(ROW_VALUES(row));
01248
01249 enabled = (unsigned int)VAL_INT(ROW_VALUES(row) + 4);
01250 if ((enabled != 0) && (enabled != 1)) {
01251 LM_ERR("lcr rule <%u> enabled is not 0 or 1\n", rule_id);
01252 goto err;
01253 }
01254 if (enabled == 0) {
01255 LM_DBG("skipping disabled lcr rule <%u>\n", rule_id);
01256 continue;
01257 }
01258
01259 if (VAL_NULL(ROW_VALUES(row) + 1) == 1) {
01260 prefix_len = 0;
01261 prefix = 0;
01262 } else {
01263 if (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_STRING) {
01264 LM_ERR("lcr rule <%u> prefix is not string\n", rule_id);
01265 goto err;
01266 }
01267 prefix = (char *)VAL_STRING(ROW_VALUES(row) + 1);
01268 prefix_len = strlen(prefix);
01269 }
01270 if (prefix_len > MAX_PREFIX_LEN) {
01271 LM_ERR("lcr rule <%u> prefix is too long\n", rule_id);
01272 goto err;
01273 }
01274
01275 if ((VAL_NULL(ROW_VALUES(row) + 3) == 1) ||
01276 (VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT)) {
01277 LM_ERR("lcr rule <%u> stopper is NULL or not int\n",
01278 rule_id);
01279 goto err;
01280 }
01281 stopper = (unsigned int)VAL_INT(ROW_VALUES(row) + 3);
01282 if ((stopper != 0) && (stopper != 1)) {
01283 LM_ERR("lcr rule <%u> stopper is not 0 or 1\n", rule_id);
01284 goto err;
01285 }
01286
01287 if ((VAL_NULL(ROW_VALUES(row) + 4) == 1) ||
01288 (VAL_TYPE(ROW_VALUES(row) + 4) != DB1_INT)) {
01289 LM_ERR("lcr rule <%u> enabled is NULL or not int\n",
01290 rule_id);
01291 goto err;
01292 }
01293
01294 if (VAL_NULL(ROW_VALUES(row) + 2) == 1) {
01295 from_uri_len = 0;
01296 from_uri = 0;
01297 } else {
01298 if (VAL_TYPE(ROW_VALUES(row) + 2) != DB1_STRING) {
01299 LM_ERR("lcr rule <%u> from_uri is not string\n",
01300 rule_id);
01301 goto err;
01302 }
01303 from_uri = (char *)VAL_STRING(ROW_VALUES(row) + 2);
01304 from_uri_len = strlen(from_uri);
01305 }
01306 if (from_uri_len > MAX_URI_LEN) {
01307 LM_ERR("lcr rule <%u> from_uri is too long\n", rule_id);
01308 goto err;
01309 }
01310 if (from_uri_len > 0) {
01311 from_uri_re = reg_ex_comp(from_uri);
01312 if (from_uri_re == 0) {
01313 LM_ERR("failed to compile lcr rule <%u> from_uri "
01314 "<%s>\n", rule_id, from_uri);
01315 goto err;
01316 }
01317 } else {
01318 from_uri_re = 0;
01319 }
01320
01321 if (VAL_NULL(ROW_VALUES(row) + 5) == 1) {
01322 request_uri_len = 0;
01323 request_uri = 0;
01324 } else {
01325 if (VAL_TYPE(ROW_VALUES(row) + 5) != DB1_STRING) {
01326 LM_ERR("lcr rule <%u> request_uri is not string\n",
01327 rule_id);
01328 goto err;
01329 }
01330 request_uri = (char *)VAL_STRING(ROW_VALUES(row) + 5);
01331 request_uri_len = strlen(request_uri);
01332 }
01333 if (request_uri_len > MAX_URI_LEN) {
01334 LM_ERR("lcr rule <%u> request_uri is too long\n", rule_id);
01335 goto err;
01336 }
01337 if (request_uri_len > 0) {
01338 request_uri_re = reg_ex_comp(request_uri);
01339 if (request_uri_re == 0) {
01340 LM_ERR("failed to compile lcr rule <%u> request_uri "
01341 "<%s>\n", rule_id, request_uri);
01342 goto err;
01343 }
01344 } else {
01345 request_uri_re = 0;
01346 }
01347
01348 if (!rule_hash_table_insert(rules, lcr_id, rule_id, prefix_len,
01349 prefix, from_uri_len, from_uri,
01350 from_uri_re, request_uri_len,
01351 request_uri, request_uri_re, stopper) ||
01352 !prefix_len_insert(rules, prefix_len)) {
01353 goto err;
01354 }
01355 }
01356
01357 if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
01358 if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
01359 LM_ERR("fetching of rows from lcr_rule table failed\n");
01360 goto err;
01361 }
01362 } else {
01363 break;
01364 }
01365
01366 } while (RES_ROW_N(res) > 0);
01367
01368 lcr_dbf.free_result(dbh, res);
01369 res = NULL;
01370
01371
01372
01373 gws = gw_pt[0];
01374
01375 if (lcr_dbf.use_table(dbh, &lcr_gw_table) < 0) {
01376 LM_ERR("error while trying to use lcr_gw table\n");
01377 goto err;
01378 }
01379
01380 VAL_INT(vals) = lcr_id;
01381 if (lcr_dbf.query(dbh, key_cols, op, vals, gw_cols, 1, 13, 0, &res)
01382 < 0) {
01383 LM_ERR("failed to query gw data\n");
01384 goto err;
01385 }
01386
01387 if (RES_ROW_N(res) + 1 > lcr_gw_count_param) {
01388 LM_ERR("too many gateways\n");
01389 goto err;
01390 }
01391
01392 null_gw_ip_addr = gw_cnt = 0;
01393
01394 if (!insert_gws(res, gws, &null_gw_ip_addr, &gw_cnt)) goto err;
01395
01396 lcr_dbf.free_result(dbh, res);
01397 res = NULL;
01398
01399 VAL_INT(vals) = 0;
01400 if (lcr_dbf.query(dbh, key_cols, op, vals, gw_cols, 1, 13, 0, &res)
01401 < 0) {
01402 LM_ERR("failed to query gw data\n");
01403 goto err;
01404 }
01405
01406 if (RES_ROW_N(res) + 1 + gw_cnt > lcr_gw_count_param) {
01407 LM_ERR("too many gateways\n");
01408 goto err;
01409 }
01410
01411 if (!insert_gws(res, gws, &null_gw_ip_addr, &gw_cnt)) goto err;
01412
01413 lcr_dbf.free_result(dbh, res);
01414 res = NULL;
01415
01416 qsort(&(gws[1]), gw_cnt, sizeof(struct gw_info), comp_gws);
01417 gws[0].ip_addr.u.addr32[0] = gw_cnt;
01418 gws[0].port = null_gw_ip_addr;
01419
01420
01421
01422 if (lcr_dbf.use_table(dbh, &lcr_rule_target_table) < 0) {
01423 LM_ERR("error while trying to use lcr_rule_target table\n");
01424 goto err;
01425 }
01426
01427 VAL_INT(vals) = lcr_id;
01428 if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
01429 if (lcr_dbf.query(dbh, key_cols, op, vals, target_cols, 1, 4, 0, 0)
01430 < 0) {
01431 LM_ERR("db query on lcr_rule_target table failed\n");
01432 goto err;
01433 }
01434 if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
01435 LM_ERR("failed to fetch rows from lcr_rule_target table\n");
01436 goto err;
01437 }
01438 } else {
01439 if (lcr_dbf.query(dbh, key_cols, op, vals, target_cols, 1, 4, 0,
01440 &res) < 0) {
01441 LM_ERR("db query on lcr_rule_target table failed\n");
01442 goto err;
01443 }
01444 }
01445
01446 n = 0;
01447 do {
01448 LM_DBG("loading, cycle %d with <%d> rows", n++, RES_ROW_N(res));
01449 for (i = 0; i < RES_ROW_N(res); i++) {
01450 row = RES_ROWS(res) + i;
01451 if ((VAL_NULL(ROW_VALUES(row)) == 1) ||
01452 (VAL_TYPE(ROW_VALUES(row)) != DB1_INT)) {
01453 LM_ERR("lcr_rule_target rule_id at row <%u> is null "
01454 "or not int\n", i);
01455 goto err;
01456 }
01457 rule_id = (unsigned int)VAL_INT(ROW_VALUES(row));
01458 if ((VAL_NULL(ROW_VALUES(row) + 1) == 1) ||
01459 (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_INT)) {
01460 LM_ERR("lcr_rule_target gw_id at row <%u> is null "
01461 "or not int\n", i);
01462 goto err;
01463 }
01464 gw_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 1);
01465 if ((VAL_NULL(ROW_VALUES(row) + 2) == 1) ||
01466 (VAL_TYPE(ROW_VALUES(row) + 2) != DB1_INT)) {
01467 LM_ERR("lcr_rule_target priority at row <%u> is null "
01468 "or not int\n", i);
01469 goto err;
01470 }
01471 priority = (unsigned int)VAL_INT(ROW_VALUES(row) + 2);
01472 if (priority > 255) {
01473 LM_ERR("lcr_rule_target priority value at row <%u> is "
01474 "not 0-255\n", i);
01475 goto err;
01476 }
01477 if ((VAL_NULL(ROW_VALUES(row) + 3) == 1) ||
01478 (VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT)) {
01479 LM_ERR("lcr_rule_target weight at row <%u> is null "
01480 "or not int\n", i);
01481 goto err;
01482 }
01483 weight = (unsigned int)VAL_INT(ROW_VALUES(row) + 3);
01484 if ((weight < 1) || (weight > 254)) {
01485 LM_ERR("lcr_rule_target weight value at row <%u> is "
01486 "not 1-254\n", i);
01487 goto err;
01488 }
01489 tmp = rule_hash_table_insert_target(rules, gws, rule_id, gw_id,
01490 priority, weight);
01491 if (tmp == 2) {
01492 LM_INFO("skipping disabled <gw/rule> = <%u/%u>\n",
01493 gw_id, rule_id);
01494 } else if (tmp != 1) {
01495 LM_ERR("could not insert target to rule <%u>\n", rule_id);
01496 goto err;
01497 }
01498 }
01499 if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
01500 if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
01501 LM_ERR("fetching of rows from lcr_rule_target table "
01502 "failed\n");
01503 goto err;
01504 }
01505 } else {
01506 break;
01507 }
01508 } while (RES_ROW_N(res) > 0);
01509
01510 lcr_dbf.free_result(dbh, res);
01511 res = NULL;
01512
01513
01514 rule_pt_tmp = rule_pt[lcr_id];
01515 gw_pt_tmp = gw_pt[lcr_id];
01516 rule_pt[lcr_id] = rules;
01517 gw_pt[lcr_id] = gws;
01518 rule_pt[0] = rule_pt_tmp;
01519 gw_pt[0] = gw_pt_tmp;
01520 }
01521
01522 lcr_db_close();
01523 rule_id_hash_table_contents_free();
01524 if (rule_id_hash_table) pkg_free(rule_id_hash_table);
01525 return 1;
01526
01527 err:
01528 lcr_dbf.free_result(dbh, res);
01529 lcr_db_close();
01530 rule_id_hash_table_contents_free();
01531 if (rule_id_hash_table) pkg_free(rule_id_hash_table);
01532 return -1;
01533 }
01534
01535
01536 inline int encode_avp_value(char *value, unsigned int gw_index, uri_type scheme,
01537 unsigned int strip,
01538 char *prefix, unsigned int prefix_len,
01539 char *tag, unsigned int tag_len,
01540 struct ip_addr *ip_addr, char *hostname,
01541 unsigned int hostname_len, unsigned int port,
01542 char *params, unsigned int params_len,
01543 uri_transport transport, unsigned int flags)
01544 {
01545 char *at, *string;
01546 int len;
01547
01548 at = value;
01549
01550
01551 string = int2str(gw_index, &len);
01552 append_str(at, string, len);
01553 append_chr(at, '|');
01554
01555 string = int2str(scheme, &len);
01556 append_str(at, string, len);
01557 append_chr(at, '|');
01558
01559 string = int2str(strip, &len);
01560 append_str(at, string, len);
01561 append_chr(at, '|');
01562
01563 append_str(at, prefix, prefix_len);
01564 append_chr(at, '|');
01565
01566 append_str(at, tag, tag_len);
01567 append_chr(at, '|');
01568
01569 if (ip_addr->af == AF_INET && ip_addr->u.addr32[0] > 0) {
01570 string = int2str(ip_addr->u.addr32[0], &len);
01571 append_str(at, string, len);
01572 }
01573 #ifdef USE_IPV6
01574 else if (ip_addr->af == AF_INET6 && !ip_addr_any(ip_addr)) {
01575 append_chr(at, '[');
01576 at += ip6tosbuf(ip_addr->u.addr, at, MAX_URI_LEN - (at - value));
01577 append_chr(at, ']');
01578 }
01579 #endif
01580 append_chr(at, '|');
01581
01582 append_str(at, hostname, hostname_len);
01583 append_chr(at, '|');
01584
01585 if (port > 0) {
01586 string = int2str(port, &len);
01587 append_str(at, string, len);
01588 }
01589 append_chr(at, '|');
01590
01591 append_str(at, params, params_len);
01592 append_chr(at, '|');
01593
01594 string = int2str(transport, &len);
01595 append_str(at, string, len);
01596 append_chr(at, '|');
01597
01598 string = int2str(flags, &len);
01599 append_str(at, string, len);
01600 return at - value;
01601 }
01602
01603 inline int decode_avp_value(char *value, unsigned int *gw_index, str *scheme,
01604 unsigned int *strip, str *prefix, str *tag,
01605 struct ip_addr *addr, str *hostname, str *port,
01606 str *params, str *transport, unsigned int *flags)
01607 {
01608 unsigned int u;
01609 str s;
01610 char *sep;
01611 struct ip_addr *ip;
01612
01613
01614 s.s = value;
01615 sep = index(s.s, '|');
01616 if (sep == NULL) {
01617 LM_ERR("index was not found in AVP value\n");
01618 return 0;
01619 }
01620 s.len = sep - s.s;
01621 str2int(&s, gw_index);
01622
01623 s.s = sep + 1;
01624 sep = index(s.s, '|');
01625 if (sep == NULL) {
01626 LM_ERR("scheme was not found in AVP value\n");
01627 return 0;
01628 }
01629 s.len = sep - s.s;
01630 str2int(&s, &u);
01631 if (u == SIP_URI_T) {
01632 scheme->s = "sip:";
01633 scheme->len = 4;
01634 } else {
01635 scheme->s = "sips:";
01636 scheme->len = 5;
01637 }
01638
01639 s.s = sep + 1;
01640 sep = index(s.s, '|');
01641 if (sep == NULL) {
01642 LM_ERR("strip was not found in AVP value\n");
01643 return 0;
01644 }
01645 s.len = sep - s.s;
01646 str2int(&s, strip);
01647
01648 prefix->s = sep + 1;
01649 sep = index(prefix->s, '|');
01650 if (sep == NULL) {
01651 LM_ERR("prefix was not found in AVP value\n");
01652 return 0;
01653 }
01654 prefix->len = sep - prefix->s;
01655
01656 tag->s = sep + 1;
01657 sep = index(tag->s, '|');
01658 if (sep == NULL) {
01659 LM_ERR("tag was not found in AVP value\n");
01660 return 0;
01661 }
01662 tag->len = sep - tag->s;
01663
01664 s.s = sep + 1;
01665 sep = index(s.s, '|');
01666 if (sep == NULL) {
01667 LM_ERR("ip_addr was not found in AVP value\n");
01668 return 0;
01669 }
01670 s.len = sep - s.s;
01671 if (s.len > 0) {
01672 if ((ip = str2ip(&s)) != NULL)
01673 *addr = *ip;
01674 #ifdef USE_IPV6
01675 else if ((ip = str2ip6(&s)) != NULL)
01676 *addr = *ip;
01677 #endif
01678 else {
01679 str2int(&s, &u);
01680 addr->af = AF_INET;
01681 addr->len = 4;
01682 addr->u.addr32[0] = u;
01683 }
01684 } else {
01685 addr->af = 0;
01686 }
01687
01688 hostname->s = sep + 1;
01689 sep = index(hostname->s, '|');
01690 if (sep == NULL) {
01691 LM_ERR("hostname was not found in AVP value\n");
01692 return 0;
01693 }
01694 hostname->len = sep - hostname->s;
01695
01696 port->s = sep + 1;
01697 sep = index(port->s, '|');
01698 if (sep == NULL) {
01699 LM_ERR("scheme was not found in AVP value\n");
01700 return 0;
01701 }
01702 port->len = sep - port->s;
01703
01704 params->s = sep + 1;
01705 sep = index(params->s, '|');
01706 if (sep == NULL) {
01707 LM_ERR("params was not found in AVP value\n");
01708 return 0;
01709 }
01710 params->len = sep - params->s;
01711
01712 s.s = sep + 1;
01713 sep = index(s.s, '|');
01714 if (sep == NULL) {
01715 LM_ERR("transport was not found in AVP value\n");
01716 return 0;
01717 }
01718 s.len = sep - s.s;
01719 str2int(&s, &u);
01720 switch (u) {
01721 case PROTO_NONE:
01722 transport->s = (char *)0;
01723 transport->len = 0;
01724 break;
01725 case PROTO_UDP:
01726 transport->s = ";transport=udp";
01727 transport->len = 14;
01728 break;
01729 case PROTO_TCP:
01730 transport->s = ";transport=tcp";
01731 transport->len = 14;
01732 break;
01733 case PROTO_TLS:
01734 transport->s = ";transport=tls";
01735 transport->len = 14;
01736 break;
01737 case PROTO_SCTP:
01738 transport->s = ";transport=sctp";
01739 transport->len = 15;
01740 break;
01741 default:
01742 LM_ERR("unknown transport '%d'\n", u);
01743 return 0;
01744 }
01745
01746 s.s = sep + 1;
01747 s.len = strlen(s.s);
01748 str2int(&s, flags);
01749
01750 return 1;
01751 }
01752
01753
01754
01755 void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
01756 unsigned int gw_cnt, str *ruri_user)
01757 {
01758 unsigned int i, index, strip, hostname_len, params_len;
01759 int prefix_len, tag_len;
01760 str value;
01761 char encoded_value[MAX_URI_LEN];
01762 int_str val;
01763
01764 delete_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp);
01765
01766 for (i = 0; i < gw_cnt; i++) {
01767 if (matched_gws[i].duplicate == 1) continue;
01768 index = matched_gws[i].gw_index;
01769 hostname_len = gws[index].hostname_len;
01770 params_len = gws[index].params_len;
01771 strip = gws[index].strip;
01772 if (strip > ruri_user->len) {
01773 LM_ERR("strip count of gw is too large <%u>\n", strip);
01774 goto skip;
01775 }
01776 prefix_len = gws[index].prefix_len;
01777 tag_len = gws[index].tag_len;
01778 if (5 + 5 + 4 + prefix_len +
01779 tag_len + 1 +
01780 ((hostname_len > IP6_MAX_STR_SIZE+2)?hostname_len:IP6_MAX_STR_SIZE+2) + 6 +
01781 params_len + 15 + 10 +
01782 7 > MAX_URI_LEN) {
01783 LM_ERR("too long AVP value\n");
01784 goto skip;
01785 }
01786 value.len =
01787 encode_avp_value(encoded_value, index, gws[index].scheme,
01788 strip, gws[index].prefix, prefix_len,
01789 gws[index].tag, tag_len,
01790 &gws[index].ip_addr,
01791 gws[index].hostname, hostname_len,
01792 gws[index].port, gws[index].params, params_len,
01793 gws[index].transport, gws[index].flags);
01794 value.s = (char *)&(encoded_value[0]);
01795 val.s = value;
01796 add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val);
01797
01798 LM_DBG("added gw_uri_avp <%.*s> with weight <%u>\n",
01799 value.len, value.s, matched_gws[i].weight);
01800 skip:
01801 continue;
01802 }
01803 }
01804
01805
01806
01807
01808
01809 static int load_gws(struct sip_msg* _m, int argc, action_u_t argv[])
01810 {
01811 str ruri_user, from_uri, *request_uri;
01812 int i, j, lcr_id;
01813 unsigned int gw_index, now, dex;
01814 int_str val;
01815 struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1];
01816 struct rule_info **rules, *rule, *pl;
01817 struct gw_info *gws;
01818 struct target *t;
01819 char* tmp;
01820
01821
01822 if (argc < 1) {
01823 LM_ERR("lcr_id parameter is missing\n");
01824 return -1;
01825 }
01826 lcr_id = strtol(argv[0].u.string, &tmp, 10);
01827 if ((tmp == 0) || (*tmp) || (tmp == argv[0].u.string)) {
01828 LM_ERR("invalid lcr_id parameter %s\n", argv[0].u.string);
01829 return -1;
01830 }
01831 if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
01832 LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
01833 return -1;
01834 }
01835 if (argc > 1) {
01836 ruri_user = argv[1].u.str;
01837 } else {
01838 if ((parse_sip_msg_uri(_m) < 0) || (!_m->parsed_uri.user.s)) {
01839 LM_ERR("error while parsing R-URI\n");
01840 return -1;
01841 }
01842 ruri_user = _m->parsed_uri.user;
01843 }
01844 if (argc > 2) {
01845 from_uri = argv[2].u.str;
01846 } else {
01847 from_uri.len = 0;
01848 from_uri.s = (char *)0;
01849 }
01850 if (argc > 3) {
01851 LM_ERR("too many parameters\n");
01852 return -1;
01853 }
01854 LM_DBG("load_gws(%u, %.*s, %.*s)\n", lcr_id, ruri_user.len, ruri_user.s,
01855 from_uri.len, from_uri.s);
01856
01857 request_uri = GET_RURI(_m);
01858
01859
01860 rules = rule_pt[lcr_id];
01861 gws = gw_pt[lcr_id];
01862
01863
01864
01865
01866
01867
01868
01869 pl = rules[lcr_rule_hash_size_param];
01870 gw_index = 0;
01871
01872 if (defunct_capability_param > 0) {
01873 delete_avp(defunct_gw_avp_type, defunct_gw_avp);
01874 }
01875
01876 now = time((time_t *)NULL);
01877
01878
01879 while (pl) {
01880 if (ruri_user.len < pl->prefix_len) {
01881 pl = pl->next;
01882 continue;
01883 }
01884 rule = rule_hash_table_lookup(rules, pl->prefix_len, ruri_user.s);
01885 while (rule) {
01886
01887 if ((rule->prefix_len != pl->prefix_len) ||
01888 (strncmp(rule->prefix, ruri_user.s, pl->prefix_len)))
01889 goto next;
01890
01891
01892 if ((rule->from_uri_len != 0) &&
01893 (pcre_exec(rule->from_uri_re, NULL, from_uri.s,
01894 from_uri.len, 0, 0, NULL, 0) < 0)) {
01895 LM_DBG("from uri <%.*s> did not match to from regex <%.*s>",
01896 from_uri.len, from_uri.s, rule->from_uri_len,
01897 rule->from_uri);
01898 goto next;
01899 }
01900
01901
01902 if ((rule->request_uri_len != 0) &&
01903 (pcre_exec(rule->request_uri_re, NULL, request_uri->s,
01904 request_uri->len, 0, 0, NULL, 0) < 0)) {
01905 LM_DBG("request uri <%.*s> did not match to request regex <%.*s>",
01906 request_uri->len, request_uri->s, rule->request_uri_len,
01907 rule->request_uri);
01908 goto next;
01909 }
01910
01911
01912 t = rule->targets;
01913 while (t) {
01914
01915 if (gws[t->gw_index].defunct_until > now) goto skip_gw;
01916 matched_gws[gw_index].gw_index = t->gw_index;
01917 matched_gws[gw_index].prefix_len = pl->prefix_len;
01918 matched_gws[gw_index].priority = t->priority;
01919 matched_gws[gw_index].weight = t->weight *
01920 (rand() >> 8);
01921 matched_gws[gw_index].duplicate = 0;
01922 LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n",
01923 gw_index, t->gw_index, pl->prefix_len,
01924 t->priority, matched_gws[gw_index].weight);
01925 gw_index++;
01926 skip_gw:
01927 t = t->next;
01928 }
01929
01930 if (rule->stopper == 1) goto done;
01931
01932 next:
01933 rule = rule->next;
01934 }
01935 pl = pl->next;
01936 }
01937
01938 done:
01939
01940
01941 qsort(matched_gws, gw_index, sizeof(struct matched_gw_info), comp_matched);
01942
01943
01944 for (i = gw_index - 1; i >= 0; i--) {
01945 if (matched_gws[i].duplicate == 1) continue;
01946 dex = matched_gws[i].gw_index;
01947 for (j = i - 1; j >= 0; j--) {
01948 if (matched_gws[j].gw_index == dex) {
01949 matched_gws[j].duplicate = 1;
01950 }
01951 }
01952 }
01953
01954
01955 add_gws_into_avps(gws, matched_gws, gw_index, &ruri_user);
01956
01957
01958 if (defunct_capability_param > 0) {
01959 delete_avp(lcr_id_avp_type, lcr_id_avp);
01960 val.n = lcr_id;
01961 add_avp(lcr_id_avp_type, lcr_id_avp, val);
01962 }
01963
01964 if (gw_index > 0) {
01965 return 1;
01966 } else {
01967 return 2;
01968 }
01969 }
01970
01971
01972
01973 static int generate_uris(struct sip_msg* _m, char *r_uri, str *r_uri_user,
01974 unsigned int *r_uri_len, char *dst_uri,
01975 unsigned int *dst_uri_len, struct ip_addr *addr,
01976 unsigned int *gw_index, unsigned int *flags,
01977 str *tag)
01978 {
01979 int_str gw_uri_val;
01980 struct usr_avp *gu_avp;
01981 str scheme, prefix, hostname, port, params, transport, addr_str,
01982 tmp_tag;
01983 char *at;
01984 unsigned int strip;
01985
01986 gu_avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &gw_uri_val, 0);
01987
01988 if (!gu_avp) return 0;
01989
01990 decode_avp_value(gw_uri_val.s.s, gw_index, &scheme, &strip, &prefix,
01991 &tmp_tag, addr, &hostname, &port, ¶ms, &transport,
01992 flags);
01993
01994 if (addr->af != 0) {
01995 addr_str.s = ip_addr2a(addr);
01996 addr_str.len = strlen(addr_str.s);
01997 } else {
01998 addr_str.len = 0;
01999 }
02000
02001 if (scheme.len + r_uri_user->len - strip + prefix.len + 1 +
02002 ((hostname.len > IP6_MAX_STR_SIZE+2)?hostname.len:IP6_MAX_STR_SIZE+2) + 1 +
02003 port.len + params.len + transport.len + 1 > MAX_URI_LEN) {
02004 LM_ERR("too long Request URI or DST URI\n");
02005 return -1;
02006 }
02007
02008 if ((dont_strip_or_prefix_flag_param != -1) &&
02009 isflagset(_m, dont_strip_or_prefix_flag_param)) {
02010 strip = 0;
02011 prefix.len = 0;
02012 }
02013
02014 at = r_uri;
02015
02016 append_str(at, scheme.s, scheme.len);
02017 append_str(at, prefix.s, prefix.len);
02018 if (strip > r_uri_user->len) {
02019 LM_ERR("strip count <%u> is larger than R-URI user <%.*s>\n",
02020 strip, r_uri_user->len, r_uri_user->s);
02021 return -1;
02022 }
02023 append_str(at, r_uri_user->s + strip, r_uri_user->len - strip);
02024
02025 append_chr(at, '@');
02026
02027 if ((addr_str.len > 0) && (hostname.len > 0)) {
02028
02029
02030 append_str(at, hostname.s, hostname.len);
02031 if (params.len > 0) {
02032 append_str(at, params.s, params.len);
02033 }
02034 *at = '\0';
02035 *r_uri_len = at - r_uri;
02036 at = dst_uri;
02037 append_str(at, scheme.s, scheme.len);
02038 if (addr->af == AF_INET6)
02039 append_chr(at, '[');
02040 append_str(at, addr_str.s, addr_str.len);
02041 if (addr->af == AF_INET6)
02042 append_chr(at, ']');
02043 if (port.len > 0) {
02044 append_chr(at, ':');
02045 append_str(at, port.s, port.len);
02046 }
02047 if (transport.len > 0) {
02048 append_str(at, transport.s, transport.len);
02049 }
02050 *at = '\0';
02051 *dst_uri_len = at - dst_uri;
02052 } else {
02053
02054
02055 if (addr_str.len > 0) {
02056 if (addr->af == AF_INET6)
02057 append_chr(at, '[');
02058 append_str(at, addr_str.s, addr_str.len);
02059 if (addr->af == AF_INET6)
02060 append_chr(at, ']');
02061 } else {
02062 append_str(at, hostname.s, hostname.len);
02063 }
02064 if (port.len > 0) {
02065 append_chr(at, ':');
02066 append_str(at, port.s, port.len);
02067 }
02068 if (transport.len > 0) {
02069 append_str(at, transport.s, transport.len);
02070 }
02071 if (params.len > 0) {
02072 append_str(at, params.s, params.len);
02073 }
02074 *at = '\0';
02075 *r_uri_len = at - r_uri;
02076 *dst_uri_len = 0;
02077 }
02078
02079 memcpy(tag->s, tmp_tag.s, tmp_tag.len);
02080 tag->len = tmp_tag.len;
02081
02082 destroy_avp(gu_avp);
02083
02084 LM_DBG("r_uri <%.*s>, dst_uri <%.*s>\n",
02085 (int)*r_uri_len, r_uri, (int)*dst_uri_len, dst_uri);
02086
02087 return 1;
02088 }
02089
02090
02091
02092
02093
02094 static int defunct_gw(struct sip_msg* _m, char *_defunct_period, char *_s2)
02095 {
02096 int_str lcr_id_val, index_val;
02097 struct gw_info *gws;
02098 char *tmp;
02099 unsigned int gw_index, defunct_until;
02100 int defunct_period;
02101
02102
02103 if (defunct_capability_param == 0) {
02104 LM_ERR("no defunct gw capability, activate by setting "
02105 "defunct_capability_param module param\n");
02106 return -1;
02107 }
02108
02109
02110
02111
02112 defunct_period = strtol(_defunct_period, &tmp, 10);
02113 if ((tmp == 0) || (*tmp) || (tmp == _defunct_period)) {
02114 LM_ERR("invalid defunct_period parameter %s\n", _defunct_period);
02115 return -1;
02116 }
02117 if (defunct_period < 1) {
02118 LM_ERR("invalid defunct_period param value %d\n", defunct_period);
02119 return -1;
02120 }
02121
02122
02123 if (search_first_avp(lcr_id_avp_type, lcr_id_avp, &lcr_id_val, 0)
02124 == NULL) {
02125 LM_ERR("lcr_id_avp was not found\n");
02126 return -1;
02127 }
02128 gws = gw_pt[lcr_id_val.n];
02129 if (search_first_avp(defunct_gw_avp_type, defunct_gw_avp,
02130 &index_val, 0) == NULL) {
02131 LM_ERR("defucnt_gw_avp was not found\n");
02132 return -1;
02133 }
02134 gw_index = index_val.n;
02135 if ((gw_index < 1) || (gw_index > gws[0].ip_addr.u.addr32[0])) {
02136 LM_ERR("gw index <%u> is out of bounds\n", gw_index);
02137 return -1;
02138 }
02139
02140
02141 defunct_until = time((time_t *)NULL) + defunct_period;
02142 LM_DBG("defuncting gw with name <%.*s> until <%u>\n",
02143 gws[gw_index].gw_name_len, gws[gw_index].gw_name, defunct_until);
02144 gws[gw_index].defunct_until = defunct_until;
02145 return 1;
02146 }
02147
02148
02149
02150
02151
02152 int rpc_defunct_gw(unsigned int lcr_id, unsigned int gw_id, unsigned int period)
02153 {
02154 struct gw_info *gws;
02155 unsigned int until, i;
02156
02157 if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
02158 LM_ERR("invalid lcr_id value <%u>\n", lcr_id);
02159 return 0;
02160 }
02161
02162 until = time((time_t *)NULL) + period;
02163
02164 LM_DBG("defuncting gw <lcr_id/gw_id>=<%u/%u> for %u seconds until %d\n",
02165 lcr_id, gw_id, period, until);
02166
02167 gws = gw_pt[lcr_id];
02168 for (i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) {
02169 if (gws[i].gw_id == gw_id) {
02170 gws[i].defunct_until = until;
02171 return 1;
02172 }
02173 }
02174
02175 LM_ERR("gateway with id <%u> not found\n", gw_id);
02176
02177 return 0;
02178 }
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193 static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
02194 {
02195 int_str ruri_user_val, val;
02196 struct usr_avp *ru_avp;
02197 int rval;
02198 str uri_str, tag_str;
02199 char tag[MAX_TAG_LEN];
02200 unsigned int flags, r_uri_len, dst_uri_len, gw_index;
02201 char r_uri[MAX_URI_LEN], dst_uri[MAX_URI_LEN];
02202 struct ip_addr addr;
02203
02204 tag_str.s = &(tag[0]);
02205
02206 ru_avp = search_first_avp(ruri_user_avp_type, ruri_user_avp,
02207 &ruri_user_val, 0);
02208
02209 if (ru_avp == NULL) {
02210
02211
02212
02213
02214
02215 if (parse_sip_msg_uri(_m) < 0) {
02216 LM_ERR("parsing of R-URI failed\n");
02217 return -1;
02218 }
02219 if (!generate_uris(_m, r_uri, &(_m->parsed_uri.user), &r_uri_len,
02220 dst_uri, &dst_uri_len, &addr, &gw_index, &flags,
02221 &tag_str)) {
02222 return -1;
02223 }
02224
02225
02226
02227
02228 val.s = _m->parsed_uri.user;
02229 add_avp(ruri_user_avp_type|AVP_VAL_STR, ruri_user_avp, val);
02230 LM_DBG("added ruri_user_avp <%.*s>\n", val.s.len, val.s.s);
02231
02232 } else {
02233
02234
02235
02236
02237
02238 if (!generate_uris(_m, r_uri, &(ruri_user_val.s), &r_uri_len, dst_uri,
02239 &dst_uri_len, &addr, &gw_index, &flags, &tag_str)) {
02240 return -1;
02241 }
02242 }
02243
02244
02245 uri_str.s = r_uri;
02246 uri_str.len = r_uri_len;
02247 rewrite_uri(_m, &uri_str);
02248
02249
02250 if (dst_uri_len > 0) {
02251 uri_str.s = dst_uri;
02252 uri_str.len = dst_uri_len;
02253 LM_DBG("setting du to <%.*s>\n", uri_str.len, uri_str.s);
02254 rval = set_dst_uri(_m, &uri_str);
02255 if (rval != 0) {
02256 LM_ERR("calling do_action failed with return value <%d>\n", rval);
02257 return -1;
02258 }
02259
02260 }
02261
02262
02263 if (flags_avp_param) {
02264 val.n = flags;
02265 add_avp(flags_avp_type, flags_avp, val);
02266 LM_DBG("added flags_avp <%u>\n", (unsigned int)val.n);
02267 }
02268
02269
02270 if (tag_avp_param) {
02271 val.s = tag_str;
02272 add_avp(tag_avp_type, tag_avp, val);
02273 LM_DBG("added tag_avp <%.*s>\n", val.s.len, val.s.s);
02274 }
02275
02276
02277 if (defunct_capability_param > 0) {
02278 delete_avp(defunct_gw_avp_type, defunct_gw_avp);
02279 val.n = gw_index;
02280 add_avp(defunct_gw_avp_type, defunct_gw_avp, val);
02281 LM_DBG("added defunct_gw_avp <%u>", addr.u.addr32[0]);
02282 }
02283
02284 return 1;
02285 }
02286
02287
02288
02289
02290
02291 static int do_from_gw(struct sip_msg* _m, unsigned int lcr_id,
02292 struct ip_addr *src_addr, uri_transport transport)
02293 {
02294 struct gw_info *res, gw, *gws;
02295 int_str val;
02296
02297 gws = gw_pt[lcr_id];
02298
02299
02300 if (gws[0].port != 0) {
02301 LM_DBG("lcr instance <%u> has gw(s) without ip_addr\n", lcr_id);
02302 return -1;
02303 }
02304
02305
02306 gw.ip_addr = *src_addr;
02307 res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
02308 sizeof(struct gw_info), comp_gws);
02309
02310
02311 if ((res != NULL) &&
02312 ((res->transport == transport) ||
02313 ((res->transport == PROTO_NONE) && (transport == PROTO_UDP)))) {
02314 LM_DBG("request game from gw\n");
02315 if (tag_avp_param) {
02316 val.s.s = res->tag;
02317 val.s.len = res->tag_len;
02318 add_avp(tag_avp_type, tag_avp, val);
02319 LM_DBG("added tag_avp <%.*s>\n", val.s.len, val.s.s);
02320 }
02321 if (flags_avp_param) {
02322 val.n = res->flags;
02323 add_avp(flags_avp_type, flags_avp, val);
02324 LM_DBG("added flags_avp <%u>\n", (unsigned int)val.n);
02325 }
02326 return 1;
02327 } else {
02328 LM_DBG("request did not come from gw\n");
02329 return -1;
02330 }
02331 }
02332
02333
02334
02335
02336
02337
02338 static int from_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
02339 {
02340 int lcr_id;
02341 char *tmp;
02342 uri_transport transport;
02343
02344
02345 lcr_id = strtol(_lcr_id, &tmp, 10);
02346 if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
02347 LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
02348 return -1;
02349 }
02350 if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
02351 LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
02352 return -1;
02353 }
02354
02355
02356 transport = _m->rcv.proto;
02357
02358
02359 return do_from_gw(_m, lcr_id, &_m->rcv.src_ip, transport);
02360 }
02361
02362
02363
02364
02365
02366
02367 static int from_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
02368 char* _transport)
02369 {
02370 struct ip_addr src_addr;
02371 int lcr_id;
02372 char *tmp;
02373 struct ip_addr *ip;
02374 str addr_str;
02375 uri_transport transport;
02376
02377
02378 lcr_id = strtol(_lcr_id, &tmp, 10);
02379 if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
02380 LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
02381 return -1;
02382 }
02383 if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
02384 LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
02385 return -1;
02386 }
02387 addr_str.s = _addr;
02388 addr_str.len = strlen(_addr);
02389 if ((ip = str2ip(&addr_str)) != NULL)
02390 src_addr = *ip;
02391 #ifdef USE_IPV6
02392 else if ((ip = str2ip6(&addr_str)) != NULL)
02393 src_addr = *ip;
02394 #endif
02395 else {
02396 LM_ERR("addr param value %s is not an IP address\n", _addr);
02397 return -1;
02398 }
02399 transport = strtol(_transport, &tmp, 10);
02400 if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
02401 LM_ERR("invalid transport parameter %s\n", _lcr_id);
02402 return -1;
02403 }
02404 if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
02405 LM_ERR("invalid transport parameter value %d\n", transport);
02406 return -1;
02407 }
02408
02409
02410 return do_from_gw(_m, lcr_id, &src_addr, transport);
02411 }
02412
02413
02414
02415
02416
02417
02418 static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
02419 {
02420 unsigned int i;
02421 uri_transport transport;
02422
02423 transport = _m->rcv.proto;
02424
02425 for (i = 1; i <= lcr_count_param; i++) {
02426 if (do_from_gw(_m, i, &_m->rcv.src_ip, transport) == 1) {
02427 return i;
02428 }
02429 }
02430 return -1;
02431 }
02432
02433
02434
02435
02436
02437
02438 static int from_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
02439 {
02440 unsigned int i;
02441 char *tmp;
02442 struct ip_addr *ip, src_addr;
02443 str addr_str;
02444 uri_transport transport;
02445
02446
02447 addr_str.s = _addr;
02448 addr_str.len = strlen(_addr);
02449 if ((ip = str2ip(&addr_str)) != NULL)
02450 src_addr = *ip;
02451 #ifdef USE_IPV6
02452 else if ((ip = str2ip6(&addr_str)) != NULL)
02453 src_addr = *ip;
02454 #endif
02455 else {
02456 LM_ERR("addr param value %s is not an IP address\n", _addr);
02457 return -1;
02458 }
02459 transport = strtol(_transport, &tmp, 10);
02460 if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
02461 LM_ERR("invalid transport parameter %s\n", _transport);
02462 return -1;
02463 }
02464 if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
02465 LM_ERR("invalid transport parameter value %d\n", transport);
02466 return -1;
02467 }
02468
02469
02470 for (i = 1; i <= lcr_count_param; i++) {
02471 if (do_from_gw(_m, i, &src_addr, transport) == 1) {
02472 return i;
02473 }
02474 }
02475 return -1;
02476 }
02477
02478
02479
02480
02481
02482 static int do_to_gw(struct sip_msg* _m, unsigned int lcr_id,
02483 struct ip_addr *dst_addr, uri_transport transport)
02484 {
02485 struct gw_info *res, gw, *gws;
02486
02487 gws = gw_pt[lcr_id];
02488
02489
02490 if (gws[0].port != 0) {
02491 LM_DBG("lcr instance <%u> has gw(s) without ip_addr\n", lcr_id);
02492 return -1;
02493 }
02494
02495
02496 gw.ip_addr = *dst_addr;
02497 res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
02498 sizeof(struct gw_info), comp_gws);
02499
02500
02501 if ((res != NULL) &&
02502 ((res->transport == transport) ||
02503 ((transport == PROTO_NONE) && (res->transport == PROTO_UDP)))) {
02504 LM_DBG("request goes to gw\n");
02505 return 1;
02506 } else {
02507 LM_DBG("request is not going to gw\n");
02508 return -1;
02509 }
02510 }
02511
02512
02513
02514
02515
02516
02517
02518 static int to_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
02519 {
02520 int lcr_id;
02521 char *tmp;
02522 struct ip_addr *ip, dst_addr;
02523 uri_transport transport;
02524
02525
02526 lcr_id = strtol(_lcr_id, &tmp, 10);
02527 if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
02528 LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
02529 return -1;
02530 }
02531 if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
02532 LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
02533 return -1;
02534 }
02535
02536
02537 if ((_m->parsed_uri_ok == 0) && (parse_sip_msg_uri(_m) < 0)) {
02538 LM_ERR("while parsing Request-URI\n");
02539 return -1;
02540 }
02541 if (_m->parsed_uri.host.len > IP6_MAX_STR_SIZE+2) {
02542 LM_DBG("request is not going to gw "
02543 "(Request-URI host is not an IP address)\n");
02544 return -1;
02545 }
02546 if ((ip = str2ip(&(_m->parsed_uri.host))) != NULL)
02547 dst_addr = *ip;
02548 #ifdef USE_IPV6
02549 else if ((ip = str2ip6(&(_m->parsed_uri.host))) != NULL)
02550 dst_addr = *ip;
02551 #endif
02552 else {
02553 LM_DBG("request is not going to gw "
02554 "(Request-URI host is not an IP address)\n");
02555 return -1;
02556 }
02557 transport = _m->parsed_uri.proto;
02558
02559
02560 return do_to_gw(_m, lcr_id, &dst_addr, transport);
02561 }
02562
02563
02564
02565
02566
02567
02568 static int to_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
02569 char* _transport)
02570 {
02571 int lcr_id;
02572 char *tmp;
02573 struct ip_addr *ip, dst_addr;
02574 str addr_str;
02575 uri_transport transport;
02576
02577
02578 lcr_id = strtol(_lcr_id, &tmp, 10);
02579 if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
02580 LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
02581 return -1;
02582 }
02583 if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
02584 LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
02585 return -1;
02586 }
02587 addr_str.s = _addr;
02588 addr_str.len = strlen(_addr);
02589 if ((ip = str2ip(&addr_str)) != NULL)
02590 dst_addr = *ip;
02591 #ifdef USE_IPV6
02592 else if ((ip = str2ip(&addr_str)) != NULL)
02593 dst_addr = *ip;
02594 #endif
02595 else {
02596 LM_ERR("addr param value %s is not an IP address\n", _addr);
02597 return -1;
02598 }
02599 transport = strtol(_transport, &tmp, 10);
02600 if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
02601 LM_ERR("invalid transport parameter %s\n", _transport);
02602 return -1;
02603 }
02604 if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
02605 LM_ERR("invalid transport parameter value %d\n", transport);
02606 return -1;
02607 }
02608
02609
02610 return do_to_gw(_m, lcr_id, &dst_addr, transport);
02611 }
02612
02613
02614
02615
02616
02617
02618 static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
02619 {
02620 unsigned int i;
02621 struct ip_addr *ip, dst_addr;
02622 uri_transport transport;
02623
02624
02625 if ((_m->parsed_uri_ok == 0) && (parse_sip_msg_uri(_m) < 0)) {
02626 LM_ERR("while parsing Request-URI\n");
02627 return -1;
02628 }
02629 if (_m->parsed_uri.host.len > IP6_MAX_STR_SIZE+2) {
02630 LM_DBG("request is not going to gw "
02631 "(Request-URI host is not an IP address)\n");
02632 return -1;
02633 }
02634 if ((ip = str2ip(&(_m->parsed_uri.host))) != NULL)
02635 dst_addr = *ip;
02636 #ifdef USE_IPV6
02637 else if ((ip = str2ip6(&(_m->parsed_uri.host))) != NULL)
02638 dst_addr = *ip;
02639 #endif
02640 else {
02641 LM_DBG("request is not going to gw "
02642 "(Request-URI host is not an IP address)\n");
02643 return -1;
02644 }
02645 transport = _m->parsed_uri.proto;
02646
02647
02648 for (i = 1; i <= lcr_count_param; i++) {
02649 if (do_to_gw(_m, i, &dst_addr, transport) == 1) {
02650 return i;
02651 }
02652 }
02653 return -1;
02654 }
02655
02656
02657
02658
02659
02660
02661 static int to_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
02662 {
02663 unsigned int i;
02664 char *tmp;
02665 struct ip_addr *ip, dst_addr;
02666 uri_transport transport;
02667 str addr_str;
02668
02669
02670 addr_str.s = _addr;
02671 addr_str.len = strlen(_addr);
02672 if ((ip = str2ip(&addr_str)) != NULL)
02673 dst_addr = *ip;
02674 #ifdef USE_IPV6
02675 if ((ip = str2ip6(&addr_str)) != NULL)
02676 dst_addr = *ip;
02677 #endif
02678 else {
02679 LM_ERR("addr param value %s is not an IP address\n", _addr);
02680 return -1;
02681 }
02682 transport = strtol(_transport, &tmp, 10);
02683 if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
02684 LM_ERR("invalid transport parameter %s\n", _transport);
02685 return -1;
02686 }
02687 if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
02688 LM_ERR("invalid transport parameter value %d\n", transport);
02689 return -1;
02690 }
02691
02692
02693 for (i = 1; i <= lcr_count_param; i++) {
02694 if (do_to_gw(_m, i, &dst_addr, transport) == 1) {
02695 return i;
02696 }
02697 }
02698 return -1;
02699 }