37 #define AST_SIP_X_AST_ORIG_HOST "x-ast-orig-host" 38 #define AST_SIP_X_AST_ORIG_HOST_LEN 15 40 #define is_sip_uri(uri) \ 41 (PJSIP_URI_SCHEME_IS_SIP(uri) || PJSIP_URI_SCHEME_IS_SIPS(uri)) 45 pjsip_param *x_orig_host;
48 #define MAX_PORT_LEN 5 50 if (rdata->msg_info.msg->type != PJSIP_REQUEST_MSG ||
51 rdata->msg_info.msg->line.req.method.id != PJSIP_REGISTER_METHOD) {
55 ast_debug(1,
"Saving contact '%.*s:%d'\n",
56 (
int)uri->host.slen, uri->host.ptr, uri->port);
58 x_orig_host = PJ_POOL_ALLOC_T(rdata->tp_info.pool, pjsip_param);
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);
69 static void rewrite_uri(pjsip_rx_data *rdata, pjsip_sip_uri *uri, pj_pool_t *
pool)
72 if (pj_strcmp2(&uri->host, rdata->pkt_info.src_name) != 0) {
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)) {
80 }
else if (strcasecmp(
"udp", rdata->tp_info.transport->type_name)) {
81 uri->transport_param = pj_str(rdata->tp_info.transport->type_name);
83 uri->transport_param.slen = 0;
118 pjsip_rr_hdr *rr =
NULL;
124 if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
126 for (iter = rdata->msg_info.msg->hdr.prev; iter != &rdata->msg_info.msg->hdr; iter = iter->prev) {
127 if (iter->type == PJSIP_H_RECORD_ROUTE) {
128 rr = (pjsip_rr_hdr *)iter;
132 }
else if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method)) {
133 rr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE,
NULL);
142 if (!pjsip_method_cmp(&rdata->msg_info.cseq->method, &pjsip_subscribe_method) ||
143 !pjsip_method_cmp(&rdata->msg_info.cseq->method, &pjsip_notify_method)) {
153 uri = pjsip_uri_get_uri(&rr->name_addr);
158 if (dlg && !pj_list_empty(&dlg->route_set) && !dlg->route_set_frozen) {
159 pjsip_routing_hdr *route = dlg->route_set.next;
160 uri = pjsip_uri_get_uri(&route->name_addr);
165 if (!dlg && !rr && !ignore_rr && !pubsub && rdata->msg_info.to->tag.slen){
183 contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
NULL);
184 if (contact && !contact->star && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
185 pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);
189 if (dlg && pj_list_empty(&dlg->route_set) && (!dlg->remote.contact
190 || pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, dlg->remote.contact->uri, contact->uri))) {
191 dlg->remote.contact = (pjsip_contact_hdr*)pjsip_hdr_clone(dlg->pool, contact);
192 dlg->target = dlg->remote.contact->uri;
202 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
222 rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
264 ((details->
type == transport_state->
type) && (transport_state->
factory) &&
276 pjsip_contact_hdr *
contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT,
NULL);
278 if (!contact || (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
282 return pjsip_uri_get_uri(contact->uri);
310 pjsip_param *x_orig_host;
314 if (tdata->msg->type == PJSIP_REQUEST_MSG) {
316 uri = pjsip_uri_get_uri(tdata->msg->line.req.uri);
317 while ((x_orig_host = pjsip_param_find(&uri->other_param, &x_name))) {
318 pj_list_erase(x_orig_host);
321 for (hdr = tdata->msg->hdr.next; hdr != &tdata->msg->hdr; hdr = hdr->next) {
322 if (hdr->type == PJSIP_H_TO) {
323 if (
is_sip_uri(((pjsip_fromto_hdr *) hdr)->uri)) {
324 uri = pjsip_uri_get_uri(((pjsip_fromto_hdr *) hdr)->uri);
325 while ((x_orig_host = pjsip_param_find(&uri->other_param, &x_name))) {
326 pj_list_erase(x_orig_host);
333 if (tdata->msg->type != PJSIP_RESPONSE_MSG) {
337 contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT,
NULL);
339 pjsip_sip_uri *contact_uri = pjsip_uri_get_uri(contact->uri);
340 x_orig_host = pjsip_param_find(&contact_uri->other_param, &x_name);
343 char host_port[x_orig_host->value.slen + 1];
346 ast_debug(1,
"Restoring contact %.*s:%d to %.*s\n", (
int)contact_uri->host.slen,
347 contact_uri->host.ptr, contact_uri->port,
348 (
int)x_orig_host->value.slen, x_orig_host->value.ptr);
350 strncpy(host_port, x_orig_host->value.ptr, x_orig_host->value.slen);
351 host_port[x_orig_host->value.slen] =
'\0';
352 sep = strchr(host_port,
':');
356 pj_strdup2(tdata->pool, &contact_uri->host, host_port);
357 contact_uri->port = strtol(sep,
NULL, 10);
359 pj_list_erase(x_orig_host);
361 contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, contact->next);
371 pjsip_via_hdr *via =
NULL;
373 pjsip_sip_uri *uri =
NULL;
377 if (tdata->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
378 details.
transport = tdata->tp_sel.u.transport;
379 }
else if (tdata->tp_sel.type == PJSIP_TPSELECTOR_LISTENER) {
380 details.
factory = tdata->tp_sel.u.listener;
381 }
else if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP || tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP6) {
384 details.
transport = tdata->tp_info.transport;
386 if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TCP) {
388 }
else if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TLS) {
398 }
else if ((tdata->msg->type == PJSIP_REQUEST_MSG) &&
399 (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA,
NULL))) {
423 if (transport_state->localnet) {
429 ast_debug(5,
"Request is being sent to local address, skipping NAT manipulation\n");
435 pjsip_cseq_hdr *cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg);
444 if (!cseq || tdata->msg->type == PJSIP_REQUEST_MSG ||
445 pjsip_method_cmp(&cseq->method, &pjsip_register_method)) {
449 if (
transport->external_signaling_port) {
450 uri->port =
transport->external_signaling_port;
451 ast_debug(4,
"Re-wrote Contact URI port to %d\n", uri->port);
457 if ((tdata->msg->type == PJSIP_REQUEST_MSG) && (via || (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA,
NULL)))) {
459 if (
transport->external_signaling_port) {
460 via->sent_by.port =
transport->external_signaling_port;
488 .name = {
"NAT", 3 },
490 .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 2,
500 if (session->
inv_session->state == PJSIP_INV_STATE_INCOMING) {
516 if (session->
inv_session->state == PJSIP_INV_STATE_NULL) {
541 ast_log(
LOG_ERROR,
"Could not register NAT module for incoming and outgoing requests\n");
555 .requires =
"res_pjsip,res_pjsip_session",
static int find_transport_state_in_use(void *obj, void *arg, int flags)
Callback function for finding the transport the request is going out on.
pjsip_tpfactory * factory
Potential pointer to the transport factory itself, if TCP/TLS.
Structure which contains hook details.
struct ast_sip_endpoint * endpoint
enum ast_transport type
Type of transport.
Asterisk main include file. File version handling, generic pbx functions.
struct ast_sip_transport * transport
Chosen transport.
static int unload_module(void)
static void nat_incoming_invite_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when an INVITE response comes in.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
struct ast_sip_endpoint_nat_configuration nat
pj_str_t local_address
Local address for transport.
#define ao2_callback(c, flags, cb_fn, arg)
pjsip_transport * transport
Potential pointer to the transport itself, if UDP.
static pj_bool_t nat_on_rx_message(pjsip_rx_data *rdata)
static pj_pool_t * pool
Global memory pool for configuration and timers.
static struct ao2_container * transport_states
Perform no matching, return all objects.
Structure which contains information about a transport.
Return all matching objects.
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
struct pjsip_inv_session * inv_session
Socket address structure.
A structure describing a SIP session.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
static void rewrite_uri(pjsip_rx_data *rdata, pjsip_sip_uri *uri, pj_pool_t *pool)
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.
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
static pj_bool_t handle_rx_message(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
#define ast_debug(level,...)
Log a DEBUG message.
Structure for SIP nat hook information.
#define AST_SIP_X_AST_ORIG_HOST_LEN
static pj_status_t nat_on_tx_message(pjsip_tx_data *tdata)
Structure for SIP transport information.
void(* outgoing_external_message)(struct pjsip_tx_data *tdata, struct ast_sip_transport *transport)
int local_port
Local port for transport.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct pjsip_transport * transport
Transport itself.
static pjsip_module nat_module
static struct ast_mansession session
Access Control of various sorts.
An entity with which Asterisk communicates.
static int nat_invoke_hook(void *obj, void *arg, int flags)
Callback function for invoking hooks.
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
static void save_orig_contact_host(pjsip_rx_data *rdata, pjsip_sip_uri *uri)
struct ao2_container * ast_sip_get_transport_states(void)
Retrieves all transport states.
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
static int nat_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when an INVITE goes out.
static pj_status_t process_nat(pjsip_tx_data *tdata)
#define ast_sip_transport_is_local(transport_state, addr)
unsigned int rewrite_contact
struct pjsip_tpfactory * factory
Transport factory.
Module has failed to load, may be in an inconsistent state.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
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.
A supplement to SIP message processing.
static int load_module(void)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static void restore_orig_contact_host(pjsip_tx_data *tdata)
void ast_sip_unregister_service(pjsip_module *module)
static struct ast_sip_session_supplement nat_supplement
Supplement for adding NAT functionality to dialog.
static pjsip_sip_uri * nat_get_contact_sip_uri(pjsip_tx_data *tdata)
Helper function which returns the SIP URI of a Contact header.
static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
#define AST_SIP_X_AST_ORIG_HOST
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
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...
pjsip_tx_data * tdata
Outgoing message itself.
static void nat_outgoing_invite_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Function called when an INVITE comes in.
#define ast_sip_session_register_supplement(supplement)