Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Functions | Variables
res_pjsip_nat.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/module.h"
#include "asterisk/acl.h"
Include dependency graph for res_pjsip_nat.c:

Go to the source code of this file.

Data Structures

struct  nat_hook_details
 Structure which contains hook details. More...
 

Macros

#define AST_SIP_X_AST_ORIG_HOST   "x-ast-orig-host"
 
#define AST_SIP_X_AST_ORIG_HOST_LEN   15
 
#define COLON_LEN   1
 
#define is_sip_uri(uri)    (PJSIP_URI_SCHEME_IS_SIP(uri) || PJSIP_URI_SCHEME_IS_SIPS(uri))
 
#define MAX_PORT_LEN   5
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static pj_bool_t handle_rx_message (struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
 
static int load_module (void)
 
static int nat_incoming_invite_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 Function called when an INVITE goes out. More...
 
static void nat_incoming_invite_response (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 Function called when an INVITE response comes in. More...
 
static int nat_invoke_hook (void *obj, void *arg, int flags)
 Callback function for invoking hooks. More...
 
static pj_bool_t nat_on_rx_message (pjsip_rx_data *rdata)
 
static pj_status_t nat_on_tx_message (pjsip_tx_data *tdata)
 
static void nat_outgoing_invite_request (struct ast_sip_session *session, struct pjsip_tx_data *tdata)
 Function called when an INVITE comes in. More...
 
static pj_status_t process_nat (pjsip_tx_data *tdata)
 
static void restore_orig_contact_host (pjsip_tx_data *tdata)
 
static int rewrite_contact (pjsip_rx_data *rdata, pjsip_dialog *dlg)
 
static int rewrite_route_set (pjsip_rx_data *rdata, pjsip_dialog *dlg)
 
static void rewrite_uri (pjsip_rx_data *rdata, pjsip_sip_uri *uri, pj_pool_t *pool)
 
static void save_orig_contact_host (pjsip_rx_data *rdata, pjsip_sip_uri *uri)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP NAT Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static pjsip_module nat_module
 
static struct ast_sip_session_supplement nat_supplement
 Supplement for adding NAT functionality to dialog. More...
 

Macro Definition Documentation

◆ AST_SIP_X_AST_ORIG_HOST

#define AST_SIP_X_AST_ORIG_HOST   "x-ast-orig-host"

URI parameter for original host/port

Definition at line 37 of file res_pjsip_nat.c.

◆ AST_SIP_X_AST_ORIG_HOST_LEN

#define AST_SIP_X_AST_ORIG_HOST_LEN   15

Definition at line 38 of file res_pjsip_nat.c.

◆ COLON_LEN

#define COLON_LEN   1

◆ is_sip_uri

#define is_sip_uri (   uri)     (PJSIP_URI_SCHEME_IS_SIP(uri) || PJSIP_URI_SCHEME_IS_SIPS(uri))

Definition at line 40 of file res_pjsip_nat.c.

◆ MAX_PORT_LEN

#define MAX_PORT_LEN   5

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 476 of file res_pjsip_nat.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 476 of file res_pjsip_nat.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 476 of file res_pjsip_nat.c.

◆ handle_rx_message()

static pj_bool_t handle_rx_message ( struct ast_sip_endpoint endpoint,
pjsip_rx_data *  rdata 
)
static

Definition at line 199 of file res_pjsip_nat.c.

200{
201 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
202
203 if (!endpoint) {
204 return PJ_FALSE;
205 }
206
207 if (endpoint->nat.rewrite_contact) {
208 /* rewrite_contact is intended to ensure we send requests/responses to
209 * a routable address when NAT is involved. The URI that dictates where
210 * we send requests/responses can be determined either by Record-Route
211 * headers or by the Contact header if no Record-Route headers are present.
212 * We therefore will attempt to rewrite a Record-Route header first, and if
213 * none are present, we fall back to rewriting the Contact header instead.
214 */
215 if (rewrite_route_set(rdata, dlg)) {
216 rewrite_contact(rdata, dlg);
217 }
218 }
219
220 if (endpoint->nat.force_rport) {
221 rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
222 }
223
224 return PJ_FALSE;
225}
static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
struct ast_sip_endpoint_nat_configuration nat
Definition: res_pjsip.h:1000

References ast_sip_endpoint_nat_configuration::force_rport, ast_sip_endpoint::nat, ast_sip_endpoint_nat_configuration::rewrite_contact, rewrite_contact(), and rewrite_route_set().

Referenced by nat_incoming_invite_response(), and nat_on_rx_message().

◆ load_module()

static int load_module ( void  )
static

Definition at line 458 of file res_pjsip_nat.c.

459{
461 ast_log(LOG_ERROR, "Could not register NAT module for incoming and outgoing requests\n");
463 }
464
466
468}
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:117
static pjsip_module nat_module
static struct ast_sip_session_supplement nat_supplement
Supplement for adding NAT functionality to dialog.
#define ast_sip_session_register_supplement(supplement)

References ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_sip_register_service(), ast_sip_session_register_supplement, LOG_ERROR, nat_module, and nat_supplement.

◆ nat_incoming_invite_request()

static int nat_incoming_invite_request ( struct ast_sip_session session,
struct pjsip_rx_data *  rdata 
)
static

Function called when an INVITE goes out.

Definition at line 418 of file res_pjsip_nat.c.

419{
420 if (session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
421 pjsip_dlg_add_usage(session->inv_session->dlg, &nat_module, NULL);
422 }
423
424 return 0;
425}
static struct ast_mansession session
#define NULL
Definition: resample.c:96

References nat_module, NULL, and session.

◆ nat_incoming_invite_response()

static void nat_incoming_invite_response ( struct ast_sip_session session,
struct pjsip_rx_data *  rdata 
)
static

Function called when an INVITE response comes in.

Definition at line 428 of file res_pjsip_nat.c.

429{
430 handle_rx_message(session->endpoint, rdata);
431}
static pj_bool_t handle_rx_message(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)

References handle_rx_message(), and session.

◆ nat_invoke_hook()

static int nat_invoke_hook ( void *  obj,
void *  arg,
int  flags 
)
static

Callback function for invoking hooks.

Definition at line 247 of file res_pjsip_nat.c.

248{
249 struct ast_sip_nat_hook *hook = obj;
250 struct nat_hook_details *details = arg;
251
252 if (hook->outgoing_external_message) {
253 hook->outgoing_external_message(details->tdata, details->transport);
254 }
255
256 return 0;
257}
Structure for SIP nat hook information.
Definition: res_pjsip.h:329
void(* outgoing_external_message)(struct pjsip_tx_data *tdata, struct ast_sip_transport *transport)
Definition: res_pjsip.h:333
Structure which contains hook details.
pjsip_tx_data * tdata
Outgoing message itself.
struct ast_sip_transport * transport
Chosen transport.

References ast_sip_nat_hook::outgoing_external_message, nat_hook_details::tdata, and nat_hook_details::transport.

Referenced by process_nat().

◆ nat_on_rx_message()

static pj_bool_t nat_on_rx_message ( pjsip_rx_data *  rdata)
static

Definition at line 227 of file res_pjsip_nat.c.

228{
229 pj_bool_t res;
230 struct ast_sip_endpoint *endpoint;
231
232 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
233 res = handle_rx_message(endpoint, rdata);
234 ao2_cleanup(endpoint);
235 return res;
236}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
An entity with which Asterisk communicates.
Definition: res_pjsip.h:963

References ao2_cleanup, ast_pjsip_rdata_get_endpoint(), and handle_rx_message().

◆ nat_on_tx_message()

static pj_status_t nat_on_tx_message ( pjsip_tx_data *  tdata)
static

Definition at line 397 of file res_pjsip_nat.c.

397 {
398 pj_status_t rc;
399
400 rc = process_nat(tdata);
402
403 return rc;
404}
static void restore_orig_contact_host(pjsip_tx_data *tdata)
static pj_status_t process_nat(pjsip_tx_data *tdata)

References process_nat(), restore_orig_contact_host(), and nat_hook_details::tdata.

◆ nat_outgoing_invite_request()

static void nat_outgoing_invite_request ( struct ast_sip_session session,
struct pjsip_tx_data *  tdata 
)
static

Function called when an INVITE comes in.

Definition at line 434 of file res_pjsip_nat.c.

435{
436 if (session->inv_session->state == PJSIP_INV_STATE_NULL) {
437 pjsip_dlg_add_usage(session->inv_session->dlg, &nat_module, NULL);
438 }
439}

References nat_module, NULL, and session.

◆ process_nat()

static pj_status_t process_nat ( pjsip_tx_data *  tdata)
static

Definition at line 318 of file res_pjsip_nat.c.

319{
320 RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
321 RAII_VAR(struct ast_sip_transport_state *, transport_state, NULL, ao2_cleanup);
322 struct ast_sip_request_transport_details details = { 0, };
323 pjsip_via_hdr *via = NULL;
324 struct ast_sockaddr addr = { { 0, } };
325 pjsip_sip_uri *uri = NULL;
326 RAII_VAR(struct ao2_container *, hooks, NULL, ao2_cleanup);
327
328 if (ast_sip_set_request_transport_details(&details, tdata, 0)) {
329 return PJ_SUCCESS;
330 }
331
332 uri = ast_sip_get_contact_sip_uri(tdata);
333 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
334
335 if (!(transport_state = ast_sip_find_transport_state_in_use(&details))) {
336 return PJ_SUCCESS;
337 }
338
339 if (!(transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id))) {
340 return PJ_SUCCESS;
341 }
342
343 if (transport_state->localnet) {
344 ast_sockaddr_parse(&addr, tdata->tp_info.dst_name, PARSE_PORT_FORBID);
345 ast_sockaddr_set_port(&addr, tdata->tp_info.dst_port);
346
347 /* See if where we are sending this request is local or not, and if not that we can get a Contact URI to modify */
348 if (ast_sip_transport_is_local(transport_state, &addr)) {
349 ast_debug(5, "Request is being sent to local address, skipping NAT manipulation\n");
350 return PJ_SUCCESS;
351 }
352 }
353
354 if (!ast_sockaddr_isnull(&transport_state->external_signaling_address)) {
355 pjsip_cseq_hdr *cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg);
356
357 /* Update the Contact header with the external address. We only do this if
358 * a CSeq is not present (which should not happen - but we are extra safe),
359 * if a request is being sent, or if a response is sent that is not a response
360 * to a REGISTER. We specifically don't do this for a response to a REGISTER
361 * as the Contact headers would contain the registered Contacts, and not our
362 * own Contact.
363 */
364 if (!cseq || tdata->msg->type == PJSIP_REQUEST_MSG ||
365 pjsip_method_cmp(&cseq->method, &pjsip_register_method)) {
366 /* We can only rewrite the URI when one is present */
367 if (uri || (uri = ast_sip_get_contact_sip_uri(tdata))) {
368 pj_strdup2(tdata->pool, &uri->host, ast_sockaddr_stringify_host(&transport_state->external_signaling_address));
369 if (transport->external_signaling_port) {
370 uri->port = transport->external_signaling_port;
371 ast_debug(4, "Re-wrote Contact URI port to %d\n", uri->port);
372 }
373 }
374 }
375
376 /* Update the via header if relevant */
377 if ((tdata->msg->type == PJSIP_REQUEST_MSG) && (via || (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL)))) {
378 pj_strdup2(tdata->pool, &via->sent_by.host, ast_sockaddr_stringify_host(&transport_state->external_signaling_address));
379 if (transport->external_signaling_port) {
380 via->sent_by.port = transport->external_signaling_port;
381 }
382 }
383 }
384
385 /* Invoke any additional hooks that may be registered */
387 struct nat_hook_details hook_details = {
388 .tdata = tdata,
389 .transport = transport,
390 };
391 ao2_callback(hooks, 0, nat_invoke_hook, &hook_details);
392 }
393
394 return PJ_SUCCESS;
395}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ast_debug(level,...)
Log a DEBUG message.
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:327
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
struct ast_sip_transport_state * ast_sip_find_transport_state_in_use(struct ast_sip_request_transport_details *details)
Returns the transport state currently in use based on request transport details.
Definition: res_pjsip.c:595
int ast_sip_set_request_transport_details(struct ast_sip_request_transport_details *details, pjsip_tx_data *tdata, int use_ipv6)
Sets request transport details based on tdata.
Definition: res_pjsip.c:648
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ast_sip_transport_is_local(transport_state, addr)
Definition: res_pjsip.h:215
pjsip_sip_uri * ast_sip_get_contact_sip_uri(pjsip_tx_data *tdata)
Return the SIP URI of the Contact header.
Definition: res_pjsip.c:564
static int nat_invoke_hook(void *obj, void *arg, int flags)
Callback function for invoking hooks.
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
Generic container type.
Structure which contains information about a transport.
Definition: res_pjsip.h:337
Structure for SIP transport information.
Definition: res_pjsip.h:119
Transport to bind to.
Definition: res_pjsip.h:221
Socket address structure.
Definition: netsock2.h:97
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_callback, ao2_cleanup, ast_debug, AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_find_transport_state_in_use(), ast_sip_get_contact_sip_uri(), ast_sip_get_sorcery(), ast_sip_set_request_transport_details(), ast_sip_transport_is_local, ast_sockaddr_isnull(), ast_sockaddr_parse(), ast_sockaddr_set_port, ast_sockaddr_stringify_host(), ast_sorcery_retrieve_by_fields(), ast_sorcery_retrieve_by_id(), nat_invoke_hook(), NULL, PARSE_PORT_FORBID, RAII_VAR, nat_hook_details::tdata, and nat_hook_details::transport.

