time_t lastrtptx; /*!< Last RTP sent */
int rtptimeout; /*!< RTP timeout time */
struct sockaddr_in recv; /*!< Received as */
- struct in_addr ourip; /*!< Our IP */
+ struct sockaddr_in ourip; /*!< Our IP (as seen from the outside) */
struct ast_channel *owner; /*!< Who owns us (if we have an owner) */
struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
int route_persistant; /*!< Is this the "real" route? */
*/
static int sipsock = -1;
-static struct sockaddr_in bindaddr = { 0, }; /*!< The address we bind to */
+static struct sockaddr_in bindaddr; /*!< The address we bind to */
+
+/*! \brief our (internal) default address/port to put in SIP/SDP messages
+ * internip is initialized picking a suitable address from one of the
+ * interfaces, and the same port number we bind to. It is used as the
+ * default address/port in SIP messages, and as the default address
+ * (but not port) in SDP messages.
+ */
+static struct sockaddr_in internip;
/*! \brief our external IP address/port for SIP sessions.
* externip.sin_addr is only set when we know we might be behind
*
* + with "stunaddr = host[:port]" we run queries every externrefresh seconds
* to the specified server, and store the result in externip.
- * XXX not implemented yet.
*
* Other variables (externhost, externexpire, externrefresh) are used
* to support the above functions.
*/
static struct sockaddr_in externip; /*!< External IP address if we are behind NAT */
-static char externhost[MAXHOSTNAMELEN]; /*!< External host name (possibly with dynamic DNS and DHCP */
-static time_t externexpire = 0; /*!< Expiration counter for re-resolving external host name in dynamic DNS */
+static char externhost[MAXHOSTNAMELEN]; /*!< External host name */
+static time_t externexpire; /*!< Expiration counter for re-resolving external host name in dynamic DNS */
static int externrefresh = 10;
+static struct sockaddr_in stunaddr; /*!< stun server address */
/*! \brief List of local networks
* We store "localnet" addresses from the config file into an access list,
*/
static struct ast_ha *localaddr; /*!< List of local networks, on the same side of NAT as this Asterisk */
-static struct in_addr __ourip;
-static int ourport;
static struct sockaddr_in debugaddr;
static struct ast_config *notify_types; /*!< The list of manual NOTIFY types we know how to send */
static int sip_prune_realtime(int fd, int argc, char *argv[]);
/*--- Internal UA client handling (outbound registrations) */
-static void ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us);
+static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us);
static void sip_registry_destroy(struct sip_registry *reg);
static int sip_register(char *value, int lineno);
static char *regstate2str(enum sipregistrystate regstate) attribute_const;
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
- ast_inet_ntoa(p->ourip), ourport, p->branch, rport);
+ ast_inet_ntoa(p->ourip.sin_addr),
+ ntohs(p->ourip.sin_port), p->branch, rport);
}
-/*! \brief NAT fix - decide which IP address to use for ASterisk server?
+/*! \brief NAT fix - decide which IP address to use for Asterisk server?
*
* Using the localaddr structure built up with localnet statements in sip.conf
* apply it to their address to see if we need to substitute our
* externip or can get away with our internal bindaddr
+ * 'us' is always overwritten.
*/
-static void ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us)
-{
- struct sockaddr_in theirs, ours;
+static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us)
+{
+ struct sockaddr_in theirs;
+ /* Set want_remap to non-zero if we want to remap 'us' to an externally
+ * reachable IP address and port. This is done if:
+ * 1. we have a localaddr list (containing 'internal' addresses marked
+ * as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them,
+ * and AST_SENSE_ALLOW on 'external' ones);
+ * 2. either stunaddr or externip is set, so we know what to use as the
+ * externally visible address;
+ * 3. the remote address, 'them', is external;
+ * 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY
+ * when passed to ast_apply_ha() so it does need to be remapped.
+ * This fourth condition is checked later.
+ */
+ int want_remap = localaddr &&
+ (externip.sin_addr.s_addr || stunaddr.sin_addr.s_addr) &&
+ ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ;
- /* Get our local information */
- ast_ouraddrfor(them, us);
+ *us = internip; /* starting guess for the internal address */
+ /* now ask the system what would it use to talk to 'them' */
+ ast_ouraddrfor(them, &us->sin_addr);
theirs.sin_addr = *them;
- ours.sin_addr = *us;
- if (localaddr && externip.sin_addr.s_addr &&
- (ast_apply_ha(localaddr, &theirs)) &&
- (!global_matchexterniplocally || !ast_apply_ha(localaddr, &ours))) {
+ if (want_remap &&
+ (!global_matchexterniplocally || !ast_apply_ha(localaddr, us)) ) {
+ /* if we used externhost or stun, see if it is time to refresh the info */
if (externexpire && time(NULL) >= externexpire) {
- struct ast_hostent ahp;
- struct hostent *hp;
-
+ if (stunaddr.sin_addr.s_addr) {
+ ast_stun_request(sipsock, &stunaddr, NULL, &externip);
+ } else {
+ if (ast_parse_arg(externhost, PARSE_INADDR, &externip))
+ ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
+ }
externexpire = time(NULL) + externrefresh;
- if ((hp = ast_gethostbyname(externhost, &ahp))) {
- memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
- } else
- ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
}
- *us = externip.sin_addr;
+ if (externip.sin_addr.s_addr)
+ *us = externip;
+ else
+ ast_log(LOG_WARNING, "stun failed\n");
ast_debug(1, "Target address %s is not local, substituting externip\n",
ast_inet_ntoa(*(struct in_addr *)&them->s_addr));
- } else if (bindaddr.sin_addr.s_addr)
- *us = bindaddr.sin_addr;
+ } else if (bindaddr.sin_addr.s_addr) {
+ /* no remapping, but we bind to a specific address, so use it. */
+ *us = bindaddr;
+ }
}
/*! \brief Append to SIP dialog history with arg list */
{
char buf[33];
- const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip));
+ const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip.sin_addr));
ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host);
if (intended_method != SIP_OPTIONS) /* Peerpoke has it's own system */
p->timer_t1 = SIP_TIMER_T1; /* Default SIP retransmission timer T1 (RFC 3261) */
- if (sin) {
+ if (!sin)
+ p->ourip = internip;
+ else {
p->sa = *sin;
ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
- } else
- p->ourip = __ourip;
+ }
/* Copy global flags to this PVT at setup. */
ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
/* Initialize the bare minimum */
p->method = intended_method;
- if (sin) {
+ if (!sin)
+ p->ourip = internip;
+ else {
p->sa = *sin;
ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
- } else
- p->ourip = __ourip;
+ }
p->branch = ast_random();
make_our_tag(p->tag, sizeof(p->tag));
udptldest.sin_port = p->udptlredirip.sin_port;
udptldest.sin_addr = p->udptlredirip.sin_addr;
} else {
- udptldest.sin_addr = p->ourip;
+ udptldest.sin_addr = p->ourip.sin_addr;
udptldest.sin_port = udptlsin.sin_port;
}
if (debug)
- ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(udptlsin.sin_port));
+ ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(udptlsin.sin_port));
/* We break with the "recommendation" and send our IP, in order that our
peer doesn't have to ast_gethostbyname() us */
dest->sin_port = p->redirip.sin_port;
dest->sin_addr = p->redirip.sin_addr;
} else {
- dest->sin_addr = p->ourip;
+ dest->sin_addr = p->ourip.sin_addr;
dest->sin_port = sin->sin_port;
}
if (needvideo) {
vdest->sin_addr = p->vredirip.sin_addr;
vdest->sin_port = p->vredirip.sin_port;
} else {
- vdest->sin_addr = p->ourip;
+ vdest->sin_addr = p->ourip.sin_addr;
vdest->sin_port = vsin->sin_port;
}
}
get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest);
if (debug)
- ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(sin.sin_port));
+ ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port));
/* Ok, we need video. Let's add what we need for video and set codecs.
Video is handled differently than audio since we can not transcode. */
if (p->maxcallbitrate)
snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
if (debug)
- ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(vsin.sin_port));
+ ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port));
}
/* Check if we need text in this call */
tdest.sin_addr = p->tredirip.sin_addr;
tdest.sin_port = p->tredirip.sin_port;
} else {
- tdest.sin_addr = p->ourip;
+ tdest.sin_addr = p->ourip.sin_addr;
tdest.sin_port = tsin.sin_port;
}
ast_build_string(&m_text_next, &m_text_left, "m=text %d RTP/AVP", ntohs(tdest.sin_port));
- if (debug)
- ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(tsin.sin_port));
+ if (debug) /* XXX should I use tdest below ? */
+ ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port));
}
static void build_contact(struct sip_pvt *p)
{
/* Construct Contact: header */
- if (ourport != STANDARD_SIP_PORT)
- ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip), ourport);
+ if (ntohs(p->ourip.sin_port) != STANDARD_SIP_PORT)
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->ourip.sin_port));
else
- ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip));
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr));
}
/*! \brief Build the Remote Party-ID & From using callingpres options */
break;
}
- fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip));
+ fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
if (send_pres_tags)
l = tmp2;
}
- if (ourport != STANDARD_SIP_PORT && ast_strlen_zero(p->fromdomain))
- snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), ourport, p->tag);
+ if (ntohs(p->ourip.sin_port) != STANDARD_SIP_PORT && ast_strlen_zero(p->fromdomain))
+ snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), ntohs(p->ourip.sin_port), p->tag);
else
- snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), p->tag);
+ snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), p->tag);
/* If we're calling a registered SIP peer, use the fullcontact to dial to the peer */
if (!ast_strlen_zero(p->fullcontact)) {
ast_build_string(&t, &maxbytes, "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no");
ast_build_string(&t, &maxbytes, "Message-Account: sip:%s@%s\r\n",
- S_OR(vmexten, default_vmexten), S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)));
+ S_OR(vmexten, default_vmexten), S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)));
/* Cisco has a bug in the SIP stack where it can't accept the
(0/0) notification. This can temporarily be disabled in
sip.conf with the "buggymwi" option */
} else {
/* Build callid for registration if we haven't registered before */
if (!r->callid_valid) {
- build_callid_registry(r, __ourip, default_fromdomain);
+ build_callid_registry(r, internip.sin_addr, default_fromdomain);
r->callid_valid = TRUE;
}
/* Allocate SIP packet for registration */
msg = "Disabled, no localnet list";
else if (externip.sin_addr.s_addr == 0)
msg = "Disabled, externip is 0.0.0.0";
+ else if (stunaddr.sin_addr.s_addr != 0)
+ msg = "Enabled using STUN";
else if (!ast_strlen_zero(externhost))
msg = "Enabled using externhost";
else
ast_cli(fd, " Externhost: %s\n", S_OR(externhost, "<none>"));
ast_cli(fd, " Externip: %s:%d\n", ast_inet_ntoa(externip.sin_addr), ntohs(externip.sin_port));
ast_cli(fd, " Externrefresh: %d\n", externrefresh);
- ast_cli(fd, " Internal IP: %s:%d\n", ast_inet_ntoa(__ourip), ntohs(bindaddr.sin_port));
+ ast_cli(fd, " Internal IP: %s:%d\n", ast_inet_ntoa(internip.sin_addr), ntohs(internip.sin_port));
{
struct ast_ha *a;
const char *prefix = "Localnet:";
inet_ntop(AF_INET, &a->netmask, buf, sizeof(buf)) );
}
}
+ ast_cli(fd, " STUN server: %s:%d\n", ast_inet_ntoa(stunaddr.sin_addr), ntohs(stunaddr.sin_port));
ast_cli(fd, "\nGlobal Signalling Settings:\n");
ast_cli(fd, "---------------------------\n");
ast_cli(fd, " Received Address: %s:%d\n", ast_inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port));
ast_cli(fd, " SIP Transfer mode: %s\n", transfermode2str(cur->allowtransfer));
ast_cli(fd, " NAT Support: %s\n", nat2str(ast_test_flag(&cur->flags[0], SIP_NAT)));
- ast_cli(fd, " Audio IP: %s %s\n", ast_inet_ntoa(cur->redirip.sin_addr.s_addr ? cur->redirip.sin_addr : cur->ourip), cur->redirip.sin_addr.s_addr ? "(Outside bridge)" : "(local)" );
+ ast_cli(fd, " Audio IP: %s %s\n", ast_inet_ntoa(cur->redirip.sin_addr.s_addr ? cur->redirip.sin_addr : cur->ourip.sin_addr), cur->redirip.sin_addr.s_addr ? "(Outside bridge)" : "(local)" );
ast_cli(fd, " Our Tag: %s\n", cur->tag);
ast_cli(fd, " Their Tag: %s\n", cur->theirtag);
ast_cli(fd, " SIP User agent: %s\n", cur->useragent);
struct ast_variable *v;
struct sip_peer *peer;
struct sip_user *user;
- struct ast_hostent ahp;
char *cat, *stringp, *context, *oldregcontext;
char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT];
- struct hostent *hp;
struct ast_flags dummy[2];
int auto_sip_domains = FALSE;
struct sockaddr_in old_bindaddr = bindaddr;
/* Reset IP addresses */
memset(&bindaddr, 0, sizeof(bindaddr));
+ memset(&stunaddr, 0, sizeof(stunaddr));
+ memset(&internip, 0, sizeof(internip));
+ /* Free memory for local network address mask */
+ ast_free_ha(localaddr);
memset(&localaddr, 0, sizeof(localaddr));
memset(&externip, 0, sizeof(externip));
memset(&default_prefs, 0 , sizeof(default_prefs));
memset(&global_outboundproxy, 0, sizeof(struct sip_proxy));
global_outboundproxy.ip.sin_port = htons(STANDARD_SIP_PORT);
global_outboundproxy.ip.sin_family = AF_INET; /* Type of address: IPv4 */
- ourport = STANDARD_SIP_PORT;
+ bindaddr.sin_port = htons(STANDARD_SIP_PORT);
global_srvlookup = DEFAULT_SRVLOOKUP;
global_tos_sip = DEFAULT_TOS_SIP;
global_tos_audio = DEFAULT_TOS_AUDIO;
global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
} else if (!strcasecmp(v->name, "registerattempts")) {
global_regattempts_max = atoi(v->value);
+ } else if (!strcasecmp(v->name, "stunaddr")) {
+ stunaddr.sin_port = htons(3478);
+ if (ast_parse_arg(v->value, PARSE_INADDR, &stunaddr))
+ ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value);
} else if (!strcasecmp(v->name, "bindaddr")) {
- if (!(hp = ast_gethostbyname(v->value, &ahp))) {
+ if (ast_parse_arg(v->value, PARSE_INADDR, &bindaddr))
ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
- } else {
- memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
- }
} else if (!strcasecmp(v->name, "localnet")) {
struct ast_ha *na;
int ha_error = 0;
if (ha_error)
ast_log(LOG_ERROR, "Bad localnet configuration value line %d : %s\n", v->lineno, v->value);
} else if (!strcasecmp(v->name, "externip")) {
- if (!(hp = ast_gethostbyname(v->value, &ahp)))
+ if (ast_parse_arg(v->value, PARSE_INADDR, &externip))
ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value);
- else
- memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
externexpire = 0;
} else if (!strcasecmp(v->name, "externhost")) {
ast_copy_string(externhost, v->value, sizeof(externhost));
- if (!(hp = ast_gethostbyname(externhost, &ahp)))
+ if (ast_parse_arg(externhost, PARSE_INADDR, &externip))
ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost);
- else
- memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
externexpire = time(NULL);
} else if (!strcasecmp(v->name, "externrefresh")) {
if (sscanf(v->value, "%d", &externrefresh) != 1) {
} else if (!strcasecmp(v->name, "cos_text")) {
ast_str2cos(v->value, &global_cos_text);
} else if (!strcasecmp(v->name, "bindport")) {
- if (sscanf(v->value, "%d", &ourport) == 1) {
- bindaddr.sin_port = htons(ourport);
+ int i;
+ if (sscanf(v->value, "%d", &i) == 1) {
+ bindaddr.sin_port = htons(i);
} else {
ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
}
}
}
}
- if (ast_find_ourip(&__ourip, bindaddr)) {
+ bindaddr.sin_family = AF_INET;
+ internip = bindaddr;
+ if (ast_find_ourip(&internip.sin_addr, bindaddr)) {
ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n");
return 0;
}
- if (!ntohs(bindaddr.sin_port))
- bindaddr.sin_port = ntohs(STANDARD_SIP_PORT);
- bindaddr.sin_family = AF_INET;
ast_mutex_lock(&netlock);
if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) {
close(sipsock);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "SIP Listening on %s:%d\n",
ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
-
+ if (stunaddr.sin_addr.s_addr != 0) {
+ ast_debug(1, "stun to %s:%d\n",
+ ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port));
+ ast_stun_request(sipsock, &stunaddr,
+ NULL, &externip);
+ ast_debug(1, "STUN sees us at %s:%d\n",
+ ast_inet_ntoa(externip.sin_addr) , ntohs(externip.sin_port));
+ }
ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip);
}
}
memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
if (!p->pendinginvite) {
- ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
+ ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
transmit_reinvite_with_sdp(p, TRUE);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
- ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
+ ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
}
}
if (flag)
ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(p->udptlredirip.sin_addr), ntohs(p->udptlredirip.sin_port));
else
- ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to us (IP %s)\n", p->callid, ast_inet_ntoa(p->ourip));
+ ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to us (IP %s)\n", p->callid, ast_inet_ntoa(p->ourip.sin_addr));
transmit_reinvite_with_sdp(p, TRUE);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
if (flag)
ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(p->udptlredirip.sin_addr), ntohs(p->udptlredirip.sin_port));
else
- ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to us (IP %s)\n", p->callid, ast_inet_ntoa(p->ourip));
+ ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to us (IP %s)\n", p->callid, ast_inet_ntoa(p->ourip.sin_addr));
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
}
}
if (flag)
ast_debug(3, "Responding 200 OK on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(p->udptlredirip.sin_addr), ntohs(p->udptlredirip.sin_port));
else
- ast_debug(3, "Responding 200 OK on SIP '%s' - It's UDPTL soon redirected to us (IP %s)\n", p->callid, ast_inet_ntoa(p->ourip));
+ ast_debug(3, "Responding 200 OK on SIP '%s' - It's UDPTL soon redirected to us (IP %s)\n", p->callid, ast_inet_ntoa(p->ourip.sin_addr));
pvt->t38.state = T38_ENABLED;
p->t38.state = T38_ENABLED;
ast_debug(2, "T38 changed state to %d on channel %s\n", pvt->t38.state, pvt->owner ? pvt->owner->name : "<none>");
if (chan->_state != AST_STATE_UP) { /* We are in early state */
if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
- ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip));
+ ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
} else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */
- ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip));
+ ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
transmit_reinvite_with_sdp(p, FALSE);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
- ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip));
+ ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
/* We have a pending Invite. Send re-invite when we're done with the invite */
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
}
; Default is 0 tries, continue forever
;----------------------------------------- NAT SUPPORT ------------------------
-; The externip, externhost and localnet settings are used if you use Asterisk
-; behind a NAT device to communicate with services on the outside.
-
-;externip = 200.201.202.203 ; Address that we're going to put in outbound SIP
- ; messages if we're behind a NAT
-
- ; The externip and localnet is used
- ; when registering and communicating with other proxies
- ; that we're registered with
-;externhost=foo.dyndns.net ; Alternatively you can specify an
- ; external host, and Asterisk will
- ; perform DNS queries periodically. Not
- ; recommended for production
- ; environments! Use externip instead
-;externrefresh=10 ; How often to refresh externhost if
- ; used
- ; You may add multiple local networks. A reasonable
- ; set of defaults are:
-;localnet=192.168.0.0/255.255.0.0; All RFC 1918 addresses are local networks
-;localnet=10.0.0.0/255.0.0.0 ; Also RFC1918
-;localnet=172.16.0.0/12 ; Another RFC1918 with CIDR notation
-;localnet=169.254.0.0/255.255.0.0 ;Zero conf local network
-
-; The nat= setting is used when Asterisk is on a public IP, communicating with
-; devices hidden behind a NAT device (broadband router). If you have one-way
-; audio problems, you usually have problems with your NAT configuration or your
-; firewall's support of SIP+RTP ports. You configure Asterisk choice of RTP
-; ports for incoming audio in rtp.conf
-;
-;nat=no ; Global NAT settings (Affects all peers and users)
- ; yes = Always ignore info and assume NAT
- ; no = Use NAT mode only according to RFC3581 (;rport)
- ; never = Never attempt NAT mode or RFC3581 support
- ; route = Assume NAT, don't send rport
- ; (work around more UNIDEN bugs)
+;
+; WARNING: SIP operation behind a NAT is tricky and you really need
+; to read and understand well the following section.
+;
+; When Asterisk is behind a NAT device, the "local" address (and port) that
+; a socket is bound to has different values when seen from the inside or
+; from the outside of the NATted network. Unfortunately this address must
+; be communicated to the outside (e.g. in SIP and SDP messages), and in
+; order to determine the correct value Asterisk needs to know:
+;
+; + whether it is talking to someone "inside" or "outside" of the NATted network.
+; This is configured by assigning the "localnet" parameter with a list
+; of network addresses that are considered "inside" of the NATted network.
+; IF LOCALNET IS NOT SET, THE EXTERNAL ADDRESS WILL NOT BE SET CORRECTLY.
+; Multiple entries are allowed, e.g. a reasonable set is the following:
+;
+; localnet=192.168.0.0/255.255.0.0 ; RFC 1918 addresses
+; localnet=10.0.0.0/255.0.0.0 ; Also RFC1918
+; localnet=172.16.0.0/12 ; Another RFC1918 with CIDR notation
+; localnet=169.254.0.0/255.255.0.0 ; Zero conf local network
+;
+; + the "externally visible" address and port number to be used when talking
+; to a host outside the NAT. This information is derived by one of the
+; following (mutually exclusive) config file parameters:
+;
+; a. "externip = hostname[:port]" specifies a static address[:port] to
+; be used in SIP and SDP messages.
+; The hostname is looked up only once, when [re]loading sip.conf .
+; If a port number is not present, use the "bindport" value (which is
+; not guaranteed to work correctly, because a NAT box might remap the
+; port number as well as the address).
+; This approach can be useful if you have a NAT device where you can
+; configure the mapping statically. Examples:
+;
+; externip = 12.34.56.78 ; use this address.
+; externip = 12.34.56.78:9900 ; use this address and port.
+; externip = mynat.my.org:12600 ; Public address of my nat box.
+;
+; b. "externhost = hostname[:port]" is similar to "externip" except
+; that the hostname is looked up every "externrefresh" seconds
+; (default 10s). This can be useful when your NAT device lets you choose
+; the port mapping, but the IP address is dynamic.
+; Beware, you might suffer from service disruption when the name server
+; resolution fails. Examples:
+;
+; externhost=foo.dyndns.net ; refreshed periodically
+; externrefresh=180 ; change the refresh interval
+;
+; c. "stunaddr = stun.server[:port]" queries the STUN server specified
+; as an argument to obtain the external address/port.
+; Queries are also sent periodically every "externrefresh" seconds
+; (as a side effect, sending the query also acts as a keepalive for
+; the state entry on the nat box):
+;
+; stunaddr = foo.stun.com:3478
+; externrefresh = 15
+;
+; Note that at the moment all these mechanism work only for the SIP socket.
+; The IP address discovered with externip/externhost/STUN is reused for
+; media sessions as well, but the port numbers are not remapped so you
+; may still experience problems.
+;
+; NOTE 1: in some cases, NAT boxes will use different port numbers in
+; the internal<->external mapping. In these cases, the "externip" and
+; "externhost" might not help you configure addresses properly, and you
+; really need to use STUN.
+;
+; NOTE 2: when using "externip" or "externhost", the address part is
+; also used as the external address for media sessions.
+; If you use "stunaddr", STUN queries will be sent to the same server
+; also from media sockets, and this should permit a correct mapping of
+; the port numbers as well.
+;
+; In addition to the above, Asterisk has an additional "nat" parameter to
+; address NAT-related issues in incoming SIP or media sessions.
+; In particular, depending on the 'nat= ' settings described below, Asterisk
+; may override the address/port information specified in the SIP/SDP messages,
+; and use the information (sender address) supplied by the network stack instead.
+; However, this is only useful if the external traffic can reach us.
+; The following settings are allowed (both globally and in individual sections):
+;
+; nat = no ; default. Use NAT mode only according to RFC3581 (;rport)
+; nat = yes ; Always ignore info and assume NAT
+; nat = never ; Never attempt NAT mode or RFC3581 support
+; nat = route ; route = Assume NAT, don't send rport
+; ; (work around more UNIDEN bugs)
;----------------------------------- MEDIA HANDLING --------------------------------
; By default, Asterisk tries to re-invite the audio to an optimal path. If there's