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