Referenced by nat_on_tx_message().

◆ restore_orig_contact_host()

static void restore_orig_contact_host ( pjsip_tx_data *  tdata)
static

Definition at line 259 of file res_pjsip_nat.c.

260{
261 pjsip_contact_hdr *contact;
263 pjsip_param *x_orig_host;
264 pjsip_sip_uri *uri;
265 pjsip_hdr *hdr;
266
267 if (tdata->msg->type == PJSIP_REQUEST_MSG) {
268 if (is_sip_uri(tdata->msg->line.req.uri)) {
269 uri = pjsip_uri_get_uri(tdata->msg->line.req.uri);
270 while ((x_orig_host = pjsip_param_find(&uri->other_param, &x_name))) {
271 pj_list_erase(x_orig_host);
272 }
273 }
274 for (hdr = tdata->msg->hdr.next; hdr != &tdata->msg->hdr; hdr = hdr->next) {
275 if (hdr->type == PJSIP_H_TO) {
276 if (is_sip_uri(((pjsip_fromto_hdr *) hdr)->uri)) {
277 uri = pjsip_uri_get_uri(((pjsip_fromto_hdr *) hdr)->uri);
278 while ((x_orig_host = pjsip_param_find(&uri->other_param, &x_name))) {
279 pj_list_erase(x_orig_host);
280 }
281 }
282 }
283 }
284 }
285
286 if (tdata->msg->type != PJSIP_RESPONSE_MSG) {
287 return;
288 }
289
290 contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
291 while (contact) {
292 pjsip_sip_uri *contact_uri = pjsip_uri_get_uri(contact->uri);
293 x_orig_host = pjsip_param_find(&contact_uri->other_param, &x_name);
294
295 if (x_orig_host) {
296 char host_port[x_orig_host->value.slen + 1];
297 char *sep;
298
299 ast_debug(1, "Restoring contact %.*s:%d to %.*s\n", (int)contact_uri->host.slen,
300 contact_uri->host.ptr, contact_uri->port,
301 (int)x_orig_host->value.slen, x_orig_host->value.ptr);
302
303 strncpy(host_port, x_orig_host->value.ptr, x_orig_host->value.slen);
304 host_port[x_orig_host->value.slen] = '\0';
305 sep = strchr(host_port, ':');
306 if (sep) {
307 *sep = '\0';
308 sep++;
309 pj_strdup2(tdata->pool, &contact_uri->host, host_port);
310 contact_uri->port = strtol(sep, NULL, 10);
311 }
312 pj_list_erase(x_orig_host);
313 }
314 contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, contact->next);
315 }
316}
#define is_sip_uri(uri)
Definition: res_pjsip_nat.c:40
#define AST_SIP_X_AST_ORIG_HOST_LEN
Definition: res_pjsip_nat.c:38
#define AST_SIP_X_AST_ORIG_HOST
Definition: res_pjsip_nat.c:37

