Browse code

registrar: add optional check for local path during lookup()

- when performing a lookup the Path (if present) is evaluated
and if the first hop is local we skip it to avoid looping.
- useful if multiple servers are sharing a common database,
each saving contacts with their local address as the Path.

Charles Chance authored on 09/01/2015 17:16:07
Showing 3 changed files
... ...
@@ -41,6 +41,7 @@
41 41
 #include "../../action.h"
42 42
 #include "../../mod_fix.h"
43 43
 #include "../../parser/parse_rr.h"
44
+#include "../../forward.h"
44 45
 #include "../usrloc/usrloc.h"
45 46
 #include "common.h"
46 47
 #include "regtime.h"
... ...
@@ -121,6 +122,8 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
121 122
 	sr_xavp_t *list=NULL;
122 123
 	str xname = {"ruid", 4};
123 124
 	sr_xval_t xval;
125
+	sip_uri_t path_uri;
126
+	str path_str;
124 127
 
125 128
 	ret = -1;
126 129
 
... ...
@@ -256,16 +259,47 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
256 259
 				xavp_add_value(&reg_xavp_rcd, &xval, NULL);
257 260
 			}
258 261
 		}
262
+
259 263
 		/* If a Path is present, use first path-uri in favour of
260 264
 		 * received-uri because in that case the last hop towards the uac
261 265
 		 * has to handle NAT. - agranig */
262 266
 		if (ptr->path.s && ptr->path.len) {
263
-			if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
267
+			/* make a copy, so any change we need to make here does not mess up the structure in usrloc */
268
+			path_str = ptr->path;
269
+			if (get_path_dst_uri(&path_str, &path_dst) < 0) {
264 270
 				LM_ERR("failed to get dst_uri for Path\n");
265 271
 				ret = -3;
266 272
 				goto done;
267 273
 			}
268
-			if (set_path_vector(_m, &ptr->path) < 0) {
274
+			if (path_check_local > 0) {
275
+				if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0){
276
+					LM_ERR("failed to parse the Path URI\n");
277
+					ret = -3;
278
+					goto done;
279
+				}
280
+				if (check_self(&(path_uri.host), 0, 0)) {
281
+					/* first hop in path vector is local - check for additional hops and if present, point to next one */
282
+					if (path_str.len > (path_dst.len + 3)) {
283
+						path_str.s = path_str.s + path_dst.len + 3;
284
+						path_str.len = path_str.len - path_dst.len - 3;
285
+						if (get_path_dst_uri(&path_str, &path_dst) < 0) {
286
+							LM_ERR("failed to get second dst_uri for Path\n");
287
+							ret = -3;
288
+							goto done;
289
+						}
290
+					} else {
291
+						/* no more hops */
292
+						path_dst.s = NULL;
293
+						path_dst.len = 0;
294
+					}
295
+				}
296
+			}
297
+		} else {
298
+			path_dst.s = NULL;
299
+			path_dst.len = 0;
300
+		}
301
+		if (path_dst.s && path_dst.len) {
302
+			if (set_path_vector(_m, &path_str) < 0) {
269 303
 				LM_ERR("failed to set path vector\n");
270 304
 				ret = -3;
271 305
 				goto done;
... ...
@@ -333,10 +367,36 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
333 367
 	for( ; ptr ; ptr = ptr->next ) {
334 368
 		if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
335 369
 			path_dst.len = 0;
336
-			if(ptr->path.s && ptr->path.len 
337
-			&& get_path_dst_uri(&ptr->path, &path_dst) < 0) {
338
-				LM_ERR("failed to get dst_uri for Path\n");
339
-				continue;
370
+			if(ptr->path.s && ptr->path.len) {
371
+				path_str = ptr->path;
372
+				if (get_path_dst_uri(&path_str, &path_dst) < 0) {
373
+					LM_ERR("failed to get dst_uri for Path\n");
374
+					continue;
375
+				}
376
+				if (path_check_local > 0) {
377
+					if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0) {
378
+						LM_ERR("failed to parse the Path URI\n");
379
+						continue;
380
+					}
381
+					if (check_self(&(path_uri.host), 0, 0)) {
382
+						/* first hop in path vector is local - check for additional hops and if present, point to next one */
383
+						if (path_str.len > (path_dst.len + 3)) {
384
+							path_str.s = path_str.s + path_dst.len + 3;
385
+							path_str.len = path_str.len - path_dst.len - 3;
386
+							if (get_path_dst_uri(&path_str, &path_dst) < 0) {
387
+								LM_ERR("failed to get second dst_uri for Path\n");
388
+								continue;
389
+							}
390
+						} else {
391
+							/* no more hops */
392
+							path_dst.s = NULL;
393
+							path_dst.len = 0;
394
+						}
395
+					}
396
+				}
397
+			} else {
398
+				path_dst.s = NULL;
399
+				path_dst.len = 0;
340 400
 			}
341 401
 
342 402
 			/* The same as for the first contact applies for branches 
... ...
@@ -345,7 +405,7 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
345 405
 			       ptr->instance.len, ptr->instance.s);
346 406
 			if (append_branch(_m, &ptr->c,
347 407
 					  path_dst.len?&path_dst:&ptr->received,
348
-					  &ptr->path, ptr->q, ptr->cflags,
408
+					  path_dst.len?&path_str:0, ptr->q, ptr->cflags,
349 409
 					  ptr->sock,
350 410
 					  ptr->instance.len?&(ptr->instance):0,
351 411
 				          ptr->instance.len?ptr->reg_id:0,
... ...
@@ -116,6 +116,7 @@ int path_mode = PATH_MODE_STRICT;		/*!< if the Path HF should be inserted in the
116 116
 
117 117
 int path_use_params = 0;			/*!< if the received- and nat-parameters of last Path uri should be used
118 118
  						 * to determine if UAC is nat'ed */
119
+int path_check_local = 0;
119 120
 
120 121
 /* sruid to get internal uid */
121 122
 sruid_t _reg_sruid;
... ...
@@ -233,6 +234,7 @@ static param_export_t params[] = {
233 234
 	{"use_path",           INT_PARAM, &path_enabled        					},
234 235
 	{"path_mode",          INT_PARAM, &path_mode           					},
235 236
 	{"path_use_received",  INT_PARAM, &path_use_params     					},
237
+        {"path_check_local",   INT_PARAM, &path_check_local                                     },
236 238
 	{"xavp_cfg",           PARAM_STR, &reg_xavp_cfg     					},
237 239
 	{"xavp_rcd",           PARAM_STR, &reg_xavp_rcd     					},
238 240
 	{"gruu_enabled",       INT_PARAM, &reg_gruu_enabled    					},
... ...
@@ -94,6 +94,7 @@ extern int method_filtering;
94 94
 extern int path_enabled;
95 95
 extern int path_mode;
96 96
 extern int path_use_params;
97
+extern int path_check_local;
97 98
 extern int reg_gruu_enabled;
98 99
 extern int reg_outbound_mode;
99 100
 extern int reg_regid_mode;