Browse code

path: option to add two path headers and use alias like received value

- enable_r2 - add two path headers, one for incoming socket and one for
outgoing socket
- received_format - parameter to control if received value should be
in sip uri (as so far) or in contact-alias param format

Daniel-Constantin Mierla authored on 27/06/2017 13:04:31
Showing 4 changed files
... ...
@@ -34,6 +34,7 @@
34 34
 #include "../../core/mem/mem.h"
35 35
 #include "../../core/data_lump.h"
36 36
 #include "../../core/parser/parse_param.h"
37
+#include "../../core/parser/parse_uri.h"
37 38
 #include "../../core/strutils.h"
38 39
 #include "../../core/dset.h"
39 40
 
... ...
@@ -55,16 +56,34 @@ const static char *proto_strings[] = {
55 56
 	[PROTO_WSS] = "%3Btransport%3Dws",
56 57
 };
57 58
 
58
-static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *add_params)
59
+static char *path_strzdup(char *src, int len)
60
+{
61
+	char *res;
62
+
63
+	if (!src)
64
+		return NULL;
65
+	if(len<0) {
66
+		len = strlen(src);
67
+	}
68
+	if (!(res = (char *) pkg_malloc(len + 1)))
69
+		return NULL;
70
+	strncpy(res, src, len);
71
+	res[len] = 0;
72
+
73
+	return res;
74
+}
75
+
76
+static int prepend_path(sip_msg_t* _m, str *user, path_param_t param,
77
+		str *add_params)
59 78
 {
60 79
 	struct lump *l;
61
-	char *prefix, *suffix, *cp;
80
+	char *prefix, *suffix, *cp, *dp;
62 81
 	const char *proto_str;
63 82
 	int prefix_len, suffix_len;
64 83
 	struct hdr_field *hf;
65 84
 
66 85
 	/* maximum possible length of suffix */
67
-	suffix_len = strlen(";lr;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
86
+	suffix_len = sizeof(";lr;r2=on;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
68 87
 			+ IP_ADDR_MAX_STR_SIZE + 2 + (add_params ? add_params->len : 0) + 1;
69 88
 
70 89
 	cp = suffix = pkg_malloc(suffix_len);
... ...
@@ -79,17 +98,32 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
79 98
 	default:
80 99
 		break;
81 100
 	case PATH_PARAM_RECEIVED:
82
-		if (_m->rcv.proto < (sizeof(proto_strings) / sizeof(*proto_strings)))
83
-			proto_str = proto_strings[(unsigned int) _m->rcv.proto];
84
-		else
85
-			proto_str = NULL;
86
-
87
-		if(_m->rcv.src_ip.af==AF_INET6) {
88
-			cp += sprintf(cp, ";received=sip:[%s]:%hu%s", ip_addr2a(&_m->rcv.src_ip),
89
-					_m->rcv.src_port, proto_str ? : "");
101
+		if(path_received_format==0) {
102
+			if (_m->rcv.proto
103
+						< (sizeof(proto_strings) / sizeof(*proto_strings))) {
104
+				proto_str = proto_strings[(unsigned int) _m->rcv.proto];
105
+			} else {
106
+				proto_str = NULL;
107
+			}
108
+			if(_m->rcv.src_ip.af==AF_INET6) {
109
+				cp += sprintf(cp, ";received=sip:[%s]:%hu%s",
110
+						ip_addr2a(&_m->rcv.src_ip),
111
+						_m->rcv.src_port, proto_str ? : "");
112
+			} else {
113
+				cp += sprintf(cp, ";received=sip:%s:%hu%s"
114
+						, ip_addr2a(&_m->rcv.src_ip),
115
+						_m->rcv.src_port, proto_str ? : "");
116
+			}
90 117
 		} else {
91
-			cp += sprintf(cp, ";received=sip:%s:%hu%s", ip_addr2a(&_m->rcv.src_ip),
92
-					_m->rcv.src_port, proto_str ? : "");
118
+			if(_m->rcv.src_ip.af==AF_INET6) {
119
+				cp += sprintf(cp, ";received=[%s]~%hu~%d",
120
+						ip_addr2a(&_m->rcv.src_ip),
121
+						_m->rcv.src_port, (int)_m->rcv.proto);
122
+			} else {
123
+				cp += sprintf(cp, ";received=%s~%hu~%d",
124
+						ip_addr2a(&_m->rcv.src_ip),
125
+						_m->rcv.src_port, (int)_m->rcv.proto);
126
+			}
93 127
 		}
94 128
 		break;
95 129
 	case PATH_PARAM_OB:
... ...
@@ -100,7 +134,11 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
100 134
 	if (add_params && add_params->len)
101 135
 		cp += sprintf(cp, ";%.*s", add_params->len, add_params->s);
102 136
 
103
-	cp += sprintf(cp, ">\r\n");
137
+	if(path_enable_r2==0) {
138
+		cp += sprintf(cp, ">\r\n");
139
+	} else {
140
+		cp += sprintf(cp, ";r2=on>\r\n");
141
+	}
104 142
 
105 143
 	prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2;
106 144
 	prefix = pkg_malloc(prefix_len);
... ...
@@ -136,6 +174,19 @@ static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *
136 174
 	l = insert_new_lump_before(l, suffix, cp - suffix, 0);
137 175
 	if (!l) goto out2;
138 176
 
177
+	if(path_enable_r2!=0) {
178
+		dp = path_strzdup(prefix, prefix_len);
179
+		if(dp==NULL) goto out1;
180
+		l = insert_new_lump_before(l, dp, prefix_len, 0);
181
+		if (!l) goto out1;
182
+		l = insert_subst_lump_before(l, SUBST_RCV_ALL, 0);
183
+		if (!l) goto out1;
184
+		dp = path_strzdup(suffix, cp - suffix);
185
+		if(dp==NULL) goto out1;
186
+		l = insert_new_lump_before(l, suffix, cp - suffix, 0);
187
+		if (!l) goto out1;
188
+	}
189
+
139 190
 	return 1;
140 191
 
141 192
 out3:
... ...
@@ -162,11 +213,11 @@ int ki_add_path(struct sip_msg* _msg)
162 213
 		&& path_obb.use_outbound(_msg)) {
163 214
 		if (path_obb.encode_flow_token(&user, _msg->rcv) != 0) {
164 215
 			LM_ERR("encoding outbound flow-token\n");
165
-			return -1;	
216
+			return -1;
166 217
 		}
167 218
 
168
-		/* Only include ;ob parameter if this is the first-hop (that
169
-		   means only one Via:) */
219
+		/* Only include ;ob parameter if this is the first-hop
220
+		 * (that means only one Via:) */
170 221
 		if (parse_via_header(_msg, 2, &via) < 0)
171 222
 			param = PATH_PARAM_OB;
172 223
 	}
... ...
@@ -284,20 +335,77 @@ void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
284 335
 	param_t *params;
285 336
 	static char dst_uri_buf[MAX_URI_SIZE];
286 337
 	static str dst_uri;
287
-			
338
+	char *p;
339
+	int n;
340
+	int nproto;
341
+	str sproto;
342
+
288 343
 	if (parse_params(r_param, CLASS_CONTACT, &hooks, &params) != 0) {
289 344
 		LM_ERR("failed to parse route parameters\n");
290 345
 		return;
291 346
 	}
292 347
 
293
-	if (hooks.contact.received) {
294
-	        dst_uri.s = dst_uri_buf;
348
+	if (hooks.contact.received
349
+			&& hooks.contact.received->body.len>0) {
350
+		/* 24 => sip:...;transport=sctp */
351
+		if(hooks.contact.received->body.len + 24 >= MAX_URI_SIZE) {
352
+			LM_ERR("received uri is too long\n");
353
+			goto done;
354
+		}
355
+		dst_uri.s = dst_uri_buf;
295 356
 		dst_uri.len = MAX_URI_SIZE;
296
-		if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
297
-		        LM_ERR("unescaping received failed\n");
298
-			free_params(params);
299
-			return;
300
-		}	    
357
+		if(path_enable_r2==0) {
358
+			if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
359
+				LM_ERR("unescaping received failed\n");
360
+				free_params(params);
361
+				return;
362
+			} else {
363
+				/* ip~port~proto */
364
+				strncpy(dst_uri_buf, "sip:", 4);
365
+				strncpy(dst_uri_buf+4, hooks.contact.received->body.s,
366
+						hooks.contact.received->body.len);
367
+				dst_uri_buf[hooks.contact.received->body.len] = '\0';
368
+				p = dst_uri_buf + 4;
369
+				n = 0;
370
+				while(*p!='\0') {
371
+					if(*p=='~') {
372
+						n++;
373
+						if(n==1) {
374
+							/* port */
375
+							*p = ':';
376
+						} else if(n==2) {
377
+							/* proto */
378
+							*p = ';';
379
+							p++;
380
+							if(*p=='\0') {
381
+								LM_ERR("invalid received format\n");
382
+								goto done;
383
+							}
384
+							nproto = *p - '0';
385
+							if (nproto != PROTO_UDP) {
386
+								proto_type_to_str(nproto, &sproto);
387
+								if (sproto.len == 0) {
388
+									LM_ERR("unknown proto in received param\n");
389
+									goto done;
390
+								}
391
+								strncpy(p, "transport=", 10);
392
+								p += 10;
393
+								memcpy(p, sproto.s, sproto.len);
394
+								p += sproto.len;
395
+								*p = '\0';
396
+								dst_uri.len = p - dst_uri_buf;
397
+								break;
398
+							}
399
+						} else {
400
+							LM_ERR("invalid number of spearators (%d)\n", n);
401
+							goto done;
402
+						}
403
+					}
404
+					p++;
405
+				}
406
+			}
407
+		}
408
+		LM_DBG("setting dst uri: %.*s\n", dst_uri.len, dst_uri.s);
301 409
 		if (set_dst_uri(_m, &dst_uri) != 0) {
302 410
 			LM_ERR("failed to set dst-uri\n");
303 411
 			free_params(params);
... ...
@@ -307,5 +415,6 @@ void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
307 415
 			forking */
308 416
 		ruri_mark_new(); /* re-use uri for serial forking */
309 417
 	}
418
+done:
310 419
 	free_params(params);
311 420
 }
... ...
@@ -1,6 +1,4 @@
1 1
 /*
2
- * $Id$
3
- *
4 2
  * Path handling for intermediate proxies.
5 3
  *
6 4
  * Copyright (C) 2006 Inode GmbH (Andreas Granig <andreas.granig@inode.info>)
... ...
@@ -17,8 +15,8 @@
17 15
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 16
  * GNU General Public License for more details.
19 17
  *
20
- * You should have received a copy of the GNU General Public License 
21
- * along with this program; if not, write to the Free Software 
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
22 20
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 21
  *
24 22
 
... ...
@@ -64,7 +64,10 @@ MODULE_VERSION
64 64
 
65 65
 /*! \brief If received-param of current Route uri should be used
66 66
  * as dst-uri. */
67
-int use_received = 0;
67
+int path_use_received = 0;
68
+
69
+int path_received_format = 0;
70
+int path_enable_r2 = 0;
68 71
 
69 72
 /*! \brief
70 73
  * Module initialization function prototype
... ...
@@ -105,7 +108,9 @@ static cmd_export_t cmds[] = {
105 108
  * Exported parameters
106 109
  */
107 110
 static param_export_t params[] = {
108
-	{"use_received", INT_PARAM, &use_received },
111
+	{"use_received",    INT_PARAM, &path_use_received },
112
+	{"received_format", INT_PARAM, &path_received_format },
113
+	{"enable_r2",       INT_PARAM, &path_enable_r2 },
109 114
 	{ 0, 0, 0 }
110 115
 };
111 116
 
... ...
@@ -114,7 +119,7 @@ static param_export_t params[] = {
114 119
  * Module interface
115 120
  */
116 121
 struct module_exports exports = {
117
-	"path", 
122
+	"path",
118 123
 	DEFAULT_DLFLAGS, /* dlopen flags */
119 124
 	cmds,       /* Exported functions */
120 125
 	params,     /* Exported parameters */
... ...
@@ -131,7 +136,7 @@ struct module_exports exports = {
131 136
 
132 137
 static int mod_init(void)
133 138
 {
134
-	if (use_received) {
139
+	if (path_use_received) {
135 140
 		if (load_rr_api(&path_rrb) != 0) {
136 141
 			LM_ERR("failed to load rr-API\n");
137 142
 			return -1;
... ...
@@ -148,7 +153,7 @@ static int mod_init(void)
148 153
 		LM_INFO("outbound module not available\n");
149 154
 		memset(&path_obb, 0, sizeof(ob_api_t));
150 155
 	}
151
-	
156
+
152 157
 	return 0;
153 158
 }
154 159
 
... ...
@@ -198,4 +203,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
198 203
 {
199 204
 	sr_kemi_modules_add(sr_kemi_path_exports);
200 205
 	return 0;
201
-}
202 206
\ No newline at end of file
207
+}
... ...
@@ -1,6 +1,4 @@
1 1
 /*
2
- * $Id$
3
- *
4 2
  * Path handling for intermediate proxies
5 3
  *
6 4
  * Copyright (C) 2006 Inode GmbH (Andreas Granig <andreas.granig@inode.info>)
... ...
@@ -17,8 +15,8 @@
17 15
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 16
  * GNU General Public License for more details.
19 17
  *
20
- * You should have received a copy of the GNU General Public License 
21
- * along with this program; if not, write to the Free Software 
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
22 20
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 21
  *
24 22
  */
... ...
@@ -36,7 +34,9 @@
36 34
 
37 35
 #include "../outbound/api.h"
38 36
 
39
-extern int use_received;
37
+extern int path_use_received;
38
+extern int path_received_format;
39
+extern int path_enable_r2;
40 40
 extern ob_api_t path_obb;
41 41
 
42 42
 #endif /* PATH_MOD_H */