References ast_debug, AST_SIP_X_AST_ORIG_HOST, AST_SIP_X_AST_ORIG_HOST_LEN, is_sip_uri, NULL, and nat_hook_details::tdata.

Referenced by nat_on_tx_message().

◆ rewrite_contact()

static int rewrite_contact ( pjsip_rx_data *  rdata,
pjsip_dialog *  dlg 
)
static

Definition at line 178 of file res_pjsip_nat.c.

179{
180 pjsip_contact_hdr *contact;
181
182 contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
183 if (contact && !contact->star && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
184 pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);
185
186 rewrite_uri(rdata, uri, rdata->tp_info.pool);
187
188 if (dlg && pj_list_empty(&dlg->route_set) && (!dlg->remote.contact
189 || pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, dlg->remote.contact->uri, contact->uri))) {
190 dlg->remote.contact = (pjsip_contact_hdr*)pjsip_hdr_clone(dlg->pool, contact);
191 dlg->target = dlg->remote.contact->uri;
192 }
193 return 0;
194 }
195
196 return -1;
197}
static void rewrite_uri(pjsip_rx_data *rdata, pjsip_sip_uri *uri, pj_pool_t *pool)
Definition: res_pjsip_nat.c:69

References NULL, and rewrite_uri().

Referenced by handle_rx_message().

