path.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * $Id$
  3. *
  4. * Path handling for intermediate proxies.
  5. *
  6. * Copyright (C) 2006 Inode GmbH (Andreas Granig <[email protected]>)
  7. *
  8. * This file is part of Kamailio, a free SIP server.
  9. *
  10. * Kamailio is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * Kamailio is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  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
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. */
  25. /*! \file
  26. * \brief Path :: Utilities
  27. *
  28. * \ingroup path
  29. * - Module: path
  30. */
  31. #include <string.h>
  32. #include <stdio.h>
  33. #include "../../mem/mem.h"
  34. #include "../../data_lump.h"
  35. #include "../../parser/parse_param.h"
  36. #include "../../lib/kcore/strcommon.h"
  37. #include "../../dset.h"
  38. #include "path.h"
  39. #include "path_mod.h"
  40. typedef enum {
  41. PATH_PARAM_NONE, PATH_PARAM_RECEIVED, PATH_PARAM_OB
  42. } path_param_t;
  43. #define PATH_PREFIX "Path: <sip:"
  44. #define PATH_PREFIX_LEN (sizeof(PATH_PREFIX)-1)
  45. const static char *proto_strings[] = {
  46. [PROTO_TCP] = "%3Btransport%3Dtcp",
  47. [PROTO_TLS] = "%3Btransport%3Dtls",
  48. [PROTO_SCTP] = "%3Btransport%3Dsctp",
  49. [PROTO_WS] = "%3Btransport%3Dws",
  50. [PROTO_WSS] = "%3Btransport%3Dws",
  51. };
  52. static int prepend_path(struct sip_msg* _m, str *user, path_param_t param, str *add_params)
  53. {
  54. struct lump *l;
  55. char *prefix, *suffix, *cp;
  56. const char *proto_str;
  57. int prefix_len, suffix_len;
  58. struct hdr_field *hf;
  59. /* maximum possible length of suffix */
  60. suffix_len = strlen(";lr;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
  61. + IP_ADDR_MAX_STR_SIZE + (add_params ? add_params->len : 0) + 1;
  62. cp = suffix = pkg_malloc(suffix_len);
  63. if (!suffix) {
  64. LM_ERR("no pkg memory left for suffix\n");
  65. goto out1;
  66. }
  67. cp += sprintf(cp, ";lr");
  68. switch(param) {
  69. default:
  70. break;
  71. case PATH_PARAM_RECEIVED:
  72. if (_m->rcv.proto < (sizeof(proto_strings) / sizeof(*proto_strings)))
  73. proto_str = proto_strings[(unsigned int) _m->rcv.proto];
  74. else
  75. proto_str = NULL;
  76. cp += sprintf(cp, ";received=sip:%s:%hu%s", ip_addr2a(&_m->rcv.src_ip),
  77. _m->rcv.src_port, proto_str ? : "");
  78. break;
  79. case PATH_PARAM_OB:
  80. cp += sprintf(cp, ";ob");
  81. break;
  82. }
  83. if (add_params && add_params->len)
  84. cp += sprintf(cp, ";%.*s", add_params->len, add_params->s);
  85. cp += sprintf(cp, ">\r\n");
  86. prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2;
  87. prefix = pkg_malloc(prefix_len);
  88. if (!prefix) {
  89. LM_ERR("no pkg memory left for prefix\n");
  90. goto out2;
  91. }
  92. if (user && user->len)
  93. prefix_len = sprintf(prefix, PATH_PREFIX "%.*s@", user->len, user->s);
  94. else
  95. prefix_len = sprintf(prefix, PATH_PREFIX);
  96. if (parse_headers(_m, HDR_PATH_F, 0) < 0) {
  97. LM_ERR("failed to parse message for Path header\n");
  98. goto out3;
  99. }
  100. hf = get_hdr(_m, HDR_PATH_T);
  101. if (hf)
  102. /* path found, add ours in front of that */
  103. l = anchor_lump(_m, hf->name.s - _m->buf, 0, 0);
  104. else
  105. /* no path, append to message */
  106. l = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
  107. if (!l) {
  108. LM_ERR("failed to get anchor\n");
  109. goto out3;
  110. }
  111. l = insert_new_lump_before(l, prefix, prefix_len, 0);
  112. if (!l) goto out3;
  113. l = insert_subst_lump_before(l, SUBST_SND_ALL, 0);
  114. if (!l) goto out2;
  115. l = insert_new_lump_before(l, suffix, cp - suffix, 0);
  116. if (!l) goto out2;
  117. return 1;
  118. out3:
  119. pkg_free(prefix);
  120. out2:
  121. pkg_free(suffix);
  122. out1:
  123. LM_ERR("failed to insert Path header\n");
  124. return -1;
  125. }
  126. /*! \brief
  127. * Prepend own uri to Path header
  128. */
  129. int add_path(struct sip_msg* _msg, char* _a, char* _b)
  130. {
  131. str user = {0,0};
  132. int ret;
  133. path_param_t param = PATH_PARAM_NONE;
  134. struct via_body *via;
  135. if (path_obb.use_outbound != NULL
  136. && path_obb.use_outbound(_msg)) {
  137. if (path_obb.encode_flow_token(&user, _msg->rcv) != 0) {
  138. LM_ERR("encoding outbound flow-token\n");
  139. return -1;
  140. }
  141. /* Only include ;ob parameter if this is the first-hop (that
  142. means only one Via:) */
  143. if (parse_via_header(_msg, 2, &via) < 0)
  144. param = PATH_PARAM_OB;
  145. }
  146. ret = prepend_path(_msg, &user, param, NULL);
  147. if (user.s != NULL)
  148. pkg_free(user.s);
  149. return ret;
  150. }
  151. /*! \brief
  152. * Prepend own uri to Path header and take care of given
  153. * user.
  154. */
  155. int add_path_usr(struct sip_msg* _msg, char* _usr, char* _parms)
  156. {
  157. str user = {0,0};
  158. str parms = {0,0};
  159. if (_usr)
  160. get_str_fparam(&user, _msg, (fparam_t *) _usr);
  161. if (_parms)
  162. get_str_fparam(&parms, _msg, (fparam_t *) _parms);
  163. return prepend_path(_msg, &user, PATH_PARAM_NONE, &parms);
  164. }
  165. /*! \brief
  166. * Prepend own uri to Path header and append received address as
  167. * "received"-param to that uri.
  168. */
  169. int add_path_received(struct sip_msg* _msg, char* _a, char* _b)
  170. {
  171. return prepend_path(_msg, NULL, PATH_PARAM_RECEIVED, NULL);
  172. }
  173. /*! \brief
  174. * Prepend own uri to Path header and append received address as
  175. * "received"-param to that uri and take care of given user.
  176. */
  177. int add_path_received_usr(struct sip_msg* _msg, char* _usr, char* _parms)
  178. {
  179. str user = {0,0};
  180. str parms = {0,0};
  181. if (_usr)
  182. get_str_fparam(&user, _msg, (fparam_t *) _usr);
  183. if (_parms)
  184. get_str_fparam(&parms, _msg, (fparam_t *) _parms);
  185. return prepend_path(_msg, &user, PATH_PARAM_RECEIVED, &parms);
  186. }
  187. /*! \brief
  188. * rr callback
  189. */
  190. void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
  191. {
  192. param_hooks_t hooks;
  193. param_t *params;
  194. static char dst_uri_buf[MAX_URI_SIZE];
  195. static str dst_uri;
  196. if (parse_params(r_param, CLASS_CONTACT, &hooks, &params) != 0) {
  197. LM_ERR("failed to parse route parameters\n");
  198. return;
  199. }
  200. if (hooks.contact.received) {
  201. dst_uri.s = dst_uri_buf;
  202. dst_uri.len = MAX_URI_SIZE;
  203. if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
  204. LM_ERR("unescaping received failed\n");
  205. free_params(params);
  206. return;
  207. }
  208. if (set_dst_uri(_m, &dst_uri) != 0) {
  209. LM_ERR("failed to set dst-uri\n");
  210. free_params(params);
  211. return;
  212. }
  213. /* dst_uri changed, so it makes sense to re-use the current uri for
  214. forking */
  215. ruri_mark_new(); /* re-use uri for serial forking */
  216. }
  217. free_params(params);
  218. }