modules/lcr: Fixed to/from_gw tests when proto parameter is 0 (ANY)
[sip-router] / modules / lcr / lcr_mod.c
1 /*
2  * Least Cost Routing module
3  *
4  * Copyright (C) 2005-2012 Juha Heinanen
5  * Copyright (C) 2006 Voice Sistem SRL
6  *
7  * This file is part of SIP Router, a free SIP server.
8  *
9  * SIP Router is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * SIP Router is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License 
20  * along with this program; if not, write to the Free Software 
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * History:
24  * -------
25  *  2005-02-14: Introduced lcr module (jh)
26  *  2005-02-20: Added sequential forking functions (jh)
27  *  2005-02-25: Added support for int AVP names, combined addr and port
28  *              AVPs (jh)
29  *  2005-07-28: Added support for gw URI scheme and transport, 
30  *              backport from ser (kd)
31  *  2005-08-20: Added support for gw prefixes (jh)
32  *  2005-09-03: Request-URI user part can be modified between load_gws()
33  *              and first next_gw() calls.
34  *  2008-10-10: Database values are now checked and from/to_gw functions
35  *              execute in O(logN) time.
36  *  2008-11-26: Added timer based check of gateways (shurik)
37  *  2009-05-12  added RPC support (andrei)
38  *  2009-06-21  Added support for more than one lcr instance and
39                 gw defunct capability (jh)
40  */
41 /*!
42  * \file
43  * \brief SIP-router LCR :: Module interface
44  * \ingroup lcr
45  * Module: \ref lcr
46  */
47
48 /*! \defgroup lcr SIP-router Least Cost Routing Module
49  *
50  * The Least Cost Routing (LCR) module implements capability to serially
51  * forward a request to one or more gateways so that the order in which
52  * the gateways is tried is based on admin defined "least cost" rules.
53
54  * The LCR module supports many independent LCR instances (gateways and
55  * least cost rules). Each such instance has its own LCR identifier.
56  */
57
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <arpa/inet.h>
62 #include <pcre.h>
63 #include "../../locking.h"
64 #include "../../sr_module.h"
65 #include "../../dprint.h"
66 #include "../../ut.h"
67 #include "../../error.h"
68 #include "../../mem/mem.h"
69 #include "../../mem/shm_mem.h"
70 #include "../../lib/srdb1/db.h"
71 #include "../../usr_avp.h"
72 #include "../../parser/parse_from.h"
73 #include "../../parser/msg_parser.h"
74 #include "../../action.h"
75 #include "../../qvalue.h"
76 #include "../../dset.h"
77 #include "../../ip_addr.h"
78 #include "../../resolve.h"
79 #include "../../mod_fix.h"
80 #include "../../socket_info.h"
81 #include "../../pvar.h"
82 #include "../../mod_fix.h"
83 #include "hash.h"
84 #include "lcr_rpc.h"
85 #include "../../rpc_lookup.h"
86
87 MODULE_VERSION
88
89 /*
90  * versions of database tables required by the module.
91  */
92 #define LCR_RULE_TABLE_VERSION 2
93 #define LCR_RULE_TARGET_TABLE_VERSION 1
94 #define LCR_GW_TABLE_VERSION 2
95
96 /* database defaults */
97
98 #define LCR_RULE_TABLE "lcr_rule"
99 #define LCR_RULE_TARGET_TABLE "lcr_rule_target"
100 #define LCR_GW_TABLE "lcr_gw"
101
102 #define ID_COL "id"
103 #define LCR_ID_COL "lcr_id"
104 #define PREFIX_COL "prefix"
105 #define FROM_URI_COL "from_uri"
106 #define REQUEST_URI_COL "request_uri"
107 #define STOPPER_COL "stopper"
108 #define ENABLED_COL "enabled"
109 #define RULE_ID_COL "rule_id"
110 #define PRIORITY_COL "priority"
111 #define GW_ID_COL "gw_id"
112 #define WEIGHT_COL "weight"
113 #define GW_NAME_COL "gw_name"
114 #define IP_ADDR_COL "ip_addr"
115 #define PORT_COL "port"
116 #define URI_SCHEME_COL "uri_scheme"
117 #define TRANSPORT_COL "transport"
118 #define PARAMS_COL "params"
119 #define HOSTNAME_COL "hostname"
120 #define STRIP_COL "strip"
121 #define PREFIX_COL "prefix"
122 #define TAG_COL "tag"
123 #define FLAGS_COL "flags"
124 #define DEFUNCT_COL "defunct"
125
126 /* Default module parameter values */
127 #define DEF_LCR_COUNT 1
128 #define DEF_LCR_RULE_HASH_SIZE 128
129 #define DEF_LCR_GW_COUNT 128
130 #define DEF_FETCH_ROWS 1024
131
132 /*
133  * Type definitions
134  */
135
136 struct matched_gw_info {
137     unsigned short gw_index;
138     unsigned short prefix_len;
139     unsigned short priority;
140     unsigned int weight;
141     unsigned short duplicate;
142 };
143
144 /*
145  * Database variables
146  */
147 static db1_con_t* dbh = 0;   /* Database connection handle */
148 static db_func_t lcr_dbf;
149
150 /*
151  * Locking variables
152  */
153 gen_lock_t *reload_lock;
154
155 /*
156  * Module parameter variables
157  */
158
159 /* database variables */
160 static str db_url           = str_init(DEFAULT_RODB_URL);
161 static str lcr_rule_table   = str_init(LCR_RULE_TABLE);
162 static str lcr_rule_target_table = str_init(LCR_RULE_TARGET_TABLE);
163 static str lcr_gw_table     = str_init(LCR_GW_TABLE);
164 static str id_col           = str_init(ID_COL);
165 static str lcr_id_col       = str_init(LCR_ID_COL);
166 static str prefix_col       = str_init(PREFIX_COL);
167 static str from_uri_col     = str_init(FROM_URI_COL);
168 static str request_uri_col  = str_init(REQUEST_URI_COL);
169 static str stopper_col      = str_init(STOPPER_COL);
170 static str enabled_col      = str_init(ENABLED_COL);
171 static str rule_id_col      = str_init(RULE_ID_COL);
172 static str priority_col     = str_init(PRIORITY_COL);
173 static str gw_id_col        = str_init(GW_ID_COL);
174 static str weight_col       = str_init(WEIGHT_COL);
175 static str gw_name_col      = str_init(GW_NAME_COL);
176 static str ip_addr_col      = str_init(IP_ADDR_COL);
177 static str port_col         = str_init(PORT_COL);
178 static str uri_scheme_col   = str_init(URI_SCHEME_COL);
179 static str transport_col    = str_init(TRANSPORT_COL);
180 static str params_col       = str_init(PARAMS_COL);
181 static str hostname_col     = str_init(HOSTNAME_COL);
182 static str strip_col        = str_init(STRIP_COL);
183 static str tag_col          = str_init(TAG_COL);
184 static str flags_col        = str_init(FLAGS_COL);
185 static str defunct_col      = str_init(DEFUNCT_COL);
186
187 /* number of rows to fetch at a shot */
188 static int fetch_rows_param = DEF_FETCH_ROWS;
189
190 /* avps */
191 static char *gw_uri_avp_param = NULL;
192 static char *ruri_user_avp_param = NULL;
193 static char *tag_avp_param = NULL;
194 static char *flags_avp_param = NULL;
195 static char *defunct_gw_avp_param = NULL;
196 static char *lcr_id_avp_param = NULL;
197
198 /* max number of lcr instances */
199 unsigned int lcr_count_param = DEF_LCR_COUNT;
200
201 /* size of lcr rules hash table */
202 unsigned int lcr_rule_hash_size_param = DEF_LCR_RULE_HASH_SIZE;
203
204 /* max no of gws */
205 unsigned int lcr_gw_count_param = DEF_LCR_GW_COUNT;
206
207 /* can gws be defuncted */
208 static unsigned int defunct_capability_param = 0;
209
210 /* dont strip or tag param */
211 static int dont_strip_or_prefix_flag_param = -1;
212
213
214 /*
215  * Other module types and variables
216  */
217
218 static int     gw_uri_avp_type;
219 static int_str gw_uri_avp;
220 static int     ruri_user_avp_type;
221 static int_str ruri_user_avp;
222 static int     tag_avp_type;
223 static int_str tag_avp;
224 static int     flags_avp_type;
225 static int_str flags_avp;
226 static int     defunct_gw_avp_type;
227 static int_str defunct_gw_avp;
228 static int     lcr_id_avp_type;
229 static int_str lcr_id_avp;
230
231 /* Pointer to rule hash table pointer table */
232 struct rule_info ***rule_pt = (struct rule_info ***)NULL;
233
234 /* Pointer to gw table pointer table */
235 struct gw_info **gw_pt = (struct gw_info **)NULL;
236
237 /* Pointer to rule_id info hash table */
238 struct rule_id_info **rule_id_hash_table = (struct rule_id_info **)NULL;
239
240 /*
241  * Functions that are defined later
242  */
243 static void destroy(void);
244 static int mod_init(void);
245 static int child_init(int rank);
246 static void free_shared_memory(void);
247
248 static int load_gws(struct sip_msg* _m, int argc, action_u_t argv[]);
249 static int next_gw(struct sip_msg* _m, char* _s1, char* _s2);
250 static int defunct_gw(struct sip_msg* _m, char* _s1, char* _s2);
251 static int from_gw_1(struct sip_msg* _m, char* _s1, char* _s2);
252 static int from_gw_3(struct sip_msg* _m, char* _s1, char* _s2, char* _s3);
253 static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2);
254 static int from_any_gw_2(struct sip_msg* _m, char* _s1, char* _s2);
255 static int to_gw_1(struct sip_msg* _m, char* _s1, char* _s2);
256 static int to_gw_3(struct sip_msg* _m, char* _s1, char* _s2, char* _s3);
257 static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2);
258 static int to_any_gw_2(struct sip_msg* _m, char* _s1, char* _s2);
259
260 /*
261  * Exported functions
262  */
263 static cmd_export_t cmds[] = {
264     {"load_gws", (cmd_function)load_gws, VAR_PARAM_NO, 0, 0,
265      REQUEST_ROUTE | FAILURE_ROUTE},
266     {"next_gw", (cmd_function)next_gw, 0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
267     {"defunct_gw", (cmd_function)defunct_gw, 1, 0, 0,
268      REQUEST_ROUTE | FAILURE_ROUTE},
269     {"from_gw", (cmd_function)from_gw_1, 1, 0, 0,
270      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
271     {"from_gw", (cmd_function)from_gw_3, 3, 0, 0,
272      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
273     {"from_any_gw", (cmd_function)from_any_gw_0, 0, 0, 0,
274      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
275     {"from_any_gw", (cmd_function)from_any_gw_2, 2, 0, 0,
276      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
277     {"to_gw", (cmd_function)to_gw_1, 1, 0, 0,
278      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
279     {"to_gw", (cmd_function)to_gw_3, 3, 0, 0,
280      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
281     {"to_any_gw", (cmd_function)to_any_gw_0, 0, 0, 0,
282      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
283     {"to_any_gw", (cmd_function)to_any_gw_2, 2, 0, 0,
284      REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
285     {0, 0, 0, 0, 0, 0}
286 };
287
288
289 /*
290  * Exported parameters
291  */
292 static param_export_t params[] = {
293     {"db_url",                   STR_PARAM, &db_url.s},
294     {"lcr_rule_table",           STR_PARAM, &lcr_rule_table.s},
295     {"lcr_rule_target_table",    STR_PARAM, &lcr_rule_target_table.s},
296     {"lcr_gw_table",             STR_PARAM, &lcr_gw_table.s},
297     {"lcr_id_column",            STR_PARAM, &lcr_id_col.s},
298     {"id_column",                STR_PARAM, &id_col.s},
299     {"prefix_column",            STR_PARAM, &prefix_col.s},
300     {"from_uri_column",          STR_PARAM, &from_uri_col.s},
301     {"request_uri_column",       STR_PARAM, &request_uri_col.s},
302     {"stopper_column",           STR_PARAM, &stopper_col.s},
303     {"enabled_column",           STR_PARAM, &enabled_col.s},
304     {"rule_id_column",           STR_PARAM, &rule_id_col.s},
305     {"priority_column",          STR_PARAM, &priority_col.s},
306     {"gw_id_column",             STR_PARAM, &gw_id_col.s},
307     {"weight_column",            STR_PARAM, &weight_col.s},
308     {"gw_name_column",           STR_PARAM, &gw_name_col.s},
309     {"ip_addr_column",           STR_PARAM, &ip_addr_col.s},
310     {"port_column",              STR_PARAM, &port_col.s},
311     {"uri_scheme_column",        STR_PARAM, &uri_scheme_col.s},
312     {"transport_column",         STR_PARAM, &transport_col.s},
313     {"params_column",            STR_PARAM, &params_col.s},
314     {"hostname_column",          STR_PARAM, &hostname_col.s},
315     {"strip_column",             STR_PARAM, &strip_col.s},
316     {"prefix_column",            STR_PARAM, &prefix_col.s},
317     {"tag_column",               STR_PARAM, &tag_col.s},
318     {"flags_column",             STR_PARAM, &flags_col.s},
319     {"defunct_column",           STR_PARAM, &defunct_col.s},
320     {"gw_uri_avp",               STR_PARAM, &gw_uri_avp_param},
321     {"ruri_user_avp",            STR_PARAM, &ruri_user_avp_param},
322     {"tag_avp",                  STR_PARAM, &tag_avp_param},
323     {"flags_avp",                STR_PARAM, &flags_avp_param},
324     {"defunct_capability",       INT_PARAM, &defunct_capability_param},
325     {"defunct_gw_avp",           STR_PARAM, &defunct_gw_avp_param},
326     {"lcr_id_avp",               STR_PARAM, &lcr_id_avp_param},
327     {"lcr_count",                INT_PARAM, &lcr_count_param},
328     {"lcr_rule_hash_size",       INT_PARAM, &lcr_rule_hash_size_param},
329     {"lcr_gw_count",             INT_PARAM, &lcr_gw_count_param},
330     {"dont_strip_or_prefix_flag",INT_PARAM, &dont_strip_or_prefix_flag_param},
331     {"fetch_rows",               INT_PARAM, &fetch_rows_param},
332     {0, 0, 0}
333 };
334
335 /*
336  * Module interface
337  */
338 struct module_exports exports = {
339         "lcr", 
340         DEFAULT_DLFLAGS, /* dlopen flags */
341         cmds,      /* Exported functions */
342         params,    /* Exported parameters */
343         0,         /* exported statistics */
344         0,         /* exported MI functions */
345         0,         /* exported pseudo-variables */
346         0,         /* extra processes */
347         mod_init,  /* module initialization function */
348         0,         /* response function */
349         destroy,   /* destroy function */
350         child_init /* child initialization function */
351 };
352
353 static int lcr_db_init(const str* db_url)
354 {       
355         if (lcr_dbf.init==0){
356                 LM_CRIT("null lcr_dbf\n");
357                 goto error;
358         }
359         if (dbh) {
360             LM_ERR("database is already connected\n");
361             goto error;
362         }
363         dbh=lcr_dbf.init(db_url);
364         if (dbh==0){
365                 LM_ERR("unable to connect to the database\n");
366                 goto error;
367         }
368         return 0;
369 error:
370         return -1;
371 }
372
373
374
375 static int lcr_db_bind(const str* db_url)
376 {
377     if (db_bind_mod(db_url, &lcr_dbf)<0){
378         LM_ERR("unable to bind to the database module\n");
379         return -1;
380     }
381
382     if (!DB_CAPABILITY(lcr_dbf, DB_CAP_QUERY)) {
383         LM_ERR("database module does not implement 'query' function\n");
384         return -1;
385     }
386
387     return 0;
388 }
389
390
391 static void lcr_db_close(void)
392 {
393         if (dbh && lcr_dbf.close){
394                 lcr_dbf.close(dbh);
395                 dbh=0;
396         }
397 }
398
399
400 /*
401  * Module initialization function that is called before the main process forks
402  */
403 static int mod_init(void)
404 {
405     pv_spec_t avp_spec;
406     str s;
407     unsigned short avp_flags;
408     unsigned int i;
409
410     /* Register RPC commands */
411     if (rpc_register_array(lcr_rpc)!=0) {
412         LM_ERR("failed to register RPC commands\n");
413         return -1;
414     }
415
416     /* Update length of module variables */
417     db_url.len = strlen(db_url.s);
418     lcr_rule_table.len = strlen(lcr_rule_table.s);
419     lcr_rule_target_table.len = strlen(lcr_rule_target_table.s);
420     lcr_gw_table.len = strlen(lcr_gw_table.s);
421     id_col.len = strlen(id_col.s);
422     lcr_id_col.len = strlen(lcr_id_col.s);
423     prefix_col.len = strlen(prefix_col.s);
424     from_uri_col.len = strlen(from_uri_col.s);
425     request_uri_col.len = strlen(request_uri_col.s);
426     stopper_col.len = strlen(stopper_col.s);
427     enabled_col.len = strlen(enabled_col.s);
428     rule_id_col.len = strlen(rule_id_col.s);
429     priority_col.len = strlen(priority_col.s);
430     gw_id_col.len = strlen(gw_id_col.s);
431     weight_col.len = strlen(weight_col.s);
432     gw_name_col.len = strlen(gw_name_col.s);
433     ip_addr_col.len = strlen(ip_addr_col.s);
434     port_col.len = strlen(port_col.s);
435     uri_scheme_col.len = strlen(uri_scheme_col.s);
436     transport_col.len = strlen(transport_col.s);
437     params_col.len = strlen(params_col.s);
438     hostname_col.len = strlen(hostname_col.s);
439     strip_col.len = strlen(strip_col.s);
440     prefix_col.len = strlen(prefix_col.s);
441     tag_col.len = strlen(tag_col.s);
442     flags_col.len = strlen(flags_col.s);
443     defunct_col.len = strlen(defunct_col.s);
444
445     /* Bind database */
446     if (lcr_db_bind(&db_url)) {
447         LM_ERR("no database module found\n");
448         return -1;
449     }
450
451     /* Check values of some params */
452     if (lcr_count_param < 1) {
453         LM_ERR("invalid lcr_count module parameter value <%d>\n",
454                lcr_count_param);
455         return -1;
456     }
457     if (lcr_rule_hash_size_param < 1) {
458         LM_ERR("invalid lcr_rule_hash_size module parameter value <%d>\n",
459                lcr_rule_hash_size_param);
460         return -1;
461     }
462     if (lcr_gw_count_param < 1) {
463         LM_ERR("invalid lcr_gw_count module parameter value <%d>\n",
464                lcr_gw_count_param);
465         return -1;
466     }
467     if ((dont_strip_or_prefix_flag_param != -1) &&
468         !flag_in_range(dont_strip_or_prefix_flag_param)) {
469         LM_ERR("invalid dont_strip_or_prefix_flag value <%d>\n",
470                dont_strip_or_prefix_flag_param);
471         return -1;
472     }
473
474     /* Process AVP params */
475
476     if (gw_uri_avp_param && *gw_uri_avp_param) {
477         s.s = gw_uri_avp_param; s.len = strlen(s.s);
478         if (pv_parse_spec(&s, &avp_spec)==0
479             || avp_spec.type!=PVT_AVP) {
480             LM_ERR("malformed or non AVP definition <%s>\n", gw_uri_avp_param);
481             return -1;
482         }
483         
484         if (pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags) != 0) {
485             LM_ERR("invalid AVP definition <%s>\n", gw_uri_avp_param);
486             return -1;
487         }
488         gw_uri_avp_type = avp_flags;
489     } else {
490         LM_ERR("AVP gw_uri_avp has not been defined\n");
491         return -1;
492     }
493
494     if (ruri_user_avp_param && *ruri_user_avp_param) {
495         s.s = ruri_user_avp_param; s.len = strlen(s.s);
496         if (pv_parse_spec(&s, &avp_spec)==0
497             || avp_spec.type!=PVT_AVP) {
498             LM_ERR("malformed or non AVP definition <%s>\n",
499                    ruri_user_avp_param);
500             return -1;
501         }
502         
503         if (pv_get_avp_name(0, &(avp_spec.pvp), &ruri_user_avp, &avp_flags)
504             != 0) {
505             LM_ERR("invalid AVP definition <%s>\n", ruri_user_avp_param);
506             return -1;
507         }
508         ruri_user_avp_type = avp_flags;
509     } else {
510         LM_ERR("AVP ruri_user_avp has not been defined\n");
511         return -1;
512     }
513
514     if (tag_avp_param) {
515         s.s = tag_avp_param; s.len = strlen(s.s);
516         if ((pv_parse_spec(&s, &avp_spec)==0) || (avp_spec.type!=PVT_AVP)) {
517             LM_ERR("malformed or non AVP definition <%s>\n", tag_avp_param);
518             return -1;
519         }
520         if (pv_get_avp_name(0, &(avp_spec.pvp), &tag_avp, &avp_flags) != 0) {
521             LM_ERR("invalid AVP definition <%s>\n", tag_avp_param);
522             return -1;
523         }
524         tag_avp_type = avp_flags | AVP_VAL_STR;
525     }
526
527     if (flags_avp_param) {
528         s.s = flags_avp_param; s.len = strlen(s.s);
529         if ((pv_parse_spec(&s, &avp_spec)==0) || (avp_spec.type != PVT_AVP)) {
530             LM_ERR("malformed or non AVP definition <%s>\n", flags_avp_param);
531             return -1;
532         }
533         if (pv_get_avp_name(0, &(avp_spec.pvp), &flags_avp, &avp_flags) != 0) {
534             LM_ERR("invalid AVP definition <%s>\n", flags_avp_param);
535             return -1;
536         }
537         flags_avp_type = avp_flags;
538     }
539
540     if (defunct_capability_param > 0) {
541         if (defunct_gw_avp_param && *defunct_gw_avp_param) {
542             s.s = defunct_gw_avp_param; s.len = strlen(s.s);
543             if ((pv_parse_spec(&s, &avp_spec) == 0) ||
544                 (avp_spec.type != PVT_AVP)) {
545                 LM_ERR("malformed or non AVP definition <%s>\n",
546                        defunct_gw_avp_param);
547                 return -1;
548             }
549             if (pv_get_avp_name(0, &(avp_spec.pvp), &defunct_gw_avp,
550                                 &avp_flags) != 0) {
551                 LM_ERR("invalid AVP definition <%s>\n", defunct_gw_avp_param);
552                 return -1;
553             }
554             defunct_gw_avp_type = avp_flags;
555         } else {
556             LM_ERR("AVP defunct_gw_avp has not been defined\n");
557             return -1;
558         }
559         if (lcr_id_avp_param && *lcr_id_avp_param) {
560             s.s = lcr_id_avp_param; s.len = strlen(s.s);
561             if ((pv_parse_spec(&s, &avp_spec) == 0) ||
562                 (avp_spec.type != PVT_AVP)) {
563                 LM_ERR("malformed or non AVP definition <%s>\n",
564                        lcr_id_avp_param);
565                 return -1;
566             }
567             if (pv_get_avp_name(0, &(avp_spec.pvp), &lcr_id_avp,
568                                 &avp_flags) != 0) {
569                 LM_ERR("invalid AVP definition <%s>\n", lcr_id_avp_param);
570                 return -1;
571             }
572             lcr_id_avp_type = avp_flags;
573         } else {
574             LM_ERR("AVP lcr_id_avp has not been defined\n");
575             return -1;
576         }
577     }
578
579     if (fetch_rows_param < 1) {
580         LM_ERR("invalid fetch_rows module parameter value <%d>\n",
581                fetch_rows_param);
582         return -1;
583     }
584
585     /* Check table version */
586     if (lcr_db_init(&db_url) < 0) {
587         LM_ERR("unable to open database connection\n");
588         return -1;
589     }
590     if ((db_check_table_version(&lcr_dbf, dbh, &lcr_rule_table,
591                                 LCR_RULE_TABLE_VERSION) < 0) ||
592         (db_check_table_version(&lcr_dbf, dbh, &lcr_rule_target_table,
593                                 LCR_RULE_TARGET_TABLE_VERSION) < 0) ||
594         (db_check_table_version(&lcr_dbf, dbh, &lcr_gw_table,
595                                 LCR_GW_TABLE_VERSION) < 0)) {
596         LM_ERR("error during table version check\n");
597         lcr_db_close();
598         goto err;
599     }
600     lcr_db_close();
601
602     /* rule shared memory */
603
604     /* rule hash table pointer table */
605     /* pointer at index 0 points to temp rule hash table */
606     rule_pt = (struct rule_info ***)shm_malloc(sizeof(struct rule_info **) *
607                                                (lcr_count_param + 1));
608     if (rule_pt == 0) {
609         LM_ERR("no memory for rule hash table pointer table\n");
610         goto err;
611     }
612     memset(rule_pt, 0, sizeof(struct rule_info **) * (lcr_count_param + 1));
613
614     /* rules hash tables */
615     /* last entry in hash table contains list of different prefix lengths */
616     for (i = 0; i <= lcr_count_param; i++) {
617         rule_pt[i] = (struct rule_info **)
618             shm_malloc(sizeof(struct rule_info *) *
619                        (lcr_rule_hash_size_param + 1));
620         if (rule_pt[i] == 0) {
621             LM_ERR("no memory for rules hash table\n");
622             goto err;
623         }
624         memset(rule_pt[i], 0, sizeof(struct rule_info *) *
625                (lcr_rule_hash_size_param + 1));
626     }
627     /* gw shared memory */
628
629     /* gw table pointer table */
630     /* pointer at index 0 points to temp rule hash table */
631     gw_pt = (struct gw_info **)shm_malloc(sizeof(struct gw_info *) *
632                                           (lcr_count_param + 1));
633     if (gw_pt == 0) {
634         LM_ERR("no memory for gw table pointer table\n");
635         goto err;
636     }
637     memset(gw_pt, 0, sizeof(struct gw_info *) * (lcr_count_param + 1));
638
639     /* gw tables themselves */
640     /* ordered by ip_addr for from_gw/to_gw functions */
641     /* in each table i, (gw_pt[i])[0].ip_addr contains number of
642        gateways in the table and (gw_pt[i])[0].port as value 1
643        if some gateways in the table have null ip addr */
644     for (i = 0; i <= lcr_count_param; i++) {
645         gw_pt[i] = (struct gw_info *)shm_malloc(sizeof(struct gw_info) *
646                                                 (lcr_gw_count_param + 1));
647         if (gw_pt[i] == 0) {
648             LM_ERR("no memory for gw table\n");
649             goto err;
650         }
651         memset(gw_pt[i], 0, sizeof(struct gw_info *) *
652                (lcr_gw_count_param + 1));
653     }
654
655     /* Allocate and initialize locks */
656     reload_lock = lock_alloc();
657     if (reload_lock == NULL) {
658         LM_ERR("cannot allocate reload_lock\n");
659         goto err;
660     }
661     if (lock_init(reload_lock) == NULL) {
662         LM_ERR("cannot init reload_lock\n");
663         goto err;
664     }
665
666     /* First reload */
667     lock_get(reload_lock);
668     if (reload_tables() < 0) {
669         lock_release(reload_lock);
670         LM_CRIT("failed to reload lcr tables\n");
671         goto err;
672     }
673     lock_release(reload_lock);
674
675     return 0;
676
677 err:
678     free_shared_memory();
679     return -1;
680 }
681
682
683 /* Module initialization function called in each child separately */
684 static int child_init(int rank)
685 {
686     return 0;
687 }
688
689
690 static void destroy(void)
691 {
692     lcr_db_close();
693
694     free_shared_memory();
695 }
696
697
698 /* Free shared memory */
699 static void free_shared_memory(void)
700 {
701     int i;
702     for (i = 0; i <= lcr_count_param; i++) {
703         if (rule_pt && rule_pt[i]) {
704             rule_hash_table_contents_free(rule_pt[i]);
705             shm_free(rule_pt[i]);
706             rule_pt[i] = 0;
707         }
708     }
709     if (rule_pt) {
710         shm_free(rule_pt);
711         rule_pt = 0;
712     }
713     for (i = 0; i <= lcr_count_param; i++) {
714         if (gw_pt && gw_pt[i]) {
715             shm_free(gw_pt[i]);
716             gw_pt[i] = 0;
717         }
718     }
719     if (gw_pt) {
720         shm_free(gw_pt);
721         gw_pt = 0;
722     }
723     if (reload_lock) {
724         lock_destroy(reload_lock);
725         lock_dealloc(reload_lock);
726         reload_lock=0;
727     }
728 }
729    
730 /*
731  * Compare matched gateways based on prefix_len, priority, and randomized
732  * weight.
733  */
734 static int comp_matched(const void *m1, const void *m2)
735 {
736     struct matched_gw_info *mi1 = (struct matched_gw_info *) m1;
737     struct matched_gw_info *mi2 = (struct matched_gw_info *) m2;
738
739     /* Sort by prefix_len */
740     if (mi1->prefix_len > mi2->prefix_len) return 1;
741     if (mi1->prefix_len == mi2->prefix_len) {
742         /* Sort by priority */
743         if (mi1->priority < mi2->priority) return 1;
744         if (mi1->priority == mi2->priority) {
745             /* Sort by randomized weigth */
746             if (mi1->weight > mi2->weight) return 1;
747             if (mi1->weight == mi2->weight) return 0;
748             return -1;
749         }
750         return -1;
751     }
752     return -1;
753 }
754
755
756 /* Compile pattern into shared memory and return pointer to it. */
757 static pcre *reg_ex_comp(const char *pattern)
758 {
759     pcre *re, *result;
760     const char *error;
761     int rc, size, err_offset;
762
763     re = pcre_compile(pattern, 0, &error, &err_offset, NULL);
764     if (re == NULL) {
765         LM_ERR("pcre compilation of '%s' failed at offset %d: %s\n",
766                pattern, err_offset, error);
767         return (pcre *)0;
768     }
769     rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
770     if (rc != 0) {
771         LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
772                pattern, rc);
773         return (pcre *)0;
774     }
775     result = (pcre *)shm_malloc(size);
776     if (result == NULL) {
777         pcre_free(re);
778         LM_ERR("not enough shared memory for compiled PCRE pattern\n");
779         return (pcre *)0;
780     }
781     memcpy(result, re, size);
782     pcre_free(re);
783     return result;
784 }
785
786
787 /*
788  * Compare gateways based on their IP address
789  */
790 static int comp_gws(const void *_g1, const void *_g2)
791 {
792     struct gw_info *g1 = (struct gw_info *)_g1;
793     struct gw_info *g2 = (struct gw_info *)_g2;
794
795     if (g1->ip_addr.af < g2->ip_addr.af)   return -1;
796     if (g1->ip_addr.af > g2->ip_addr.af)   return  1;
797     if (g1->ip_addr.len < g2->ip_addr.len) return -1;
798     if (g1->ip_addr.len > g2->ip_addr.len) return  1;
799     return memcmp(g1->ip_addr.u.addr, g2->ip_addr.u.addr, g1->ip_addr.len);
800 }
801
802
803 /* 
804  * Insert gw info into index i or gws table
805  */
806 static int insert_gw(struct gw_info *gws, unsigned int i, unsigned int gw_id,
807                      char *gw_name, unsigned int gw_name_len,
808                      unsigned int scheme, struct ip_addr *ip_addr,
809                      unsigned int port, unsigned int transport,
810                      char *params, unsigned int params_len,
811                      char *hostname, unsigned int hostname_len,
812                      char *ip_string, unsigned int strip, char *prefix,
813                      unsigned int prefix_len, char *tag, unsigned int tag_len,
814                      unsigned int flags, unsigned int defunct_until)
815 {
816     gws[i].gw_id = gw_id;
817     if (gw_name_len) memcpy(&(gws[i].gw_name[0]), gw_name, gw_name_len);
818     gws[i].gw_name_len = gw_name_len;
819     gws[i].scheme = scheme;
820     gws[i].ip_addr = *ip_addr;
821     gws[i].port = port;
822     gws[i].transport = transport;
823     if (params_len) memcpy(&(gws[i].params[0]), params, params_len);
824     gws[i].params_len = params_len;
825     if (hostname_len) memcpy(&(gws[i].hostname[0]), hostname, hostname_len);
826     gws[i].hostname_len = hostname_len;
827     gws[i].strip = strip;
828     gws[i].prefix_len = prefix_len;
829     if (prefix_len) memcpy(&(gws[i].prefix[0]), prefix, prefix_len);
830     gws[i].tag_len = tag_len;
831     if (tag_len) memcpy(&(gws[i].tag[0]), tag, tag_len);
832     gws[i].flags = flags;
833     gws[i].defunct_until = defunct_until;
834     LM_DBG("inserted gw <%u, %.*s, %s, %u, %.*s> at index %u\n", gw_id,
835            gw_name_len, gw_name, ip_string, port, hostname_len, hostname, i);
836     return 1;
837 }
838
839
840 /*
841  * Insert prefix_len into list pointed by last rule hash table entry 
842  * if not there already. Keep list in decending prefix_len order.
843  */
844 static int prefix_len_insert(struct rule_info **table,
845                              unsigned short prefix_len)
846 {
847     struct rule_info *lcr_rec, **previous, *this;
848     
849     previous = &(table[lcr_rule_hash_size_param]);
850     this = table[lcr_rule_hash_size_param];
851
852     while (this) {
853         if (this->prefix_len == prefix_len)
854             return 1;
855         if (this->prefix_len < prefix_len) {
856             lcr_rec = shm_malloc(sizeof(struct rule_info));
857             if (lcr_rec == NULL) {
858                 LM_ERR("no shared memory for rule_info\n");
859                 return 0;
860             }
861             memset(lcr_rec, 0, sizeof(struct rule_info));
862             lcr_rec->prefix_len = prefix_len;
863             lcr_rec->next = this;
864             *previous = lcr_rec;
865             return 1;
866         }
867         previous = &(this->next);
868         this = this->next;
869     }
870
871     lcr_rec = shm_malloc(sizeof(struct rule_info));
872     if (lcr_rec == NULL) {
873         LM_ERR("no shared memory for rule_info\n");
874         return 0;
875     }
876     memset(lcr_rec, 0, sizeof(struct rule_info));
877     lcr_rec->prefix_len = prefix_len;
878     lcr_rec->next = NULL;
879     *previous = lcr_rec;
880     return 1;
881 }
882
883 static int insert_gws(db1_res_t *res, struct gw_info *gws,
884                       unsigned int *null_gw_ip_addr,
885                       unsigned int *gw_cnt)
886 {
887     unsigned int i, gw_id, defunct_until, gw_name_len, port, params_len,
888         hostname_len, strip, prefix_len, tag_len, flags;
889     char *gw_name, *params, *hostname, *prefix, *tag;
890     db_row_t* row;
891     struct in_addr in_addr;
892     struct ip_addr ip_addr, *ip_p;
893     str ip_string;
894     uri_type scheme;
895     uri_transport transport;
896     
897     for (i = 0; i < RES_ROW_N(res); i++) {
898         row = RES_ROWS(res) + i;
899         if ((VAL_NULL(ROW_VALUES(row) + 12) == 1) ||
900             (VAL_TYPE(ROW_VALUES(row) + 12) != DB1_INT)) {
901             LM_ERR("lcr_gw id at row <%u> is null or not int\n", i);
902             return 0;
903         }
904         gw_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 12);
905         if (VAL_NULL(ROW_VALUES(row) + 11)) {
906             defunct_until = 0;
907         } else {
908             if (VAL_TYPE(ROW_VALUES(row) + 11) != DB1_INT) {
909                 LM_ERR("lcr_gw defunct at row <%u> is not int\n", i);
910                 return 0;
911             }
912             defunct_until = (unsigned int)VAL_INT(ROW_VALUES(row) + 11);
913             if (defunct_until > 4294967294UL) {
914                 LM_DBG("skipping disabled gw <%u>\n", gw_id);
915                 continue;
916             }
917         }
918         if (!VAL_NULL(ROW_VALUES(row)) &&
919             (VAL_TYPE(ROW_VALUES(row)) != DB1_STRING)) {
920             LM_ERR("lcr_gw gw_name at row <%u> is not null or string\n", i);
921             return 0;
922         }
923         if (VAL_NULL(ROW_VALUES(row))) {
924             gw_name_len = 0;
925             gw_name = (char *)0;
926         } else {
927             if (VAL_TYPE(ROW_VALUES(row)) != DB1_STRING) {
928                 LM_ERR("lcr_gw gw_name at row <%u> is not string\n", i);
929                 return 0;
930             }
931             gw_name = (char *)VAL_STRING(ROW_VALUES(row));
932             gw_name_len = strlen(gw_name);
933         }
934         if (gw_name_len > MAX_NAME_LEN) {
935             LM_ERR("lcr_gw gw_name <%u> at row <%u> it too long\n",
936                    gw_name_len, i);
937             return 0;
938         }
939         if (!VAL_NULL(ROW_VALUES(row) + 1) &&
940             (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_STRING)) {
941             LM_ERR("lcr_gw ip_addr at row <%u> is not null or string\n",
942                    i);
943             return 0;
944         }
945         if (VAL_NULL(ROW_VALUES(row) + 1)) {
946             ip_string.s = (char *)0;
947             ip_addr.af = 0;
948             ip_addr.len = 0;
949             *null_gw_ip_addr = 1;
950         } else {
951             ip_string.s = (char *)VAL_STRING(ROW_VALUES(row) + 1);
952             ip_string.len = strlen(ip_string.s);
953             if ((ip_p = str2ip(&ip_string))) {
954                 /* 123.123.123.123 */
955                 ip_addr = *ip_p;
956             }
957 #ifdef USE_IPV6
958             else if ((ip_p = str2ip6(&ip_string))) {
959                 /* fe80::123:4567:89ab:cdef and [fe80::123:4567:89ab:cdef] */
960                 ip_addr = *ip_p;
961             }
962 #endif
963             else if (inet_aton(ip_string.s, &in_addr) == 0) {
964                 /* backwards compatibility for integer or hex notations */
965                 ip_addr.u.addr32[0] = in_addr.s_addr;
966                 ip_addr.af = AF_INET;
967                 ip_addr.len = 4;
968             }
969             else {
970                 LM_ERR("lcr_gw ip_addr <%s> at row <%u> is invalid\n",
971                        ip_string.s, i);
972                 return 0;
973             }
974         }
975         if (VAL_NULL(ROW_VALUES(row) + 2)) {
976             port = 0;
977         } else {
978             if (VAL_TYPE(ROW_VALUES(row) + 2) != DB1_INT) {
979                 LM_ERR("lcr_gw port at row <%u> is not int\n", i);
980                 return 0;
981             }
982             port = (unsigned int)VAL_INT(ROW_VALUES(row) + 2);
983         }
984         if (port > 65536) {
985             LM_ERR("lcr_gw port <%d> at row <%u> is too large\n", port, i);
986             return 0;
987         }
988         if (VAL_NULL(ROW_VALUES(row) + 3)) {
989             scheme = SIP_URI_T;
990         } else {
991             if (VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT) {
992                 LM_ERR("lcr_gw uri scheme at row <%u> is not int\n", i);
993                 return 0;
994             }
995             scheme = (uri_type)VAL_INT(ROW_VALUES(row) + 3);
996         }
997         if ((scheme != SIP_URI_T) && (scheme != SIPS_URI_T)) {
998             LM_ERR("lcr_gw has unknown or unsupported URI scheme <%u> at "
999                    "row <%u>\n", (unsigned int)scheme, i);
1000             return 0;
1001         }
1002         if (VAL_NULL(ROW_VALUES(row) + 4)) {
1003             transport = PROTO_NONE;
1004         } else {
1005             if (VAL_TYPE(ROW_VALUES(row) + 4) != DB1_INT) {
1006                 LM_ERR("lcr_gw transport at row <%u> is not int\n", i);
1007                 return 0;
1008             }
1009             transport = (uri_transport)VAL_INT(ROW_VALUES(row) + 4);
1010         }
1011         if ((transport != PROTO_UDP) && (transport != PROTO_TCP) &&
1012             (transport != PROTO_TLS) && (transport != PROTO_SCTP) &&
1013             (transport != PROTO_NONE)) {
1014             LM_ERR("lcr_gw has unknown or unsupported transport <%u> at "
1015                    " row <%u>\n", (unsigned int)transport, i);
1016             return 0;
1017         }
1018         if ((scheme == SIPS_URI_T) && (transport == PROTO_UDP)) {
1019             LM_ERR("lcr_gw has wrong transport <%u> for SIPS URI "
1020                    "scheme at row <%u>\n", transport, i);
1021             return 0;
1022         }
1023         if (VAL_NULL(ROW_VALUES(row) + 5)) {
1024             params_len = 0;
1025             params = (char *)0;
1026         } else {
1027             if (VAL_TYPE(ROW_VALUES(row) + 5) != DB1_STRING) {
1028                 LM_ERR("lcr_gw params at row <%u> is not string\n", i);
1029                 return 0;
1030             }
1031             params = (char *)VAL_STRING(ROW_VALUES(row) + 5);
1032             params_len = strlen(params);
1033             if ((params_len > 0) && (params[0] != ';')) {
1034                 LM_ERR("lcr_gw params at row <%u> does not start "
1035                        "with ';'\n", i);
1036                 return 0;
1037             }
1038         }
1039         if (params_len > MAX_PARAMS_LEN) {
1040             LM_ERR("lcr_gw params length <%u> at row <%u> it too large\n",
1041                    params_len, i);
1042             return 0;
1043         }
1044         if (VAL_NULL(ROW_VALUES(row) + 6)) {
1045             if (ip_string.s == 0) {
1046                 LM_ERR("lcr_gw gw ip_addr and hostname are both null "
1047                        "at row <%u>\n", i);
1048                 return 0;
1049             }
1050             hostname_len = 0;
1051             hostname = (char *)0;
1052         } else {
1053             if (VAL_TYPE(ROW_VALUES(row) + 6) != DB1_STRING) {
1054                 LM_ERR("hostname at row <%u> is not string\n", i);
1055                 return 0;
1056             }
1057             hostname = (char *)VAL_STRING(ROW_VALUES(row) + 6);
1058             hostname_len = strlen(hostname);
1059         }
1060         if (hostname_len > MAX_HOST_LEN) {
1061             LM_ERR("lcr_gw hostname at row <%u> it too long\n", i);
1062             return 0;
1063         }
1064         if (VAL_NULL(ROW_VALUES(row) + 7)) {
1065             strip = 0;
1066         } else {
1067             if (VAL_TYPE(ROW_VALUES(row) + 7) != DB1_INT) {
1068                 LM_ERR("lcr_gw strip count at row <%u> is not int\n", i);
1069                 return 0;
1070             }
1071             strip = (unsigned int)VAL_INT(ROW_VALUES(row) + 7);
1072         }
1073         if (strip > MAX_USER_LEN) {
1074             LM_ERR("lcr_gw strip count <%u> at row <%u> it too large\n",
1075                    strip, i);
1076             return 0;
1077         }
1078         if (VAL_NULL(ROW_VALUES(row) + 8)) {
1079             prefix_len = 0;
1080             prefix = (char *)0;
1081         } else {
1082             if (VAL_TYPE(ROW_VALUES(row) + 8) != DB1_STRING) {
1083                 LM_ERR("lcr_gw prefix at row <%u> is not string\n", i);
1084                 return 0;
1085             }
1086             prefix = (char *)VAL_STRING(ROW_VALUES(row) + 8);
1087             prefix_len = strlen(prefix);
1088         }
1089         if (prefix_len > MAX_PREFIX_LEN) {
1090             LM_ERR("lcr_gw prefix at row <%u> it too long\n", i);
1091             return 0;
1092         }
1093         if (VAL_NULL(ROW_VALUES(row) + 9)) {
1094             tag_len = 0;
1095             tag = (char *)0;
1096         } else {
1097             if (VAL_TYPE(ROW_VALUES(row) + 9) != DB1_STRING) {
1098                 LM_ERR("lcr_gw tag at row <%u> is not string\n", i);
1099                 return 0;
1100             }
1101             tag = (char *)VAL_STRING(ROW_VALUES(row) + 9);
1102             tag_len = strlen(tag);
1103         }
1104         if (tag_len > MAX_TAG_LEN) {
1105             LM_ERR("lcr_gw tag at row <%u> it too long\n", i);
1106             return 0;
1107         }
1108         if (VAL_NULL(ROW_VALUES(row) + 10)) {
1109             flags = 0;
1110         } else {
1111             if (VAL_TYPE(ROW_VALUES(row) + 10) != DB1_INT) {
1112                 LM_ERR("lcr_gw flags at row <%u> is not int\n", i);
1113                 return 0;
1114             }
1115             flags = (unsigned int)VAL_INT(ROW_VALUES(row) + 10);
1116         }
1117         (*gw_cnt)++;
1118         if (!insert_gw(gws, *gw_cnt, gw_id, gw_name, gw_name_len,
1119                        scheme, &ip_addr, port,
1120                        transport, params, params_len, hostname,
1121                        hostname_len, ip_string.s, strip, prefix, prefix_len,
1122                        tag, tag_len, flags, defunct_until)) {
1123             return 0;
1124         }
1125     }
1126     return 1;
1127 }
1128
1129
1130 /*
1131  * Reload gws to unused gw table, rules to unused lcr hash table, and
1132  * prefix lens to a new prefix_len list.  When done, make these tables
1133  * and list the current ones.
1134  */
1135 int reload_tables()
1136 {
1137     unsigned int i, n, lcr_id, rule_id, gw_id, from_uri_len, request_uri_len,
1138         stopper, prefix_len, enabled, gw_cnt, null_gw_ip_addr, priority,
1139         weight, tmp;
1140     char *prefix, *from_uri, *request_uri;
1141     db1_res_t* res = NULL;
1142     db_row_t* row;
1143     db_key_t key_cols[1];
1144     db_op_t op[1];
1145     db_val_t vals[1];
1146     db_key_t gw_cols[13];
1147     db_key_t rule_cols[6];
1148     db_key_t target_cols[4];
1149     pcre *from_uri_re, *request_uri_re;
1150     struct gw_info *gws, *gw_pt_tmp;
1151     struct rule_info **rules, **rule_pt_tmp;
1152
1153     key_cols[0] = &lcr_id_col;
1154     op[0] = OP_EQ;
1155     VAL_TYPE(vals) = DB1_INT;
1156     VAL_NULL(vals) = 0;
1157
1158     rule_cols[0] = &id_col;
1159     rule_cols[1] = &prefix_col;
1160     rule_cols[2] = &from_uri_col;
1161     rule_cols[3] = &stopper_col;
1162     rule_cols[4] = &enabled_col;
1163     rule_cols[5] = &request_uri_col;
1164         
1165     gw_cols[0] = &gw_name_col;
1166     gw_cols[1] = &ip_addr_col;
1167     gw_cols[2] = &port_col;
1168     gw_cols[3] = &uri_scheme_col;
1169     gw_cols[4] = &transport_col;
1170     gw_cols[5] = &params_col;
1171     gw_cols[6] = &hostname_col;
1172     gw_cols[7] = &strip_col;
1173     gw_cols[8] = &prefix_col;
1174     gw_cols[9] = &tag_col;
1175     gw_cols[10] = &flags_col;
1176     gw_cols[11] = &defunct_col;
1177     gw_cols[12] = &id_col;
1178
1179     target_cols[0] = &rule_id_col;
1180     target_cols[1] = &gw_id_col;
1181     target_cols[2] = &priority_col;
1182     target_cols[3] = &weight_col;
1183
1184     request_uri_re = from_uri_re = 0;
1185
1186     if (lcr_db_init(&db_url) < 0) {
1187         LM_ERR("unable to open database connection\n");
1188         return -1;
1189     }
1190
1191     rule_id_hash_table = pkg_malloc(sizeof(struct rule_id_info *) *
1192                                     lcr_rule_hash_size_param);
1193     if (!rule_id_hash_table) {
1194         LM_ERR("no pkg memory for rule_id hash table\n");
1195         goto err;
1196     }
1197     memset(rule_id_hash_table, 0, sizeof(struct rule_id_info *) *
1198            lcr_rule_hash_size_param);
1199
1200     for (lcr_id = 1; lcr_id <= lcr_count_param; lcr_id++) {
1201
1202         /* Reload rules */
1203
1204         rules = rule_pt[0];
1205         rule_hash_table_contents_free(rules);
1206         rule_id_hash_table_contents_free();
1207         
1208         if (lcr_dbf.use_table(dbh, &lcr_rule_table) < 0) {
1209             LM_ERR("error while trying to use lcr_rule table\n");
1210             goto err;
1211         }
1212
1213         VAL_INT(vals) = lcr_id;
1214         if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
1215             if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, 0)
1216                 < 0) {
1217                 LM_ERR("db query on lcr_rule table failed\n");
1218                 goto err;
1219             }
1220             if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
1221                 LM_ERR("failed to fetch rows from lcr_rule table\n");
1222                 goto err;
1223             }
1224         } else {
1225             if (lcr_dbf.query(dbh, key_cols, op, vals, rule_cols, 1, 6, 0, &res)
1226                 < 0) {
1227                 LM_ERR("db query on lcr_rule table failed\n");
1228                 goto err;
1229             }
1230         }
1231
1232         n = 0;
1233         request_uri_re = from_uri_re = 0;
1234     
1235         do {
1236             LM_DBG("loading, cycle %d with <%d> rows", n++, RES_ROW_N(res));
1237             for (i = 0; i < RES_ROW_N(res); i++) {
1238
1239                 request_uri_re = from_uri_re = 0;
1240                 row = RES_ROWS(res) + i;
1241
1242                 if ((VAL_NULL(ROW_VALUES(row)) == 1) ||
1243                     (VAL_TYPE(ROW_VALUES(row)) != DB1_INT)) {
1244                     LM_ERR("lcr rule id at row <%u> is null or not int\n", i);
1245                     goto err;
1246                 }
1247                 rule_id = (unsigned int)VAL_INT(ROW_VALUES(row));
1248
1249                 enabled = (unsigned int)VAL_INT(ROW_VALUES(row) + 4);
1250                 if ((enabled != 0) && (enabled != 1)) {
1251                     LM_ERR("lcr rule <%u> enabled is not 0 or 1\n", rule_id);
1252                     goto err;
1253                 }
1254                 if (enabled == 0) {
1255                     LM_DBG("skipping disabled lcr rule <%u>\n", rule_id);
1256                     continue;
1257                 }
1258
1259                 if (VAL_NULL(ROW_VALUES(row) + 1) == 1) {
1260                     prefix_len = 0;
1261                     prefix = 0;
1262                 } else {
1263                     if (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_STRING) {
1264                         LM_ERR("lcr rule <%u> prefix is not string\n", rule_id);
1265                         goto err;
1266                     }
1267                     prefix = (char *)VAL_STRING(ROW_VALUES(row) + 1);
1268                     prefix_len = strlen(prefix);
1269                 }
1270                 if (prefix_len > MAX_PREFIX_LEN) {
1271                     LM_ERR("lcr rule <%u> prefix is too long\n", rule_id);
1272                     goto err;
1273                 }
1274
1275                 if ((VAL_NULL(ROW_VALUES(row) + 3) == 1) ||
1276                     (VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT)) {
1277                     LM_ERR("lcr rule <%u> stopper is NULL or not int\n",
1278                            rule_id);
1279                     goto err;
1280                 }
1281                 stopper = (unsigned int)VAL_INT(ROW_VALUES(row) + 3);
1282                 if ((stopper != 0) && (stopper != 1)) {
1283                     LM_ERR("lcr rule <%u> stopper is not 0 or 1\n", rule_id);
1284                     goto err;
1285                 }
1286
1287                 if ((VAL_NULL(ROW_VALUES(row) + 4) == 1) ||
1288                     (VAL_TYPE(ROW_VALUES(row) + 4) != DB1_INT)) {
1289                     LM_ERR("lcr rule <%u> enabled is NULL or not int\n",
1290                            rule_id);
1291                     goto err;
1292                 }
1293
1294                 if (VAL_NULL(ROW_VALUES(row) + 2) == 1) {
1295                     from_uri_len = 0;
1296                     from_uri = 0;
1297                 } else {
1298                     if (VAL_TYPE(ROW_VALUES(row) + 2) != DB1_STRING) {
1299                         LM_ERR("lcr rule <%u> from_uri is not string\n",
1300                                rule_id);
1301                         goto err;
1302                     }
1303                     from_uri = (char *)VAL_STRING(ROW_VALUES(row) + 2);
1304                     from_uri_len = strlen(from_uri);
1305                 }
1306                 if (from_uri_len > MAX_URI_LEN) {
1307                     LM_ERR("lcr rule <%u> from_uri is too long\n", rule_id);
1308                     goto err;
1309                 }
1310                 if (from_uri_len > 0) {
1311                     from_uri_re = reg_ex_comp(from_uri);
1312                     if (from_uri_re == 0) {
1313                         LM_ERR("failed to compile lcr rule <%u> from_uri "
1314                                "<%s>\n", rule_id, from_uri);
1315                         goto err;
1316                     }
1317                 } else {
1318                     from_uri_re = 0;
1319                 }
1320
1321                 if (VAL_NULL(ROW_VALUES(row) + 5) == 1) {
1322                     request_uri_len = 0;
1323                     request_uri = 0;
1324                 } else {
1325                     if (VAL_TYPE(ROW_VALUES(row) + 5) != DB1_STRING) {
1326                         LM_ERR("lcr rule <%u> request_uri is not string\n",
1327                                rule_id);
1328                         goto err;
1329                     }
1330                     request_uri = (char *)VAL_STRING(ROW_VALUES(row) + 5);
1331                     request_uri_len = strlen(request_uri);
1332                 }
1333                 if (request_uri_len > MAX_URI_LEN) {
1334                     LM_ERR("lcr rule <%u> request_uri is too long\n", rule_id);
1335                     goto err;
1336                 }
1337                 if (request_uri_len > 0) {
1338                     request_uri_re = reg_ex_comp(request_uri);
1339                     if (request_uri_re == 0) {
1340                         LM_ERR("failed to compile lcr rule <%u> request_uri "
1341                                "<%s>\n", rule_id, request_uri);
1342                         goto err;
1343                     }
1344                 } else {
1345                     request_uri_re = 0;
1346                 }
1347
1348                 if (!rule_hash_table_insert(rules, lcr_id, rule_id, prefix_len,
1349                                             prefix, from_uri_len, from_uri,
1350                                             from_uri_re, request_uri_len,
1351                                             request_uri, request_uri_re, stopper) ||
1352                     !prefix_len_insert(rules, prefix_len)) {
1353                     goto err;
1354                 }
1355             }
1356
1357             if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
1358                 if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
1359                     LM_ERR("fetching of rows from lcr_rule table failed\n");
1360                     goto err;
1361                 }
1362             } else {
1363                 break;
1364             }
1365
1366         } while (RES_ROW_N(res) > 0);
1367
1368         lcr_dbf.free_result(dbh, res);
1369         res = NULL;
1370
1371         /* Reload gws */
1372
1373         gws = gw_pt[0];
1374
1375         if (lcr_dbf.use_table(dbh, &lcr_gw_table) < 0) {
1376             LM_ERR("error while trying to use lcr_gw table\n");
1377             goto err;
1378         }
1379
1380         VAL_INT(vals) = lcr_id;
1381         if (lcr_dbf.query(dbh, key_cols, op, vals, gw_cols, 1, 13, 0, &res)
1382             < 0) {
1383             LM_ERR("failed to query gw data\n");
1384             goto err;
1385         }
1386
1387         if (RES_ROW_N(res) + 1 > lcr_gw_count_param) {
1388             LM_ERR("too many gateways\n");
1389             goto err;
1390         }
1391
1392         null_gw_ip_addr = gw_cnt = 0;
1393
1394         if (!insert_gws(res, gws, &null_gw_ip_addr, &gw_cnt)) goto err;
1395
1396         lcr_dbf.free_result(dbh, res);
1397         res = NULL;
1398
1399         VAL_INT(vals) = 0;
1400         if (lcr_dbf.query(dbh, key_cols, op, vals, gw_cols, 1, 13, 0, &res)
1401             < 0) {
1402             LM_ERR("failed to query gw data\n");
1403             goto err;
1404         }
1405
1406         if (RES_ROW_N(res) + 1 + gw_cnt > lcr_gw_count_param) {
1407             LM_ERR("too many gateways\n");
1408             goto err;
1409         }
1410
1411         if (!insert_gws(res, gws, &null_gw_ip_addr, &gw_cnt)) goto err;
1412
1413         lcr_dbf.free_result(dbh, res);
1414         res = NULL;
1415
1416         qsort(&(gws[1]), gw_cnt, sizeof(struct gw_info), comp_gws);
1417         gws[0].ip_addr.u.addr32[0] = gw_cnt;
1418         gws[0].port = null_gw_ip_addr;
1419
1420         /* Reload targets */
1421
1422         if (lcr_dbf.use_table(dbh, &lcr_rule_target_table) < 0) {
1423             LM_ERR("error while trying to use lcr_rule_target table\n");
1424             goto err;
1425         }
1426
1427         VAL_INT(vals) = lcr_id;
1428         if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
1429             if (lcr_dbf.query(dbh, key_cols, op, vals, target_cols, 1, 4, 0, 0)
1430                 < 0) {
1431                 LM_ERR("db query on lcr_rule_target table failed\n");
1432                 goto err;
1433             }
1434             if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
1435                 LM_ERR("failed to fetch rows from lcr_rule_target table\n");
1436                 goto err;
1437             }
1438         } else {
1439             if (lcr_dbf.query(dbh, key_cols, op, vals, target_cols, 1, 4, 0,
1440                               &res) < 0) {
1441                 LM_ERR("db query on lcr_rule_target table failed\n");
1442                 goto err;
1443             }
1444         }
1445
1446         n = 0;
1447         do {
1448             LM_DBG("loading, cycle %d with <%d> rows", n++, RES_ROW_N(res));
1449             for (i = 0; i < RES_ROW_N(res); i++) {
1450                 row = RES_ROWS(res) + i;
1451                 if ((VAL_NULL(ROW_VALUES(row)) == 1) ||
1452                     (VAL_TYPE(ROW_VALUES(row)) != DB1_INT)) {
1453                     LM_ERR("lcr_rule_target rule_id at row <%u> is null "
1454                            "or not int\n", i);
1455                     goto err;
1456                 }
1457                 rule_id = (unsigned int)VAL_INT(ROW_VALUES(row));
1458                 if ((VAL_NULL(ROW_VALUES(row) + 1) == 1) ||
1459                     (VAL_TYPE(ROW_VALUES(row) + 1) != DB1_INT)) {
1460                     LM_ERR("lcr_rule_target gw_id at row <%u> is null "
1461                            "or not int\n", i);
1462                     goto err;
1463                 }
1464                 gw_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 1);
1465                 if ((VAL_NULL(ROW_VALUES(row) + 2) == 1) ||
1466                     (VAL_TYPE(ROW_VALUES(row) + 2) != DB1_INT)) {
1467                     LM_ERR("lcr_rule_target priority at row <%u> is null "
1468                            "or not int\n", i);
1469                     goto err;
1470                 }
1471                 priority = (unsigned int)VAL_INT(ROW_VALUES(row) + 2);
1472                 if (priority > 255) {
1473                     LM_ERR("lcr_rule_target priority value at row <%u> is "
1474                            "not 0-255\n", i);
1475                     goto err;
1476                 }
1477                 if ((VAL_NULL(ROW_VALUES(row) + 3) == 1) ||
1478                     (VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT)) {
1479                     LM_ERR("lcr_rule_target weight at row <%u> is null "
1480                            "or not int\n", i);
1481                     goto err;
1482                 }
1483                 weight = (unsigned int)VAL_INT(ROW_VALUES(row) + 3);
1484                 if ((weight < 1) || (weight > 254)) {
1485                     LM_ERR("lcr_rule_target weight value at row <%u> is "
1486                            "not 1-254\n", i);
1487                     goto err;
1488                 }
1489                 tmp = rule_hash_table_insert_target(rules, gws, rule_id, gw_id,
1490                                                     priority, weight);
1491                 if (tmp == 2) {
1492                     LM_INFO("skipping disabled <gw/rule> = <%u/%u>\n",
1493                             gw_id, rule_id);
1494                 } else if (tmp != 1) {
1495                     LM_ERR("could not insert target to rule <%u>\n", rule_id);
1496                     goto err;
1497                 }
1498             }
1499             if (DB_CAPABILITY(lcr_dbf, DB_CAP_FETCH)) {
1500                 if (lcr_dbf.fetch_result(dbh, &res, fetch_rows_param) < 0) {
1501                     LM_ERR("fetching of rows from lcr_rule_target table "
1502                            "failed\n");
1503                     goto err;
1504                 }
1505             } else {
1506                 break;
1507             }
1508         } while (RES_ROW_N(res) > 0);
1509
1510         lcr_dbf.free_result(dbh, res);
1511         res = NULL;
1512
1513         /* swap tables */
1514         rule_pt_tmp = rule_pt[lcr_id];
1515         gw_pt_tmp = gw_pt[lcr_id];
1516         rule_pt[lcr_id] = rules;
1517         gw_pt[lcr_id] = gws;
1518         rule_pt[0] = rule_pt_tmp;
1519         gw_pt[0] = gw_pt_tmp;
1520     }
1521
1522     lcr_db_close();
1523     rule_id_hash_table_contents_free();
1524     if (rule_id_hash_table) pkg_free(rule_id_hash_table);
1525     return 1;
1526
1527  err:
1528     lcr_dbf.free_result(dbh, res);
1529     lcr_db_close();
1530     rule_id_hash_table_contents_free();
1531     if (rule_id_hash_table) pkg_free(rule_id_hash_table);
1532     return -1;
1533 }
1534
1535
1536 inline int encode_avp_value(char *value, unsigned int gw_index, uri_type scheme,
1537                             unsigned int strip,
1538                             char *prefix, unsigned int prefix_len,
1539                             char *tag, unsigned int tag_len,
1540                             struct ip_addr *ip_addr, char *hostname, 
1541                             unsigned int hostname_len, unsigned int port,
1542                             char *params, unsigned int params_len,
1543                             uri_transport transport, unsigned int flags)
1544 {
1545     char *at, *string;
1546     int len;
1547
1548     at = value;
1549
1550     /* gw index */
1551     string = int2str(gw_index, &len);
1552     append_str(at, string, len);
1553     append_chr(at, '|');
1554     /* scheme */
1555     string = int2str(scheme, &len);
1556     append_str(at, string, len);
1557     append_chr(at, '|');
1558     /* strip */
1559     string = int2str(strip, &len);
1560     append_str(at, string, len);
1561     append_chr(at, '|');
1562     /* prefix */
1563     append_str(at, prefix, prefix_len);
1564     append_chr(at, '|');
1565     /* tag */
1566     append_str(at, tag, tag_len);
1567     append_chr(at, '|');
1568     /* ip_addr */
1569     if (ip_addr->af == AF_INET && ip_addr->u.addr32[0] > 0) {
1570         string = int2str(ip_addr->u.addr32[0], &len);
1571         append_str(at, string, len);
1572     }
1573 #ifdef USE_IPV6
1574     else if (ip_addr->af == AF_INET6 && !ip_addr_any(ip_addr)) {
1575         append_chr(at, '[');
1576         at += ip6tosbuf(ip_addr->u.addr, at, MAX_URI_LEN - (at - value));
1577         append_chr(at, ']');
1578     }
1579 #endif
1580     append_chr(at, '|');
1581     /* hostname */
1582     append_str(at, hostname, hostname_len);
1583     append_chr(at, '|');
1584     /* port */
1585     if (port > 0) {
1586         string = int2str(port, &len);
1587         append_str(at, string, len);
1588     }
1589     append_chr(at, '|');
1590     /* params */
1591     append_str(at, params, params_len);
1592     append_chr(at, '|');
1593     /* transport */
1594     string = int2str(transport, &len);
1595     append_str(at, string, len);
1596     append_chr(at, '|');
1597     /* flags */
1598     string = int2str(flags, &len);
1599     append_str(at, string, len);
1600     return at - value;
1601 }
1602
1603 inline int decode_avp_value(char *value, unsigned int *gw_index, str *scheme,
1604                             unsigned int *strip, str *prefix, str *tag,
1605                             struct ip_addr *addr, str *hostname, str *port,
1606                             str *params, str *transport, unsigned int *flags)
1607 {
1608     unsigned int u;
1609     str s;
1610     char *sep;
1611     struct ip_addr *ip;
1612
1613     /* gw index */
1614     s.s = value;
1615     sep = index(s.s, '|');
1616     if (sep == NULL) {
1617         LM_ERR("index was not found in AVP value\n");
1618         return 0;
1619     }
1620     s.len = sep - s.s;
1621     str2int(&s, gw_index);
1622     /* scheme */
1623     s.s = sep + 1;
1624     sep = index(s.s, '|');
1625     if (sep == NULL) {
1626         LM_ERR("scheme was not found in AVP value\n");
1627         return 0;
1628     }
1629     s.len = sep - s.s;
1630     str2int(&s, &u);
1631     if (u == SIP_URI_T) {
1632         scheme->s = "sip:";
1633         scheme->len = 4;
1634     } else {
1635         scheme->s = "sips:";
1636         scheme->len = 5;
1637     }
1638     /* strip */
1639     s.s = sep + 1;
1640     sep = index(s.s, '|');
1641     if (sep == NULL) {
1642         LM_ERR("strip was not found in AVP value\n");
1643         return 0;
1644     }
1645     s.len = sep - s.s;
1646     str2int(&s, strip);
1647     /* prefix */
1648     prefix->s = sep + 1;
1649     sep = index(prefix->s, '|');
1650     if (sep == NULL) {
1651         LM_ERR("prefix was not found in AVP value\n");
1652         return 0;
1653     }
1654     prefix->len = sep - prefix->s;
1655     /* tag */
1656     tag->s = sep + 1;
1657     sep = index(tag->s, '|');
1658     if (sep == NULL) {
1659         LM_ERR("tag was not found in AVP value\n");
1660         return 0;
1661     }
1662     tag->len = sep - tag->s;
1663     /* addr */
1664     s.s = sep + 1;
1665     sep = index(s.s, '|');
1666     if (sep == NULL) {
1667         LM_ERR("ip_addr was not found in AVP value\n");
1668         return 0;
1669     }
1670     s.len = sep - s.s;
1671     if (s.len > 0) {
1672         if ((ip = str2ip(&s)) != NULL)
1673             *addr = *ip;
1674 #ifdef USE_IPV6
1675         else if ((ip = str2ip6(&s)) != NULL)
1676             *addr = *ip;
1677 #endif
1678         else {
1679             str2int(&s, &u);
1680             addr->af = AF_INET;
1681             addr->len = 4;
1682             addr->u.addr32[0] = u;
1683         }
1684     } else {
1685         addr->af = 0;
1686     }
1687     /* hostname */
1688     hostname->s = sep + 1;
1689     sep = index(hostname->s, '|');
1690     if (sep == NULL) {
1691         LM_ERR("hostname was not found in AVP value\n");
1692         return 0;
1693     }
1694     hostname->len = sep - hostname->s;
1695     /* port */
1696     port->s = sep + 1;
1697     sep = index(port->s, '|');
1698     if (sep == NULL) {
1699         LM_ERR("scheme was not found in AVP value\n");
1700         return 0;
1701     }
1702     port->len = sep - port->s;
1703     /* params */
1704     params->s = sep + 1;
1705     sep = index(params->s, '|');
1706     if (sep == NULL) {
1707         LM_ERR("params was not found in AVP value\n");
1708         return 0;
1709     }
1710     params->len = sep - params->s;
1711     /* transport */
1712     s.s = sep + 1;
1713     sep = index(s.s, '|');
1714     if (sep == NULL) {
1715         LM_ERR("transport was not found in AVP value\n");
1716         return 0;
1717     }
1718     s.len = sep - s.s;
1719     str2int(&s, &u);
1720     switch (u) {
1721     case PROTO_NONE:
1722         transport->s = (char *)0;
1723         transport->len = 0;
1724         break;
1725     case PROTO_UDP:
1726         transport->s = ";transport=udp";
1727         transport->len = 14;
1728         break;
1729     case PROTO_TCP:
1730         transport->s = ";transport=tcp";
1731         transport->len = 14;
1732         break;
1733     case PROTO_TLS:
1734         transport->s = ";transport=tls";
1735         transport->len = 14;
1736         break;
1737     case PROTO_SCTP:
1738         transport->s = ";transport=sctp";
1739         transport->len = 15;
1740         break;
1741     default:
1742         LM_ERR("unknown transport '%d'\n", u);
1743         return 0;
1744     }
1745     /* flags */
1746     s.s = sep + 1;
1747     s.len = strlen(s.s);
1748     str2int(&s, flags);
1749
1750     return 1;
1751 }
1752     
1753
1754 /* Add gateways in matched_gws array into gw_uri_avps */
1755 void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
1756                        unsigned int gw_cnt, str *ruri_user)
1757 {
1758     unsigned int i, index, strip, hostname_len, params_len;
1759     int prefix_len, tag_len;
1760     str value;
1761     char encoded_value[MAX_URI_LEN];
1762     int_str val;
1763
1764     delete_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp);
1765
1766     for (i = 0; i < gw_cnt; i++) {
1767         if (matched_gws[i].duplicate == 1) continue;
1768         index = matched_gws[i].gw_index;
1769         hostname_len = gws[index].hostname_len;
1770         params_len = gws[index].params_len;
1771         strip = gws[index].strip;
1772         if (strip > ruri_user->len) {
1773             LM_ERR("strip count of gw is too large <%u>\n", strip);
1774             goto skip;
1775         }
1776         prefix_len = gws[index].prefix_len;
1777         tag_len = gws[index].tag_len;
1778         if (5 /* gw_index */ + 5 /* scheme */ + 4 /* strip */ + prefix_len +
1779             tag_len + 1 /* @ */ +
1780             ((hostname_len > IP6_MAX_STR_SIZE+2)?hostname_len:IP6_MAX_STR_SIZE+2) + 6 /* port */ +
1781             params_len /* params */ + 15 /* transport */ + 10 /* flags */ +
1782             7 /* separators */ > MAX_URI_LEN) {
1783             LM_ERR("too long AVP value\n");
1784             goto skip;
1785         }
1786         value.len = 
1787             encode_avp_value(encoded_value, index, gws[index].scheme,
1788                              strip, gws[index].prefix, prefix_len,
1789                              gws[index].tag, tag_len,
1790                              &gws[index].ip_addr,
1791                              gws[index].hostname, hostname_len,
1792                              gws[index].port, gws[index].params, params_len,
1793                              gws[index].transport, gws[index].flags);
1794         value.s = (char *)&(encoded_value[0]);
1795         val.s = value;
1796         add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val);
1797
1798         LM_DBG("added gw_uri_avp <%.*s> with weight <%u>\n",
1799                value.len, value.s, matched_gws[i].weight);
1800     skip:
1801         continue;
1802     }
1803 }
1804
1805
1806 /*
1807  * Load info of matching GWs into gw_uri_avps
1808  */
1809 static int load_gws(struct sip_msg* _m, int argc, action_u_t argv[])
1810 {
1811     str ruri_user, from_uri, *request_uri;
1812     int i, j, lcr_id;
1813     unsigned int gw_index, now, dex;
1814     int_str val;
1815     struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1];
1816     struct rule_info **rules, *rule, *pl;
1817     struct gw_info *gws;
1818     struct target *t;
1819     char* tmp;
1820
1821     /* Get and check parameter values */
1822     if (argc < 1) {
1823         LM_ERR("lcr_id parameter is missing\n");
1824         return -1;
1825     }
1826     lcr_id = strtol(argv[0].u.string, &tmp, 10);
1827     if ((tmp == 0) || (*tmp) || (tmp == argv[0].u.string)) {
1828         LM_ERR("invalid lcr_id parameter %s\n", argv[0].u.string);
1829         return -1;
1830     }
1831     if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
1832         LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
1833         return -1;
1834     }
1835     if (argc > 1) {
1836         ruri_user = argv[1].u.str;
1837     } else {
1838         if ((parse_sip_msg_uri(_m) < 0) || (!_m->parsed_uri.user.s)) {
1839             LM_ERR("error while parsing R-URI\n");
1840             return -1;
1841         }
1842         ruri_user = _m->parsed_uri.user;
1843     }
1844     if (argc > 2) {
1845         from_uri = argv[2].u.str;
1846     } else {
1847         from_uri.len = 0;
1848         from_uri.s = (char *)0;
1849     }
1850     if (argc > 3) {
1851         LM_ERR("too many parameters\n");
1852         return -1;
1853     }
1854     LM_DBG("load_gws(%u, %.*s, %.*s)\n", lcr_id, ruri_user.len, ruri_user.s,
1855            from_uri.len, from_uri.s);
1856
1857     request_uri = GET_RURI(_m);
1858
1859     /* Use rules and gws with index lcr_id */
1860     rules = rule_pt[lcr_id];
1861     gws = gw_pt[lcr_id];
1862
1863     /*
1864      * Find lcr entries that match based on prefix and from_uri and collect
1865      * gateways of matching entries into matched_gws array so that each
1866      * gateway appears in the array only once.
1867      */
1868
1869     pl = rules[lcr_rule_hash_size_param];
1870     gw_index = 0;
1871
1872     if (defunct_capability_param > 0) {
1873         delete_avp(defunct_gw_avp_type, defunct_gw_avp);
1874     }
1875
1876     now = time((time_t *)NULL);
1877
1878     /* check prefixes in from longest to shortest */
1879     while (pl) {
1880         if (ruri_user.len < pl->prefix_len) {
1881             pl = pl->next;
1882             continue;
1883         }
1884         rule = rule_hash_table_lookup(rules, pl->prefix_len, ruri_user.s);
1885         while (rule) {
1886             /* Match prefix */
1887             if ((rule->prefix_len != pl->prefix_len) ||
1888                 (strncmp(rule->prefix, ruri_user.s, pl->prefix_len)))
1889                     goto next;
1890
1891             /* Match from uri */
1892             if ((rule->from_uri_len != 0) &&
1893                 (pcre_exec(rule->from_uri_re, NULL, from_uri.s,
1894                            from_uri.len, 0, 0, NULL, 0) < 0)) {
1895                 LM_DBG("from uri <%.*s> did not match to from regex <%.*s>",
1896                        from_uri.len, from_uri.s, rule->from_uri_len,
1897                        rule->from_uri);
1898                 goto next;
1899             }
1900
1901             /* Match request uri */
1902             if ((rule->request_uri_len != 0) &&
1903                 (pcre_exec(rule->request_uri_re, NULL, request_uri->s,
1904                            request_uri->len, 0, 0, NULL, 0) < 0)) {
1905                 LM_DBG("request uri <%.*s> did not match to request regex <%.*s>",
1906                        request_uri->len, request_uri->s, rule->request_uri_len,
1907                        rule->request_uri);
1908                 goto next;
1909             }
1910
1911             /* Load gws associated with this rule */
1912             t = rule->targets;
1913             while (t) {
1914                 /* If this gw is defunct, skip it */
1915                 if (gws[t->gw_index].defunct_until > now) goto skip_gw;
1916                 matched_gws[gw_index].gw_index = t->gw_index;
1917                 matched_gws[gw_index].prefix_len = pl->prefix_len;
1918                 matched_gws[gw_index].priority = t->priority;
1919                 matched_gws[gw_index].weight = t->weight *
1920                     (rand() >> 8);
1921                 matched_gws[gw_index].duplicate = 0;
1922                 LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n",
1923                        gw_index, t->gw_index, pl->prefix_len,
1924                        t->priority, matched_gws[gw_index].weight);
1925                 gw_index++;
1926             skip_gw:
1927                 t = t->next;
1928             }
1929             /* Do not look further if this matching rule was stopper */
1930             if (rule->stopper == 1) goto done;
1931
1932 next:
1933             rule = rule->next;
1934         }
1935         pl = pl->next;
1936     }
1937
1938  done:
1939     /* Sort gateways in reverse order based on prefix_len, priority,
1940        and randomized weight */
1941     qsort(matched_gws, gw_index, sizeof(struct matched_gw_info), comp_matched);
1942
1943     /* Remove duplicate gws */
1944     for (i = gw_index - 1; i >= 0; i--) {
1945         if (matched_gws[i].duplicate == 1) continue;
1946         dex = matched_gws[i].gw_index;
1947         for (j = i - 1; j >= 0; j--) {
1948             if (matched_gws[j].gw_index == dex) {
1949                 matched_gws[j].duplicate = 1;
1950             }
1951         }
1952     }
1953
1954     /* Add gateways into gw_uris_avp */
1955     add_gws_into_avps(gws, matched_gws, gw_index, &ruri_user);
1956
1957     /* Add lcr_id into AVP */
1958     if (defunct_capability_param > 0) {
1959         delete_avp(lcr_id_avp_type, lcr_id_avp);
1960         val.n = lcr_id;
1961         add_avp(lcr_id_avp_type, lcr_id_avp, val);
1962     }
1963     
1964     if (gw_index > 0) {
1965         return 1;
1966     } else {
1967         return 2;
1968     }
1969 }
1970
1971
1972 /* Generate Request-URI and Destination URI */
1973 static int generate_uris(struct sip_msg* _m, char *r_uri, str *r_uri_user,
1974                          unsigned int *r_uri_len, char *dst_uri,
1975                          unsigned int *dst_uri_len, struct ip_addr *addr,
1976                          unsigned int *gw_index, unsigned int *flags,
1977                          str *tag)
1978 {
1979     int_str gw_uri_val;
1980     struct usr_avp *gu_avp;
1981     str scheme, prefix, hostname, port, params, transport, addr_str,
1982         tmp_tag;
1983     char *at;
1984     unsigned int strip;
1985     
1986     gu_avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &gw_uri_val, 0);
1987
1988     if (!gu_avp) return 0; /* No more gateways left */
1989
1990     decode_avp_value(gw_uri_val.s.s, gw_index, &scheme, &strip, &prefix,
1991                      &tmp_tag, addr, &hostname, &port, &params, &transport,
1992                      flags);
1993
1994     if (addr->af != 0) {
1995         addr_str.s = ip_addr2a(addr);
1996         addr_str.len = strlen(addr_str.s);
1997     } else {
1998         addr_str.len = 0;
1999     }
2000     
2001     if (scheme.len + r_uri_user->len - strip + prefix.len + 1 /* @ */ +
2002         ((hostname.len > IP6_MAX_STR_SIZE+2)?hostname.len:IP6_MAX_STR_SIZE+2) + 1 /* : */ +
2003         port.len + params.len + transport.len + 1 /* null */ > MAX_URI_LEN) {
2004         LM_ERR("too long Request URI or DST URI\n");
2005         return -1;
2006     }
2007
2008     if ((dont_strip_or_prefix_flag_param != -1) &&
2009         isflagset(_m, dont_strip_or_prefix_flag_param)) {
2010         strip = 0;
2011         prefix.len = 0;
2012     }
2013
2014     at = r_uri;
2015     
2016     append_str(at, scheme.s, scheme.len);
2017     append_str(at, prefix.s, prefix.len);
2018     if (strip > r_uri_user->len) {
2019         LM_ERR("strip count <%u> is larger than R-URI user <%.*s>\n",
2020                strip, r_uri_user->len, r_uri_user->s);
2021         return -1;
2022     }
2023     append_str(at, r_uri_user->s + strip, r_uri_user->len - strip);
2024
2025     append_chr(at, '@');
2026
2027     if ((addr_str.len > 0) && (hostname.len > 0)) {
2028         /* both ip_addr and hostname specified:
2029            place hostname in r-uri and ip_addr in dst-uri */
2030         append_str(at, hostname.s, hostname.len);
2031         if (params.len > 0) {
2032             append_str(at, params.s, params.len);
2033         }
2034         *at = '\0';
2035         *r_uri_len = at - r_uri;
2036         at = dst_uri;
2037         append_str(at, scheme.s, scheme.len);
2038         if (addr->af == AF_INET6)
2039             append_chr(at, '[');
2040         append_str(at, addr_str.s, addr_str.len);
2041         if (addr->af == AF_INET6)
2042             append_chr(at, ']');
2043         if (port.len > 0) {
2044             append_chr(at, ':');
2045             append_str(at, port.s, port.len);
2046         }
2047         if (transport.len > 0) {
2048             append_str(at, transport.s, transport.len);
2049         }
2050         *at = '\0';
2051         *dst_uri_len = at - dst_uri;
2052     } else {
2053         /* either ip_addr or hostname specified:
2054            place the given one in r-uri and leave dst-uri empty */
2055         if (addr_str.len > 0) {
2056             if (addr->af == AF_INET6)
2057                 append_chr(at, '[');
2058             append_str(at, addr_str.s, addr_str.len);
2059             if (addr->af == AF_INET6)
2060                 append_chr(at, ']');
2061         } else {
2062             append_str(at, hostname.s, hostname.len);
2063         }
2064         if (port.len > 0) {
2065             append_chr(at, ':');
2066             append_str(at, port.s, port.len);
2067         }
2068         if (transport.len > 0) {
2069             append_str(at, transport.s, transport.len);
2070         }
2071         if (params.len > 0) {
2072             append_str(at, params.s, params.len);
2073         }
2074         *at = '\0';
2075         *r_uri_len = at - r_uri;
2076         *dst_uri_len = 0;
2077     }
2078
2079     memcpy(tag->s, tmp_tag.s, tmp_tag.len);
2080     tag->len = tmp_tag.len;
2081
2082     destroy_avp(gu_avp);
2083         
2084     LM_DBG("r_uri <%.*s>, dst_uri <%.*s>\n",
2085            (int)*r_uri_len, r_uri, (int)*dst_uri_len, dst_uri);
2086
2087     return 1;
2088 }
2089
2090
2091 /*
2092  * Defunct current gw until time given as argument has passed.
2093  */
2094 static int defunct_gw(struct sip_msg* _m, char *_defunct_period, char *_s2)
2095 {
2096     int_str lcr_id_val, index_val;
2097     struct gw_info *gws;
2098     char *tmp;
2099     unsigned int gw_index, defunct_until;
2100     int defunct_period;
2101
2102     /* Check defunct gw capability */
2103     if (defunct_capability_param == 0) {
2104         LM_ERR("no defunct gw capability, activate by setting "
2105                "defunct_capability_param module param\n");
2106         return -1;
2107     }
2108
2109     /* Get parameter value */
2110
2111     /* Get and check parameter value */
2112     defunct_period = strtol(_defunct_period, &tmp, 10);
2113     if ((tmp == 0) || (*tmp) || (tmp == _defunct_period)) {
2114         LM_ERR("invalid defunct_period parameter %s\n", _defunct_period);
2115         return -1;
2116     }
2117     if (defunct_period < 1) {
2118         LM_ERR("invalid defunct_period param value %d\n", defunct_period);
2119         return -1;
2120     }
2121
2122     /* Get AVP values */
2123     if (search_first_avp(lcr_id_avp_type, lcr_id_avp, &lcr_id_val, 0)
2124         == NULL) {
2125         LM_ERR("lcr_id_avp was not found\n");
2126         return -1;
2127     }
2128     gws = gw_pt[lcr_id_val.n];
2129     if (search_first_avp(defunct_gw_avp_type, defunct_gw_avp,
2130                          &index_val, 0) == NULL) {
2131         LM_ERR("defucnt_gw_avp was not found\n");
2132         return -1;
2133     }
2134     gw_index = index_val.n;
2135     if ((gw_index < 1) || (gw_index > gws[0].ip_addr.u.addr32[0])) {
2136         LM_ERR("gw index <%u> is out of bounds\n", gw_index);
2137         return -1;
2138     }
2139     
2140     /* Defunct gw */
2141     defunct_until = time((time_t *)NULL) + defunct_period;
2142     LM_DBG("defuncting gw with name <%.*s> until <%u>\n",
2143            gws[gw_index].gw_name_len, gws[gw_index].gw_name, defunct_until);
2144     gws[gw_index].defunct_until = defunct_until;
2145     return 1;
2146 }    
2147
2148
2149 /*
2150  * Defunct given gw in given lcr until time period given as argument has passed.
2151  */
2152 int rpc_defunct_gw(unsigned int lcr_id, unsigned int gw_id, unsigned int period)
2153 {
2154     struct gw_info *gws;
2155     unsigned int until, i;
2156
2157     if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
2158         LM_ERR("invalid lcr_id value <%u>\n", lcr_id);
2159         return 0;
2160     }
2161
2162     until = time((time_t *)NULL) + period;
2163
2164     LM_DBG("defuncting gw <lcr_id/gw_id>=<%u/%u> for %u seconds until %d\n",
2165            lcr_id, gw_id, period, until);
2166
2167     gws = gw_pt[lcr_id];
2168     for (i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) {
2169         if (gws[i].gw_id == gw_id) {
2170             gws[i].defunct_until = until;
2171             return 1;
2172         }
2173     }
2174     
2175     LM_ERR("gateway with id <%u> not found\n", gw_id);
2176
2177     return 0;
2178 }
2179
2180
2181 /*
2182  * When called first time, rewrites scheme, host, port, and
2183  * transport parts of R-URI based on first gw_uri_avp value, which is then
2184  * destroyed.  Saves R-URI user to ruri_user_avp for later use.
2185  *
2186  * On other calls, rewrites R-URI, where scheme, host, port,
2187  * and transport of URI are taken from the first gw_uri_avp value, 
2188  * which is then destroyed. URI user is taken either from ruri_user_avp
2189  * value saved earlier.
2190  *
2191  * Returns 1 upon success and -1 upon failure.
2192  */
2193 static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
2194 {
2195     int_str ruri_user_val, val;
2196     struct usr_avp *ru_avp;
2197     int rval;
2198     str uri_str, tag_str;
2199     char tag[MAX_TAG_LEN];
2200     unsigned int flags, r_uri_len, dst_uri_len, gw_index;
2201     char r_uri[MAX_URI_LEN], dst_uri[MAX_URI_LEN];
2202     struct ip_addr addr;
2203
2204     tag_str.s = &(tag[0]);
2205
2206     ru_avp = search_first_avp(ruri_user_avp_type, ruri_user_avp,
2207                               &ruri_user_val, 0);
2208
2209     if (ru_avp == NULL) {
2210         
2211         /* First invocation either in route or failure route block.
2212          * Take Request-URI user from Request-URI and generate Request
2213          * and Destination URIs. */
2214
2215         if (parse_sip_msg_uri(_m) < 0) {
2216             LM_ERR("parsing of R-URI failed\n");
2217             return -1;
2218         }
2219         if (!generate_uris(_m, r_uri, &(_m->parsed_uri.user), &r_uri_len,
2220                            dst_uri, &dst_uri_len, &addr, &gw_index, &flags,
2221                            &tag_str)) {
2222             return -1;
2223         }
2224
2225         /* Save Request-URI user into uri_user_avp for use in subsequent
2226          * invocations. */
2227
2228         val.s = _m->parsed_uri.user;
2229         add_avp(ruri_user_avp_type|AVP_VAL_STR, ruri_user_avp, val);
2230         LM_DBG("added ruri_user_avp <%.*s>\n", val.s.len, val.s.s);
2231
2232     } else {
2233
2234         /* Subsequent invocation either in route or failure route block.
2235          * Take Request-URI user from ruri_user_avp and generate Request
2236          * and Destination URIs. */
2237
2238         if (!generate_uris(_m, r_uri, &(ruri_user_val.s), &r_uri_len, dst_uri,
2239                            &dst_uri_len, &addr, &gw_index, &flags, &tag_str)) {
2240             return -1;
2241         }
2242     }
2243
2244     /* Rewrite Request URI */
2245     uri_str.s = r_uri;
2246     uri_str.len = r_uri_len;
2247     rewrite_uri(_m, &uri_str);
2248     
2249     /* Set Destination URI if not empty */
2250     if (dst_uri_len > 0) {
2251         uri_str.s = dst_uri;
2252         uri_str.len = dst_uri_len;
2253         LM_DBG("setting du to <%.*s>\n", uri_str.len, uri_str.s);
2254         rval = set_dst_uri(_m, &uri_str);
2255         if (rval != 0) {
2256             LM_ERR("calling do_action failed with return value <%d>\n", rval);
2257             return -1;
2258         }
2259         
2260     }
2261
2262     /* Set flags_avp */
2263     if (flags_avp_param) {
2264         val.n = flags;
2265         add_avp(flags_avp_type, flags_avp, val);
2266         LM_DBG("added flags_avp <%u>\n", (unsigned int)val.n);
2267     }
2268
2269     /* Set tag_avp */
2270     if (tag_avp_param) {
2271         val.s = tag_str;
2272         add_avp(tag_avp_type, tag_avp, val);
2273         LM_DBG("added tag_avp <%.*s>\n", val.s.len, val.s.s);
2274     }
2275
2276     /* Add index of selected gw to defunct gw AVP */
2277     if (defunct_capability_param > 0) {
2278         delete_avp(defunct_gw_avp_type, defunct_gw_avp);
2279         val.n = gw_index;
2280         add_avp(defunct_gw_avp_type, defunct_gw_avp, val);
2281         LM_DBG("added defunct_gw_avp <%u>", addr.u.addr32[0]);
2282     }
2283     
2284     return 1;
2285 }
2286
2287
2288 /*
2289  * Checks if request comes from ip address of a gateway
2290  */
2291 static int do_from_gw(struct sip_msg* _m, unsigned int lcr_id,
2292                       struct ip_addr *src_addr, uri_transport transport)
2293 {
2294     struct gw_info *res, gw, *gws;
2295     int_str val;
2296         
2297     gws = gw_pt[lcr_id];
2298
2299     /* Skip lcr instance if some of its gws do not have ip_addr */
2300     if (gws[0].port != 0) {
2301         LM_DBG("lcr instance <%u> has gw(s) without ip_addr\n", lcr_id);
2302         return -1;
2303     }
2304
2305     /* Search for gw ip address */
2306     gw.ip_addr = *src_addr;
2307     res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
2308                                     sizeof(struct gw_info), comp_gws);
2309
2310     /* Store tag and flags and return result */
2311     if ((res != NULL) &&
2312         ((transport == PROTO_NONE) || (res->transport == transport))) {
2313         LM_DBG("request game from gw\n");
2314         if (tag_avp_param) {
2315             val.s.s = res->tag;
2316             val.s.len = res->tag_len;
2317             add_avp(tag_avp_type, tag_avp, val);
2318             LM_DBG("added tag_avp <%.*s>\n", val.s.len, val.s.s);
2319         }
2320         if (flags_avp_param) {
2321             val.n = res->flags;
2322             add_avp(flags_avp_type, flags_avp, val);
2323             LM_DBG("added flags_avp <%u>\n", (unsigned int)val.n);
2324         }
2325         return 1;
2326     } else {
2327         LM_DBG("request did not come from gw\n");
2328         return -1;
2329     }
2330 }
2331
2332
2333 /*
2334  * Checks if request comes from ip address of a gateway taking source
2335  * address and transport protocol from request.
2336  */
2337 static int from_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
2338 {
2339     int lcr_id;
2340     char *tmp;
2341     uri_transport transport;
2342
2343     /* Get and check parameter value */
2344     lcr_id = strtol(_lcr_id, &tmp, 10);
2345     if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
2346         LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
2347         return -1;
2348     }
2349     if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
2350         LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
2351         return -1;
2352     }
2353
2354     /* Get transport protocol */
2355     transport = _m->rcv.proto;
2356
2357     /* Do test */
2358     return do_from_gw(_m, lcr_id, &_m->rcv.src_ip, transport);
2359 }
2360
2361
2362 /*
2363  * Checks if request comes from ip address of a gateway taking source
2364  * address and transport protocol from parameters
2365  */
2366 static int from_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
2367                      char* _transport)
2368 {
2369     struct ip_addr src_addr;
2370     int lcr_id;
2371     char *tmp;
2372     struct ip_addr *ip;
2373     str addr_str;
2374     uri_transport transport;
2375
2376     /* Get and check parameter values */
2377     lcr_id = strtol(_lcr_id, &tmp, 10);
2378     if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
2379         LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
2380         return -1;
2381     }
2382     if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
2383         LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
2384         return -1;
2385     }
2386     addr_str.s = _addr;
2387     addr_str.len = strlen(_addr);
2388     if ((ip = str2ip(&addr_str)) != NULL)
2389         src_addr = *ip;
2390 #ifdef USE_IPV6
2391     else if ((ip = str2ip6(&addr_str)) != NULL)
2392         src_addr = *ip;
2393 #endif
2394     else {
2395         LM_ERR("addr param value %s is not an IP address\n", _addr);
2396         return -1;
2397     }
2398     transport = strtol(_transport, &tmp, 10);
2399     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
2400         LM_ERR("invalid transport parameter %s\n", _lcr_id);
2401         return -1;
2402     }
2403     if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
2404         LM_ERR("invalid transport parameter value %d\n", transport);
2405         return -1;
2406     }
2407
2408     /* Do test */
2409     return do_from_gw(_m, lcr_id, &src_addr, transport);
2410 }
2411
2412
2413 /*
2414  * Checks if request comes from ip address of any gateway taking source
2415  * address from request.
2416  */
2417 static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
2418 {
2419     unsigned int i;
2420     uri_transport transport;
2421
2422     transport = _m->rcv.proto;
2423
2424     for (i = 1; i <= lcr_count_param; i++) {
2425         if (do_from_gw(_m, i, &_m->rcv.src_ip, transport) == 1) {
2426             return i;
2427         }
2428     }
2429     return -1;
2430 }
2431
2432
2433 /*
2434  * Checks if request comes from ip address of a a gateway taking source
2435  * IP address and transport protocol from parameters.
2436  */
2437 static int from_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
2438 {
2439     unsigned int i;
2440     char *tmp;
2441     struct ip_addr *ip, src_addr;
2442     str addr_str;
2443     uri_transport transport;
2444
2445     /* Get and check parameter values */
2446     addr_str.s = _addr;
2447     addr_str.len = strlen(_addr);
2448     if ((ip = str2ip(&addr_str)) != NULL)
2449         src_addr = *ip;
2450 #ifdef USE_IPV6
2451     else if ((ip = str2ip6(&addr_str)) != NULL)
2452         src_addr = *ip;
2453 #endif
2454     else {
2455         LM_ERR("addr param value %s is not an IP address\n", _addr);
2456         return -1;
2457     }
2458     transport = strtol(_transport, &tmp, 10);
2459     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
2460         LM_ERR("invalid transport parameter %s\n", _transport);
2461         return -1;
2462     }
2463     if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
2464         LM_ERR("invalid transport parameter value %d\n", transport);
2465         return -1;
2466     }
2467
2468     /* Do test */
2469     for (i = 1; i <= lcr_count_param; i++) {
2470         if (do_from_gw(_m, i, &src_addr, transport) == 1) {
2471             return i;
2472         }
2473     }
2474     return -1;
2475 }
2476
2477
2478 /*
2479  * Checks if in-dialog request goes to ip address of a gateway.
2480  */
2481 static int do_to_gw(struct sip_msg* _m, unsigned int lcr_id,
2482                     struct ip_addr *dst_addr, uri_transport transport)
2483 {
2484     struct gw_info *res, gw, *gws;
2485
2486     gws = gw_pt[lcr_id];
2487
2488     /* Skip lcr instance if some of its gws do not have ip addr */
2489     if (gws[0].port != 0) {
2490         LM_DBG("lcr instance <%u> has gw(s) without ip_addr\n", lcr_id);
2491         return -1;
2492     }
2493
2494     /* Search for gw ip address */
2495     gw.ip_addr = *dst_addr;
2496     res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
2497                                     sizeof(struct gw_info), comp_gws);
2498
2499     /* Return result */
2500     if ((res != NULL) &&
2501         ((transport == PROTO_NONE) || (res->transport == transport))) {
2502         LM_DBG("request goes to gw\n");
2503         return 1;
2504     } else {
2505         LM_DBG("request is not going to gw\n");
2506         return -1;
2507     }
2508 }
2509
2510
2511 /*
2512  * Checks if request goes to ip address and transport protocol of a gateway
2513  * taking lcr_id from parameter and destination address and transport protocol
2514  * from Request URI.
2515  */
2516 static int to_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
2517 {
2518     int lcr_id;
2519     char *tmp;
2520     struct ip_addr *ip, dst_addr;
2521     uri_transport transport;
2522
2523     /* Get and check parameter value */
2524     lcr_id = strtol(_lcr_id, &tmp, 10);
2525     if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
2526         LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
2527         return -1;
2528     }
2529     if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
2530         LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
2531         return -1;
2532     }
2533
2534     /* Get destination address and transport protocol from R-URI */
2535     if ((_m->parsed_uri_ok == 0) && (parse_sip_msg_uri(_m) < 0)) {
2536         LM_ERR("while parsing Request-URI\n");
2537         return -1;
2538     }
2539     if (_m->parsed_uri.host.len > IP6_MAX_STR_SIZE+2) {
2540         LM_DBG("request is not going to gw "
2541                "(Request-URI host is not an IP address)\n");
2542         return -1;
2543     }
2544     if ((ip = str2ip(&(_m->parsed_uri.host))) != NULL)
2545         dst_addr = *ip;
2546 #ifdef USE_IPV6
2547     else if ((ip = str2ip6(&(_m->parsed_uri.host))) != NULL)
2548         dst_addr = *ip;
2549 #endif
2550     else {
2551         LM_DBG("request is not going to gw "
2552                "(Request-URI host is not an IP address)\n");
2553         return -1;
2554     }
2555     transport = _m->parsed_uri.proto;
2556
2557     /* Do test */
2558     return do_to_gw(_m, lcr_id, &dst_addr, transport);
2559 }
2560
2561
2562 /*
2563  * Checks if request goes to ip address of a gateway taking lcr_id,
2564  * destination address and transport protocol from parameters.
2565  */
2566 static int to_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
2567                    char* _transport)
2568 {
2569     int lcr_id;
2570     char *tmp;
2571     struct ip_addr *ip, dst_addr;
2572     str addr_str;
2573     uri_transport transport;
2574
2575     /* Get and check parameter values */
2576     lcr_id = strtol(_lcr_id, &tmp, 10);
2577     if ((tmp == 0) || (*tmp) || (tmp == _lcr_id)) {
2578         LM_ERR("invalid lcr_id parameter %s\n", _lcr_id);
2579         return -1;
2580     }
2581     if ((lcr_id < 1) || (lcr_id > lcr_count_param)) {
2582         LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
2583         return -1;
2584     }
2585     addr_str.s = _addr;
2586     addr_str.len = strlen(_addr);
2587     if ((ip = str2ip(&addr_str)) != NULL)
2588         dst_addr = *ip;
2589 #ifdef USE_IPV6
2590     else if ((ip = str2ip(&addr_str)) != NULL)
2591         dst_addr = *ip;
2592 #endif
2593     else {
2594         LM_ERR("addr param value %s is not an IP address\n", _addr);
2595         return -1;
2596     }
2597     transport = strtol(_transport, &tmp, 10);
2598     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
2599         LM_ERR("invalid transport parameter %s\n", _transport);
2600         return -1;
2601     }
2602     if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
2603         LM_ERR("invalid transport parameter value %d\n", transport);
2604         return -1;
2605     }
2606     
2607     /* Do test */
2608     return do_to_gw(_m, lcr_id, &dst_addr, transport);
2609 }
2610
2611
2612 /*
2613  * Checks if request goes to ip address of any gateway taking destination
2614  * address and transport protocol from Request-URI.
2615  */
2616 static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
2617 {
2618     unsigned int i;
2619     struct ip_addr *ip, dst_addr;
2620     uri_transport transport;
2621
2622     /* Get destination address and transport protocol from R-URI */
2623     if ((_m->parsed_uri_ok == 0) && (parse_sip_msg_uri(_m) < 0)) {
2624         LM_ERR("while parsing Request-URI\n");
2625         return -1;
2626     }
2627     if (_m->parsed_uri.host.len > IP6_MAX_STR_SIZE+2) {
2628         LM_DBG("request is not going to gw "
2629                "(Request-URI host is not an IP address)\n");
2630         return -1;
2631     }
2632     if ((ip = str2ip(&(_m->parsed_uri.host))) != NULL)
2633         dst_addr = *ip;
2634 #ifdef USE_IPV6
2635     else if ((ip = str2ip6(&(_m->parsed_uri.host))) != NULL)
2636         dst_addr = *ip;
2637 #endif
2638     else {
2639         LM_DBG("request is not going to gw "
2640                "(Request-URI host is not an IP address)\n");
2641         return -1;
2642     }
2643     transport = _m->parsed_uri.proto;
2644
2645     /* Do test */
2646     for (i = 1; i <= lcr_count_param; i++) {
2647         if (do_to_gw(_m, i, &dst_addr, transport) == 1) {
2648             return i;
2649         }
2650     }
2651     return -1;
2652 }
2653
2654
2655 /*
2656  * Checks if request goes to ip address of any gateway taking destination
2657  * address and transport protocol from parameters.
2658  */
2659 static int to_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
2660 {
2661     unsigned int i;
2662     char *tmp;
2663     struct ip_addr *ip, dst_addr;
2664     uri_transport transport;
2665     str addr_str;
2666
2667     /* Get and check parameter values */
2668     addr_str.s = _addr;
2669     addr_str.len = strlen(_addr);
2670     if ((ip = str2ip(&addr_str)) != NULL)
2671         dst_addr = *ip;
2672 #ifdef USE_IPV6
2673     if ((ip = str2ip6(&addr_str)) != NULL)
2674         dst_addr = *ip;
2675 #endif
2676     else {
2677         LM_ERR("addr param value %s is not an IP address\n", _addr);
2678         return -1;
2679     }
2680     transport = strtol(_transport, &tmp, 10);
2681     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
2682         LM_ERR("invalid transport parameter %s\n", _transport);
2683         return -1;
2684     }
2685     if ((transport < PROTO_NONE) || (transport > PROTO_SCTP)) {
2686         LM_ERR("invalid transport parameter value %d\n", transport);
2687         return -1;
2688     }
2689
2690     /* Do test */
2691     for (i = 1; i <= lcr_count_param; i++) {
2692         if (do_to_gw(_m, i, &dst_addr, transport) == 1) {
2693             return i;
2694         }
2695     }
2696     return -1;
2697 }