res_pjsip_nat.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*** MODULEINFO
  19. <depend>pjproject</depend>
  20. <depend>res_pjsip</depend>
  21. <support_level>core</support_level>
  22. ***/
  23. #include "asterisk.h"
  24. #include <pjsip.h>
  25. #include <pjsip_ua.h>
  26. #include "asterisk/res_pjsip.h"
  27. #include "asterisk/res_pjsip_session.h"
  28. #include "asterisk/module.h"
  29. #include "asterisk/acl.h"
  30. static pj_bool_t handle_rx_message(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
  31. {
  32. pjsip_contact_hdr *contact;
  33. if (!endpoint) {
  34. return PJ_FALSE;
  35. }
  36. if (endpoint->nat.rewrite_contact && (contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL)) &&
  37. !contact->star && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
  38. pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);
  39. pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
  40. pj_cstr(&uri->host, rdata->pkt_info.src_name);
  41. if (strcasecmp("udp", rdata->tp_info.transport->type_name)) {
  42. uri->transport_param = pj_str(rdata->tp_info.transport->type_name);
  43. } else {
  44. uri->transport_param.slen = 0;
  45. }
  46. uri->port = rdata->pkt_info.src_port;
  47. ast_debug(4, "Re-wrote Contact URI host/port to %.*s:%d\n",
  48. (int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port);
  49. /* rewrite the session target since it may have already been pulled from the contact header */
  50. if (dlg && (!dlg->remote.contact
  51. || pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, dlg->remote.contact->uri, contact->uri))) {
  52. dlg->remote.contact = (pjsip_contact_hdr*)pjsip_hdr_clone(dlg->pool, contact);
  53. dlg->target = dlg->remote.contact->uri;
  54. }
  55. }
  56. if (endpoint->nat.force_rport) {
  57. rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
  58. }
  59. return PJ_FALSE;
  60. }
  61. static pj_bool_t nat_on_rx_message(pjsip_rx_data *rdata)
  62. {
  63. pj_bool_t res;
  64. struct ast_sip_endpoint *endpoint;
  65. endpoint = ast_pjsip_rdata_get_endpoint(rdata);
  66. res = handle_rx_message(endpoint, rdata);
  67. ao2_cleanup(endpoint);
  68. return res;
  69. }
  70. /*! \brief Structure which contains information about a transport */
  71. struct request_transport_details {
  72. /*! \brief Type of transport */
  73. enum ast_transport type;
  74. /*! \brief Potential pointer to the transport itself, if UDP */
  75. pjsip_transport *transport;
  76. /*! \brief Potential pointer to the transport factory itself, if TCP/TLS */
  77. pjsip_tpfactory *factory;
  78. /*! \brief Local address for transport */
  79. pj_str_t local_address;
  80. /*! \brief Local port for transport */
  81. int local_port;
  82. };
  83. /*! \brief Callback function for finding the transport the request is going out on */
  84. static int find_transport_in_use(void *obj, void *arg, int flags)
  85. {
  86. struct ast_sip_transport *transport = obj;
  87. struct request_transport_details *details = arg;
  88. /* If an explicit transport or factory matches then this is what is in use, if we are unavailable
  89. * to compare based on that we make sure that the type is the same and the source IP address/port are the same
  90. */
  91. if ((details->transport && details->transport == transport->state->transport) ||
  92. (details->factory && details->factory == transport->state->factory) ||
  93. ((details->type == transport->type) && (transport->state->factory) &&
  94. !pj_strcmp(&transport->state->factory->addr_name.host, &details->local_address) &&
  95. transport->state->factory->addr_name.port == details->local_port)) {
  96. return CMP_MATCH | CMP_STOP;
  97. }
  98. return 0;
  99. }
  100. /*! \brief Helper function which returns the SIP URI of a Contact header */
  101. static pjsip_sip_uri *nat_get_contact_sip_uri(pjsip_tx_data *tdata)
  102. {
  103. pjsip_contact_hdr *contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
  104. if (!contact || (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
  105. return NULL;
  106. }
  107. return pjsip_uri_get_uri(contact->uri);
  108. }
  109. /*! \brief Structure which contains hook details */
  110. struct nat_hook_details {
  111. /*! \brief Outgoing message itself */
  112. pjsip_tx_data *tdata;
  113. /*! \brief Chosen transport */
  114. struct ast_sip_transport *transport;
  115. };
  116. /*! \brief Callback function for invoking hooks */
  117. static int nat_invoke_hook(void *obj, void *arg, int flags)
  118. {
  119. struct ast_sip_nat_hook *hook = obj;
  120. struct nat_hook_details *details = arg;
  121. if (hook->outgoing_external_message) {
  122. hook->outgoing_external_message(details->tdata, details->transport);
  123. }
  124. return 0;
  125. }
  126. static pj_status_t nat_on_tx_message(pjsip_tx_data *tdata)
  127. {
  128. RAII_VAR(struct ao2_container *, transports, NULL, ao2_cleanup);
  129. RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
  130. struct request_transport_details details = { 0, };
  131. pjsip_via_hdr *via = NULL;
  132. struct ast_sockaddr addr = { { 0, } };
  133. pjsip_sip_uri *uri = NULL;
  134. RAII_VAR(struct ao2_container *, hooks, NULL, ao2_cleanup);
  135. /* If a transport selector is in use we know the transport or factory, so explicitly find it */
  136. if (tdata->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
  137. details.transport = tdata->tp_sel.u.transport;
  138. } else if (tdata->tp_sel.type == PJSIP_TPSELECTOR_LISTENER) {
  139. details.factory = tdata->tp_sel.u.listener;
  140. } else if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP || tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP6) {
  141. /* Connectionless uses the same transport for all requests */
  142. details.type = AST_TRANSPORT_UDP;
  143. details.transport = tdata->tp_info.transport;
  144. } else {
  145. if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TCP) {
  146. details.type = AST_TRANSPORT_TCP;
  147. } else if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TLS) {
  148. details.type = AST_TRANSPORT_TLS;
  149. } else {
  150. /* Unknown transport type, we can't map and thus can't apply NAT changes */
  151. return PJ_SUCCESS;
  152. }
  153. if ((uri = nat_get_contact_sip_uri(tdata))) {
  154. details.local_address = uri->host;
  155. details.local_port = uri->port;
  156. } else if ((tdata->msg->type == PJSIP_REQUEST_MSG) &&
  157. (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL))) {
  158. details.local_address = via->sent_by.host;
  159. details.local_port = via->sent_by.port;
  160. } else {
  161. return PJ_SUCCESS;
  162. }
  163. if (!details.local_port) {
  164. details.local_port = (details.type == AST_TRANSPORT_TLS) ? 5061 : 5060;
  165. }
  166. }
  167. if (!(transports = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "transport", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL)) ||
  168. !(transport = ao2_callback(transports, 0, find_transport_in_use, &details)) || !transport->localnet ||
  169. ast_sockaddr_isnull(&transport->external_address)) {
  170. return PJ_SUCCESS;
  171. }
  172. ast_sockaddr_parse(&addr, tdata->tp_info.dst_name, PARSE_PORT_FORBID);
  173. ast_sockaddr_set_port(&addr, tdata->tp_info.dst_port);
  174. /* See if where we are sending this request is local or not, and if not that we can get a Contact URI to modify */
  175. if (ast_apply_ha(transport->localnet, &addr) != AST_SENSE_ALLOW) {
  176. return PJ_SUCCESS;
  177. }
  178. /* Update the contact header with the external address */
  179. if (uri || (uri = nat_get_contact_sip_uri(tdata))) {
  180. pj_strdup2(tdata->pool, &uri->host, ast_sockaddr_stringify_host(&transport->external_address));
  181. if (transport->external_signaling_port) {
  182. uri->port = transport->external_signaling_port;
  183. ast_debug(4, "Re-wrote Contact URI port to %d\n", uri->port);
  184. }
  185. }
  186. /* Update the via header if relevant */
  187. if ((tdata->msg->type == PJSIP_REQUEST_MSG) && (via || (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL)))) {
  188. pj_strdup2(tdata->pool, &via->sent_by.host, ast_sockaddr_stringify_host(&transport->external_address));
  189. if (transport->external_signaling_port) {
  190. via->sent_by.port = transport->external_signaling_port;
  191. }
  192. }
  193. /* Invoke any additional hooks that may be registered */
  194. if ((hooks = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "nat_hook", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL))) {
  195. struct nat_hook_details hook_details = {
  196. .tdata = tdata,
  197. .transport = transport,
  198. };
  199. ao2_callback(hooks, 0, nat_invoke_hook, &hook_details);
  200. }
  201. return PJ_SUCCESS;
  202. }
  203. static pjsip_module nat_module = {
  204. .name = { "NAT", 3 },
  205. .id = -1,
  206. .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 2,
  207. .on_rx_request = nat_on_rx_message,
  208. .on_rx_response = nat_on_rx_message,
  209. .on_tx_request = nat_on_tx_message,
  210. .on_tx_response = nat_on_tx_message,
  211. };
  212. /*! \brief Function called when an INVITE goes out */
  213. static int nat_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
  214. {
  215. if (session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
  216. pjsip_dlg_add_usage(session->inv_session->dlg, &nat_module, NULL);
  217. }
  218. return 0;
  219. }
  220. /*! \brief Function called when an INVITE response comes in */
  221. static void nat_incoming_invite_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
  222. {
  223. handle_rx_message(session->endpoint, rdata);
  224. }
  225. /*! \brief Function called when an INVITE comes in */
  226. static void nat_outgoing_invite_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
  227. {
  228. if (session->inv_session->state == PJSIP_INV_STATE_NULL) {
  229. pjsip_dlg_add_usage(session->inv_session->dlg, &nat_module, NULL);
  230. }
  231. }
  232. /*! \brief Supplement for adding NAT functionality to dialog */
  233. static struct ast_sip_session_supplement nat_supplement = {
  234. .method = "INVITE",
  235. .priority = AST_SIP_SUPPLEMENT_PRIORITY_FIRST + 1,
  236. .incoming_request = nat_incoming_invite_request,
  237. .outgoing_request = nat_outgoing_invite_request,
  238. .incoming_response = nat_incoming_invite_response,
  239. };
  240. static int unload_module(void)
  241. {
  242. ast_sip_session_unregister_supplement(&nat_supplement);
  243. ast_sip_unregister_service(&nat_module);
  244. return 0;
  245. }
  246. static int load_module(void)
  247. {
  248. CHECK_PJSIP_SESSION_MODULE_LOADED();
  249. if (ast_sip_register_service(&nat_module)) {
  250. ast_log(LOG_ERROR, "Could not register NAT module for incoming and outgoing requests\n");
  251. return AST_MODULE_LOAD_FAILURE;
  252. }
  253. if (ast_sip_session_register_supplement(&nat_supplement)) {
  254. ast_log(LOG_ERROR, "Could not register NAT session supplement for incoming and outgoing INVITE requests\n");
  255. unload_module();
  256. return AST_MODULE_LOAD_FAILURE;
  257. }
  258. return AST_MODULE_LOAD_SUCCESS;
  259. }
  260. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP NAT Support",
  261. .support_level = AST_MODULE_SUPPORT_CORE,
  262. .load = load_module,
  263. .unload = unload_module,
  264. .load_pri = AST_MODPRI_APP_DEPEND,
  265. );