◆ rewrite_route_set()

static int rewrite_route_set ( pjsip_rx_data *  rdata,
pjsip_dialog *  dlg 
)
static

Record-Route header has no meaning in REGISTER requests and should be ignored

There is currently no good way to get the dlg object for a pubsub dialog so we will just look at the rr & contact of the current message and hope for the best

Even if this message doesn't have any route headers the dialog may, so wait until a later invocation that has a dialog reference to make sure there isn't a previously saved routset in the dialog before deciding the contact needs to be modified

Definition at line 115 of file res_pjsip_nat.c.

116{
117 pjsip_rr_hdr *rr = NULL;
118 pjsip_sip_uri *uri;
119 int res = -1;
120 int ignore_rr = 0;
121 int pubsub = 0;
122
123 if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
124 pjsip_hdr *iter;
125 for (iter = rdata->msg_info.msg->hdr.prev; iter != &rdata->msg_info.msg->hdr; iter = iter->prev) {
126 if (iter->type == PJSIP_H_RECORD_ROUTE) {
127 rr = (pjsip_rr_hdr *)iter;
128 break;
129 }
130 }
131 } else if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method)) {
132 rr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
133 } else {
134 /**
135 * Record-Route header has no meaning in REGISTER requests
136 * and should be ignored
137 */
138 ignore_rr = 1;
139 }
140
141 if (!pjsip_method_cmp(&rdata->msg_info.cseq->method, &pjsip_subscribe_method) ||
142 !pjsip_method_cmp(&rdata->msg_info.cseq->method, &pjsip_notify_method)) {
143 /**
144 * There is currently no good way to get the dlg object for a pubsub dialog
145 * so we will just look at the rr & contact of the current message and
146 * hope for the best
147 */
148 pubsub = 1;
149 }
150
151 if (rr) {
152 uri = pjsip_uri_get_uri(&rr->name_addr);
153 rewrite_uri(rdata, uri, rdata->tp_info.pool);
154 res = 0;
155 }
156
157 if (dlg && !pj_list_empty(&dlg->route_set) && !dlg->route_set_frozen) {
158 pjsip_routing_hdr *route = dlg->route_set.next;
159 uri = pjsip_uri_get_uri(&route->name_addr);
160 rewrite_uri(rdata, uri, dlg->pool);
161 res = 0;
162 }
163
164 if (!dlg && !rr && !ignore_rr && !pubsub && rdata->msg_info.to->tag.slen){
165 /**
166 * Even if this message doesn't have any route headers
167 * the dialog may, so wait until a later invocation that
168 * has a dialog reference to make sure there isn't a
169 * previously saved routset in the dialog before deciding
170 * the contact needs to be modified
171 */
172 res = 0;
173 }
174
175 return res;
176}

