Browse code

* Moved lcr module from modules_k to modules and removed it from modules_s.

Juha Heinanen authored on 09/05/2009 16:14:18
Showing 22 changed files
1 1
similarity index 100%
2 2
rename from modules_k/lcr/Makefile
3 3
rename to modules/lcr/Makefile
4 4
similarity index 100%
5 5
rename from modules_k/lcr/README
6 6
rename to modules/lcr/README
7 7
similarity index 100%
8 8
rename from modules_k/lcr/doc/Makefile
9 9
rename to modules/lcr/doc/Makefile
10 10
similarity index 100%
11 11
rename from modules_k/lcr/doc/lcr.xml
12 12
rename to modules/lcr/doc/lcr.xml
13 13
similarity index 100%
14 14
rename from modules_k/lcr/doc/lcr_admin.xml
15 15
rename to modules/lcr/doc/lcr_admin.xml
16 16
similarity index 100%
17 17
rename from modules_k/lcr/hash.c
18 18
rename to modules/lcr/hash.c
19 19
similarity index 100%
20 20
rename from modules_k/lcr/hash.h
21 21
rename to modules/lcr/hash.h
22 22
similarity index 100%
23 23
rename from modules_k/lcr/lcr_mod.c
24 24
rename to modules/lcr/lcr_mod.c
25 25
similarity index 100%
26 26
rename from modules_k/lcr/lcr_mod.h
27 27
rename to modules/lcr/lcr_mod.h
28 28
similarity index 100%
29 29
rename from modules_k/lcr/mi.c
30 30
rename to modules/lcr/mi.c
31 31
similarity index 100%
32 32
rename from modules_k/lcr/mi.h
33 33
rename to modules/lcr/mi.h
34 34
deleted file mode 100644
... ...
@@ -1,17 +0,0 @@
1
-#
2
-# Least Cost Routing Module
3
-#
4
-# 
5
-# WARNING: do not run this directly, it should be run by the master Makefile
6
-
7
-include ../../Makefile.defs
8
-auto_gen=
9
-NAME=lcr.so
10
-LIBS=
11
-
12
-DEFS+=-DSER_MOD_INTERFACE
13
-
14
-SERLIBPATH=../../lib
15
-SER_LIBS+=$(SERLIBPATH)/srdb2/srdb2
16
-include ../../Makefile.modules
17
-
18 1
deleted file mode 100644
... ...
@@ -1,259 +0,0 @@
1
-
2
-Least Cost Routing Module
3
-
4
-Juha Heinanen
5
-
6
-Edited by
7
-
8
-Juha Heinanen
9
-
10
-   Copyright � 2005 Juha Heinanen
11
-     _________________________________________________________
12
-
13
-   Table of Contents
14
-
15
-   1. User's Guide
16
-
17
-        1.1. Overview
18
-        1.2. Dependencies
19
-        1.3. Exported Parameters
20
-        1.4. Exported Functions
21
-        1.5. FIFO Commands
22
-        1.6. Known Limitations
23
-
24
-   2. TODO
25
-     _________________________________________________________
26
-
27
-Chapter 1. User's Guide
28
-
29
-1.1. Overview
30
-
31
-   Least cost routing (LCR) module implements two related capabilities:
32
-
33
-   (1) sequential forwarding of a request to one or more gateways
34
-       (functions load_gws and next_gw),
35
-
36
-   (2) sequential forwarding to contacts if they don't share the
37
-       the same qvalue (functions load_contacts and next_contacts).
38
-
39
-   Gateway selection is based on caller's RPID URI (if available in
40
-   caller's RPID AVP after authentication) or From URI and user part of
41
-   Request-URI (telephone number).  Gateway patterns matching RPID or
42
-   From URI and telephone number are ordered for forwarding purpose (1)
43
-   according to longest user part match, (2) according to priority, and
44
-   (3) randomly.
45
-
46
-   Each gateway belongs to a gateway group either alone or among other
47
-   gateways.  All gateways in a group share the same priority.
48
-
49
-   Gateway and routing information is kept in two tables:  gw and lcr.
50
-
51
-   When a gateway is selected, Request-URI is rewritten with information
52
-   from gw table: URI scheme, prefix, IP address, port, and transport
53
-   protocol.  Valid URI scheme values are NULL = sip, 1 = sip and 2 =
54
-   sips.  Prefix is appended in front of Request-URI user part.
55
-   Currently valid transport protocol values are NULL = none, 1 = udp, 2
56
-   = tcp, and 3 = tls.
57
-
58
-   Table lcr contains prefix of user part of Request-URI, From URI,
59
-   gateway group id, and priority.  From URI can contain special
60
-   characters % and _ matching any number of any characters and any one
61
-   character, respectively.  
62
-
63
-   In addition to gw and lcr tables there is third table gw_grp that is
64
-   used for administrative purposes only to associate names with gateway
65
-   group ids.
66
-   _________________________________________________________
67
-
68
-1.2. Dependencies
69
-
70
-   The module depends on the following modules (in the other
71
-   words the listed modules must be loaded before this module):
72
-
73
-     * tm module
74
-     * mysql module
75
-     _________________________________________________________
76
-
77
-1.3. Exported Parameters
78
-
79
-   LCR module exports the following database related parameters that
80
-   have usual purpose:
81
-
82
-     * db_url (default system default)
83
-     * gw_table (default "gw")
84
-     * gw_name_column (default "gw_name")
85
-     * ip_addr_column (default "ip_addr")
86
-     * port_column (default "port")
87
-     * uri_scheme_column (default "uri_scheme")
88
-     * transport_column (default "transport")
89
-     * grp_id_column (default "grp_id")
90
-     * lcr_table (default "lcr")
91
-     * prefix_column (default "prefix")
92
-     * from_uri_column (default "from_uri")
93
-     * priority_column (default "priority")
94
-
95
-   In addition there are parameters that can be used to override names
96
-   of the AVPs used by LCR module:
97
-
98
-     * gw_uri_avp	  (default "1400")
99
-     * contact_avp	  (default "1401")
100
-     * fr_inv_timer_avp	  (default "fr_inv_timer_avp")
101
-     * rpid_avp		  (default "rpid")
102
-
103
-   If string value of an AVP parameter contains only digits, the name of
104
-   the AVP is int value of the string.
105
-
106
-   Finally, the parameters used by sequential forwarding:
107
-
108
-     * fr_inv_timer		(default 90)
109
-     * fr_inv_timer_next	(default 30)
110
-     * fr_inv_timer_param	(default "")
111
-     * fr_inv_timer_next_param	(default "")
112
-
113
-   Function next_contacts() sets tm fr_inv_timer to fr_inv_timer_next
114
-   value if, after next contacts, there are still lower qvalue
115
-   contacts available, and to fr_inv_timer value if next contacts are
116
-   the last ones left. fr_inv_timer_param can define an AVP
117
-   overwriting fr_inv_timer value, and similarly, AVP defined by
118
-   fr_inv_timer_next_param can overwrite fr_inv_timer_next value.
119
-    _________________________________________________________
120
-
121
-1.4. Exported Functions
122
-
123
-1.4.1. load_gws()
124
-
125
-   Loads URIs of gateways matching RPID AVP (if available) or From URI
126
-   and user part of Request-URI to gw_uri_avp AVPs.  Returns 1 or -1
127
-   depending on success.
128
-
129
-   Example:
130
-
131
-   if (!load_gws()) {
132
-      sl_send_reply("500", "Server Internal Error - Cannot load gateways");
133
-      break;
134
-   };
135
-
136
-1.4.2. next_gw()
137
-
138
-   If called from a route block, replaces Request-URI by the first
139
-   gw_uri_avp AVP value and destroys that AVP.
140
-
141
-   If called from a failure route block, appends a new branch to request,
142
-   whose Request-URI is the first gw_uri_avp AVP value, and destroys that
143
-   AVP.
144
-
145
-   Returns 1 on success and -1 if there were no gateways left or if an
146
-   error occurred (see syslog).
147
-
148
-   Must be preceded by successful load_gws() call.
149
-
150
-   Example from route block:
151
-   
152
-   if (!next_gw()) {
153
-      sl_send_reply("503", "Service not available - No gateways");
154
-      break;
155
-    };
156
-
157
-   Example from failure route block:
158
-
159
-   if (!next_gw()) {
160
-      t_reply("503", "Service not available - No more gateways");
161
-      break;	     
162
-    };
163
-
164
-1.4.3. from_gw()
165
-
166
-   Checks if request came from IP address of a gateway.
167
-
168
-   Example:
169
-   
170
-   if (from_gw()) {
171
-      ...
172
-      break;
173
-   };
174
-
175
-1.4.4. to_gw()
176
-
177
-   Checks if in-dialog request goes to a gateway.
178
-
179
-   Example:
180
-   
181
-   if (to_gw()) {
182
-      ...
183
-      break;
184
-   };
185
-
186
-1.4.5. load_contacts()
187
-
188
-   Loads contacts in destination set in increasing qvalue order as
189
-   values of lcr_contact AVP.  If all contacts in the destination set
190
-   have the same qvalue, load_contacts() does not do anything thus
191
-   minimizing performance impact of sequential forking capability when
192
-   it is not needed.  Returns 1 if loading of contacts succeeded or
193
-   there was nothing to do.  Returns -1 on error (see syslog).
194
-
195
-   Example:
196
-
197
-   if (!load_contacts()) {
198
-      sl_send_reply("500", "Server Internal Error - Cannot load contacts");
199
-      break;
200
-   };
201
-
202
-1.4.6. next_contacts()
203
-
204
-   If called from a route block, replaces Request-URI with the first
205
-   lcr_contact AVP value, adds the remaining lcr_contact AVP values with
206
-   the same qvalue as branches, and destroys those AVPs.  It does
207
-   nothing if there are no lcr_contact AVPs.  Returns 1 if there were no
208
-   errors and -1 if an error occurred (see syslog).
209
-
210
-   If called from a failure route block, adds the first lcr_contact AVP
211
-   value and all following lcr_contact AVP values with the same qvalue
212
-   as new branches to request and destroys those AVPs.  Returns 1 if new
213
-   branches were successfully added and -1 on error (see syslog) or if
214
-   there were no more lcr_contact AVPs.
215
-
216
-   Must be preceded by successful load_contacts() call.
217
-
218
-   Example from route block:
219
-   
220
-   if (!next_contacts()) {
221
-       sl_send_reply("500", "Server Internal Error");
222
-        break;
223
-   } else {
224
-      t_relay();
225
-   };
226
-
227
-   Example from failure route block:
228
-   
229
-   if (next_contacts()) {
230
-       t_relay();
231
-   };
232
-
233
-
234
-1.5. FIFO Commands
235
-
236
-1.5.1. lcr_reload
237
-
238
-   Causes lcr module to re-read the contents of gateway table
239
-   into memory.
240
-
241
-1.5.2. lcr_dump
242
-
243
-   Causes lcr module to dump the contents of its in-memory gateway
244
-   table. 
245
-
246
-1.6. Known Limitations
247
-
248
-   There is an unlikely race condition on lcr reload. If a process uses
249
-   in memory gw table, which is reloaded at the same time twice through
250
-   FIFO, the second reload will delete the original table still in use
251
-   by the process.
252
-   _________________________________________________________
253
-
254
-2.0. TODO
255
-
256
-   Function load_gws() currently makes an SQL query for the matching
257
-   gateways.  In order to avoid the query, also lcr table should be
258
-   read into memory and the corresponding query should be rewritten in
259
-   C.
260 1
deleted file mode 100644
... ...
@@ -1,4 +0,0 @@
1
-docs = lcr.xml
2
-
3
-docbook_dir=../../../docbook
4
-include $(docbook_dir)/Makefile.module
5 1
deleted file mode 100644
... ...
@@ -1,17 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
3
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4
-
5
-<section id="flatstore.functions" xmlns:xi="http://www.w3.org/2001/XInclude">
6
-    <sectioninfo>
7
-	<revhistory>
8
-	    <revision>
9
-		<revnumber>$Revision$</revnumber>
10
-		<date>$Date$</date>
11
-	    </revision>
12
-	</revhistory>
13
-    </sectioninfo>
14
-
15
-    <title>Functions</title>
16
-
17
-</section>
18 1
deleted file mode 100644
... ...
@@ -1,121 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
3
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4
-
5
-<section id="lcr" xmlns:xi="http://www.w3.org/2001/XInclude">
6
-    <sectioninfo>
7
-	<authorgroup>
8
-	    <author>
9
-		<firstname>Juha</firstname>
10
-		<surname>Heinanen</surname>
11
-		<affiliation><orgname>FhG FOKUS</orgname></affiliation>
12
-		<address>
13
-		    <email></email>
14
-		</address>
15
-	    </author>
16
-	</authorgroup>
17
-	<copyright>
18
-	    <year>2003</year>
19
-	    <holder>FhG FOKUS</holder>
20
-	</copyright>
21
-	<revhistory>
22
-	    <revision>
23
-		<revnumber>$Revision$</revnumber>
24
-		<date>$Date$</date>
25
-	    </revision>
26
-	</revhistory>
27
-    </sectioninfo>
28
-
29
-    <title>LCR Module</title>
30
-
31
-    <section id="lcr.overview">
32
-	<title>Overview</title>
33
-	<para>
34
-         Least cost routing (LCR) module implements two related capabilities:
35
-       <itemizedlist>
36
-            <listitem> LCR may sequentially forward requests to one or more gateways using the load_gws 
37
-            and next_gw functions.
38
-            </listitem>
39
-
40
-            <listitem> LCR may sequentially forward contacts if they don't share the same qvalues.
41
-            Use the functions load_contacts and next_contacts to access and select a contact.
42
-            </listitem>
43
-        </itemizedlist>
44
-
45
-       <para>Gateway selection is based on caller's RPID URI (if available in caller's RPID AVP after 
46
-        authentication) or From URI and user part of Request-URI (telephone number).  Gateway patterns
47
-        matching RPID or From URI and telephone number are ordered for forwarding purposes as follows:
48
-        <itemizedlist>
49
-            <listitem>According to longest user part match
50
-            </listitem>
51
-
52
-            <listitem>According to priority
53
-            </listitem>
54
-
55
-            <listitem>Randomly
56
-            </listitem>
57
-        </itemizedlist>
58
-
59
-        Each gateway belongs to a gateway group either alone or among other gateways.  All gateways in a 
60
-        group share the same priority.  Gateway and routing information is kept in two tables:  
61
-        gw and lcr.
62
-        </para>
63
-
64
-        <para> When a gateway is selected, Request-URI is rewritten with information from gw table: 
65
-         URI scheme, prefix, IP address, port, and transport protocol.  Valid URI scheme values are:
66
-         <itemizedlist>
67
-            <listitem>NULL = sip
68
-            </listitem>
69
-            <listitem>1 = sip 
70
-            </listitem>
71
-            <listitem>2 = sips.  
72
-            </listitem>
73
-        </itemizedlist>
74
-        </para>
75
-
76
-        <para> If a prefix is specified it will be prepended to the Request-URI user part.
77
-        </para>
78
-
79
-        <para>Currently valid transport protocol values are: 
80
-         <itemizedlist>
81
-            <listitem>NULL = none
82
-            </listitem>
83
-            <listitem>1 = udp 
84
-            </listitem>
85
-            <listitem>2 = tcp  
86
-            </listitem>
87
-            <listitem>3 = tls  
88
-            </listitem>
89
-        </itemizedlist>
90
-        </para>
91
-
92
-        <para> Table lcr contains any prefix to be applied to the user part of Request-URI, the From URI,
93
-         the gateway group id, and the priority.  The From URI can contain special characters % and _ 
94
-         matching any number of any characters and any one character, respectively. 
95
-        </para>
96
-
97
-        <para> In addition to gw and lcr tables there is third table gw_grp that is used for 
98
-         administrative purposes only. In this table you may map names to the gateway group ids.
99
-        </para>
100
-
101
-	</para>
102
-    </section>
103
-
104
-    <section id="lcr.dependencies">
105
-	<title>Dependencies</title>
106
-	<para>The module depends on the following modules. These modules must be loaded before the LCR module
107
-         <itemizedlist>
108
-            <listitem>tm module
109
-            </listitem>
110
-            <listitem>mysql module
111
-            </listitem>
112
-        </itemizedlist>
113
-	</para>
114
-    </section>
115
-
116
-    
117
-    <xi:include href="params.xml"/>
118
-    <xi:include href="functions.xml"/>
119
-
120
-</section>
121
-
122 1
deleted file mode 100644
... ...
@@ -1,235 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
3
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4
-
5
-<section id="lcr.parameters" xmlns:xi="http://www.w3.org/2001/XInclude">
6
-    <sectioninfo>
7
-	<revhistory>
8
-	    <revision>
9
-		<revnumber>$Revision$</revnumber>
10
-		<date>$Date$</date>
11
-	    </revision>
12
-	</revhistory>
13
-    </sectioninfo>
14
-
15
-    <title>Parameters</title>
16
-
17
-    <section id="db_url">
18
-	<title><varname>db_url</varname> (string)</title>
19
-	<para>
20
-	    The URL for accessing the database where the LCR tables reside
21
-	</para>
22
-	<para>
23
-	    Default value is NULL.
24
-	</para>
25
-	<example>
26
-	    <title>Set <varname>db_url</varname> parameter</title>
27
-	    <programlisting>
28
-		...
29
-		modparam("lcr", "db_url", "mysql://ser:pwd@localhost/ser") 
30
-		...
31
-	    </programlisting>
32
-	</example>
33
-    </section>
34
-
35
-    <section id="gw_table">
36
-	<title><varname>gw_table</varname> (string)</title>
37
-	<para>
38
-	    The name of the table containing the list of gateways
39
-	</para>
40
-	<para>
41
-	    Default value is gw.
42
-	</para>
43
-	<example>
44
-	    <title>Set <varname>gw_table</varname> parameter</title>
45
-	    <programlisting>
46
-		...
47
-		modparam("lcr", "gw_table", "mygateways") 
48
-		...
49
-	    </programlisting>
50
-	</example>
51
-    </section>
52
-
53
-    <section id="gw_name_column">
54
-	<title><varname>gw_name_column</varname> (string)</title>
55
-	<para>
56
-	    The name of the column that contains the actual name of the gateway
57
-	</para>
58
-	<para>
59
-	    Default value is gw_name.
60
-	</para>
61
-	<example>
62
-	    <title>Set <varname>gw_name_column</varname> parameter</title>
63
-	    <programlisting>
64
-		...
65
-		modparam("lcr", "gw_name_column", "Agateway") 
66
-		...
67
-	    </programlisting>
68
-	</example>
69
-    </section>
70
-
71
-    <section id="ip_addr_column">
72
-	<title><varname>ip_addr_column</varname> (string)</title>
73
-	<para>
74
-	    The name of the column that contains the IP address for a specific gateway
75
-	</para>
76
-	<para>
77
-	    Default value is ip_addr.
78
-	</para>
79
-	<example>
80
-	    <title>Set <varname>ip_addr_column</varname> parameter</title>
81
-	    <programlisting>
82
-		...
83
-		modparam("lcr", "ip_addr_column", "gatewayIPs") 
84
-		...
85
-	    </programlisting>
86
-	</example>
87
-    </section>
88
-
89
-    <section id="port_column">
90
-	<title><varname>port_column</varname> (string)</title>
91
-	<para>
92
-	    The name of the column that contains the port number through which this gateway communicates
93
-	</para>
94
-	<para>
95
-	    Default value is port.
96
-	</para>
97
-	<example>
98
-	    <title>Set <varname>port_column</varname> parameter</title>
99
-	    <programlisting>
100
-		...
101
-		modparam("lcr", "port_column", "gatewayPort") 
102
-		...
103
-	    </programlisting>
104
-	</example>
105
-    </section>
106
-
107
-    <section id="uri_scheme_column ">
108
-	<title><varname>uri_scheme_column </varname> (string)</title>
109
-	<para>
110
-	    The name of the column that contains the scheme to be used when rewriting the R-URI
111
-	</para>
112
-	<para>
113
-	    Default value is uri_scheme.
114
-	</para>
115
-	<example>
116
-	    <title>Set <varname>uri_scheme_column</varname> parameter</title>
117
-	    <programlisting>
118
-		...
119
-		modparam("lcr", "uri_scheme", "myURIScheme") 
120
-		...
121
-	    </programlisting>
122
-	</example>
123
-    </section>
124
-
125
-    <section id="transport_column ">
126
-	<title><varname>transport_column</varname> (string)</title>
127
-	<para>
128
-	    The name of the column that contains the transport to be used when contacting a gateway
129
-	</para>
130
-	<para>
131
-	    Default value is transport.
132
-	</para>
133
-	<example>
134
-	    <title>Set <varname>transport_column</varname> parameter</title>
135
-	    <programlisting>
136
-		...
137
-		modparam("lcr", "transport", "mySIPXport") 
138
-		...
139
-	    </programlisting>
140
-	</example>
141
-    </section>
142
-
143
-    <section id="grp_id_column ">
144
-	<title><varname>grp_id_column</varname> (string)</title>
145
-	<para>
146
-	    The name of the column that contains the gateway group ID number
147
-	</para>
148
-	<para>
149
-	    Default value is grp_id.
150
-	</para>
151
-	<example>
152
-	    <title>Set <varname>grp_id_column</varname> parameter</title>
153
-	    <programlisting>
154
-		...
155
-		modparam("lcr", "grp_id_column", "GwyGroups") 
156
-		...
157
-	    </programlisting>
158
-	</example>
159
-    </section>
160
-
161
-    <section id="lcr_table ">
162
-	<title><varname>lcr_table</varname> (string)</title>
163
-	<para>
164
-	    The name of the column that contains the LCR table
165
-	</para>
166
-	<para>
167
-	    Default value is lcr.
168
-	</para>
169
-	<example>
170
-	    <title>Set <varname>lcr_table</varname> parameter</title>
171
-	    <programlisting>
172
-		...
173
-		modparam("lcr", "lcr_table", "lcr") 
174
-		...
175
-	    </programlisting>
176
-	</example>
177
-    </section>
178
-
179
-    <section id="prefix_column ">
180
-	<title><varname>prefix_column</varname> (string)</title>
181
-	<para>
182
-	    The name of the column that contains the prefix to be prepended to the R-URI user part.
183
-	</para>
184
-	<para>
185
-	    Default value is prefix.
186
-	</para>
187
-	<example>
188
-	    <title>Set <varname>prefix_column</varname> parameter</title>
189
-	    <programlisting>
190
-		...
191
-		modparam("lcr", "prefix_column", "prefix") 
192
-		...
193
-	    </programlisting>
194
-	</example>
195
-    </section>
196
-
197
-    <section id="from_uri_column ">
198
-	<title><varname>from_uri_column</varname> (string)</title>
199
-	<para>
200
-	    The name of the column that contains the From URI which must match in order to select this gateway.
201
-            Note that the values in this column may contain wildcard characters as mentioned earlier in this 
202
-            document.
203
-	</para>
204
-	<para>
205
-	    Default value is from_uri.
206
-	</para>
207
-	<example>
208
-	    <title>Set <varname>from_uri_column</varname> parameter</title>
209
-	    <programlisting>
210
-		...
211
-		modparam("lcr", "from_uri_column", "FromURI") 
212
-		...
213
-	    </programlisting>
214
-	</example>
215
-    </section>
216
-
217
-    <section id="priority_column ">
218
-	<title><varname>priority_column</varname> (string)</title>
219
-	<para>
220
-	    The name of the column that contains a number indicating the priority of this gateway
221
-	</para>
222
-	<para>
223
-	    Default value is priority.
224
-	</para>
225
-	<example>
226
-	    <title>Set <varname>priority_column</varname> parameter</title>
227
-	    <programlisting>
228
-		...
229
-		modparam("lcr", "priority_column", "priority") 
230
-		...
231
-	    </programlisting>
232
-	</example>
233
-    </section>
234
-
235
-</section>
236 1
deleted file mode 100644
... ...
@@ -1,1113 +0,0 @@
1
-/*
2
- * Least Cost Routing module (also implements sequential forking)
3
- *
4
- * Copyright (C) 2005 Juha Heinanen
5
- *
6
- * This file is part of ser, a free SIP server.
7
- *
8
- * ser is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version
12
- *
13
- * For a license to use the ser software under conditions
14
- * other than those described here, or to purchase support for this
15
- * software, please contact iptel.org by e-mail at the following addresses:
16
- *    info@iptel.org
17
- *
18
- * ser is distributed in the hope that it will be useful,
19
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
- * GNU General Public License for more details.
22
- *
23
- * You should have received a copy of the GNU General Public License
24
- * along with this program; if not, write to the Free Software
25
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
- *
27
- * History:
28
- * -------
29
- *  2005-02-14: Introduced lcr module (jh)
30
- *  2005-02-20: Added sequential forking functions (jh)
31
- *  2005-02-25: Added support for int AVP names, combined addr and port
32
- *              AVPs (jh)
33
- *  2005-07-23: Added support for gw URI scheme and transport (jh)
34
- *  2005-08-20: Added support for gw prefixes (jh)
35
- */
36
-
37
-#include <stdio.h>
38
-#include <stdlib.h>
39
-#include <string.h>
40
-#include <arpa/inet.h>
41
-#include "../../sr_module.h"
42
-#include "../../dprint.h"
43
-#include "../../ut.h"
44
-#include "../../error.h"
45
-#include "../../mem/mem.h"
46
-#include "../../mem/shm_mem.h"
47
-#include "../../lib/srdb2/db.h"
48
-#include "../../usr_avp.h"
49
-#include "../../parser/parse_uri.h"
50
-#include "../../parser/parse_from.h"
51
-#include "../../parser/msg_parser.h"
52
-#include "../../action.h"
53
-#include "../../modules/tm/tm_load.h"
54
-#include "../../qvalue.h"
55
-#include "../../dset.h"
56
-#include "../../ip_addr.h"
57
-#include "../../config.h"
58
-#include "../../route.h"
59
-#include "lcr_rpc.h"
60
-#include "lcr_mod.h"
61
-
62
-MODULE_VERSION
63
-
64
-/* usr_avp flag for sequential forking */
65
-#define DEF_Q_FLAG	"q_flag"
66
-avp_flags_t	Q_FLAG = 0;
67
-
68
-static void destroy(void);       /* Module destroy function */
69
-static int child_init(int rank); /* Per-child initialization function */
70
-static int mod_init(void);       /* Module initialization function */
71
-
72
-int reload_gws ( void );
73
-
74
-#define LCR_MAX_QUERY_SIZE 512
75
-#define MAX_PREFIX_LEN 16
76
-
77
-/* Default avp names */
78
-#define DEF_GW_URI_AVP "1400"
79
-#define DEF_CONTACT_AVP "1401"
80
-#define DEF_FR_INV_TIMER_AVP "$t.callee_fr_inv_timer"
81
-#define DEF_FR_INV_TIMER 90
82
-#define DEF_FR_INV_TIMER_NEXT 30
83
-#define DEF_RPID_AVP "rpid"
84
-
85
-/*
86
- * Database variables
87
- */
88
-db_ctx_t* ctx = NULL;
89
-db_cmd_t *lcr_load = NULL;
90
-db_cmd_t *lcr_reload = NULL;
91
-
92
-/* This is the stack of all used IP addresses, this stack is
93
- * used to make sure that no IP address (gateway) gets the same
94
- * request more than once.
95
- */
96
-static unsigned int addrs[MAX_BRANCHES];
97
-unsigned int addrs_top = 0;
98
-
99
-/*
100
- * Module parameter variables
101
- */
102
-static str db_url    = STR_STATIC_INIT(DEFAULT_RODB_URL);
103
-
104
-char* gw_table         = "gw";
105
-char* gw_name_col      = "gw_name";
106
-char* ip_addr_col      = "ip_addr";
107
-char* port_col         = "port";
108
-char* uri_scheme_col   = "uri_scheme";
109
-char* transport_col    = "transport";
110
-char* grp_id_col       = "grp_id";
111
-char* lcr_table        = "lcr";
112
-char* prefix_col       = "prefix";
113
-char* from_uri_col     = "from_uri";
114
-char* priority_col     = "priority";
115
-
116
-str gw_uri_avp       = STR_STATIC_INIT(DEF_GW_URI_AVP);
117
-str contact_avp      = STR_STATIC_INIT(DEF_CONTACT_AVP);
118
-str inv_timer_avp    = STR_STATIC_INIT(DEF_FR_INV_TIMER_AVP);
119
-int inv_timer        = DEF_FR_INV_TIMER;
120
-int inv_timer_next   = DEF_FR_INV_TIMER_NEXT;
121
-str inv_timer_ps     = STR_STATIC_INIT("");
122
-str inv_timer_next_ps = STR_STATIC_INIT("");
123
-str rpid_avp         = STR_STATIC_INIT(DEF_RPID_AVP);
124
-
125
-/*
126
- * Other module types and variables
127
- */
128
-
129
-struct contact {
130
-    str uri;
131
-    qvalue_t q;
132
-    unsigned short q_flag;
133
-    struct contact *next;
134
-};
135
-
136
-int_str gw_uri_name, contact_name, rpid_name;
137
-unsigned short gw_uri_avp_name_str;
138
-unsigned short contact_avp_name_str;
139
-unsigned short rpid_avp_name_str;
140
-
141
-static avp_ident_t tm_timer_param;	/* TM module's invite timer avp */
142
-
143
-struct gw_info **gws;	/* Pointer to current gw table pointer */
144
-struct gw_info *gws_1;	/* Pointer to gw table 1 */
145
-struct gw_info *gws_2;	/* Pointer to gw table 2 */
146
-struct tm_binds tmb;
147
-
148
-/* AVPs overwriting the module parameters */
149
-static avp_ident_t *inv_timer_param = NULL;
150
-static avp_ident_t *inv_timer_next_param = NULL;
151
-
152
-/*
153
- * Module functions that are defined later
154
- */
155
-int load_gws(struct sip_msg* _m, char* _s1, char* _s2);
156
-int next_gw(struct sip_msg* _m, char* _s1, char* _s2);
157
-int from_gw(struct sip_msg* _m, char* _s1, char* _s2);
158
-int to_gw(struct sip_msg* _m, char* _s1, char* _s2);
159
-int load_contacts (struct sip_msg*, char*, char*);
160
-int next_contacts (struct sip_msg*, char*, char*);
161
-
162
-
163
-/*
164
- * Exported functions
165
- */
166
-static cmd_export_t cmds[] = {
167
-	{"load_gws",      load_gws,      0, 0, REQUEST_ROUTE},
168
-	{"next_gw",       next_gw,       0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
169
-	{"from_gw",       from_gw,       0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
170
-	{"to_gw",         to_gw,         0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
171
-	{"load_contacts", load_contacts, 0, 0, REQUEST_ROUTE},
172
-	{"next_contacts", next_contacts, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
173
-	{0, 0, 0, 0, 0}
174
-};
175
-
176
-
177
-/*
178
- * Exported parameters
179
- */
180
-static param_export_t params[] = {
181
-	{"db_url",                   PARAM_STR,  &db_url              },
182
-	{"gw_table",                 PARAM_STRING, &gw_table          },
183
-	{"gw_name_column",           PARAM_STRING, &gw_name_col       },
184
-	{"ip_addr_column",           PARAM_STRING, &ip_addr_col       },
185
-	{"port_column",              PARAM_STRING, &port_col          },
186
-	{"uri_scheme_column",        PARAM_STRING, &uri_scheme_col    },
187
-	{"transport_column",         PARAM_STRING, &transport_col     },
188
-	{"grp_id_column",            PARAM_STRING, &grp_id_col        },
189
-	{"lcr_table",                PARAM_STRING, &lcr_table         },
190
-	{"prefix_column",            PARAM_STRING, &prefix_col        },
191
-	{"from_uri_column",          PARAM_STRING, &from_uri_col      },
192
-	{"priority_column",          PARAM_STRING, &priority_col      },
193
-	{"gw_uri_avp",               PARAM_STR,    &gw_uri_avp        },
194
-	{"contact_avp",              PARAM_STR,    &contact_avp       },
195
-	{"fr_inv_timer_avp",         PARAM_STR,    &inv_timer_avp     },
196
-	{"fr_inv_timer",             PARAM_INT,    &inv_timer         },
197
-	{"fr_inv_timer_next",        PARAM_INT,    &inv_timer_next    },
198
-	{"fr_inv_timer_param",       PARAM_STR,    &inv_timer_ps      },
199
-	{"fr_inv_timer_next_param",  PARAM_STR,    &inv_timer_next_ps },
200
-	{"rpid_avp",                 PARAM_STR,    &rpid_avp          },
201
-	{0, 0, 0}
202
-};
203
-
204
-
205
-/*
206
- * Module interface
207
- */
208
-struct module_exports exports = {
209
-	"lcr",
210
-	cmds,      /* Exported functions */
211
-	lcr_rpc,   /* RPC methods */
212
-	params,    /* Exported parameters */
213
-	mod_init,  /* module initialization function */
214
-	0,         /* response function */
215
-	destroy,   /* destroy function */
216
-	0,         /* oncancel function */
217
-	child_init /* child initialization function */
218
-};
219
-
220
-
221
-void lcr_db_close()
222
-{
223
-	if (lcr_load) db_cmd_free(lcr_load);
224
-	lcr_load = NULL;
225
-
226
-	if (lcr_reload) db_cmd_free(lcr_reload);
227
-	lcr_reload = NULL;
228
-
229
-	if (ctx) {
230
-		db_disconnect(ctx);
231
-		db_ctx_free(ctx);
232
-		ctx = NULL;
233
-	}
234
-}
235
-
236
-
237
-int lcr_db_init(char* db_url)
238
-{
239
-	int q_len;
240
-    static char query[LCR_MAX_QUERY_SIZE];
241
-	db_fld_t reload_cols[] = {
242
-		{.name = ip_addr_col,    .type = DB_INT},
243
-		{.name = port_col,       .type = DB_INT},
244
-		{.name = uri_scheme_col, .type = DB_INT},
245
-		{.name = transport_col,  .type = DB_INT},
246
-		{.name = prefix_col,     .type = DB_STR},
247
-		{.name = 0}
248
-	};
249
-
250
-	db_fld_t load_cols[] = {
251
-		{.name = "gw.ip_addr",    .type = DB_INT},
252
-		{.name = "gw.port",       .type = DB_INT},
253
-		{.name = "gw.uri_scheme", .type = DB_INT},
254
-		{.name = "gw.transport",  .type = DB_INT},
255
-		{.name = "gw.prefix",     .type = DB_STR},
256
-		{.name = 0}
257
-	};
258
-
259
-	db_fld_t load_match[] = {
260
-		{.name = "lcr.from_uri",      .type = DB_STR},
261
-		{.name = "lcr.ruri_username", .type = DB_STR},
262
-		{.name = 0}
263
-	};
264
-	  
265
-	ctx = db_ctx("lcr");
266
-	if (!ctx) goto err;
267
-	if (db_add_db(ctx, db_url) < 0) goto err;
268
-	if (db_connect(ctx) < 0) goto err;
269
-
270
-    q_len = snprintf(query, LCR_MAX_QUERY_SIZE, 
271
-					 "SELECT %s.%s, %s.%s, %s.%s, %s.%s, %s.%s from %s, %s "
272
-					 "WHERE ? LIKE %s.%s AND ? LIKE CONCAT(%s.%s, '%%') "
273
-					 "AND %s.%s = %s.%s ORDER BY CHAR_LENGTH(%s.%s) DESC, "
274
-					 "%s.%s, RAND()",
275
-					 gw_table, ip_addr_col, gw_table, port_col, 
276
-					 gw_table, uri_scheme_col, gw_table, transport_col, 
277
-					 gw_table, prefix_col, gw_table, lcr_table,
278
-					 lcr_table, from_uri_col, lcr_table, prefix_col,
279
-					 lcr_table, grp_id_col, gw_table, grp_id_col,
280
-					 lcr_table, prefix_col, lcr_table, priority_col);
281
-    if (q_len < 0 || q_len >= LCR_MAX_QUERY_SIZE) {
282
-		ERR("lcr: Database query too long\n");
283
-		return -1;
284
-    }
285
-	
286
-	lcr_load = db_cmd(DB_SQL, ctx, query, load_cols, load_match, NULL);
287
-	if (!lcr_load) goto err;
288
-
289
-	lcr_reload = db_cmd(DB_GET, ctx, gw_table, reload_cols, NULL, NULL);
290
-	if (!lcr_reload) goto err;
291
-    return 0;
292
-
293
-err:
294
-	lcr_db_close();
295
-	ERR("lcr: Error while initializing database layer\n");
296
-	return -1;
297
-}
298
-
299
-
300
-/*
301
- * Module initialization function callee in each child separately
302
- */
303
-static int child_init(int rank)
304
-{
305
-	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
306
-		return 0; /* do nothing for the main or tcp_main processes */
307
-	if (lcr_db_init(db_url.s) < 0) {
308
-		ERR("lcr: Unable to initialize database layer\n");
309
-		return -1;
310
-	}
311
-
312
-	return 0;
313
-}
314
-
315
-/* get AVP module parameter */
316
-static int get_avp_modparam(str *s, avp_ident_t *avp)
317
-{
318
-	if (!s->s || (s->len < 2)) return -1;
319
-
320
-	if (s->s[0] != '$') {
321
-		ERR("lcr: get_avp_modparam(): "
322
-			"unknown AVP identifier: %.*s\n", s->len, s->s);
323
-		return -1;
324
-	}
325
-	s->s++;
326
-	s->len--;
327
-	if (parse_avp_ident(s, avp)) {
328
-		ERR("lcr: get_avp_modparam(): "
329
-			"cannot parse AVP identifier: %.*s\n", s->len, s->s);
330
-		return -1;
331
-	}
332
-	return 0;
333
-}
334
-
335
-/*
336
- * Module initialization function that is called before the main process forks
337
- */
338
-static int mod_init(void)
339
-{
340
-	load_tm_f  load_tm;
341
-	int i;
342
-	unsigned int par;
343
-
344
-	DBG("lcr - initializing\n");
345
-
346
-	Q_FLAG = register_avpflag(DEF_Q_FLAG);
347
-	if (Q_FLAG == 0) {
348
-		ERR("lcr: Cannot regirser AVP flag: %s\n", DEF_Q_FLAG);
349
-		return -1;
350
-	}
351
-
352
-	/* import the TM auto-loading function */
353
-	if (!(load_tm = (load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
354
-	    ERR("lcr: cannot import load_tm\n");
355
-		goto err;
356
-	}
357
-	/* let the auto-loading function load all TM stuff */
358
-	if (load_tm(&tmb) == -1) goto err;
359
-
360
-	/* Initializing gw tables and gw table pointer variable */
361
-	gws_1 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) * (MAX_NO_OF_GWS + 1));
362
-	if (gws_1 == 0) {
363
-	    ERR("lcr: mod_init(): No memory for gw table\n");
364
-	    goto err;
365
-	}
366
-	gws_2 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) * (MAX_NO_OF_GWS + 1));
367
-	if (gws_2 == 0) {
368
-	    ERR("lcr: mod_init(): No memory for gw table\n");
369
-	    goto err;
370
-	}
371
-	for (i = 0; i < MAX_NO_OF_GWS + 1; i++) {
372
-		gws_1[i].ip_addr = gws_2[i].ip_addr = 0;
373
-	}
374
-	gws = (struct gw_info **)shm_malloc(sizeof(struct gw_info *));
375
-	*gws = gws_1;
376
-
377
-	if (lcr_db_init(db_url.s) < 0) {
378
-		ERR("lcr: Unable to initialize database layer\n");
379
-		return -1;
380
-	}
381
-
382
-	/* First reload */
383
-	if (reload_gws() == -1) {
384
-		LOG(L_CRIT, "lcr: failed to reload gateways\n");
385
-		goto err;
386
-	}
387
-
388
-	lcr_db_close();
389
-
390
-	/* Assign parameter names */
391
-	if (str2int(&gw_uri_avp, &par) == 0) {
392
-	    gw_uri_name.n = par;
393
-	    gw_uri_avp_name_str = 0;
394
-	} else {
395
-	    gw_uri_name.s = gw_uri_avp;
396
-	    gw_uri_avp_name_str = AVP_NAME_STR;
397
-	}
398
-	if (str2int(&contact_avp, &par) == 0) {
399
-	    contact_name.n = par;
400
-	    contact_avp_name_str = 0;
401
-	} else {
402
-	    contact_name.s = contact_avp;
403
-	    contact_avp_name_str = AVP_NAME_STR;
404
-	}
405
-	if (str2int(&rpid_avp, &par) == 0) {
406
-	    rpid_name.n = par;
407
-	    rpid_avp_name_str = 0;
408
-	} else {
409
-	    rpid_name.s = rpid_avp;
410
-	    rpid_avp_name_str = AVP_NAME_STR;
411
-	}
412
-
413
-	if (get_avp_modparam(&inv_timer_avp, &tm_timer_param))
414
-		goto err;
415
-
416
-	if (inv_timer_ps.len) {
417
-		inv_timer_param = (avp_ident_t*)pkg_malloc(sizeof(avp_ident_t));
418
-		if (!inv_timer_param) {
419
-			ERR("lcr: Not enough memory\n");
420
-			return -1;
421
-		}
422
-		if (get_avp_modparam(&inv_timer_ps, inv_timer_param)) 
423
-			goto err;
424
-	}
425
-	
426
-	if (inv_timer_next_ps.len) {
427
-		inv_timer_next_param = (avp_ident_t*)pkg_malloc(sizeof(avp_ident_t));
428
-		if (!inv_timer_next_param) {
429
-			ERR("lcr: Not enough memory\n");
430
-			return -1;
431
-		}
432
-		if (get_avp_modparam(&inv_timer_next_ps, inv_timer_next_param)) 
433
-			goto err;
434
-	}
435
-	
436
-	return 0;
437
-	
438
- err:
439
-	return -1;
440
-}
441
-
442
-
443
-static void destroy(void)
444
-{
445
-	lcr_db_close();
446
-	
447
-	if (inv_timer_param) pkg_free(inv_timer_param);
448
-	if (inv_timer_next_param) pkg_free(inv_timer_next_param);
449
-}
450
-
451
-
452
-/*
453
- * Reload gws to unused gw table and when done, make the unused gw table
454
- * the one in use.
455
- */
456
-int reload_gws ( void )
457
-{
458
-    int i;
459
-    unsigned int ip_addr, port, prefix_len;
460
-    uri_type scheme;
461
-    uri_transport transport;
462
-    char* prefix;
463
-    db_res_t* res;
464
-    db_rec_t* rec;
465
-	
466
-	res = NULL;
467
-	if (db_exec(&res, lcr_reload) < 0) {
468
-		ERR("lcr: Failed to query gw data\n");
469
-		goto error;
470
-	}
471
-	if (res == NULL) {
472
-		ERR("lcr: Gw table query returned no data\n");
473
-		goto error;
474
-	}
475
-
476
-	for(rec = db_first(res), i = 0; rec; rec = db_next(res), i++) {
477
-		if (i >= MAX_NO_OF_GWS) {
478
-			ERR("lcr: Too many gw entries\n");
479
-			goto error;
480
-		}
481
-
482
-		if (rec->fld[0].flags & DB_NULL) {
483
-			ERR("lcr: IP address of GW is NULL\n");
484
-			goto error;
485
-		}
486
-		ip_addr = (unsigned int)rec->fld[0].v.int4;
487
-
488
-		if (rec->fld[1].flags & DB_NULL) port = 0;
489
-		else port = (unsigned int)rec->fld[1].v.int4;
490
-
491
-		if (port > 65535) {
492
-			ERR("lcr: Port of GW is too large: %u\n", port);
493
-			goto error;
494
-		}
495
-
496
-		if (rec->fld[2].flags & DB_NULL) scheme = SIP_URI_T;
497
-		else {
498
-			scheme = (uri_type)rec->fld[2].v.int4;
499
-			if ((scheme != SIP_URI_T) && (scheme != SIPS_URI_T)) {
500
-				ERR("lcr: Unknown or unsupported URI scheme: %u\n", (unsigned int)scheme);
501
-				goto error;
502
-			}
503
-		}
504
-
505
-		if (rec->fld[3].flags & DB_NULL) transport = PROTO_NONE;
506
-		else {
507
-			transport = (uri_transport)rec->fld[3].v.int4;
508
-			if ((transport != PROTO_UDP) && (transport != PROTO_TCP) &&
509
-				(transport != PROTO_TLS) && (transport != PROTO_SCTP)) {
510
-				ERR("lcr: Unknown or unsupported transport: %u\n", (unsigned int)transport);
511
-				goto error;
512
-			}
513
-		}
514
-
515
-		if (rec->fld[4].flags & DB_NULL) {
516
-			prefix_len = 0;
517
-			prefix = NULL;
518
-		} else {
519
-			prefix = rec->fld[4].v.lstr.s;
520
-			prefix_len = rec->fld[4].v.lstr.len;
521
-			if (prefix_len > MAX_PREFIX_LEN) {
522
-				ERR("lcr: Too long prefix\n");
523
-				goto error;
524
-			}
525
-		}
526
-
527
-		if (*gws == gws_1) {
528
-			gws_2[i].ip_addr = ip_addr;
529
-			gws_2[i].port = port;
530
-			gws_2[i].scheme = scheme;
531
-			gws_2[i].transport = transport;
532
-			gws_2[i].prefix_len = prefix_len;
533
-			if (prefix_len)
534
-				memcpy(&(gws_2[i].prefix[0]), prefix, prefix_len);
535
-		} else {
536
-			gws_1[i].ip_addr = ip_addr;
537
-			gws_1[i].port = port;
538
-			gws_1[i].scheme = scheme;
539
-			gws_1[i].transport = transport;
540
-			gws_1[i].prefix_len = prefix_len;
541
-			if (prefix_len)
542
-				memcpy(&(gws_1[i].prefix[0]), prefix, prefix_len);
543
-		}
544
-	}
545
-
546
-	db_res_free(res);
547
-
548
-    if (*gws == gws_1) {
549
-	    gws_2[i].ip_addr = 0;
550
-	    *gws = gws_2;
551
-    } else {
552
-	    gws_1[i].ip_addr = 0;
553
-	    *gws = gws_1;
554
-    }
555
-    return 1;
556
-
557
-	error:
558
-	if (res) db_res_free(res);
559
-	return -1;
560
-}
561
-
562
-/*
563
- * Load GW info from database to lcr_gw_addr_port AVPs
564
- */
565
-int load_gws(struct sip_msg* _m, char* _s1, char* _s2)
566
-{
567
-    db_res_t* res = NULL;
568
-    db_rec_t *rec;
569
-    str ruri_user, from_uri, value, addr_str, port_str;
570
-    static char ruri[MAX_URI_SIZE];
571
-    unsigned int i, j, prefix_len, addr, port;
572
-    uri_type scheme;
573
-    uri_transport transport;
574
-    struct ip_addr address;
575
-    char *at, *prefix;
576
-    int_str val;
577
-
578
-    /* Find Request-URI user */
579
-    if (parse_sip_msg_uri(_m) < 0) {
580
-	    ERR("lcr: Error while parsing R-URI\n");
581
-	    return -1;
582
-    }
583
-    ruri_user = _m->parsed_uri.user;
584
-	
585
-	/* Look for Caller RPID or From URI */
586
-    if (search_first_avp(rpid_avp_name_str, rpid_name, &val, 0) &&
587
-		val.s.s && val.s.len) {
588
-		/* Get URI user from RPID */
589
-		from_uri.len = val.s.len;
590
-		from_uri.s = val.s.s;
591
-    } else {
592
-		/* Get URI from From URI */
593
-		if ((!_m->from) && (parse_headers(_m, HDR_FROM_F, 0) == -1)) {
594
-			ERR("lcr: Error while parsing message\n");
595
-			return -1;
596
-		}
597
-		if (!_m->from) {
598
-			ERR("lcr: FROM header field not found\n");
599
-			return -1;
600
-		}
601
-		if ((!(_m->from)->parsed) && (parse_from_header(_m) < 0)) {
602
-			ERR("lcr: Error while parsing From body\n");
603
-			return -1;
604
-		}
605
-		from_uri = get_from(_m)->uri;
606
-    }
607
-	
608
-	lcr_load->match[0].v.lstr = from_uri;
609
-	lcr_load->match[1].v.lstr = ruri_user;
610
-
611
-    if (db_exec(&res, lcr_load) < 0) {
612
-		ERR("lcr: Failed to query accept data\n");
613
-		return -1;
614
-    }
615
-	if (res == NULL) {
616
-		ERR("lcr: Database query did not return any result\n");
617
-		return -1;
618
-	}
619
-
620
-	addrs_top = 0;
621
-	for(i = 0, rec = db_first(res); rec; rec = db_next(res), i++) {
622
-		if (rec->fld[0].flags & DB_NULL) {
623
-			ERR("lcr: Gateway IP address is NULL\n");
624
-			continue;
625
-		}
626
-      	addr = (unsigned int)rec->fld[0].v.int4;
627
-
628
-		if (addrs_top >= MAX_BRANCHES) {
629
-			INFO("lcr: Too many destinations\n");
630
-			goto end;
631
-		}
632
-		for(j = 0; j < addrs_top; j++) {
633
-			if (addrs[j] == addr) goto skip;
634
-		}
635
-		addrs[addrs_top++] = addr;
636
-
637
-		if (rec->fld[1].flags & DB_NULL) port = 0;
638
-		else port = (unsigned int)rec->fld[1].v.int4;
639
-
640
-		if (rec->fld[2].flags & DB_NULL) scheme = SIP_URI_T;
641
-		else scheme = (uri_type)rec->fld[2].v.int4;
642
-
643
-		if (rec->fld[3].flags & DB_NULL) transport = PROTO_NONE;
644
-		else transport = (uri_transport)rec->fld[3].v.int4;
645
-
646
-		if (rec->fld[4].flags & DB_NULL) {
647
-			prefix = NULL;
648
-			prefix_len = 0;
649
-		} else {
650
-			prefix = rec->fld[4].v.lstr.s;
651
-			prefix_len = rec->fld[4].v.lstr.len;
652
-		}
653
-
654
-		if (5 + prefix_len + ruri_user.len + 1 + 15 + 1 + 5 + 1 + 14 > MAX_URI_SIZE) {
655
-			ERR("lcr: Request URI would be too long\n");
656
-			continue;
657
-		}
658
-
659
-		at = (char *)&(ruri[0]);
660
-		if (scheme == SIP_URI_T) {
661
-			memcpy(at, "sip:", 4); at = at + 4;
662
-		} else if (scheme == SIPS_URI_T) {
663
-			memcpy(at, "sips:", 5); at = at + 5;
664
-		} else {
665
-			ERR("lcr: Unknown or unsupported URI scheme: %u\n", (unsigned int)scheme);
666
-			continue;
667
-		}
668
-
669
-		if (prefix_len) {
670
-			memcpy(at, prefix, prefix_len); at = at + prefix_len;
671
-		}
672
-		memcpy(at, ruri_user.s, ruri_user.len); at = at + ruri_user.len;
673
-		*at = '@'; at = at + 1;
674
-		address.af = AF_INET;
675
-		address.len = 4;
676
-		address.u.addr32[0] = addr;
677
-		addr_str.s = ip_addr2a(&address);
678
-		addr_str.len = strlen(addr_str.s);
679
-		memcpy(at, addr_str.s, addr_str.len); at = at + addr_str.len;
680
-		if (port != 0) {
681
-			if (port > 65535) {
682
-				ERR("lcr: Port of GW is too large: %u\n", port);
683
-				continue;
684
-			}
685
-			*at = ':'; at = at + 1;
686
-			port_str.s = int2str(port, &port_str.len);
687
-			memcpy(at, port_str.s, port_str.len); at = at + port_str.len;
688
-		}
689
-		if (transport != PROTO_NONE) {
690
-			memcpy(at, ";transport=", 11); at = at + 11;
691
-			if (transport == PROTO_UDP) {
692
-				memcpy(at, "udp", 3); at = at + 3;
693
-			} else if (transport == PROTO_TCP) {
694
-				memcpy(at, "tcp", 3); at = at + 3;
695
-			} else if (transport == PROTO_TLS) {
696
-				memcpy(at, "tls", 3); at = at + 3;
697
-			} else if (transport == PROTO_SCTP) {
698
-				memcpy(at, "sctp", 4); at = at + 4;
699