1 /*
2 * Path handling for intermediate proxies.
3 *
4 * Copyright (C) 2006 Inode GmbH (Andreas Granig <andreas.granig@inode.info>)
5 *
6 * This file is part of Kamailio, a free SIP server.
7 *
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
12 *
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
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
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24 /*! \file
25 * \brief Path :: Utilities
26 *
27 * \ingroup path
28 * - Module: path
29 */
30
31 #include <string.h>
32 #include <stdio.h>
33
34 #include "../../core/mem/mem.h"
35 #include "../../core/data_lump.h"
36 #include "../../core/parser/parse_param.h"
37 #include "../../core/parser/parse_uri.h"
38 #include "../../core/strutils.h"
39 #include "../../core/dset.h"
40
41 #include "path.h"
42 #include "path_mod.h"
43
44 typedef enum {
45 PATH_PARAM_NONE = 0, PATH_PARAM_RECEIVED = 1, PATH_PARAM_OB = 2
46 } path_param_t;
47
48 #define PATH_PREFIX "Path: <sip:"
49 #define PATH_PREFIX_LEN (sizeof(PATH_PREFIX)-1)
50
51 const static char *proto_strings[] = {
52 [PROTO_TCP] = "%3Btransport%3Dtcp",
53 [PROTO_TLS] = "%3Btransport%3Dtls",
54 [PROTO_SCTP] = "%3Btransport%3Dsctp",
55 [PROTO_WS] = "%3Btransport%3Dws",
56 [PROTO_WSS] = "%3Btransport%3Dws",
57 };
58
59 extern int path_sockname_mode;
60
path_strzdup(char * src,int len)61 static char *path_strzdup(char *src, int len)
62 {
63 char *res;
64
65 if (!src)
66 return NULL;
67 if(len<0) {
68 len = strlen(src);
69 }
70 if (!(res = (char *) pkg_malloc(len + 1)))
71 return NULL;
72 strncpy(res, src, len);
73 res[len] = 0;
74
75 return res;
76 }
77
handleOutbound(sip_msg_t * _m,str * user,path_param_t * param)78 static int handleOutbound(sip_msg_t* _m, str *user, path_param_t *param)
79 {
80 if (path_obb.use_outbound != NULL && path_obb.use_outbound(_m)) {
81 struct via_body *via;
82
83 if (path_obb.encode_flow_token(user, &_m->rcv) != 0) {
84 LM_ERR("encoding outbound flow-token\n");
85 return -1;
86 }
87
88 /* Only include ;ob parameter if this is the first-hop
89 * (that means only one Via:) */
90 if (parse_via_header(_m, 2, &via) < 0) {
91 *param |= PATH_PARAM_OB;
92 }
93 }
94
95 return 1;
96 }
97
prepend_path(sip_msg_t * _m,str * user,path_param_t param,str * add_params)98 static int prepend_path(sip_msg_t* _m, str *user, path_param_t param,
99 str *add_params)
100 {
101 struct lump *l;
102 char *prefix, *suffix, *cp, *dp;
103 const char *proto_str;
104 int prefix_len, suffix_len;
105 struct hdr_field *hf;
106
107 /* maximum possible length of suffix */
108 suffix_len = sizeof(";lr;r2=on;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
109 + IP_ADDR_MAX_STR_SIZE + 2 + (add_params ? add_params->len : 0) + 1;
110
111 cp = suffix = pkg_malloc(suffix_len);
112 if (!suffix) {
113 LM_ERR("no pkg memory left for suffix\n");
114 goto out1;
115 }
116
117 cp += sprintf(cp, ";lr");
118
119 if (param & PATH_PARAM_RECEIVED) {
120 if(path_received_format==0) {
121 if (_m->rcv.proto
122 < (sizeof(proto_strings) / sizeof(*proto_strings))) {
123 proto_str = proto_strings[(unsigned int) _m->rcv.proto];
124 } else {
125 proto_str = NULL;
126 }
127 if(_m->rcv.src_ip.af==AF_INET6) {
128 cp += sprintf(cp, ";received=sip:[%s]:%hu%s",
129 ip_addr2a(&_m->rcv.src_ip),
130 _m->rcv.src_port, proto_str ? : "");
131 } else {
132 cp += sprintf(cp, ";received=sip:%s:%hu%s"
133 , ip_addr2a(&_m->rcv.src_ip),
134 _m->rcv.src_port, proto_str ? : "");
135 }
136 } else {
137 if(_m->rcv.src_ip.af==AF_INET6) {
138 cp += sprintf(cp, ";received=[%s]~%hu~%d",
139 ip_addr2a(&_m->rcv.src_ip),
140 _m->rcv.src_port, (int)_m->rcv.proto);
141 } else {
142 cp += sprintf(cp, ";received=%s~%hu~%d",
143 ip_addr2a(&_m->rcv.src_ip),
144 _m->rcv.src_port, (int)_m->rcv.proto);
145 }
146 }
147 }
148
149 if (param & PATH_PARAM_OB) {
150 cp += sprintf(cp, ";ob");
151 }
152
153 if (add_params && add_params->len) {
154 cp += sprintf(cp, ";%.*s", add_params->len, add_params->s);
155 }
156
157 if(path_enable_r2==0) {
158 cp += sprintf(cp, ">\r\n");
159 } else {
160 cp += sprintf(cp, ";r2=on>\r\n");
161 }
162
163 prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2;
164 prefix = pkg_malloc(prefix_len);
165 if (!prefix) {
166 LM_ERR("no pkg memory left for prefix\n");
167 goto out2;
168 }
169 if (user && user->len)
170 prefix_len = sprintf(prefix, PATH_PREFIX "%.*s@", user->len, user->s);
171 else
172 prefix_len = sprintf(prefix, PATH_PREFIX);
173
174 if (parse_headers(_m, HDR_PATH_F, 0) < 0) {
175 LM_ERR("failed to parse message for Path header\n");
176 goto out3;
177 }
178 hf = get_hdr(_m, HDR_PATH_T);
179 if (hf)
180 /* path found, add ours in front of that */
181 l = anchor_lump(_m, hf->name.s - _m->buf, 0, 0);
182 else
183 /* no path, append to message */
184 l = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
185 if (!l) {
186 LM_ERR("failed to get anchor\n");
187 goto out3;
188 }
189
190 l = insert_new_lump_before(l, prefix, prefix_len, 0);
191 if (!l) goto out3;
192 l = insert_subst_lump_before(l,
193 (path_sockname_mode)?SUBST_SND_ALL_EX:SUBST_SND_ALL, 0);
194 if (!l) goto out2;
195 l = insert_new_lump_before(l, suffix, cp - suffix, 0);
196 if (!l) goto out2;
197
198 if(path_enable_r2!=0) {
199 dp = path_strzdup(prefix, prefix_len);
200 if(dp==NULL) goto out1;
201 l = insert_new_lump_before(l, dp, prefix_len, 0);
202 if (!l) goto out1;
203 l = insert_subst_lump_before(l,
204 (path_sockname_mode)?SUBST_RCV_ALL_EX:SUBST_RCV_ALL, 0);
205 if (!l) goto out1;
206 dp = path_strzdup(suffix, cp - suffix);
207 if(dp==NULL) goto out1;
208 l = insert_new_lump_before(l, dp, cp - suffix, 0);
209 if (!l) goto out1;
210 }
211
212 return 1;
213
214 out3:
215 pkg_free(prefix);
216 out2:
217 pkg_free(suffix);
218 out1:
219 LM_ERR("failed to insert Path header\n");
220
221 return -1;
222 }
223
224 /*! \brief
225 * Prepend own uri to Path header
226 */
ki_add_path(struct sip_msg * _msg)227 int ki_add_path(struct sip_msg* _msg)
228 {
229 str user = {0,0};
230 int ret;
231 path_param_t param = PATH_PARAM_NONE;
232
233 ret = handleOutbound(_msg, &user, ¶m);
234
235 if (ret > 0) {
236 ret = prepend_path(_msg, &user, param, NULL);
237 }
238
239 if (user.s != NULL) {
240 pkg_free(user.s);
241 }
242
243 return ret;
244 }
245
add_path(sip_msg_t * _msg,char * _a,char * _b)246 int add_path(sip_msg_t* _msg, char* _a, char* _b)
247 {
248 return ki_add_path(_msg);
249 }
250
251 /*! \brief
252 * Prepend own uri to Path header and take care of given
253 * user.
254 */
add_path_usr(struct sip_msg * _msg,char * _usr,char * _parms)255 int add_path_usr(struct sip_msg* _msg, char* _usr, char* _parms)
256 {
257 str user = {0,0};
258 str parms = {0,0};
259
260 if (_usr) {
261 if(get_str_fparam(&user, _msg, (fparam_t *) _usr)<0) {
262 LM_ERR("failed to get user value\n");
263 return -1;
264 }
265 }
266 if (_parms) {
267 if(get_str_fparam(&parms, _msg, (fparam_t *) _parms)<0) {
268 LM_ERR("failed to get params value\n");
269 return -1;
270 }
271 }
272
273 return prepend_path(_msg, &user, PATH_PARAM_NONE, &parms);
274 }
275
276 /*! \brief
277 * Prepend own uri to Path header and take care of given
278 * user.
279 */
ki_add_path_user(sip_msg_t * _msg,str * _user)280 int ki_add_path_user(sip_msg_t* _msg, str* _user)
281 {
282 str parms = {0,0};
283 return prepend_path(_msg, _user, PATH_PARAM_NONE, &parms);
284 }
285
286 /*! \brief
287 * Prepend own uri to Path header and take care of given
288 * user.
289 */
ki_add_path_user_params(sip_msg_t * _msg,str * _user,str * _params)290 int ki_add_path_user_params(sip_msg_t* _msg, str* _user, str* _params)
291 {
292 return prepend_path(_msg, _user, PATH_PARAM_NONE, _params);
293 }
294
295 /*! \brief
296 * Prepend own uri to Path header and append received address as
297 * "received"-param to that uri.
298 */
ki_add_path_received(sip_msg_t * _msg)299 int ki_add_path_received(sip_msg_t* _msg)
300 {
301 str user = {0,0};
302 int ret;
303 path_param_t param = PATH_PARAM_RECEIVED;
304
305 ret = handleOutbound(_msg, &user, ¶m);
306
307 if (ret > 0) {
308 ret = prepend_path(_msg, &user, param, NULL);
309 }
310
311 if (user.s != NULL) {
312 pkg_free(user.s);
313 }
314
315 return ret;
316 }
317
318 /*! \brief
319 * Prepend own uri to Path header and append received address as
320 * "received"-param to that uri.
321 */
add_path_received(struct sip_msg * _msg,char * _a,char * _b)322 int add_path_received(struct sip_msg* _msg, char* _a, char* _b)
323 {
324 return ki_add_path_received(_msg);
325 }
326
327 /*! \brief
328 * Prepend own uri to Path header and append received address as
329 * "received"-param to that uri and take care of given user.
330 */
add_path_received_usr(struct sip_msg * _msg,char * _usr,char * _parms)331 int add_path_received_usr(struct sip_msg* _msg, char* _usr, char* _parms)
332 {
333 str user = {0,0};
334 str parms = {0,0};
335
336 if (_usr) {
337 if(get_str_fparam(&user, _msg, (fparam_t *) _usr)<0) {
338 LM_ERR("failed to get user value\n");
339 return -1;
340 }
341 }
342 if (_parms) {
343 if(get_str_fparam(&parms, _msg, (fparam_t *) _parms)<0) {
344 LM_ERR("failed to get params value\n");
345 return -1;
346 }
347 }
348
349 return prepend_path(_msg, &user, PATH_PARAM_RECEIVED, &parms);
350 }
351
352 /*! \brief
353 * Prepend own uri to Path header and append received address as
354 * "received"-param to that uri and take care of given user.
355 */
ki_add_path_received_user(sip_msg_t * _msg,str * _user)356 int ki_add_path_received_user(sip_msg_t* _msg, str* _user)
357 {
358 str parms = {0,0};
359 return prepend_path(_msg, _user, PATH_PARAM_RECEIVED, &parms);
360 }
361
362 /*! \brief
363 * Prepend own uri to Path header and append received address as
364 * "received"-param to that uri and take care of given user.
365 */
ki_add_path_received_user_params(sip_msg_t * _msg,str * _user,str * _params)366 int ki_add_path_received_user_params(sip_msg_t* _msg, str* _user, str* _params)
367 {
368 return prepend_path(_msg, _user, PATH_PARAM_RECEIVED, _params);
369 }
370
371 /*! \brief
372 * rr callback
373 */
path_rr_callback(struct sip_msg * _m,str * r_param,void * cb_param)374 void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
375 {
376 param_hooks_t hooks;
377 param_t *params;
378 static char dst_uri_buf[MAX_URI_SIZE];
379 static str dst_uri;
380 char *p;
381 int n;
382 int nproto;
383 str sproto;
384
385 if (parse_params(r_param, CLASS_CONTACT, &hooks, ¶ms) != 0) {
386 LM_ERR("failed to parse route parameters\n");
387 return;
388 }
389
390 if (hooks.contact.received==NULL
391 || hooks.contact.received->body.len<=0) {
392 LM_DBG("no received parameter in route header\n");
393 free_params(params);
394 return;
395 }
396
397 /* 24 => sip:...;transport=sctp */
398 if(hooks.contact.received->body.len + 24 >= MAX_URI_SIZE) {
399 LM_ERR("received uri is too long\n");
400 goto done;
401 }
402 dst_uri.s = dst_uri_buf;
403 dst_uri.len = MAX_URI_SIZE;
404 if(path_received_format==0) {
405 /* received=sip:...;transport... */
406 if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
407 LM_ERR("unescaping received failed\n");
408 free_params(params);
409 return;
410 }
411 } else {
412 /* received=ip~port~proto */
413 memcpy(dst_uri_buf, "sip:", 4);
414 memcpy(dst_uri_buf+4, hooks.contact.received->body.s,
415 hooks.contact.received->body.len);
416 dst_uri_buf[4+hooks.contact.received->body.len] = '\0';
417 p = dst_uri_buf + 4;
418 n = 0;
419 while(*p!='\0') {
420 if(*p=='~') {
421 n++;
422 if(n==1) {
423 /* port */
424 *p = ':';
425 } else if(n==2) {
426 /* proto */
427 *p = ';';
428 p++;
429 if(*p=='\0') {
430 LM_ERR("invalid received format\n");
431 goto done;
432 }
433 nproto = *p - '0';
434 if (nproto != PROTO_UDP) {
435 proto_type_to_str(nproto, &sproto);
436 if (sproto.len == 0) {
437 LM_ERR("unknown proto in received param\n");
438 goto done;
439 }
440 memcpy(p, "transport=", 10);
441 p += 10;
442 memcpy(p, sproto.s, sproto.len);
443 p += sproto.len;
444 } else {
445 /* go back one byte to overwrite ';' */
446 p--;
447 }
448 *p = '\0';
449 dst_uri.len = p - dst_uri_buf;
450 break;
451 } else {
452 LM_ERR("invalid number of separators (%d)\n", n);
453 goto done;
454 }
455 }
456 p++;
457 }
458 }
459
460 LM_DBG("setting dst uri: %.*s\n", dst_uri.len, dst_uri.s);
461 if (set_dst_uri(_m, &dst_uri) != 0) {
462 LM_ERR("failed to set dst-uri\n");
463 free_params(params);
464 return;
465 }
466 /* dst_uri changed, so it makes sense to re-use the current uri
467 * for forking */
468 ruri_mark_new(); /* re-use uri for serial forking */
469
470 done:
471 free_params(params);
472 }
473