Browse code

uac_redirect: fetch all contact headers in redirect replies

- only first header was considered for redirect handling
- based on a report by Geoffrey Mina
- generate fake ruid (used as instance and user-agent) to satisfy the
requirements of t_load_contacts()/t_next_contacts()

Daniel-Constantin Mierla authored on 03/07/2013 21:23:40
Showing 3 changed files
... ...
@@ -10,4 +10,6 @@ LIBS=
10 10
 
11 11
 DEFS+=-DKAMAILIO_MOD_INTERFACE
12 12
 
13
+SERLIBPATH=../../lib
14
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
13 15
 include ../../Makefile.modules
... ...
@@ -32,11 +32,14 @@
32 32
 #include "../../dprint.h"
33 33
 #include "../../qvalue.h"
34 34
 #include "../../parser/contact/parse_contact.h"
35
+#include "../../lib/srutils/sruid.h"
35 36
 #include "../../qvalue.h"
36 37
 #include "rd_filter.h"
37 38
 #include "rd_funcs.h"
38 39
 
39 40
 
41
+extern sruid_t _redirect_sruid;
42
+
40 43
 #define MAX_CONTACTS_PER_REPLY   16
41 44
 #define DEFAULT_Q_VALUE          10
42 45
 
... ...
@@ -115,7 +118,7 @@ error:
115 118
 
116 119
 
117 120
 /* returns the number of contacts put in the sorted array */
