Browse code

Merge remote branch 'origin/tmp/core_events'

* origin/tmp/core_events:
core ev: minor cleanups
topoh: new module for hiding topology details
core: new sr events system
core: execute callbacks for NET_DATA_IN and NET_DATA_OUT

Andrei Pelinescu-Onciul authored on 09/10/2009 12:16:41
Showing 14 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,98 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2009 SIP-Router.org
5
+ *
6
+ * This file is part of Extensible SIP Router, a free SIP server.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ */
20
+
21
+#include "dprint.h"
22
+#include "mem/mem.h"
23
+#include "events.h"
24
+
25
+static sr_event_cb_t _sr_events_list;
26
+static int _sr_events_inited = 0;
27
+
28
+void sr_event_cb_init(void)
29
+{
30
+	if(_sr_events_inited == 0)
31
+	{
32
+		memset(&_sr_events_list, 0, sizeof(sr_event_cb_t));
33
+		_sr_events_inited = 1;
34
+	}
35
+}
36
+
37
+int sr_event_register_cb(int type, sr_event_cb_f f)
38
+{
39
+	sr_event_cb_init();
40
+	switch(type) {
41
+		case SREV_NET_DATA_IN:
42
+				if(_sr_events_list.net_data_in==0)
43
+					_sr_events_list.net_data_in = f;
44
+				else return -1;
45
+			break;
46
+		case SREV_NET_DATA_OUT:
47
+				if(_sr_events_list.net_data_out==0)
48
+					_sr_events_list.net_data_out = f;
49
+				else return -1;
50
+			break;
51
+		default:
52
+			return -1;
53
+	}
54
+	return 0;
55
+}
56
+
57
+int sr_event_exec(int type, void *data)
58
+{
59
+	int ret;
60
+	str *p;
61
+	switch(type) {
62
+		case SREV_NET_DATA_IN:
63
+				if(unlikely(_sr_events_list.net_data_in!=0))
64
+				{
65
+					p = (str*)data;
66
+#ifdef EXTRA_DEBUG
67
+					LM_DBG("PRE-IN ++++++++++++++++++++++++++++++++\n"
68
+							"%.*s\n+++++\n", p->len, p->s);
69
+#endif /* EXTRA_DEBUG */
70
+					ret = _sr_events_list.net_data_in(data);
71
+#ifdef EXTRA_DEBUG
72
+					LM_DBG("POST-IN ++++++++++++++++++++++++++++++++\n"
73
+							"%.*s\n+++++\n", p->len, p->s);
74
+#endif /* EXTRA_DEBUG */
75
+					return ret;
76
+				} else return 1;
77
+			break;
78
+		case SREV_NET_DATA_OUT:
79
+				if(unlikely(_sr_events_list.net_data_out!=0))
80
+				{
81
+					p = (str*)data;
82
+#ifdef EXTRA_DEBUG
83
+					LM_DBG("PRE-OUT ++++++++++++++++++++\n"
84
+							"%.*s\n+++++++++++++++++++\n", p->len, p->s);
85
+#endif /* EXTRA_DEBUG */
86
+					ret = _sr_events_list.net_data_out(data);
87
+#ifdef EXTRA_DEBUG
88
+					LM_DBG("POST-OUT ++++++++++++++++++++\n"
89
+							"%.*s\n+++++++++++++++++++\n", p->len, p->s);
90
+#endif /* EXTRA_DEBUG */
91
+					return ret;
92
+				} else return 1;
93
+			break;
94
+		default:
95
+			return -1;
96
+	}
97
+}
98
+
0 99
new file mode 100644
... ...
@@ -0,0 +1,40 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2009 SIP-Router.org
5
+ *
6
+ * This file is part of Extensible SIP Router, a free SIP server.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ */
20
+
21
+#ifndef _SR_EVENTS_H_
22
+#define _SR_EVENTS_H_
23
+
24
+#include "parser/msg_parser.h"
25
+
26
+#define SREV_NET_DATA_IN	1
27
+#define SREV_NET_DATA_OUT	2
28
+
29
+typedef int (*sr_event_cb_f)(void *data);
30
+
31
+typedef struct sr_event_cb {
32
+	sr_event_cb_f net_data_in;
33
+	sr_event_cb_f net_data_out;
34
+} sr_event_cb_t;
35
+
36
+void sr_event_cb_init(void);
37
+int sr_event_register_cb(int type, sr_event_cb_f f);
38
+int sr_event_exec(int type, void *data);
39
+
40
+#endif
... ...
@@ -60,6 +60,7 @@
60 60
 #endif
61 61
 
62 62
 #include "compiler_opt.h"
63
+#include "events.h"
63 64
 
64 65
 
