lcr_mod.c

Go to the documentation of this file.
00001 /*
00002  * Least Cost Routing module
00003  *
00004  * Copyright (C) 2005-2012 Juha Heinanen
00005  * Copyright (C) 2006 Voice Sistem SRL
00006  *
00007  * This file is part of SIP Router, a free SIP server.
00008  *
00009  * SIP Router is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * SIP Router is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License 
00020  * along with this program; if not, write to the Free Software 
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * History:
00024  * -------
00025  *  2005-02-14: Introduced lcr module (jh)
00026  *  2005-02-20: Added sequential forking functions (jh)
00027  *  2005-02-25: Added support for int AVP names, combined addr and port
00028  *              AVPs (jh)
00029  *  2005-07-28: Added support for gw URI scheme and transport, 
00030  *              backport from ser (kd)
00031  *  2005-08-20: Added support for gw prefixes (jh)
00032  *  2005-09-03: Request-URI user part can be modified between load_gws()
00033  *              and first next_gw() calls.
00034  *  2008-10-10: Database values are now checked and from/to_gw functions
00035  *              execute in O(logN) time.
00036  *  2008-11-26: Added timer based check of gateways (shurik)
00037  *  2009-05-12  added RPC support (andrei)
00038  *  2009-06-21  Added support for more than one lcr instance and
00039                 gw defunct capability (jh)
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  * versions of database tables required by the module.
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 /* database defaults */
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 /* Default module parameter values */
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  * Type definitions
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  * Database variables
00146  */
00147 static db1_con_t* dbh = 0;   /* Database connection handle */
00148 static db_func_t lcr_dbf;
00149 
00150 /*
00151  * Locking variables
00152  */
00153 gen_lock_t *reload_lock;
00154 
00155 /*
00156  * Module parameter variables
00157  */
00158 
00159 /* database variables */
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 /* number of rows to fetch at a shot */
00188 static int fetch_rows_param = DEF_FETCH_ROWS;
00189 
00190 /* avps */
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 /* max number of lcr instances */
00199 unsigned int lcr_count_param = DEF_LCR_COUNT;
00200 
00201 /* size of lcr rules hash table */
00202 unsigned int lcr_rule_hash_size_param = DEF_LCR_RULE_HASH_SIZE;
00203 
00204 /* max no of gws */
00205 unsigned int lcr_gw_count_param = DEF_LCR_GW_COUNT;
00206 
00207 /* can gws be defuncted */
00208 static unsigned int defunct_capability_param = 0;
00209 
00210 /* dont strip or tag param */
00211 static int dont_strip_or_prefix_flag_param = -1;
00212 
00213 
00214 /*
00215  * Other module types and variables
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 /* Pointer to rule hash table pointer table */
00232 struct rule_info ***rule_pt = (struct rule_info ***)NULL;
00233 
00234 /* Pointer to gw table pointer table */
00235 struct gw_info **gw_pt = (struct gw_info **)NULL;
00236 
00237 /* Pointer to rule_id info hash table */
00238 struct rule_id_info **rule_id_hash_table = (struct rule_id_info **)NULL;
00239 
00240 /*
00241  * Functions that are defined later
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  * Exported functions
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  * Exported parameters
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, &params_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  * Module interface
00337  */
00338 struct module_exports exports = {
00339         "lcr", 
00340         DEFAULT_DLFLAGS, /* dlopen flags */
00341         cmds,      /* Exported functions */
00342         params,    /* Exported parameters */
00343         0,         /* exported statistics */
00344         0,         /* exported MI functions */
00345         0,         /* exported pseudo-variables */
00346         0,         /* extra processes */
00347         mod_init,  /* module initialization function */
00348         0,         /* response function */
00349         destroy,   /* destroy function */
00350         child_init /* child initialization function */
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  * Module initialization function that is called before the main process forks
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     /* Register RPC commands */
00411     if (rpc_register_array(lcr_rpc)!=0) {
00412         LM_ERR("failed to register RPC commands\n");
00413         return -1;
00414     }
00415 
00416     /* Update length of module variables */
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     /* Bind database */
00446     if (lcr_db_bind(&db_url)) {
00447         LM_ERR("no database module found\n");
00448         return -1;
00449     }
00450 
00451     /* Check values of some params */
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     /* Process AVP params */
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     /* Check table version */
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     /* rule shared memory */
00603 
00604     /* rule hash table pointer table */
00605     /* pointer at index 0 points to temp rule hash table */
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     /* rules hash tables */
00615     /* last entry in hash table contains list of different prefix lengths */
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     /* gw shared memory */
00628 
00629     /* gw table pointer table */
00630     /* pointer at index 0 points to temp rule hash table */
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     /* gw tables themselves */
00640     /* ordered by ip_addr for from_gw/to_gw functions */
00641     /* in each table i, (gw_pt[i])[0].ip_addr contains number of
00642        gateways in the table and (gw_pt[i])[0].port as value 1
00643        if some gateways in the table have null ip addr */
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     /* Allocate and initialize locks */
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     /* First reload */
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 /* Module initialization function called in each child separately */
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 /* Free shared memory */
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  * Compare matched gateways based on prefix_len, priority, and randomized
00732  * weight.
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     /* Sort by prefix_len */
00740     if (mi1->prefix_len > mi2->prefix_len) return 1;
00741     if (mi1->prefix_len == mi2->prefix_len) {
00742         /* Sort by priority */
00743         if (mi1->priority < mi2->priority) return 1;
00744         if (mi1->priority == mi2->priority) {
00745             /* Sort by randomized weigth */
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 /* Compile pattern into shared memory and return pointer to it. */
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  * Compare gateways based on their IP address
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  * Insert gw info into index i or gws table
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  * Insert prefix_len into list pointed by last rule hash table entry 
00842  * if not there already. Keep list in decending prefix_len order.
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                 /* 123.123.123.123 */
00955                 ip_addr = *ip_p;
00956             }
00957 #ifdef USE_IPV6
00958             else if ((ip_p = str2ip6(&ip_string))) {
00959                 /* fe80::123:4567:89ab:cdef and [fe80::123:4567:89ab:cdef] */
00960                 ip_addr = *ip_p;
00961             }
00962 #endif
00963             else if (inet_aton(ip_string.s, &in_addr) == 0) {
00964                 /* backwards compatibility for integer or hex notations */
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  * Reload gws to unused gw table, rules to unused lcr hash table, and
01132  * prefix lens to a new prefix_len list.  When done, make these tables
01133  * and list the current ones.
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] = &params_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         /* Reload rules */
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         /* Reload gws */
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         /* Reload targets */
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         /* swap tables */
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     /* gw index */
01551     string = int2str(gw_index, &len);
01552     append_str(at, string, len);
01553     append_chr(at, '|');
01554     /* scheme */
01555     string = int2str(scheme, &len);
01556     append_str(at, string, len);
01557     append_chr(at, '|');
01558     /* strip */
01559     string = int2str(strip, &len);
01560     append_str(at, string, len);
01561     append_chr(at, '|');
01562     /* prefix */
01563     append_str(at, prefix, prefix_len);
01564     append_chr(at, '|');
01565     /* tag */
01566     append_str(at, tag, tag_len);
01567     append_chr(at, '|');
01568     /* ip_addr */
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     /* hostname */
01582     append_str(at, hostname, hostname_len);
01583     append_chr(at, '|');
01584     /* port */
01585     if (port > 0) {
01586         string = int2str(port, &len);
01587         append_str(at, string, len);
01588     }
01589     append_chr(at, '|');
01590     /* params */
01591     append_str(at, params, params_len);
01592     append_chr(at, '|');
01593     /* transport */
01594     string = int2str(transport, &len);
01595     append_str(at, string, len);
01596     append_chr(at, '|');
01597     /* flags */
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     /* gw index */
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     /* scheme */
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     /* strip */
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     /* prefix */
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     /* tag */
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     /* addr */
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     /* hostname */
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     /* port */
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     /* params */
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     /* transport */
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     /* flags */
01746     s.s = sep + 1;
01747     s.len = strlen(s.s);
01748     str2int(&s, flags);
01749 
01750     return 1;
01751 }
01752     
01753 
01754 /* Add gateways in matched_gws array into gw_uri_avps */
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 /* gw_index */ + 5 /* scheme */ + 4 /* strip */ + prefix_len +
01779             tag_len + 1 /* @ */ +
01780             ((hostname_len > IP6_MAX_STR_SIZE+2)?hostname_len:IP6_MAX_STR_SIZE+2) + 6 /* port */ +
01781             params_len /* params */ + 15 /* transport */ + 10 /* flags */ +
01782             7 /* separators */ > 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  * Load info of matching GWs into gw_uri_avps
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     /* Get and check parameter values */
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     /* Use rules and gws with index lcr_id */
01860     rules = rule_pt[lcr_id];
01861     gws = gw_pt[lcr_id];
01862 
01863     /*
01864      * Find lcr entries that match based on prefix and from_uri and collect
01865      * gateways of matching entries into matched_gws array so that each
01866      * gateway appears in the array only once.
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     /* check prefixes in from longest to shortest */
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             /* Match prefix */
01887             if ((rule->prefix_len != pl->prefix_len) ||
01888                 (strncmp(rule->prefix, ruri_user.s, pl->prefix_len)))
01889                     goto next;
01890 
01891             /* Match from uri */
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             /* Match request uri */
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             /* Load gws associated with this rule */
01912             t = rule->targets;
01913             while (t) {
01914                 /* If this gw is defunct, skip it */
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             /* Do not look further if this matching rule was stopper */
01930             if (rule->stopper == 1) goto done;
01931 
01932 next:
01933             rule = rule->next;
01934         }
01935         pl = pl->next;
01936     }
01937 
01938  done:
01939     /* Sort gateways in reverse order based on prefix_len, priority,
01940        and randomized weight */
01941     qsort(matched_gws, gw_index, sizeof(struct matched_gw_info), comp_matched);
01942 
01943     /* Remove duplicate gws */
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     /* Add gateways into gw_uris_avp */
01955     add_gws_into_avps(gws, matched_gws, gw_index, &ruri_user);
01956 
01957     /* Add lcr_id into AVP */
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 /* Generate Request-URI and Destination URI */
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; /* No more gateways left */
01989 
01990     decode_avp_value(gw_uri_val.s.s, gw_index, &scheme, &strip, &prefix,
01991                      &tmp_tag, addr, &hostname, &port, &params, &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 /* null */ > 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         /* both ip_addr and hostname specified:
02029            place hostname in r-uri and ip_addr in dst-uri */
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         /* either ip_addr or hostname specified:
02054            place the given one in r-uri and leave dst-uri empty */
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  * Defunct current gw until time given as argument has passed.
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     /* Check defunct gw capability */
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     /* Get parameter value */
02110 
02111     /* Get and check parameter value */
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     /* Get AVP values */
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     /* Defunct gw */
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  * Defunct given gw in given lcr until time period given as argument has passed.
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  * When called first time, rewrites scheme, host, port, and
02183  * transport parts of R-URI based on first gw_uri_avp value, which is then
02184  * destroyed.  Saves R-URI user to ruri_user_avp for later use.
02185  *
02186  * On other calls, rewrites R-URI, where scheme, host, port,
02187  * and transport of URI are taken from the first gw_uri_avp value, 
02188  * which is then destroyed. URI user is taken either from ruri_user_avp
02189  * value saved earlier.
02190  *
02191  * Returns 1 upon success and -1 upon failure.
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         /* First invocation either in route or failure route block.
02212          * Take Request-URI user from Request-URI and generate Request
02213          * and Destination URIs. */
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         /* Save Request-URI user into uri_user_avp for use in subsequent
02226          * invocations. */
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         /* Subsequent invocation either in route or failure route block.
02235          * Take Request-URI user from ruri_user_avp and generate Request
02236          * and Destination URIs. */
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     /* Rewrite Request URI */
02245     uri_str.s = r_uri;
02246     uri_str.len = r_uri_len;
02247     rewrite_uri(_m, &uri_str);
02248     
02249     /* Set Destination URI if not empty */
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     /* Set flags_avp */
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     /* Set tag_avp */
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     /* Add index of selected gw to defunct gw AVP */
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  * Checks if request comes from ip address of a gateway
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     /* Skip lcr instance if some of its gws do not have ip_addr */
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     /* Search for gw ip address */
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     /* Store tag and flags and return result */
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  * Checks if request comes from ip address of a gateway taking source
02336  * address and transport protocol from request.
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     /* Get and check parameter value */
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     /* Get transport protocol */
02356     transport = _m->rcv.proto;
02357 
02358     /* Do test */
02359     return do_from_gw(_m, lcr_id, &_m->rcv.src_ip, transport);
02360 }
02361 
02362 
02363 /*
02364  * Checks if request comes from ip address of a gateway taking source
02365  * address and transport protocol from parameters
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     /* Get and check parameter values */
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     /* Do test */
02410     return do_from_gw(_m, lcr_id, &src_addr, transport);
02411 }
02412 
02413 
02414 /*
02415  * Checks if request comes from ip address of any gateway taking source
02416  * address from request.
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  * Checks if request comes from ip address of a a gateway taking source
02436  * IP address and transport protocol from parameters.
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     /* Get and check parameter values */
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     /* Do test */
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  * Checks if in-dialog request goes to ip address of a gateway.
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     /* Skip lcr instance if some of its gws do not have ip addr */
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     /* Search for gw ip address */
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     /* Return result */
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  * Checks if request goes to ip address and transport protocol of a gateway
02515  * taking lcr_id from parameter and destination address and transport protocol
02516  * from Request URI.
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     /* Get and check parameter value */
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     /* Get destination address and transport protocol from R-URI */
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     /* Do test */
02560     return do_to_gw(_m, lcr_id, &dst_addr, transport);
02561 }
02562 
02563 
02564 /*
02565  * Checks if request goes to ip address of a gateway taking lcr_id,
02566  * destination address and transport protocol from parameters.
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     /* Get and check parameter values */
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     /* Do test */
02610     return do_to_gw(_m, lcr_id, &dst_addr, transport);
02611 }
02612 
02613 
02614 /*
02615  * Checks if request goes to ip address of any gateway taking destination
02616  * address and transport protocol from Request-URI.
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     /* Get destination address and transport protocol from R-URI */
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     /* Do test */
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  * Checks if request goes to ip address of any gateway taking destination
02659  * address and transport protocol from parameters.
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     /* Get and check parameter values */
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     /* Do test */
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 }