References NULL, and rewrite_uri().

Referenced by handle_rx_message().

◆ rewrite_uri()

static void rewrite_uri ( pjsip_rx_data *  rdata,
pjsip_sip_uri *  uri,
pj_pool_t *  pool 
)
static

Definition at line 69 of file res_pjsip_nat.c.

70{
71
72 if (pj_strcmp2(&uri->host, rdata->pkt_info.src_name) != 0) {
73 save_orig_contact_host(rdata, uri);
74 }
75
76 pj_strdup2(pool, &uri->host, rdata->pkt_info.src_name);
77 uri->port = rdata->pkt_info.src_port;
78 if (!strcasecmp("WSS", rdata->tp_info.transport->type_name)) {
79 /* WSS is special, we don't want to overwrite the URI at all as it needs to be ws */
80 } else if (strcasecmp("udp", rdata->tp_info.transport->type_name)) {
81 uri->transport_param = pj_str(rdata->tp_info.transport->type_name);
82 } else {
83 uri->transport_param.slen = 0;
84 }
85}
static void save_orig_contact_host(pjsip_rx_data *rdata, pjsip_sip_uri *uri)
Definition: res_pjsip_nat.c:43

References save_orig_contact_host().

Referenced by rewrite_contact(), and rewrite_route_set().