65 66
 enum ss_mismatch {
... ...
@@ -117,9 +118,14 @@ int forward_reply( struct sip_msg* msg);
117 118
  *         that generated them; use 0 if you don't want this)
118 119
  * buf, len = buffer
119 120
  * returns: 0 if ok, -1 on error*/
121
+
120 122
 static inline int msg_send(struct dest_info* dst, char* buf, int len)
121 123
 {
122 124
 	struct dest_info new_dst;
125
+	str outb;
126
+	outb.s = buf;
127
+	outb.len = len;
128
+	sr_event_exec(SREV_NET_DATA_OUT, (void*)&outb);
123 129
 	
124 130
 	if (likely(dst->proto==PROTO_UDP)){
125 131
 		if (unlikely((dst->send_sock==0) || 
... ...
@@ -132,7 +138,7 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
132 138
 			}
133 139
 			dst=&new_dst;
134 140
 		}
135
-		if (unlikely(udp_send(dst, buf, len)==-1)){
141
+		if (unlikely(udp_send(dst, outb.s, outb.len)==-1)){
136 142
 			STATS_TX_DROPS;
137 143
 			LOG(L_ERR, "msg_send: ERROR: udp_send failed\n");
138 144
 			goto error;
... ...
@@ -146,7 +152,7 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
146 152
 					" support is disabled\n");
147 153
 			goto error;
148 154
 		}else{
149
-			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
155
+			if (unlikely(tcp_send(dst, 0, outb.s, outb.len)<0)){
150 156
 				STATS_TX_DROPS;
151 157
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
152 158
 				goto error;
... ...
@@ -161,7 +167,7 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
161 167
 					" support is disabled\n");
162 168
 			goto error;
163 169
 		}else{
164
-			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
170
+			if (unlikely(tcp_send(dst, 0, outb.s, outb.len)<0)){
165 171
 				STATS_TX_DROPS;
166 172
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
167 173
 				goto error;
... ...
@@ -187,7 +193,7 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
187 193
 				}
188 194
 				dst=&new_dst;
189 195
 			}
190
-			if (unlikely(sctp_msg_send(dst, buf, len)<0)){
196
+			if (unlikely(sctp_msg_send(dst, outb.s, outb.len)<0)){
191 197
 				STATS_TX_DROPS;
192 198
 				LOG(L_ERR, "msg_send: ERROR: sctp_msg_send failed\n");
193 199
 				goto error;
... ...
@@ -199,8 +205,12 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
199 205
 			LOG(L_CRIT, "BUG: msg_send: unknown proto %d\n", dst->proto);
200 206
 			goto error;
201 207
 	}
208
+	if(outb.s != buf)
209
+		pkg_free(outb.s);
202 210
 	return 0;
203 211
 error:
212
+	if(outb.s != buf)
213
+		pkg_free(outb.s);
204 214
 	return -1;
205 215
 }
206 216
 
207 217
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+# $Id$
2
+#
3
+# example module makefile
4
+#
5
+# 
6
+# WARNING: do not run this directly, it should be run by the master Makefile
7
+
8
+include ../../Makefile.defs
9
+auto_gen=
10
+NAME=topoh.so
11
+LIBS=
12
+
13
+DEFS+=-DOPENSER_MOD_INTERFACE
14
+
15
+include ../../Makefile.modules
0 16
new file mode 100644
... ...
@@ -0,0 +1,186 @@
1
+topoh Module
2
+
3
+Daniel-Constantin Mierla
4
+
5
+   <miconda@gmail.com>
6
+
7
+Edited by
8
+
9
+Daniel-Constantin Mierla
10
+
11
+   <miconda@gmail.com>
12
+
13
+   Copyright � 2009 FhG FOKUS
14
+     __________________________________________________________________
15
+
16
+   Table of Contents
17
+
18
+   1. Admin Guide
19
+
20
+        1. Overview
21
+        2. Dependencies
22
+
23
+              2.1. Kamailio Modules
24
+              2.2. External Libraries or Applications
25
+
26
+        3. Exported Parameters
27
+
28
+              3.1. mask_key (str)
29
+              3.2. mask_callid (integer)
30
+              3.3. uparam_name (str)
31
+              3.4. uparam_prefix (str)
32
+              3.5. vparam_name (str)
33
+              3.6. vparam_prefix (str)
34
+
35
+        4. Exported Functions
36
+
37
+              4.1.
38
+
39
+   List of Examples
40
+
41
+   1.1. Set mask_key parameter
42
+   1.2. Set mask_callid parameter
43
+   1.3. Set uparam_name parameter
44
+   1.4. Set uparam_prefix parameter
45
+   1.5. Set vparam_name parameter
46
+   1.6. Set vparam_prefix parameter
47
+
48
+Chapter 1. Admin Guide
49
+
50
+   Table of Contents
51
+
52
+   1. Overview
53
+   2. Dependencies
54
+
55
+        2.1. Kamailio Modules
56
+        2.2. External Libraries or Applications
57
+
58
+   3. Exported Parameters
59
+
60
+        3.1. mask_key (str)
61
+        3.2. mask_callid (integer)
62
+        3.3. uparam_name (str)
63
+        3.4. uparam_prefix (str)
64
+        3.5. vparam_name (str)
65
+        3.6. vparam_prefix (str)
66
+
67
+   4. Exported Functions
68
+
69
+        4.1.
70
+
71
+1. Overview
72
+
73
+   This module hides the routing headers that show topology details. It it
74
+   is not affected by the server being transaction statless or stateful.
75
+   The script interpretor gets the SIP messages decoded, so all
76
+   functionality existing so far is preserved.
77
+
78
+   The module is transparent for config writer. It only needs to be loaded
79
+   (tune the parameters if wanted). The SIP server can be restarted
80
+   whitout affecting ongoing calls - once it is up, can encode/decode
81
+   topology details, thus no call is lost.
82
+
83
+   By using same mask_key, many SIP servers can decode the message, for
84
+   examlple, applicable for servers behind load balancers.
85
+
86
+2. Dependencies
87
+
88
+   2.1. Kamailio Modules
89
+   2.2. External Libraries or Applications
90
+
91
+2.1. Kamailio Modules
92
+
93
+   The following modules must be loaded before this module:
94
+     * rr module - server must perform record routing to ensure in-dialog
95
+       requests are encoded/decoded.
96
+
97
+2.2. External Libraries or Applications
98
+
99
+   The following libraries or applications must be installed before
100
+   running Kamailio with this module loaded:
101
+     * None. In the future the module can be enhnaced to use a stronger
102
+       encryption algorithm.
103
+
104
+3. Exported Parameters
105
+
106
+   3.1. mask_key (str)
107
+   3.2. mask_callid (integer)
108
+   3.3. uparam_name (str)
109
+   3.4. uparam_prefix (str)
110
+   3.5. vparam_name (str)
111
+   3.6. vparam_prefix (str)
112
+
113
+3.1. mask_key (str)
114
+
115
+   Keyword to mask the headers.
116
+
117
+   Default value is "_static_value_".
118
+
119
+   Example 1.1. Set mask_key parameter
120
+...
121
+modparam("topoh", "mask_key", "some secret here")
122
+...
123
+
124
+3.2. mask_callid (integer)
125
+
126
+   Whether to encode or not the call-id. Some SIP extensions include the
127
+   call-id in SIP message payload or header, so it is safe to not encode
128
+   call-id in such cases. Well-known extensions such as call transfer or
129
+   conference join will be added to work with encoded call-id.
130
+
131
+   Default value is 0 (do not mask).
132
+
133
+   Example 1.2. Set mask_callid parameter
134
+...
135
+modparam("topoh", "mask_callid", 1)
136
+...
137
+
138
+3.3. uparam_name (str)
139
+
140
+   Name of URI param where to store encoded value.
141
+
142
+   Default value is "line".
143
+
144
+   Example 1.3. Set uparam_name parameter
145
+...
146
+modparam("topoh", "uparam_name", "myparam")
147
+...
148
+
149
+3.4. uparam_prefix (str)
150
+
151
+   Prefix to be added in encoded URI params.
152
+
153
+   Default value is "sr-".
154
+
155
+   Example 1.4. Set uparam_prefix parameter
156
+...
157
+modparam("topoh", "uparam_prefix", "xyz")
158
+...
159
+
160
+3.5. vparam_name (str)
161
+
162
+   Name of Via param where to store encoded value.
163
+
164
+   Default value is "branch".
165
+
166
+   Example 1.5. Set vparam_name parameter
167
+...
168
+modparam("topoh", "vparam_name", "myv")
169
+...
170
+
171
+3.6. vparam_prefix (str)
172
+
173
+   Prefix to be added in encoded Via params.
174
+
175
+   Default value is "z9hG4bKsr-".
176
+
177
+   Example 1.6. Set vparam_prefix parameter
178
+...
179
+modparam("topoh", "vparam_prefix", "xyz")
180
+...
181
+
182
+4. Exported Functions
183
+
184
+   4.1.
185
+
186
+   None.
0 187
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+docs = topoh.xml
2
+
3
+docbook_dir = ../../../docbook
4
+include $(docbook_dir)/Makefile.module
0 5
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+
11
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
12
+    <bookinfo>
13
+	<title>topoh Module</title>
14
+	<productname class="trade">sip-router.org</productname>
15
+	<authorgroup>
16
+	    <author>
17
+		<firstname>Daniel-Constantin</firstname>
18
+		<surname>Mierla</surname>
19
+		<email>miconda@gmail.com</email>
20
+	    </author>
21
+	    <editor>
22
+		<firstname>Daniel-Constantin</firstname>
23
+		<surname>Mierla</surname>
24
+		<email>miconda@gmail.com</email>
25
+	    </editor>
26
+	</authorgroup>
27
+	<copyright>
28
+	    <year>2009</year>
29
+	    <holder>&fhg;</holder>
30
+	</copyright>
31
+    </bookinfo>
32
+    <toc></toc>
33
+    
34
+    <xi:include href="topoh_admin.xml"/>
35
+    
36
+    
37
+</book>
0 38
new file mode 100644
... ...
@@ -0,0 +1,198 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+<!-- Module User's Guide -->
11
+
12
+<chapter>
13
+	
14
+	<title>&adminguide;</title>
15
+	
16
+	<section>
17
+	<title>Overview</title>
18
+	<para>
19
+		This module hides the routing headers that show topology details.
20
+		It it is not affected by the server being transaction statless or
21
+		stateful. The script interpretor gets the SIP messages decoded,
22
+		so all functionality existing so far is preserved.
23
+	</para>
24
+	<para>
25
+		The module is transparent for config writer. It only needs to be
26
+		loaded (tune the parameters if wanted). The SIP server can be restarted
27
+		whitout affecting ongoing calls - once it is up, can encode/decode
28
+		topology details, thus no call is lost.
29
+	</para>
30
+	<para>
31
+		By using same mask_key, many SIP servers can decode the message,
32
+		for examlple, applicable for servers behind load balancers.
33
+	</para>
34
+	</section>
35
+	<section>
36
+	<title>Dependencies</title>
37
+	<section>
38
+		<title>&kamailio; Modules</title>
39
+		<para>
40
+		The following modules must be loaded before this module:
41
+			<itemizedlist>
42
+			<listitem>
43
+			<para>
44
+				<emphasis>rr module</emphasis> - server must perform record
45
+				routing to ensure in-dialog requests are encoded/decoded.
46
+			</para>
47
+			</listitem>
48
+			</itemizedlist>
49
+		</para>
50
+	</section>
51
+	<section>
52
+		<title>External Libraries or Applications</title>
53
+		<para>
54
+		The following libraries or applications must be installed before running
55
+		&kamailio; with this module loaded:
56
+			<itemizedlist>
57
+			<listitem>
58
+			<para>
59
+				<emphasis>None</emphasis>. In the future the module can be
60
+				enhnaced to use a stronger encryption algorithm.
61
+			</para>
62
+			</listitem>
63
+			</itemizedlist>
64
+		</para>
65
+	</section>
66
+	</section>
67
+	<section>
68
+	<title>Exported Parameters</title>
69
+	<section>
70
+		<title><varname>mask_key</varname> (str)</title>
71
+		<para>
72
+		Keyword to mask the headers.
73
+		</para>
74
+		<para>
75
+		<emphasis>
76
+			Default value is "_static_value_".
77
+		</emphasis>
78
+		</para>
79
+		<example>
80
+		<title>Set <varname>mask_key</varname> parameter</title>
81
+		<programlisting format="linespecific">
82
+...
83
+modparam("topoh", "mask_key", "some secret here")
84
+...
85
+</programlisting>
86
+		</example>
87
+	</section>
88
+	<section>
89
+		<title><varname>mask_callid</varname> (integer)</title>
90
+		<para>
91
+			Whether to encode or not the call-id. Some SIP extensions include
92
+			the call-id in SIP message payload or header, so it is safe to
93
+			not encode call-id in such cases. Well-known extensions such as
94
+			call transfer or conference join will be added to work with encoded
95
+			call-id.
96
+		</para>
97
+		<para>
98
+		<emphasis>
99
+			Default value is 0 (do not mask).
100
+		</emphasis>
101
+		</para>
102
+		<example>
103
+		<title>Set <varname>mask_callid</varname> parameter</title>
104
+		<programlisting format="linespecific">
105
+...
106
+modparam("topoh", "mask_callid", 1)
107
+...
108
+</programlisting>
109
+		</example>
110
+	</section>
111
+	<section>
112
+		<title><varname>uparam_name</varname> (str)</title>
113
+		<para>
114
+		Name of URI param where to store encoded value.
115
+		</para>
116
+		<para>
117
+		<emphasis>
118
+			Default value is "line".
119
+		</emphasis>
120
+		</para>
121
+		<example>
122
+		<title>Set <varname>uparam_name</varname> parameter</title>
123
+		<programlisting format="linespecific">
124
+...
125
+modparam("topoh", "uparam_name", "myparam")
126
+...
127
+</programlisting>
128
+		</example>
129
+	</section>
130
+	<section>
131
+		<title><varname>uparam_prefix</varname> (str)</title>
132
+		<para>
133
+		Prefix to be added in encoded URI params.
134
+		</para>
135
+		<para>
136
+		<emphasis>
137
+			Default value is "sr-".
138
+		</emphasis>
139
+		</para>
140
+		<example>
141
+		<title>Set <varname>uparam_prefix</varname> parameter</title>
142
+		<programlisting format="linespecific">
143
+...
144
+modparam("topoh", "uparam_prefix", "xyz")
145
+...
146
+</programlisting>
147
+		</example>
148
+	</section>
149
+		<section>
150
+		<title><varname>vparam_name</varname> (str)</title>
151
+		<para>
152
+		Name of Via param where to store encoded value.
153
+		</para>
154
+		<para>
155
+		<emphasis>
156
+			Default value is "branch".
157
+		</emphasis>
158
+		</para>
159
+		<example>
160
+		<title>Set <varname>vparam_name</varname> parameter</title>
161
+		<programlisting format="linespecific">
162
+...
163
+modparam("topoh", "vparam_name", "myv")
164
+...
165
+</programlisting>
166
+		</example>
167
+	</section>
168
+	<section>
169
+		<title><varname>vparam_prefix</varname> (str)</title>
170
+		<para>
171
+		Prefix to be added in encoded Via params.
172
+		</para>
173
+		<para>
174
+		<emphasis>
175
+			Default value is "z9hG4bKsr-".
176
+		</emphasis>
177
+		</para>
178
+		<example>
179
+		<title>Set <varname>vparam_prefix</varname> parameter</title>
180
+		<programlisting format="linespecific">
181
+...
182
+modparam("topoh", "vparam_prefix", "xyz")
183
+...
184
+</programlisting>
185
+		</example>
186
+	</section>
187
+
188
+	</section>
189
+	<section>
190
+	<title>Exported Functions</title>
191
+	<section>
192
+		<para>
193
+			None.
194
+		</para>
195
+	</section>
196
+	</section>
197
+</chapter>
198
+
0 199
new file mode 100644
... ...
@@ -0,0 +1,175 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2009 SIP-Router.org
5
+ *
6
+ * This file is part of Extensible SIP Router, a free SIP server.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ */
20
+
21
+#include <string.h>
22
+
23
+#include "../../dprint.h"
24
+#include "../../md5.h"
25
+#include "../../crc.h"
26
+#include "../../mem/mem.h"
27
+#include "th_mask.h"
28
+
29
+#define TH_EB64I \
30
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-"
31
+
32
+char _th_EB64[65];
33
+int _th_DB64[256];
34
+char *_th_PD64 = "*";
35
+
36
+extern str _th_key;
37
+
38
+void th_shuffle(char *in, int size)
39
+{
40
+	char tmp;
41
+	int last;
42
+	unsigned int r;
43
+	unsigned char md5[16];
44
+	unsigned int *md5i;
45
+	unsigned int crc;
46
+	MD5_CTX ctx;
47
+
48
+	MD5Init(&ctx);
49
+	MD5Update(&ctx, _th_key.s, _th_key.len);
50
+	MD5Update(&ctx, _th_key.s, _th_key.len);
51
+	MD5Final(md5, &ctx);
52
+
53
+	md5i = (unsigned int*)md5;
54
+
55
+	crc = (unsigned int)crcitt_string(_th_key.s, _th_key.len);
56
+	for (last = size; last > 1; last--)
57
+	{
58
+		r = (md5i[(crc+last+_th_key.len)%4]
59
+				+ _th_key.s[(crc+last+_th_key.len)%_th_key.len]) % last;
60
+		tmp = in[r];
61
+		in[r] = in[last - 1];
62
+		in[last - 1] = tmp;
63
+	}
64
+}
65
+
66
+void th_mask_init(void)
67
+{
68
+	int i;
69
+
70
+	_th_key.len = strlen(_th_key.s);
71
+	memcpy(_th_EB64, TH_EB64I, sizeof(TH_EB64I));
72
+	th_shuffle(_th_EB64, 64);
73
+	LM_ERR("+++ %s\n", TH_EB64I);
74
+	LM_ERR("+++ %s\n", _th_EB64);
75
+	for(i=0; i<256; i++)
76
+		_th_DB64[i] = -1;
77
+	for(i=0; i<64; i++)
78
+		_th_DB64[(int)_th_EB64[i]] = i;
79
+
80
+	return;
81
+}
82
+
83
+char* th_mask_encode(char *in, int ilen, str *prefix, int *olen)
84
+{
85
+	char *out;
86
+	int  left;
87
+	int  idx;
88
+	int  i;
89
+	int  r;
90
+	char *p;
91
+	int  block;
92
+
93
+	*olen = (((ilen+2)/3)<<2) + ((prefix!=NULL&&prefix->len>0)?prefix->len:0);
94
+	out = (char*)pkg_malloc((*olen+1)*sizeof(char));
95
+	if(out==NULL)
96
+	{
97
+		LM_ERR("no more pkg\n");
98
+		*olen = 0;
99
+		return NULL;
100
+	}
101
+	memset(out, 0, (*olen+1)*sizeof(char));
102
+	if(prefix!=NULL&&prefix->len>0)
103
+		memcpy(out, prefix->s, prefix->len);
104
+
105
+	p = out + (int)((prefix!=NULL&&prefix->len>0)?prefix->len:0);
106
+	for(idx=0; idx<ilen; idx+=3)
107
+	{
108
+		left = ilen - idx - 1 ;
109
+		left = (left>1)?2:left;
110
+
111
+		block = 0;
112
+		for(i=0, r=16; i<=left; i++, r-=8)
113
+			block += ((unsigned char)in[idx+i]) << r;
114
+
115
+		*(p++) = _th_EB64[(block >> 18) & 0x3f];
116
+		*(p++) = _th_EB64[(block >> 12) & 0x3f];
117
+		*(p++) = (left>0)?_th_EB64[(block >> 6) & 0x3f]:_th_PD64[0];
118
+		*(p++) = (left>1)?_th_EB64[block & 0x3f]:_th_PD64[0];
119
+	}
120
+
121
+	return out;
122
+}
123
+
124
+char* th_mask_decode(char *in, int ilen, str *prefix, int extra, int *olen)
125
+{
126
+	char *out;
127
+	int n;
128
+	int block;
129
+	int idx;
130
+	int i;
131
+	int j;
132
+	int end;
133
+	char c;
134
+
135
+	for(n=0,i=ilen-1; in[i]==_th_PD64[0]; i--)
136
+		n++;
137
+
138
+	*olen = (((ilen-((prefix!=NULL&&prefix->len>0)?prefix->len:0)) * 6) >> 3)
139
+				- n;
140
+	out = (char*)pkg_malloc((*olen+1+extra)*sizeof(char));
141
+
142
+	if(out==NULL)
143
+	{
144
+		LM_ERR("no more pkg\n");
145
+		*olen = 0;
146
+		return NULL;
147
+	}
148
+	memset(out, 0, (*olen+1+extra)*sizeof(char));
149
+
150
+	end = ilen - n;
151
+	i = (prefix!=NULL&&prefix->len>0)?prefix->len:0;
152
+	for(idx=0; i<end; idx+=3)
153
+	{
154
+		block = 0;
155
+		for(j=0; j<4 && i<end ; j++)
156
+		{
157
+			c = _th_DB64[(int)in[i++]];
158
+			if(c<0)
159
+			{
160
+				LM_ERR("invalid input string\"%.*s\"\n", ilen, in);
161
+				pkg_free(out);
162
+				*olen = 0;
163
+				return NULL;
164
+			}
165
+			block += c << (18 - 6*j);
166
+		}
167
+
168
+		for(j=0, n=16; j<3 && idx+j< *olen; j++, n-=8)
169
+			out[idx+j] = (char)((block >> n) & 0xff);
170
+	}
171
+
172
+	return out;
173
+}
174
+
175
+
0 176
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2009 SIP-Router.org
5
+ *
6
+ * This file is part of Extensible SIP Router, a free SIP server.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ */
20
+
21
+#ifndef _TH_MASK_H_
22
+#define _TH_MASK_H_
23
+
24
+#include "../../str.h"
25
+
26
+void th_mask_init(void);
27
+char* th_mask_encode(char *in, int ilen, str *prefix, int *olen);
28
+char* th_mask_decode(char *in, int ilen, str *prefix, int extra, int *olen);
29
+
30
+#endif
0 31
new file mode 100644
... ...
@@ -0,0 +1,913 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2009 SIP-Router.org
5
+ *
6
+ * This file is part of Extensible SIP Router, a free SIP server.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ */
20
+
21
+#include <string.h>
22
+
23
+#include "../../dprint.h"
24
+#include "../../mem/mem.h"
25
+#include "../../data_lump.h"
26
+#include "../../forward.h"
27
+#include "../../msg_translator.h"
28
+#include "../../parser/parse_rr.h"
29
+#include "../../parser/parse_uri.h"
30
+#include "../../parser/parse_param.h"
31
+#include "../../parser/parse_from.h"
32
+#include "../../parser/parse_to.h"
33
+#include "../../parser/parse_via.h"
34
+#include "../../parser/contact/parse_contact.h"
35
+#include "th_mask.h"
36
+#include "th_msg.h"
37
+
38
+extern str th_cookie_name;
39
+extern str th_cookie_value;
40
+extern str th_via_prefix;
41
+extern str th_uri_prefix;
42
+
43
+extern str th_ip;
44
+extern str th_uparam_name;
45
+extern str th_uparam_prefix;
46
+extern str th_vparam_name;
47
+extern str th_vparam_prefix;
48
+
49
+extern int th_param_mask_callid;
50
+
51
+int th_skip_rw(char *s, int len)
52
+{
53
+	while(len>0)
54
+	{
55
+		if(s[len-1]==' ' || s[len-1]=='\t' || s[len-1]=='\n' || s[len-1]=='\r'
56
+				|| s[len-1]==',')
57
+			len--;
58
+		else return len;
59
+	}
60
+	return 0;
61
+}
62
+
63
+struct via_param *th_get_via_param(struct via_body *via, str *name)
64
+{
65
+	struct via_param *p;
66
+	for(p=via->param_lst; p; p=p->next)
67
+	{
68
+		if(p->name.len==name->len
69
+				&& strncasecmp(p->name.s, name->s, name->len)==0)
70
+			return p;
71
+	}
72
+	return NULL;
73
+}
74
+
75
+int th_get_param_value(str *in, str *name, str *value)
76
+{
77
+	param_t* params = NULL;
78
+	param_t* p = NULL;
79
+	param_hooks_t phooks;
80
+	if (parse_params(in, CLASS_ANY, &phooks, &params)<0)
81
+		return -1;
82
+	for (p = params; p; p=p->next)
83
+	{
84
+		if (p->name.len==name->len
85
+				&& strncasecmp(p->name.s, name->s, name->len)==0)
86
+		{
87
+			*value = p->body;
88
+			free_params(params);
89
+			return 0;
90
+		}
91
+	}
92
+	
93
+	if(params) free_params(params);
94
+	return 1;
95
+
96
+}
97
+
98
+int th_get_uri_param_value(str *uri, str *name, str *value)
99
+{
100
+	struct sip_uri puri;
101
+
102
+	memset(value, 0, sizeof(str));
103
+	if(parse_uri(uri->s, uri->len, &puri)<0)
104
+		return -1;
105
+	return th_get_param_value(&puri.params, name, value);
106
+}
107
+
108
+int th_get_uri_type(str *uri, int *mode, str *value)
109
+{
110
+	struct sip_uri puri;
111
+	int ret;
112
+	str r2 = {"r2", 2};
113
+
114
+	memset(value, 0, sizeof(str));
115
+	*mode = 0;
116
+	if(parse_uri(uri->s, uri->len, &puri)<0)
117
+		return -1;
118
+
119
+	LM_DBG("+++++++++++ PARAMS [%.*s]\n", puri.params.len, puri.params.s);
120
+	if(puri.host.len==th_ip.len
121
+			&& strncasecmp(puri.host.s, th_ip.s, th_ip.len)==0)
122
+	{
123
+		/* host matches TH ip */
124
+		ret = th_get_param_value(&puri.params, &th_uparam_name, value);
125
+		if(ret<0)
126
+			return -1;
127
+		return 2; /* decode */
128
+	} else {
129
+		if(check_self(&puri.host, (puri.port_no)?puri.port_no:SIP_PORT, 0)==1)
130
+		{
131
+			/* myself -- matched on all protos */
132
+			ret = th_get_param_value(&puri.params, &r2, value);
133
+			if(ret<0)
134
+				return -1;
135
+			if(ret==1) /* not found */
136
+				return 0; /* skip */
137
+			LM_DBG("+++++++++++++++++++************ [%.*s]\n",
138
+					value->len, value->s);
139
+			if(value->len==2 && strncasecmp(value->s, "on", 2)==0)
140
+				*mode = 1;
141
+			memset(value, 0, sizeof(str));
142
+			return 0; /* skip */
143
+		} else {
144
+			return 1; /* encode */
145
+		}
146
+	}
147
+}
148
+
149
+int th_mask_via(sip_msg_t *msg)
150
+{
151
+	hdr_field_t *hdr;
152
+	struct via_body *via;
153
+	struct lump* l;
154
+	int i;
155
+	str out;
156
+	int vlen;
157
+
158
+	i=0;
159
+	for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr))
160
+	{
161
+		for(via=(struct via_body*)hdr->parsed; via; via=via->next)
162
+		{
163
+			i++;
164
+			LM_DBG("=======via[%d]\n", i);
165
+			LM_DBG("hdr: [%.*s]\n", via->hdr.len, via->hdr.s);
166
+			vlen = th_skip_rw(via->name.s, via->bsize);
167
+			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
168
+			if(i!=1)
169
+			{
170
+				out.s = th_mask_encode(via->name.s, vlen, &th_via_prefix,
171
+						&out.len);
172
+				if(out.s==NULL)
173
+				{
174
+					LM_ERR("cannot encode via %d\n", i);
175
+					return -1;
176
+				}
177
+					
178
+				LM_DBG("+body: %d: [%.*s]\n", out.len, out.len, out.s);
179
+				l=del_lump(msg, via->name.s-msg->buf, vlen, 0);
180
+				if (l==0)
181
+				{
182
+					LM_ERR("failed deleting via [%d]\n", i);
183
+					pkg_free(out.s);
184
+					return -1;
185
+				}
186
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
187
+					LM_ERR("could not insert new lump\n");
188
+					pkg_free(out.s);
189
+					return -1;
190
+				}
191
+			}
192
+		}
193
+	}
194
+	return 0;
195
+}
196
+
197
+int th_mask_callid(sip_msg_t *msg)
198
+{
199
+	struct lump* l;
200
+	str out;
201
+
202
+	if(th_param_mask_callid==0)
203
+		return 0;
204
+
205
+	if(msg->callid==NULL)
206
+	{
207
+		LM_ERR("cannot get Call-Id header\n");
208
+		return -1;
209
+	}
210
+				
211
+	out.s = th_mask_encode(msg->callid->body.s, msg->callid->body.len, 0,
212
+						&out.len);
213
+	if(out.s==NULL)
214
+	{
215
+		LM_ERR("cannot encode callid\n");
216
+		return -1;
217
+	}
218
+				
219
+	l=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, 0);
220
+	if (l==0)
221
+	{
222
+		LM_ERR("failed deleting callid\n");
223
+		pkg_free(out.s);
224
+		return -1;
225
+	}
226
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
227
+		LM_ERR("could not insert new lump\n");
228
+		pkg_free(out.s);
229
+		return -1;
230
+	}
231
+
232
+	return 0;
233
+}
234
+
235
+int th_mask_contact(sip_msg_t *msg)
236
+{
237
+	struct lump* l;
238
+	str out;
239
+	str in;
240
+	contact_t *c;
241
+
242
+	if(msg->contact==NULL) 
243
+	{
244
+		LM_DBG("no contact header\n");
245
+		return 0;
246
+	}
247
+
248
+	if(parse_contact(msg->contact) < 0)
249
+	{
250
+		LM_ERR("failed parsing contact header\n");
251
+		return -1;
252
+	}
253
+	
254
+	c = ((contact_body_t*)msg->contact->parsed)->contacts;
255
+	in = c->uri;
256
+
257
+	out.s = th_mask_encode(in.s, in.len, &th_uri_prefix, &out.len);
258
+	if(out.s==NULL)
259
+	{
260
+		LM_ERR("cannot encode contact uri\n");
261
+		return -1;
262
+	}
263
+				
264
+	l=del_lump(msg, in.s-msg->buf, in.len, 0);
265
+	if (l==0)
266
+	{
267
+		LM_ERR("failed deleting contact uri\n");
268
+		pkg_free(out.s);
269
+		return -1;
270
+	}
271
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
272
+		LM_ERR("could not insert new lump\n");
273
+		pkg_free(out.s);
274
+		return -1;
275
+	}
276
+
277
+	return 0;
278
+}
279
+
280
+int th_mask_record_route(sip_msg_t *msg)
281
+{
282
+	hdr_field_t *hdr;
283
+	struct lump* l;
284
+	int i;
285
+	rr_t *rr;
286
+	str out;
287
+
288
+	if(msg->record_route==NULL)
289
+	{
290
+		LM_DBG("no record route header\n");
291
+		return 0;
292
+	}
293
+	hdr = msg->record_route;
294
+	i = 0;
295
+	while(hdr!=NULL) 
296
+	{
297
+		if (parse_rr(hdr) < 0) 
298
+		{
299
+			LM_ERR("failed to parse RR\n");
300
+			return -1;
301
+		}
302
+
303
+		rr =(rr_t*)hdr->parsed;
304
+		while(rr)
305
+		{
306
+			i++;
307
+			if(i!=1)
308
+			{
309
+				out.s = th_mask_encode(rr->nameaddr.uri.s, rr->nameaddr.uri.len,
310
+						&th_uri_prefix, &out.len);
311
+				if(out.s==NULL)
312
+				{
313
+					LM_ERR("cannot encode r-r %d\n", i);
314
+					return -1;
315
+				}
316
+				l=del_lump(msg, rr->nameaddr.uri.s-msg->buf,
317
+						rr->nameaddr.uri.len, 0);
318
+				if (l==0)
319
+				{
320
+					LM_ERR("failed deleting r-r [%d]\n", i);
321
+					pkg_free(out.s);
322
+					return -1;
323
+				}
324
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
325
+					LM_ERR("could not insert new lump\n");
326
+					pkg_free(out.s);
327
+					return -1;
328
+				}
329
+			}
330
+			rr = rr->next;
331
+		}
332
+		hdr = next_sibling_hdr(hdr);
333
+	}
334
+
335
+	return 0;
336
+}
337
+
338
+int th_unmask_via(sip_msg_t *msg, str *cookie)
339
+{
340
+	hdr_field_t *hdr;
341
+	struct via_body *via;
342
+	struct via_body *via2;
343
+	struct via_param *vp;
344
+	struct lump* l;
345
+	int i;
346
+	str out;
347
+	int vlen;
348
+
349
+	i=0;
350
+	for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr))
351
+	{
352
+		for(via=(struct via_body*)hdr->parsed; via; via=via->next)
353
+		{
354
+			i++;
355
+			LM_DBG("=======via[%d]\n", i);
356
+			LM_DBG("hdr: [%.*s]\n", via->hdr.len, via->hdr.s);
357
+			vlen = th_skip_rw(via->name.s, via->bsize);
358
+			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
359
+			if(i!=1)
360
+			{
361
+				vp = th_get_via_param(via, &th_vparam_name);
362
+				if(vp==NULL)
363
+				{
364
+					LM_ERR("cannot find param in via %d\n", i);
365
+					return -1;
366
+				}
367
+				if(i==2)
368
+					out.s = th_mask_decode(vp->value.s, vp->value.len,
369
+							&th_vparam_prefix, CRLF_LEN+1, &out.len);
370
+				else
371
+					out.s = th_mask_decode(vp->value.s, vp->value.len,
372
+							&th_vparam_prefix, 0, &out.len);
373
+				if(out.s==NULL)
374
+				{
375
+					LM_ERR("cannot encode via %d\n", i);
376
+					return -1;
377
+				}
378
+					
379
+				LM_DBG("+body: %d: [%.*s]\n", out.len, out.len, out.s);
380
+				if(i==2)
381
+				{
382
+					via2=pkg_malloc(sizeof(struct via_body));
383
+					if (via2==0)
384
+					{
385
+						LM_ERR("out of memory\n");
386
+						pkg_free(out.s);
387
+						return -1;
388
+
389
+					}
390
+					
391
+					memset(via2, 0, sizeof(struct via_body));
392
+					memcpy(out.s+out.len, CRLF, CRLF_LEN);
393
+					out.s[out.len+CRLF_LEN]='X';
394
+					if(parse_via(out.s, out.s+out.len+CRLF_LEN+1, via2)==NULL)
395
+					{
396
+						LM_ERR("error parsing decoded via2\n");
397
+						free_via_list(via2);
398
+						pkg_free(out.s);
399
+						return -1;
400
+					}
401
+					out.s[out.len] = '\0';
402
+					vp = th_get_via_param(via2, &th_cookie_name);
403
+					if(vp==NULL)
404
+					{
405
+						LM_ERR("cannot find cookie in via2\n");
406
+						free_via_list(via2);
407
+						pkg_free(out.s);
408
+						return -1;
409
+					}
410
+					*cookie = vp->value;
411
+					free_via_list(via2);
412
+				}
413
+				l=del_lump(msg, via->name.s-msg->buf, vlen, 0);
414
+				if (l==0)
415
+				{
416
+					LM_ERR("failed deleting via [%d]\n", i);
417
+					pkg_free(out.s);
418
+					return -1;
419
+				}
420
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0)
421
+				{
422
+					LM_ERR("could not insert new lump\n");
423
+					pkg_free(out.s);
424
+					return -1;
425
+				}
426
+			}
427
+		}
428
+	}
429
+
430
+	return 0;
431
+}
432
+
433
+int th_unmask_callid(sip_msg_t *msg)
434
+{
435
+	struct lump* l;
436
+	str out;
437
+	
438
+	if(th_param_mask_callid==0)
439
+		return 0;
440
+	
441
+	if(msg->callid==NULL)
442
+	{
443
+		LM_ERR("cannot get Call-Id header\n");
444
+		return -1;
445
+	}
446
+				
447
+	out.s = th_mask_decode(msg->callid->body.s, msg->callid->body.len, 0, 0,
448
+						&out.len);
449
+	if(out.s==NULL)
450
+	{
451
+		LM_ERR("cannot decode callid\n");
452
+		return -1;
453
+	}
454
+				
455
+	l=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, 0);
456
+	if (l==0)
457
+	{
458
+		LM_ERR("failed deleting callid\n");
459
+		pkg_free(out.s);
460
+		return -1;
461
+	}
462
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
463
+		LM_ERR("could not insert new lump\n");
464
+		pkg_free(out.s);
465
+		return -1;
466
+	}
467
+
468
+	return 0;
469
+}
470
+
471
+int th_flip_record_route(sip_msg_t *msg, int mode)
472
+{
473
+	hdr_field_t *hdr;
474
+	struct lump* l;
475
+	int i;
476
+	rr_t *rr;
477
+	str out;
478
+	int utype;
479
+	str pval;
480
+	int r2;
481
+	int act;
482
+
483
+	if(msg->record_route==NULL)
484
+	{
485
+		LM_DBG("no record route header\n");
486
+		return 0;
487
+	}
488
+	hdr = msg->record_route;
489
+	i = 0;
490
+	act = 0;
491
+	if(mode==1)
492
+		act = 2;
493
+	while(hdr!=NULL) 
494
+	{
495
+		if (parse_rr(hdr) < 0) 
496
+		{
497
+			LM_ERR("failed to parse RR\n");
498
+			return -1;
499
+		}
500
+
501
+		rr =(rr_t*)hdr->parsed;
502
+		while(rr)
503
+		{
504
+			i++;
505
+			r2 = 0;
506
+			utype = th_get_uri_type(&rr->nameaddr.uri, &r2, &pval);
507
+			if(utype==0 && mode==1)
508
+			{
509
+				if(r2==1)
510
+				{
511
+					act--;
512
+					if(act==0)
513
+						return 0;
514
+					utype = 1;
515
+				} else {
516
+					return 0;
517
+				}
518
+			}
519
+			out.s = NULL;
520
+			switch(utype) {
521
+				case 1: /* encode */
522
+					if(act!=0 && mode==1)
523
+					{
524
+						out.s = th_mask_encode(rr->nameaddr.uri.s,
525
+							rr->nameaddr.uri.len, &th_uri_prefix, &out.len);
526
+						if(out.s==NULL)
527
+						{
528
+							LM_ERR("cannot encode r-r %d\n", i);
529
+							return -1;
530
+						}
531
+					}
532
+				break;
533
+				case 2: /* decode */
534
+					if(mode==0)
535
+					{
536
+						out.s = th_mask_decode(pval.s,
537
+							pval.len, &th_uparam_prefix, 0, &out.len);
538
+						if(out.s==NULL)
539
+						{
540
+							LM_ERR("cannot decode r-r %d\n", i);
541
+							return -1;
542
+						}
543
+					}
544
+				break;
545
+			}
546
+			if(out.s!=NULL)
547
+			{