Browse code

topoh: new module for hiding topology details

- transparent for script writer and processing type (stateless,
stateful)
- it is not affected by server restart
- can handle cloud deployments by using same secret key

Daniel-Constantin Mierla authored on 04/08/2009 14:53:44
Showing 10 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+# $Id$
1
+#
2
+# example module makefile
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=topoh.so
10
+LIBS=
11
+
12
+DEFS+=-DOPENSER_MOD_INTERFACE
13
+
14
+include ../../Makefile.modules
0 15
new file mode 100644
... ...
@@ -0,0 +1,186 @@
0
+topoh Module
1
+
2
+Daniel-Constantin Mierla
3
+
4
+   <miconda@gmail.com>
5
+
6
+Edited by
7
+
8
+Daniel-Constantin Mierla
9
+
10
+   <miconda@gmail.com>
11
+
12
+   Copyright � 2009 FhG FOKUS
13
+     __________________________________________________________________
14
+
15
+   Table of Contents
16
+
17
+   1. Admin Guide
18
+
19
+        1. Overview
20
+        2. Dependencies
21
+
22
+              2.1. Kamailio Modules
23
+              2.2. External Libraries or Applications
24
+
25
+        3. Exported Parameters
26
+
27
+              3.1. mask_key (str)
28
+              3.2. mask_callid (integer)
29
+              3.3. uparam_name (str)
30
+              3.4. uparam_prefix (str)
31
+              3.5. vparam_name (str)
32
+              3.6. vparam_prefix (str)
33
+
34
+        4. Exported Functions
35
+
36
+              4.1.
37
+
38
+   List of Examples
39
+
40
+   1.1. Set mask_key parameter
41
+   1.2. Set mask_callid parameter
42
+   1.3. Set uparam_name parameter
43
+   1.4. Set uparam_prefix parameter
44
+   1.5. Set vparam_name parameter
45
+   1.6. Set vparam_prefix parameter
46
+
47
+Chapter 1. Admin Guide
48
+
49
+   Table of Contents
50
+
51
+   1. Overview
52
+   2. Dependencies
53
+
54
+        2.1. Kamailio Modules
55
+        2.2. External Libraries or Applications
56
+
57
+   3. Exported Parameters
58
+
59
+        3.1. mask_key (str)
60
+        3.2. mask_callid (integer)
61
+        3.3. uparam_name (str)
62
+        3.4. uparam_prefix (str)
63
+        3.5. vparam_name (str)
64
+        3.6. vparam_prefix (str)
65
+
66
+   4. Exported Functions
67
+
68
+        4.1.
69
+
70
+1. Overview
71
+
72
+   This module hides the routing headers that show topology details. It it
73
+   is not affected by the server being transaction statless or stateful.
74
+   The script interpretor gets the SIP messages decoded, so all
75
+   functionality existing so far is preserved.
76
+
77
+   The module is transparent for config writer. It only needs to be loaded
78
+   (tune the parameters if wanted). The SIP server can be restarted
79
+   whitout affecting ongoing calls - once it is up, can encode/decode
80
+   topology details, thus no call is lost.
81
+
82
+   By using same mask_key, many SIP servers can decode the message, for
83
+   examlple, applicable for servers behind load balancers.
84
+
85
+2. Dependencies
86
+
87
+   2.1. Kamailio Modules
88
+   2.2. External Libraries or Applications
89
+
90
+2.1. Kamailio Modules
91
+
92
+   The following modules must be loaded before this module:
93
+     * rr module - server must perform record routing to ensure in-dialog
94
+       requests are encoded/decoded.
95
+
96
+2.2. External Libraries or Applications
97
+
98
+   The following libraries or applications must be installed before
99
+   running Kamailio with this module loaded:
100
+     * None. In the future the module can be enhnaced to use a stronger
101
+       encryption algorithm.
102
+
103
+3. Exported Parameters
104
+
105
+   3.1. mask_key (str)
106
+   3.2. mask_callid (integer)
107
+   3.3. uparam_name (str)
108
+   3.4. uparam_prefix (str)
109
+   3.5. vparam_name (str)
110
+   3.6. vparam_prefix (str)
111
+
112
+3.1. mask_key (str)
113
+
114
+   Keyword to mask the headers.
115
+
116
+   Default value is "_static_value_".
117
+
118
+   Example 1.1. Set mask_key parameter
119
+...
120
+modparam("topoh", "mask_key", "some secret here")
121
+...
122
+
123
+3.2. mask_callid (integer)
124
+
125
+   Whether to encode or not the call-id. Some SIP extensions include the
126
+   call-id in SIP message payload or header, so it is safe to not encode
127
+   call-id in such cases. Well-known extensions such as call transfer or
128
+   conference join will be added to work with encoded call-id.
129
+
130
+   Default value is 0 (do not mask).
131
+
132
+   Example 1.2. Set mask_callid parameter
133
+...
134
+modparam("topoh", "mask_callid", 1)
135
+...
136
+
137
+3.3. uparam_name (str)
138
+
139
+   Name of URI param where to store encoded value.
140
+
141
+   Default value is "line".
142
+
143
+   Example 1.3. Set uparam_name parameter
144
+...
145
+modparam("topoh", "uparam_name", "myparam")
146
+...
147
+
148
+3.4. uparam_prefix (str)
149
+
150
+   Prefix to be added in encoded URI params.
151
+
152
+   Default value is "sr-".
153
+
154
+   Example 1.4. Set uparam_prefix parameter
155
+...
156
+modparam("topoh", "uparam_prefix", "xyz")
157
+...
158
+
159
+3.5. vparam_name (str)
160
+
161
+   Name of Via param where to store encoded value.
162
+
163
+   Default value is "branch".
164
+
165
+   Example 1.5. Set vparam_name parameter
166
+...
167
+modparam("topoh", "vparam_name", "myv")
168
+...
169
+
170
+3.6. vparam_prefix (str)
171
+
172
+   Prefix to be added in encoded Via params.
173
+
174
+   Default value is "z9hG4bKsr-".
175
+
176
+   Example 1.6. Set vparam_prefix parameter
177
+...
178
+modparam("topoh", "vparam_prefix", "xyz")
179
+...
180
+
181
+4. Exported Functions
182
+
183
+   4.1.
184
+
185
+   None.
0 186
new file mode 100644
... ...
@@ -0,0 +1,4 @@
0
+docs = topoh.xml
1
+
2
+docbook_dir = ../../../docbook
3
+include $(docbook_dir)/Makefile.module
0 4
new file mode 100644
... ...
@@ -0,0 +1,37 @@
0
+<?xml version="1.0" encoding='ISO-8859-1'?>
1
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
2
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
3
+
4
+<!-- Include general documentation entities -->
5
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
6
+%docentities;
7
+
8
+]>
9
+
10
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
11
+    <bookinfo>
12
+	<title>topoh Module</title>
13
+	<productname class="trade">sip-router.org</productname>
14
+	<authorgroup>
15
+	    <author>
16
+		<firstname>Daniel-Constantin</firstname>
17
+		<surname>Mierla</surname>
18
+		<email>miconda@gmail.com</email>
19
+	    </author>
20
+	    <editor>
21
+		<firstname>Daniel-Constantin</firstname>
22
+		<surname>Mierla</surname>
23
+		<email>miconda@gmail.com</email>
24
+	    </editor>
25
+	</authorgroup>
26
+	<copyright>
27
+	    <year>2009</year>
28
+	    <holder>&fhg;</holder>
29
+	</copyright>
30
+    </bookinfo>
31
+    <toc></toc>
32
+    
33
+    <xi:include href="topoh_admin.xml"/>
34
+    
35
+    
36
+</book>
0 37
new file mode 100644
... ...
@@ -0,0 +1,198 @@
0
+<?xml version="1.0" encoding='ISO-8859-1'?>
1
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
2
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
3
+
4
+<!-- Include general documentation entities -->
5
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
6
+%docentities;
7
+
8
+]>
9
+<!-- Module User's Guide -->
10
+
11
+<chapter>
12
+	
13
+	<title>&adminguide;</title>
14
+	
15
+	<section>
16
+	<title>Overview</title>
17
+	<para>
18
+		This module hides the routing headers that show topology details.
19
+		It it is not affected by the server being transaction statless or
20
+		stateful. The script interpretor gets the SIP messages decoded,
21
+		so all functionality existing so far is preserved.
22
+	</para>
23
+	<para>
24
+		The module is transparent for config writer. It only needs to be
25
+		loaded (tune the parameters if wanted). The SIP server can be restarted
26
+		whitout affecting ongoing calls - once it is up, can encode/decode
27
+		topology details, thus no call is lost.
28
+	</para>
29
+	<para>
30
+		By using same mask_key, many SIP servers can decode the message,
31
+		for examlple, applicable for servers behind load balancers.
32
+	</para>
33
+	</section>
34
+	<section>
35
+	<title>Dependencies</title>
36
+	<section>
37
+		<title>&kamailio; Modules</title>
38
+		<para>
39
+		The following modules must be loaded before this module:
40
+			<itemizedlist>
41
+			<listitem>
42
+			<para>
43
+				<emphasis>rr module</emphasis> - server must perform record
44
+				routing to ensure in-dialog requests are encoded/decoded.
45
+			</para>
46
+			</listitem>
47
+			</itemizedlist>
48
+		</para>
49
+	</section>
50
+	<section>
51
+		<title>External Libraries or Applications</title>
52
+		<para>
53
+		The following libraries or applications must be installed before running
54
+		&kamailio; with this module loaded:
55
+			<itemizedlist>
56
+			<listitem>
57
+			<para>
58
+				<emphasis>None</emphasis>. In the future the module can be
59
+				enhnaced to use a stronger encryption algorithm.
60
+			</para>
61
+			</listitem>
62
+			</itemizedlist>
63
+		</para>
64
+	</section>
65
+	</section>
66
+	<section>
67
+	<title>Exported Parameters</title>
68
+	<section>
69
+		<title><varname>mask_key</varname> (str)</title>
70
+		<para>
71
+		Keyword to mask the headers.
72
+		</para>
73
+		<para>
74
+		<emphasis>
75
+			Default value is "_static_value_".
76
+		</emphasis>
77
+		</para>
78
+		<example>
79
+		<title>Set <varname>mask_key</varname> parameter</title>
80
+		<programlisting format="linespecific">
81
+...
82
+modparam("topoh", "mask_key", "some secret here")
83
+...
84
+</programlisting>
85
+		</example>
86
+	</section>
87
+	<section>
88
+		<title><varname>mask_callid</varname> (integer)</title>
89
+		<para>
90
+			Whether to encode or not the call-id. Some SIP extensions include
91
+			the call-id in SIP message payload or header, so it is safe to
92
+			not encode call-id in such cases. Well-known extensions such as
93
+			call transfer or conference join will be added to work with encoded
94
+			call-id.
95
+		</para>
96
+		<para>
97
+		<emphasis>
98
+			Default value is 0 (do not mask).
99
+		</emphasis>
100
+		</para>
101
+		<example>
102
+		<title>Set <varname>mask_callid</varname> parameter</title>
103
+		<programlisting format="linespecific">
104
+...
105
+modparam("topoh", "mask_callid", 1)
106
+...
107
+</programlisting>
108
+		</example>
109
+	</section>
110
+	<section>
111
+		<title><varname>uparam_name</varname> (str)</title>
112
+		<para>
113
+		Name of URI param where to store encoded value.
114
+		</para>
115
+		<para>
116
+		<emphasis>
117
+			Default value is "line".
118
+		</emphasis>
119
+		</para>
120
+		<example>
121
+		<title>Set <varname>uparam_name</varname> parameter</title>
122
+		<programlisting format="linespecific">
123
+...
124
+modparam("topoh", "uparam_name", "myparam")
125
+...
126
+</programlisting>
127
+		</example>
128
+	</section>
129
+	<section>
130
+		<title><varname>uparam_prefix</varname> (str)</title>
131
+		<para>
132
+		Prefix to be added in encoded URI params.
133
+		</para>
134
+		<para>
135
+		<emphasis>
136
+			Default value is "sr-".
137
+		</emphasis>
138
+		</para>
139
+		<example>
140
+		<title>Set <varname>uparam_prefix</varname> parameter</title>
141
+		<programlisting format="linespecific">
142
+...
143
+modparam("topoh", "uparam_prefix", "xyz")
144
+...
145
+</programlisting>
146
+		</example>
147
+	</section>
148
+		<section>
149
+		<title><varname>vparam_name</varname> (str)</title>
150
+		<para>
151
+		Name of Via param where to store encoded value.
152
+		</para>
153
+		<para>
154
+		<emphasis>
155
+			Default value is "branch".
156
+		</emphasis>
157
+		</para>
158
+		<example>
159
+		<title>Set <varname>vparam_name</varname> parameter</title>
160
+		<programlisting format="linespecific">
161
+...
162
+modparam("topoh", "vparam_name", "myv")
163
+...
164
+</programlisting>
165
+		</example>
166
+	</section>
167
+	<section>
168
+		<title><varname>vparam_prefix</varname> (str)</title>
169
+		<para>
170
+		Prefix to be added in encoded Via params.
171
+		</para>
172
+		<para>
173
+		<emphasis>
174
+			Default value is "z9hG4bKsr-".
175
+		</emphasis>
176
+		</para>
177
+		<example>
178
+		<title>Set <varname>vparam_prefix</varname> parameter</title>
179
+		<programlisting format="linespecific">
180
+...
181
+modparam("topoh", "vparam_prefix", "xyz")
182
+...
183
+</programlisting>
184
+		</example>
185
+	</section>
186
+
187
+	</section>
188
+	<section>
189
+	<title>Exported Functions</title>
190
+	<section>
191
+		<para>
192
+			None.
193
+		</para>
194
+	</section>
195
+	</section>
196
+</chapter>
197
+
0 198
new file mode 100644
... ...
@@ -0,0 +1,175 @@
0
+/**
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2009 SIP-Router.org
4
+ *
5
+ * This file is part of Extensible SIP Router, a free SIP server.
6
+ *
7
+ * Permission to use, copy, modify, and distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ */
19
+
20
+#include <string.h>
21
+
22
+#include "../../dprint.h"
23
+#include "../../md5.h"
24
+#include "../../crc.h"
25
+#include "../../mem/mem.h"
26
+#include "th_mask.h"
27
+
28
+#define TH_EB64I \
29
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-"
30
+
31
+char _th_EB64[65];
32
+int _th_DB64[256];
33
+char *_th_PD64 = "*";
34
+
35
+extern str _th_key;
36
+
37
+void th_shuffle(char *in, int size)
38
+{
39
+	char tmp;
40
+	int last;
41
+	unsigned int r;
42
+	unsigned char md5[16];
43
+	unsigned int *md5i;
44
+	unsigned int crc;
45
+	MD5_CTX ctx;
46
+
47
+	MD5Init(&ctx);
48
+	MD5Update(&ctx, _th_key.s, _th_key.len);
49
+	MD5Update(&ctx, _th_key.s, _th_key.len);
50
+	MD5Final(md5, &ctx);
51
+
52
+	md5i = (unsigned int*)md5;
53
+
54
+	crc = (unsigned int)crcitt_string(_th_key.s, _th_key.len);
55
+	for (last = size; last > 1; last--)
56
+	{
57
+		r = (md5i[(crc+last+_th_key.len)%4]
58
+				+ _th_key.s[(crc+last+_th_key.len)%_th_key.len]) % last;
59
+		tmp = in[r];
60
+		in[r] = in[last - 1];
61
+		in[last - 1] = tmp;
62
+	}
63
+}
64
+
65
+void th_mask_init(void)
66
+{
67
+	int i;
68
+
69
+	_th_key.len = strlen(_th_key.s);
70
+	memcpy(_th_EB64, TH_EB64I, sizeof(TH_EB64I));
71
+	th_shuffle(_th_EB64, 64);
72
+	LM_ERR("+++ %s\n", TH_EB64I);
73
+	LM_ERR("+++ %s\n", _th_EB64);
74
+	for(i=0; i<256; i++)
75
+		_th_DB64[i] = -1;
76
+	for(i=0; i<64; i++)
77
+		_th_DB64[(int)_th_EB64[i]] = i;
78
+
79
+	return;
80
+}
81
+
82
+char* th_mask_encode(char *in, int ilen, str *prefix, int *olen)
83
+{
84
+	char *out;
85
+	int  left;
86
+	int  idx;
87
+	int  i;
88
+	int  r;
89
+	char *p;
90
+	int  block;
91
+
92
+	*olen = (((ilen+2)/3)<<2) + ((prefix!=NULL&&prefix->len>0)?prefix->len:0);
93
+	out = (char*)pkg_malloc((*olen+1)*sizeof(char));
94
+	if(out==NULL)
95
+	{
96
+		LM_ERR("no more pkg\n");
97
+		*olen = 0;
98
+		return NULL;
99
+	}
100
+	memset(out, 0, (*olen+1)*sizeof(char));
101
+	if(prefix!=NULL&&prefix->len>0)
102
+		memcpy(out, prefix->s, prefix->len);
103
+
104
+	p = out + (int)((prefix!=NULL&&prefix->len>0)?prefix->len:0);
105
+	for(idx=0; idx<ilen; idx+=3)
106
+	{
107
+		left = ilen - idx - 1 ;
108
+		left = (left>1)?2:left;
109
+
110
+		block = 0;
111
+		for(i=0, r=16; i<=left; i++, r-=8)
112
+			block += ((unsigned char)in[idx+i]) << r;
113
+
114
+		*(p++) = _th_EB64[(block >> 18) & 0x3f];
115
+		*(p++) = _th_EB64[(block >> 12) & 0x3f];
116
+		*(p++) = (left>0)?_th_EB64[(block >> 6) & 0x3f]:_th_PD64[0];
117
+		*(p++) = (left>1)?_th_EB64[block & 0x3f]:_th_PD64[0];
118
+	}
119
+
120
+	return out;
121
+}
122
+
123
+char* th_mask_decode(char *in, int ilen, str *prefix, int extra, int *olen)
124
+{
125
+	char *out;
126
+	int n;
127
+	int block;
128
+	int idx;
129
+	int i;
130
+	int j;
131
+	int end;
132
+	char c;
133
+
134
+	for(n=0,i=ilen-1; in[i]==_th_PD64[0]; i--)
135
+		n++;
136
+
137
+	*olen = (((ilen-((prefix!=NULL&&prefix->len>0)?prefix->len:0)) * 6) >> 3)
138
+				- n;
139
+	out = (char*)pkg_malloc((*olen+1+extra)*sizeof(char));
140
+
141
+	if(out==NULL)
142
+	{
143
+		LM_ERR("no more pkg\n");
144
+		*olen = 0;
145
+		return NULL;
146
+	}
147
+	memset(out, 0, (*olen+1+extra)*sizeof(char));
148
+
149
+	end = ilen - n;
150
+	i = (prefix!=NULL&&prefix->len>0)?prefix->len:0;
151
+	for(idx=0; i<end; idx+=3)
152
+	{
153
+		block = 0;
154
+		for(j=0; j<4 && i<end ; j++)
155
+		{
156
+			c = _th_DB64[(int)in[i++]];
157
+			if(c<0)
158
+			{
159
+				LM_ERR("invalid input string\"%.*s\"\n", ilen, in);
160
+				pkg_free(out);
161
+				*olen = 0;
162
+				return NULL;
163
+			}
164
+			block += c << (18 - 6*j);
165
+		}
166
+
167
+		for(j=0, n=16; j<3 && idx+j< *olen; j++, n-=8)
168
+			out[idx+j] = (char)((block >> n) & 0xff);
169
+	}
170
+
171
+	return out;
172
+}
173
+
174
+
0 175
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+/**
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2009 SIP-Router.org
4
+ *
5
+ * This file is part of Extensible SIP Router, a free SIP server.
6
+ *
7
+ * Permission to use, copy, modify, and distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ */
19
+
20
+#ifndef _TH_MASK_H_
21
+#define _TH_MASK_H_
22
+
23
+#include "../../str.h"
24
+
25
+void th_mask_init(void);
26
+char* th_mask_encode(char *in, int ilen, str *prefix, int *olen);
27
+char* th_mask_decode(char *in, int ilen, str *prefix, int extra, int *olen);
28
+
29
+#endif
0 30
new file mode 100644
... ...
@@ -0,0 +1,913 @@
0
+/**
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2009 SIP-Router.org
4
+ *
5
+ * This file is part of Extensible SIP Router, a free SIP server.
6
+ *
7
+ * Permission to use, copy, modify, and distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ */
19
+
20
+#include <string.h>
21
+
22
+#include "../../dprint.h"
23
+#include "../../mem/mem.h"
24
+#include "../../data_lump.h"
25
+#include "../../forward.h"
26
+#include "../../msg_translator.h"
27
+#include "../../parser/parse_rr.h"
28
+#include "../../parser/parse_uri.h"
29
+#include "../../parser/parse_param.h"
30
+#include "../../parser/parse_from.h"
31
+#include "../../parser/parse_to.h"
32
+#include "../../parser/parse_via.h"
33
+#include "../../parser/contact/parse_contact.h"
34
+#include "th_mask.h"
35
+#include "th_msg.h"
36
+
37
+extern str th_cookie_name;
38
+extern str th_cookie_value;
39
+extern str th_via_prefix;
40
+extern str th_uri_prefix;
41
+
42
+extern str th_ip;
43
+extern str th_uparam_name;
44
+extern str th_uparam_prefix;
45
+extern str th_vparam_name;
46
+extern str th_vparam_prefix;
47
+
48
+extern int th_param_mask_callid;
49
+
50
+int th_skip_rw(char *s, int len)
51
+{
52
+	while(len>0)
53
+	{
54
+		if(s[len-1]==' ' || s[len-1]=='\t' || s[len-1]=='\n' || s[len-1]=='\r'
55
+				|| s[len-1]==',')
56
+			len--;
57
+		else return len;
58
+	}
59
+	return 0;
60
+}
61
+
62
+struct via_param *th_get_via_param(struct via_body *via, str *name)
63
+{
64
+	struct via_param *p;
65
+	for(p=via->param_lst; p; p=p->next)
66
+	{
67
+		if(p->name.len==name->len
68
+				&& strncasecmp(p->name.s, name->s, name->len)==0)
69
+			return p;
70
+	}
71
+	return NULL;
72
+}
73
+
74
+int th_get_param_value(str *in, str *name, str *value)
75
+{
76
+	param_t* params = NULL;
77
+	param_t* p = NULL;
78
+	param_hooks_t phooks;
79
+	if (parse_params(in, CLASS_ANY, &phooks, &params)<0)
80
+		return -1;
81
+	for (p = params; p; p=p->next)
82
+	{
83
+		if (p->name.len==name->len
84
+				&& strncasecmp(p->name.s, name->s, name->len)==0)
85
+		{
86
+			*value = p->body;
87
+			free_params(params);
88
+			return 0;
89
+		}
90
+	}
91
+	
92
+	if(params) free_params(params);
93
+	return 1;
94
+
95
+}
96
+
97
+int th_get_uri_param_value(str *uri, str *name, str *value)
98
+{
99
+	struct sip_uri puri;
100
+
101
+	memset(value, 0, sizeof(str));
102
+	if(parse_uri(uri->s, uri->len, &puri)<0)
103
+		return -1;
104
+	return th_get_param_value(&puri.params, name, value);
105
+}
106
+
107
+int th_get_uri_type(str *uri, int *mode, str *value)
108
+{
109
+	struct sip_uri puri;
110
+	int ret;
111
+	str r2 = {"r2", 2};
112
+
113
+	memset(value, 0, sizeof(str));
114
+	*mode = 0;
115
+	if(parse_uri(uri->s, uri->len, &puri)<0)
116
+		return -1;
117
+
118
+	LM_DBG("+++++++++++ PARAMS [%.*s]\n", puri.params.len, puri.params.s);
119
+	if(puri.host.len==th_ip.len
120
+			&& strncasecmp(puri.host.s, th_ip.s, th_ip.len)==0)
121
+	{
122
+		/* host matches TH ip */
123
+		ret = th_get_param_value(&puri.params, &th_uparam_name, value);
124
+		if(ret<0)
125
+			return -1;
126
+		return 2; /* decode */
127
+	} else {
128
+		if(check_self(&puri.host, (puri.port_no)?puri.port_no:SIP_PORT, 0)==1)
129
+		{
130
+			/* myself -- matched on all protos */
131
+			ret = th_get_param_value(&puri.params, &r2, value);
132
+			if(ret<0)
133
+				return -1;
134
+			if(ret==1) /* not found */
135
+				return 0; /* skip */
136
+			LM_DBG("+++++++++++++++++++************ [%.*s]\n",
137
+					value->len, value->s);
138
+			if(value->len==2 && strncasecmp(value->s, "on", 2)==0)
139
+				*mode = 1;
140
+			memset(value, 0, sizeof(str));
141
+			return 0; /* skip */
142
+		} else {
143
+			return 1; /* encode */
144
+		}
145
+	}
146
+}
147
+
148
+int th_mask_via(sip_msg_t *msg)
149
+{
150
+	hdr_field_t *hdr;
151
+	struct via_body *via;
152
+	struct lump* l;
153
+	int i;
154
+	str out;
155
+	int vlen;
156
+
157
+	i=0;
158
+	for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr))
159
+	{
160
+		for(via=(struct via_body*)hdr->parsed; via; via=via->next)
161
+		{
162
+			i++;
163
+			LM_DBG("=======via[%d]\n", i);
164
+			LM_DBG("hdr: [%.*s]\n", via->hdr.len, via->hdr.s);
165
+			vlen = th_skip_rw(via->name.s, via->bsize);
166
+			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
167
+			if(i!=1)
168
+			{
169
+				out.s = th_mask_encode(via->name.s, vlen, &th_via_prefix,
170
+						&out.len);
171
+				if(out.s==NULL)
172
+				{
173
+					LM_ERR("cannot encode via %d\n", i);
174
+					return -1;
175
+				}
176
+					
177
+				LM_DBG("+body: %d: [%.*s]\n", out.len, out.len, out.s);
178
+				l=del_lump(msg, via->name.s-msg->buf, vlen, 0);
179
+				if (l==0)
180
+				{
181
+					LM_ERR("failed deleting via [%d]\n", i);
182
+					pkg_free(out.s);
183
+					return -1;
184
+				}
185
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
186
+					LM_ERR("could not insert new lump\n");
187
+					pkg_free(out.s);
188
+					return -1;
189
+				}
190
+			}
191
+		}
192
+	}
193
+	return 0;
194
+}
195
+
196
+int th_mask_callid(sip_msg_t *msg)
197
+{
198
+	struct lump* l;
199
+	str out;
200
+
201
+	if(th_param_mask_callid==0)
202
+		return 0;
203
+
204
+	if(msg->callid==NULL)
205
+	{
206
+		LM_ERR("cannot get Call-Id header\n");
207
+		return -1;
208
+	}
209
+				
210
+	out.s = th_mask_encode(msg->callid->body.s, msg->callid->body.len, 0,
211
+						&out.len);
212
+	if(out.s==NULL)
213
+	{
214
+		LM_ERR("cannot encode callid\n");
215
+		return -1;
216
+	}
217
+				
218
+	l=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, 0);
219
+	if (l==0)
220
+	{
221
+		LM_ERR("failed deleting callid\n");
222
+		pkg_free(out.s);
223
+		return -1;
224
+	}
225
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
226
+		LM_ERR("could not insert new lump\n");
227
+		pkg_free(out.s);
228
+		return -1;
229
+	}
230
+
231
+	return 0;
232
+}
233
+
234
+int th_mask_contact(sip_msg_t *msg)
235
+{
236
+	struct lump* l;
237
+	str out;
238
+	str in;
239
+	contact_t *c;
240
+
241
+	if(msg->contact==NULL) 
242
+	{
243
+		LM_DBG("no contact header\n");
244
+		return 0;
245
+	}
246
+
247
+	if(parse_contact(msg->contact) < 0)
248
+	{
249
+		LM_ERR("failed parsing contact header\n");
250
+		return -1;
251
+	}
252
+	
253
+	c = ((contact_body_t*)msg->contact->parsed)->contacts;
254
+	in = c->uri;
255
+
256
+	out.s = th_mask_encode(in.s, in.len, &th_uri_prefix, &out.len);
257
+	if(out.s==NULL)
258
+	{
259
+		LM_ERR("cannot encode contact uri\n");
260
+		return -1;
261
+	}
262
+				
263
+	l=del_lump(msg, in.s-msg->buf, in.len, 0);
264
+	if (l==0)
265
+	{
266
+		LM_ERR("failed deleting contact uri\n");
267
+		pkg_free(out.s);
268
+		return -1;
269
+	}
270
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
271
+		LM_ERR("could not insert new lump\n");
272
+		pkg_free(out.s);
273
+		return -1;
274
+	}
275
+
276
+	return 0;
277
+}
278
+
279
+int th_mask_record_route(sip_msg_t *msg)
280
+{
281
+	hdr_field_t *hdr;
282
+	struct lump* l;
283
+	int i;
284
+	rr_t *rr;
285
+	str out;
286
+
287
+	if(msg->record_route==NULL)
288
+	{
289
+		LM_DBG("no record route header\n");
290
+		return 0;
291
+	}
292
+	hdr = msg->record_route;
293
+	i = 0;
294
+	while(hdr!=NULL) 
295
+	{
296
+		if (parse_rr(hdr) < 0) 
297
+		{
298
+			LM_ERR("failed to parse RR\n");
299
+			return -1;
300
+		}
301
+
302
+		rr =(rr_t*)hdr->parsed;
303
+		while(rr)
304
+		{
305
+			i++;
306
+			if(i!=1)
307
+			{
308
+				out.s = th_mask_encode(rr->nameaddr.uri.s, rr->nameaddr.uri.len,
309
+						&th_uri_prefix, &out.len);
310
+				if(out.s==NULL)
311
+				{
312
+					LM_ERR("cannot encode r-r %d\n", i);
313
+					return -1;
314
+				}
315
+				l=del_lump(msg, rr->nameaddr.uri.s-msg->buf,
316
+						rr->nameaddr.uri.len, 0);
317
+				if (l==0)
318
+				{
319
+					LM_ERR("failed deleting r-r [%d]\n", i);
320
+					pkg_free(out.s);
321
+					return -1;
322
+				}
323
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
324
+					LM_ERR("could not insert new lump\n");
325
+					pkg_free(out.s);
326
+					return -1;
327
+				}
328
+			}
329
+			rr = rr->next;
330
+		}
331
+		hdr = next_sibling_hdr(hdr);
332
+	}
333
+
334
+	return 0;
335
+}
336
+
337
+int th_unmask_via(sip_msg_t *msg, str *cookie)
338
+{
339
+	hdr_field_t *hdr;
340
+	struct via_body *via;
341
+	struct via_body *via2;
342
+	struct via_param *vp;
343
+	struct lump* l;
344
+	int i;
345
+	str out;
346
+	int vlen;
347
+
348
+	i=0;
349
+	for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr))
350
+	{
351
+		for(via=(struct via_body*)hdr->parsed; via; via=via->next)
352
+		{
353
+			i++;
354
+			LM_DBG("=======via[%d]\n", i);
355
+			LM_DBG("hdr: [%.*s]\n", via->hdr.len, via->hdr.s);
356
+			vlen = th_skip_rw(via->name.s, via->bsize);
357
+			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
358
+			if(i!=1)
359
+			{
360
+				vp = th_get_via_param(via, &th_vparam_name);
361
+				if(vp==NULL)
362
+				{
363
+					LM_ERR("cannot find param in via %d\n", i);
364
+					return -1;
365
+				}
366
+				if(i==2)
367
+					out.s = th_mask_decode(vp->value.s, vp->value.len,
368
+							&th_vparam_prefix, CRLF_LEN+1, &out.len);
369
+				else
370
+					out.s = th_mask_decode(vp->value.s, vp->value.len,
371
+							&th_vparam_prefix, 0, &out.len);
372
+				if(out.s==NULL)
373
+				{
374
+					LM_ERR("cannot encode via %d\n", i);
375
+					return -1;
376
+				}
377
+					
378
+				LM_DBG("+body: %d: [%.*s]\n", out.len, out.len, out.s);
379
+				if(i==2)
380
+				{
381
+					via2=pkg_malloc(sizeof(struct via_body));
382
+					if (via2==0)
383
+					{
384
+						LM_ERR("out of memory\n");
385
+						pkg_free(out.s);
386
+						return -1;
387
+
388
+					}
389
+					
390
+					memset(via2, 0, sizeof(struct via_body));
391
+					memcpy(out.s+out.len, CRLF, CRLF_LEN);
392
+					out.s[out.len+CRLF_LEN]='X';
393
+					if(parse_via(out.s, out.s+out.len+CRLF_LEN+1, via2)==NULL)
394
+					{
395
+						LM_ERR("error parsing decoded via2\n");
396
+						free_via_list(via2);
397
+						pkg_free(out.s);
398
+						return -1;
399
+					}
400
+					out.s[out.len] = '\0';
401
+					vp = th_get_via_param(via2, &th_cookie_name);
402
+					if(vp==NULL)
403
+					{
404
+						LM_ERR("cannot find cookie in via2\n");
405
+						free_via_list(via2);
406
+						pkg_free(out.s);
407
+						return -1;
408
+					}
409
+					*cookie = vp->value;
410
+					free_via_list(via2);
411
+				}
412
+				l=del_lump(msg, via->name.s-msg->buf, vlen, 0);
413
+				if (l==0)
414
+				{
415
+					LM_ERR("failed deleting via [%d]\n", i);
416
+					pkg_free(out.s);
417
+					return -1;
418
+				}
419
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0)
420
+				{
421
+					LM_ERR("could not insert new lump\n");
422
+					pkg_free(out.s);
423
+					return -1;
424
+				}
425
+			}
426
+		}
427
+	}
428
+
429
+	return 0;
430
+}
431
+
432
+int th_unmask_callid(sip_msg_t *msg)
433
+{
434
+	struct lump* l;
435
+	str out;
436
+	
437
+	if(th_param_mask_callid==0)
438
+		return 0;
439
+	
440
+	if(msg->callid==NULL)
441
+	{
442
+		LM_ERR("cannot get Call-Id header\n");
443
+		return -1;
444
+	}
445
+				
446
+	out.s = th_mask_decode(msg->callid->body.s, msg->callid->body.len, 0, 0,
447
+						&out.len);
448
+	if(out.s==NULL)
449
+	{
450
+		LM_ERR("cannot decode callid\n");
451
+		return -1;
452
+	}
453
+				
454
+	l=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, 0);
455
+	if (l==0)
456
+	{
457
+		LM_ERR("failed deleting callid\n");
458
+		pkg_free(out.s);
459
+		return -1;
460
+	}
461
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
462
+		LM_ERR("could not insert new lump\n");
463
+		pkg_free(out.s);
464
+		return -1;
465
+	}
466
+
467
+	return 0;
468
+}
469
+
470
+int th_flip_record_route(sip_msg_t *msg, int mode)
471
+{
472
+	hdr_field_t *hdr;
473
+	struct lump* l;
474
+	int i;
475
+	rr_t *rr;
476
+	str out;
477
+	int utype;
478
+	str pval;
479
+	int r2;
480
+	int act;
481
+
482
+	if(msg->record_route==NULL)
483
+	{
484
+		LM_DBG("no record route header\n");
485
+		return 0;
486
+	}
487
+	hdr = msg->record_route;
488
+	i = 0;
489
+	act = 0;
490
+	if(mode==1)
491
+		act = 2;
492
+	while(hdr!=NULL) 
493
+	{
494
+		if (parse_rr(hdr) < 0) 
495
+		{
496
+			LM_ERR("failed to parse RR\n");
497
+			return -1;
498
+		}
499
+
500
+		rr =(rr_t*)hdr->parsed;
501
+		while(rr)
502
+		{
503
+			i++;
504
+			r2 = 0;
505
+			utype = th_get_uri_type(&rr->nameaddr.uri, &r2, &pval);
506
+			if(utype==0 && mode==1)
507
+			{
508
+				if(r2==1)
509
+				{
510
+					act--;
511
+					if(act==0)
512
+						return 0;
513
+					utype = 1;
514
+				} else {
515
+					return 0;
516
+				}
517
+			}
518
+			out.s = NULL;
519
+			switch(utype) {
520
+				case 1: /* encode */
521
+					if(act!=0 && mode==1)
522
+					{
523
+						out.s = th_mask_encode(rr->nameaddr.uri.s,
524
+							rr->nameaddr.uri.len, &th_uri_prefix, &out.len);
525
+						if(out.s==NULL)
526
+						{
527
+							LM_ERR("cannot encode r-r %d\n", i);
528
+							return -1;
529
+						}
530
+					}
531
+				break;
532
+				case 2: /* decode */
533
+					if(mode==0)
534
+					{
535
+						out.s = th_mask_decode(pval.s,
536
+							pval.len, &th_uparam_prefix, 0, &out.len);
537
+						if(out.s==NULL)
538
+						{
539
+							LM_ERR("cannot decode r-r %d\n", i);
540
+							return -1;
541
+						}
542
+					}
543
+				break;
544
+			}
545
+			if(out.s!=NULL)
546
+			{
547
+				l=del_lump(msg, rr->nameaddr.uri.s-msg->buf,
548
+						rr->nameaddr.uri.len, 0);
549
+				if (l==0)
550
+				{
551
+					LM_ERR("failed deleting r-r [%d]\n", i);
552
+					pkg_free(out.s);
553
+					return -1;
554
+				}
555
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
556
+					LM_ERR("could not insert new lump\n");
557
+					pkg_free(out.s);
558
+					return -1;
559
+				}
560
+			}
561
+			rr = rr->next;
562
+		}
563
+		hdr = next_sibling_hdr(hdr);
564
+	}
565
+
566
+	return 0;
567
+}
568
+
569
+int th_unmask_route(sip_msg_t *msg)
570
+{
571
+	hdr_field_t *hdr;
572
+	struct lump* l;
573
+	int i;
574
+	rr_t *rr;
575
+	str out;
576
+	str eval;
577
+
578
+	if(msg->route==NULL)
579
+	{
580
+		LM_DBG("no record route header\n");
581
+		return 0;
582
+	}
583
+	hdr = msg->route;
584
+	i = 0;
585
+	while(hdr!=NULL) 
586
+	{
587
+		if (parse_rr(hdr) < 0) 
588
+		{
589
+			LM_ERR("failed to parse RR\n");
590
+			return -1;
591
+		}
592
+
593
+		rr =(rr_t*)hdr->parsed;
594
+		while(rr)
595
+		{
596
+			i++;
597
+			if(i!=1)
598
+			{
599
+				if(th_get_uri_param_value(&rr->nameaddr.uri, &th_uparam_name,
600
+							&eval)<0 || eval.len<=0)
601
+					return -1;
602
+	
603
+				out.s = th_mask_decode(eval.s, eval.len,
604
+							&th_uparam_prefix, 0, &out.len);
605
+
606
+				if(out.s==NULL)
607
+				{
608
+					LM_ERR("cannot decode R %d\n", i);
609
+					return -1;
610
+				}
611
+				l=del_lump(msg, rr->nameaddr.uri.s-msg->buf,
612
+						rr->nameaddr.uri.len, 0);
613
+				if (l==0)
614
+				{
615
+					LM_ERR("failed deleting R [%d]\n", i);
616
+					pkg_free(out.s);
617
+					return -1;
618
+				}
619
+				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
620
+					LM_ERR("could not insert new lump\n");
621
+					pkg_free(out.s);
622
+					return -1;
623
+				}
624
+			}
625
+			rr = rr->next;
626
+		}
627
+		hdr = next_sibling_hdr(hdr);
628
+	}
629
+
630
+	return 0;
631
+}
632
+
633
+int th_unmask_ruri(sip_msg_t *msg)
634
+{
635
+	str eval;
636
+	struct lump* l;
637
+	str out;
638
+
639
+	if(th_get_uri_param_value(&REQ_LINE(msg).uri, &th_uparam_name, &eval)<0
640
+			|| eval.len<=0)
641
+		return -1;
642
+	
643
+	out.s = th_mask_decode(eval.s, eval.len,
644
+				&th_uparam_prefix, 0, &out.len);
645
+	if(out.s==NULL)
646
+	{
647
+		LM_ERR("cannot decode r-uri\n");
648
+		return -1;
649
+	}
650
+					
651
+	LM_DBG("+decoded: %d: [%.*s]\n", out.len, out.len, out.s);
652
+	l=del_lump(msg, REQ_LINE(msg).uri.s-msg->buf, REQ_LINE(msg).uri.len, 0);
653
+	if (l==0)
654
+	{
655
+		LM_ERR("failed deleting r-uri\n");
656
+		pkg_free(out.s);
657
+		return -1;
658
+	}
659
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0)
660
+	{
661
+		LM_ERR("could not insert new lump\n");
662
+		pkg_free(out.s);
663
+		return -1;
664
+	}
665
+
666
+	return 0;
667
+}
668
+
669
+char* th_msg_update(sip_msg_t *msg, unsigned int *olen)
670
+{
671
+	struct dest_info dst;
672
+
673
+	init_dest_info(&dst);
674
+	dst.proto = PROTO_UDP;
675
+	return build_req_buf_from_sip_req(msg,
676
+			olen, &dst, BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE);
677
+}
678
+
679
+int th_add_via_cookie(sip_msg_t *msg, struct via_body *via)
680
+{
681
+	struct lump* l;
682
+	int viap;
683
+	str out;
684
+
685
+	if (via->params.s) {
686
+		viap = via->params.s - via->hdr.s - 1;
687
+	} else {
688
+		viap = via->host.s - via->hdr.s + via->host.len;
689
+		if (via->port!=0)
690
+			viap += via->port_str.len + 1; /* +1 for ':'*/
691
+	}
692
+	l = anchor_lump(msg, via->hdr.s - msg->buf + viap, 0, 0);
693
+	if (l==0)
694
+	{
695
+		LM_ERR("failed adding cookie to via [%p]\n", via);
696
+		return -1;
697
+	}
698
+	
699
+	out.len = 1+th_cookie_name.len+1+th_cookie_value.len+1;
700
+	out.s = (char*)pkg_malloc(out.len+1);
701
+	if(out.s==0)
702
+	{
703
+		LM_ERR("no pkg memory\n");
704
+		return -1;
705
+	}
706
+	out.s[0] = ';';
707
+	memcpy(out.s+1, th_cookie_name.s, th_cookie_name.len);
708
+	out.s[th_cookie_name.len+1]='=';
709
+	memcpy(out.s+th_cookie_name.len+2, th_cookie_value.s, th_cookie_value.len);
710
+	out.s[out.len-1] = 'v';
711
+	out.s[out.len] = '\0';
712
+	if (insert_new_lump_after(l, out.s, out.len, 0)==0){
713
+		LM_ERR("could not insert new lump!\n");
714
+		pkg_free(out.s);
715
+		return -1;
716
+	}
717
+	return 0;
718
+}
719
+
720
+int th_add_hdr_cookie(sip_msg_t *msg)
721
+{
722
+	struct lump* anchor;
723
+	str h;
724
+
725
+	h.len = th_cookie_name.len + 2 + th_cookie_value.len + 1 + CRLF_LEN;
726
+	h.s = (char*)pkg_malloc(h.len+1);
727
+	if(h.s == 0)
728
+	{
729
+		LM_ERR("no more pkg\n");
730
+		return -1;
731
+	}
732
+	anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
733
+	if(anchor == 0)
734
+	{
735
+		LM_ERR("can't get anchor\n");
736
+		pkg_free(h.s);
737
+		return -1;
738
+	}
739
+	memcpy(h.s, th_cookie_name.s, th_cookie_name.len);
740
+	memcpy(h.s+th_cookie_name.len, ": ", 2);
741
+	memcpy(h.s+th_cookie_name.len+2, th_cookie_value.s, th_cookie_value.len);
742
+	memcpy(h.s+th_cookie_name.len+2+th_cookie_value.len+1, CRLF, CRLF_LEN);
743
+	h.s[h.len-1-CRLF_LEN] = 'h';
744
+	h.s[h.len] = '\0';
745
+	if (insert_new_lump_before(anchor, h.s, h.len, 0) == 0)
746
+	{
747
+		LM_ERR("can't insert lump\n");
748
+		pkg_free(h.s);
749
+		return -1;
750
+	}
751
+	LM_DBG("+++++++++++++ added cookie header [%s]\n", h.s);
752
+	return 0;
753
+}
754
+
755
+struct via_param *th_get_via_cookie(sip_msg_t *msg, struct via_body *via)
756
+{
757
+	struct via_param *p;
758
+	for(p=via->param_lst; p; p=p->next)
759
+	{
760
+		if(p->name.len==th_cookie_name.len
761