◆ save_orig_contact_host()

static void save_orig_contact_host ( pjsip_rx_data *  rdata,
pjsip_sip_uri *  uri 
)
static

Definition at line 43 of file res_pjsip_nat.c.

44{
45 pjsip_param *x_orig_host;
46 pj_str_t p_value;
47#define COLON_LEN 1
48#define MAX_PORT_LEN 5
49
50 if (rdata->msg_info.msg->type != PJSIP_REQUEST_MSG ||
51 rdata->msg_info.msg->line.req.method.id != PJSIP_REGISTER_METHOD) {
52 return;
53 }
54
55 ast_debug(1, "Saving contact '%.*s:%d'\n",
56 (int)uri->host.slen, uri->host.ptr, uri->port);
57
58 x_orig_host = PJ_POOL_ALLOC_T(rdata->tp_info.pool, pjsip_param);
59 x_orig_host->name = pj_strdup3(rdata->tp_info.pool, AST_SIP_X_AST_ORIG_HOST);
60 p_value.slen = pj_strlen(&uri->host) + COLON_LEN + MAX_PORT_LEN;
61 p_value.ptr = (char*)pj_pool_alloc(rdata->tp_info.pool, p_value.slen + 1);
62 p_value.slen = snprintf(p_value.ptr, p_value.slen + 1, "%.*s:%d", (int)uri->host.slen, uri->host.ptr, uri->port);
63 pj_strassign(&x_orig_host->value, &p_value);
64 pj_list_insert_before(&uri->other_param, x_orig_host);
65
66 return;
67}
#define MAX_PORT_LEN
#define COLON_LEN

References ast_debug, AST_SIP_X_AST_ORIG_HOST, COLON_LEN, and MAX_PORT_LEN.

Referenced by rewrite_uri().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 451 of file res_pjsip_nat.c.

452{
455 return 0;
456}
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:133
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63

References ast_sip_session_unregister_supplement(), ast_sip_unregister_service(), nat_module, and nat_supplement.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP NAT Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
static

Definition at line 476 of file res_pjsip_nat.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 476 of file res_pjsip_nat.c.

◆ nat_module

pjsip_module nat_module
static

◆ nat_supplement

struct ast_sip_session_supplement nat_supplement
static

Supplement for adding NAT functionality to dialog.

Definition at line 442 of file res_pjsip_nat.c.

Referenced by load_module(), and unload_module().