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;
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);
69static 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;
117 pjsip_rr_hdr *rr =
NULL;
123 if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
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;
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);
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)) {
152 uri = pjsip_uri_get_uri(&rr->name_addr);
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);
164 if (!dlg && !rr && !ignore_rr && !pubsub && rdata->msg_info.to->tag.slen){
180 pjsip_contact_hdr *contact;
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);
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;
201 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
221 rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
261 pjsip_contact_hdr *contact;
263 pjsip_param *x_orig_host;
267 if (
tdata->msg->type == PJSIP_REQUEST_MSG) {
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);
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);
286 if (
tdata->msg->type != PJSIP_RESPONSE_MSG) {
290 contact = pjsip_msg_find_hdr(
tdata->msg, PJSIP_H_CONTACT,
NULL);
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);
296 char host_port[x_orig_host->value.slen + 1];
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);
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,
':');
309 pj_strdup2(
tdata->pool, &contact_uri->host, host_port);
310 contact_uri->port = strtol(sep,
NULL, 10);
312 pj_list_erase(x_orig_host);
314 contact = pjsip_msg_find_hdr(
tdata->msg, PJSIP_H_CONTACT, contact->next);
323 pjsip_via_hdr *via =
NULL;
325 pjsip_sip_uri *uri =
NULL;
333 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA,
NULL);
343 if (transport_state->localnet) {
349 ast_debug(5,
"Request is being sent to local address, skipping NAT manipulation\n");
355 pjsip_cseq_hdr *cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg);
364 if (!cseq || tdata->msg->type == PJSIP_REQUEST_MSG ||
365 pjsip_method_cmp(&cseq->method, &pjsip_register_method)) {
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);
377 if ((tdata->msg->type == PJSIP_REQUEST_MSG) && (via || (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA,
NULL)))) {
379 if (transport->external_signaling_port) {
380 via->sent_by.port = transport->external_signaling_port;
408 .name = {
"NAT", 3 },
410 .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 2,
420 if (
session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
436 if (
session->inv_session->state == PJSIP_INV_STATE_NULL) {
461 ast_log(
LOG_ERROR,
"Could not register NAT module for incoming and outgoing requests\n");
475 .
requires =
"res_pjsip,res_pjsip_session",
Access Control of various sorts.
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
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...
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
void ast_sip_unregister_service(pjsip_module *module)
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
@ AST_SIP_SUPPLEMENT_PRIORITY_FIRST
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.
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.
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.
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)
pjsip_sip_uri * ast_sip_get_contact_sip_uri(pjsip_tx_data *tdata)
Return the SIP URI of the Contact header.
static void nat_incoming_invite_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when an INVITE response comes in.
static int nat_invoke_hook(void *obj, void *arg, int flags)
Callback function for invoking hooks.
static void save_orig_contact_host(pjsip_rx_data *rdata, pjsip_sip_uri *uri)
static int nat_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when an INVITE goes out.
static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
static pjsip_module nat_module
static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
#define AST_SIP_X_AST_ORIG_HOST_LEN
static void nat_outgoing_invite_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Function called when an INVITE comes in.
static pj_bool_t handle_rx_message(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
static void restore_orig_contact_host(pjsip_tx_data *tdata)
static int load_module(void)
#define AST_SIP_X_AST_ORIG_HOST
static int unload_module(void)
static struct ast_sip_session_supplement nat_supplement
Supplement for adding NAT functionality to dialog.
static pj_status_t nat_on_tx_message(pjsip_tx_data *tdata)
static void rewrite_uri(pjsip_rx_data *rdata, pjsip_sip_uri *uri, pj_pool_t *pool)
static pj_bool_t nat_on_rx_message(pjsip_rx_data *rdata)
static pj_status_t process_nat(pjsip_tx_data *tdata)
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
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.
unsigned int rewrite_contact
An entity with which Asterisk communicates.
struct ast_sip_endpoint_nat_configuration nat
Structure for SIP nat hook information.
void(* outgoing_external_message)(struct pjsip_tx_data *tdata, struct ast_sip_transport *transport)
Structure which contains information about a transport.
A supplement to SIP message processing.
A structure describing a SIP session.
Structure for SIP transport information.
Socket address structure.
Structure which contains hook details.
pjsip_tx_data * tdata
Outgoing message itself.
struct ast_sip_transport * transport
Chosen transport.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.