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