118
-static int sort_contacts(contact_t *ct_list, contact_t **ct_array,
121
+static int sort_contacts(hdr_field_t *chdr, contact_t **ct_array,
119 122
 														qvalue_t *q_array)
120 123
 {
121 124
 	param_t *q_para;
... ...
@@ -123,48 +126,54 @@ static int sort_contacts(contact_t *ct_list, contact_t **ct_array,
123 126
 	int n;
124 127
 	int i,j;
125 128
 	char backup;
129
+	contact_t *ct_list;
130
+	hdr_field_t *hdr;
126 131
 
127 132
 	n = 0; /* number of sorted contacts */
128 133
 
129
-	for( ; ct_list ; ct_list = ct_list->next ) {
130
-		/* check the filters first */
131
-		backup = ct_list->uri.s[ct_list->uri.len];
132
-		ct_list->uri.s[ct_list->uri.len] = 0;
133
-		if ( run_filters( ct_list->uri.s )==-1 ){
134
-			ct_list->uri.s[ct_list->uri.len] = backup;
135
-			continue;
136
-		}
137
-		ct_list->uri.s[ct_list->uri.len] = backup;
138
-		/* does the contact has a q val? */
139
-		q_para = ct_list->q;
140
-		if (q_para==0 || q_para->body.len==0) {
141
-			q = DEFAULT_Q_VALUE;
142
-		} else {
143
-			if (str2q( &q, q_para->body.s, q_para->body.len)!=0) {
144
-				LM_ERR("invalid q param\n");
145
-				/* skip this contact */
134
+	for(hdr=chdr; hdr; hdr=hdr->next) {
135
+		if(hdr->type != HDR_CONTACT_T) continue;
136
+		ct_list = ((contact_body_t*)hdr->parsed)->contacts;
137
+		for( ; ct_list ; ct_list = ct_list->next ) {
138
+			/* check the filters first */
139
+			backup = ct_list->uri.s[ct_list->uri.len];
140
+			ct_list->uri.s[ct_list->uri.len] = 0;
141
+			if ( run_filters( ct_list->uri.s )==-1 ){
142
+				ct_list->uri.s[ct_list->uri.len] = backup;
146 143
 				continue;
147 144
 			}
148
-		}
149
-		LM_DBG("sort_contacts: <%.*s> q=%d\n",
150
-				ct_list->uri.len,ct_list->uri.s,q);
151
-		/*insert the contact into the sorted array */
152
-		for(i=0;i<n;i++) {
153
-			/* keep in mind that the contact list is reversts */
154
-			if (q_array[i]<=q)
155
-				continue;
156
-			break;
157
-		}
158
-		if (i!=MAX_CONTACTS_PER_REPLY) {
159
-			/* insert the contact at this position */
160
-			for( j=n-1-1*(n==MAX_CONTACTS_PER_REPLY) ; j>=i ; j-- ) {
161
-				ct_array[j+1] = ct_array[j];
162
-				q_array[j+1] = q_array[j];
145
+			ct_list->uri.s[ct_list->uri.len] = backup;
146
+			/* does the contact has a q val? */
147
+			q_para = ct_list->q;
148
+			if (q_para==0 || q_para->body.len==0) {
149
+				q = DEFAULT_Q_VALUE;
150
+			} else {
151
+				if (str2q( &q, q_para->body.s, q_para->body.len)!=0) {
152
+					LM_ERR("invalid q param\n");
153
+					/* skip this contact */
154
+					continue;
155
+				}
156
+			}
157
+			LM_DBG("sort_contacts: <%.*s> q=%d\n",
158
+					ct_list->uri.len,ct_list->uri.s,q);
159
+			/*insert the contact into the sorted array */
160
+			for(i=0;i<n;i++) {
161
+				/* keep in mind that the contact list is reversts */
162
+				if (q_array[i]<=q)
163
+					continue;
164
+				break;
165
+			}
166
+			if (i!=MAX_CONTACTS_PER_REPLY) {
167
+				/* insert the contact at this position */
168
+				for( j=n-1-1*(n==MAX_CONTACTS_PER_REPLY) ; j>=i ; j-- ) {
169
+					ct_array[j+1] = ct_array[j];
170
+					q_array[j+1] = q_array[j];
171
+				}
172
+				ct_array[j+1] = ct_list;
173
+				q_array[j+1] = q;
174
+				if (n!=MAX_CONTACTS_PER_REPLY)
175
+					n++;
163 176
 			}
164
-			ct_array[j+1] = ct_list;
165
-			q_array[j+1] = q;
166
-			if (n!=MAX_CONTACTS_PER_REPLY)
167
-				n++;
168 177
 		}
169 178
 	}
170 179
 	return n;
... ...
@@ -211,7 +220,7 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
211 220
 			memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) );
212 221
 			dup = 2;
213 222
 			/* ok -> force the parsing of contact header */
214
-			if ( parse_headers( &dup_rpl, HDR_CONTACT_F, 0)<0 ) {
223
+			if ( parse_headers( &dup_rpl, HDR_EOH_F, 0)<0 ) {
215 224
 				LM_ERR("dup_rpl parse failed\n");
216 225
 				ret = -1;
217 226
 				goto restore;
... ...
@@ -224,7 +233,7 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
224 233
 		} else {
225 234
 			dup = 3;
226 235
 			/* force the parsing of contact header */
227
-			if ( parse_headers( sh_rpl, HDR_CONTACT_F, 0)<0 ) {
236
+			if ( parse_headers( sh_rpl, HDR_EOH_F, 0)<0 ) {
228 237
 				LM_ERR("sh_rpl parse failed\n");
229 238
 				ret = -1;
230 239
 				goto restore;
... ...
@@ -239,18 +248,23 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
239 248
 		contact_hdr = sh_rpl->contact;
240 249
 	}
241 250
 
242
-	/* parse the body of contact header */
243
-	if (contact_hdr->parsed==0) {
244
-		if ( parse_contact(contact_hdr)<0 ) {
245
-			LM_ERR("contact hdr parse failed\n");
246
-			ret = -1;
247
-			goto restore;
251
+	/* parse the body of contact headers */
252
+	hdr = contact_hdr;
253
+	while(hdr) {
254
+		if (hdr->type == HDR_CONTACT_T) {
255
+			if (hdr->parsed==0) {
256
+				if(parse_contact(hdr) < 0) {
257
+					LM_ERR("failed to parse Contact body\n");
258
+					ret = -1;
259
+					goto restore;
260
+				}
261
+				if (dup==0)
262
+					dup = 1;
263
+				}
248 264
 		}
249
-		if (dup==0)
250
-			dup = 1;
265
+		hdr = hdr->next;
251 266
 	}
252 267
 
253
-
254 268
 	/* we have the contact header and its body parsed -> sort the contacts
255 269
 	 * based on the q value */
256 270
 	contacts = ((contact_body_t*)contact_hdr->parsed)->contacts;
... ...
@@ -258,7 +272,7 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
258 272
 		LM_DBG("contact hdr has no contacts\n");
259 273
 		goto restore;
260 274
 	}
261
-	n = sort_contacts( contacts, scontacts, sqvalues);
275
+	n = sort_contacts(contact_hdr, scontacts, sqvalues);
262 276
 	if (n==0) {
263 277
 		LM_DBG("no contacts left after filtering\n");
264 278
 		goto restore;
... ...
@@ -274,17 +288,22 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
274 288
 	for ( i=0 ; i<n ; i++ ) {
275 289
 		LM_DBG("adding contact <%.*s>\n", scontacts[i]->uri.len,
276 290
 				scontacts[i]->uri.s);
277
-		if (km_append_branch( 0, &scontacts[i]->uri, 0, 0, sqvalues[i],
278
-					bflags, 0)<0) {
279
-			LM_ERR("failed to add contact to dset\n");
280
-		} else {
281
-			added++;
282
-			if (rd_acc_fct!=0 && reason) {
283
-				/* log the redirect */
284
-				req->new_uri =  scontacts[i]->uri;
285
-				//FIXME
286
-				rd_acc_fct( req, (char*)reason, acc_db_table);
291
+		if(sruid_next(&_redirect_sruid)==0) {
292
+			if(append_branch( 0, &scontacts[i]->uri, 0, 0, sqvalues[i],
293
+						bflags, 0, &_redirect_sruid.uid, 0,
294
+						&_redirect_sruid.uid, &_redirect_sruid.uid)<0) {
295
+				LM_ERR("failed to add contact to dset\n");
296
+			} else {
297
+				added++;
298
+				if (rd_acc_fct!=0 && reason) {
299
+					/* log the redirect */
300
+					req->new_uri =  scontacts[i]->uri;
301
+					//FIXME
302
+					rd_acc_fct( req, (char*)reason, acc_db_table);
303
+				}
287 304
 			}
305
+		} else {
306
+			LM_ERR("failed to generate ruid for a new branch\n");
288 307
 		}
289 308
 	}
290 309
 
... ...
@@ -32,6 +32,7 @@
32 32
 #include "../../str.h"
33 33
 #include "../../dprint.h"
34 34
 #include "../../mem/mem.h"
35
+#include "../../lib/srutils/sruid.h"
35 36
 #include "../../modules/tm/tm_load.h"
36 37
 #include "rd_funcs.h"
37 38
 #include "rd_filter.h"
... ...
@@ -56,9 +57,12 @@ unsigned int bflags = 0;
56 57
 #define ACCEPT_RULE_STR "accept"
57 58
 #define DENY_RULE_STR   "deny"
58 59
 
60
+/* sruid to get internal uid */
61
+sruid_t _redirect_sruid;
59 62
 
60 63
 
61 64
 static int redirect_init(void);
65
+static int child_init(int rank);
62 66
 static int w_set_deny(struct sip_msg* msg, char *dir, char *foo);
63 67
 static int w_set_accept(struct sip_msg* msg, char *dir, char *foo);
64 68
 static int w_get_redirect1(struct sip_msg* msg, char *dir, char *foo);
... ...
@@ -103,7 +107,7 @@ struct module_exports exports = {
103 107
 	redirect_init, /* Module initialization function */
104 108
 	0,
105 109
 	0,
106
-	(child_init_function) 0 /* per-child init function */
110
+	child_init /* per-child init function */
107 111
 };
108 112
 
109 113
 
... ...
@@ -295,11 +299,20 @@ static int redirect_init(void)
295 299
 	}
296 300
 	add_default_filter( DENY_FILTER, filter);
297 301
 
302
+	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
303
+		return -1;
304
+
298 305
 	return 0;
299 306
 error:
300 307
 	return -1;
301 308
 }
302 309
 
310
+static int child_init(int rank)
311
+{
312
+	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
313
+		return -1;
314
+	return 0;
315
+}
303 316
 
304 317
 static inline void msg_tracer(struct sip_msg* msg, int reset)
305 318
 {