static const struct ast_sockaddr *sip_real_dst(const struct sip_pvt *p);
static void build_via(struct sip_pvt *p);
static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer);
-static int create_addr(struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog, struct ast_sockaddr *remote_address);
+static int create_addr(struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog);
static char *generate_random_string(char *buf, size_t size);
static void build_callid_pvt(struct sip_pvt *pvt);
static void change_callid_pvt(struct sip_pvt *pvt, const char *callid);
sip_pvt_lock(monitor_instance->subscription_pvt);
ast_set_flag(&monitor_instance->subscription_pvt->flags[0], SIP_OUTGOING);
- create_addr(monitor_instance->subscription_pvt, monitor_instance->peername, 0, 1, NULL);
+ create_addr(monitor_instance->subscription_pvt, monitor_instance->peername, 0, 1);
ast_sip_ouraddrfor(&monitor_instance->subscription_pvt->sa, &monitor_instance->subscription_pvt->ourip, monitor_instance->subscription_pvt);
monitor_instance->subscription_pvt->subscribed = CALL_COMPLETION;
monitor_instance->subscription_pvt->expiry = when;
return TRUE;
}
+/*! \brief Parse proxy string and return an ao2_alloc'd proxy. If dest is
+ * non-NULL, no allocation is performed and dest is used instead.
+ * On error NULL is returned. */
+static struct sip_proxy *proxy_from_config(const char *proxy, int sipconf_lineno, struct sip_proxy *dest)
+{
+ char *mutable_proxy, *sep, *name;
+ int allocated = 0;
+
+ if (!dest) {
+ dest = ao2_alloc(sizeof(struct sip_proxy), NULL);
+ if (!dest) {
+ ast_log(LOG_WARNING, "Unable to allocate config storage for proxy\n");
+ return NULL;
+ }
+ allocated = 1;
+ }
+
+ /* Format is: [transport://]name[:port][,force] */
+ mutable_proxy = ast_skip_blanks(ast_strdupa(proxy));
+ sep = strchr(mutable_proxy, ',');
+ if (sep) {
+ *sep++ = '\0';
+ dest->force = !strncasecmp(ast_skip_blanks(sep), "force", 5);
+ } else {
+ dest->force = FALSE;
+ }
+
+ sip_parse_host(mutable_proxy, sipconf_lineno, &name, &dest->port, &dest->transport);
+
+ /* Check that there is a name at all */
+ if (ast_strlen_zero(name)) {
+ if (allocated) {
+ ao2_ref(dest, -1);
+ } else {
+ dest->name[0] = '\0';
+ }
+ return NULL;
+ }
+ ast_copy_string(dest->name, name, sizeof(dest->name));
+
+ /* Resolve host immediately */
+ proxy_update(dest);
+
+ return dest;
+}
+
/*! \brief converts ascii port to int representation. If no
* pt buffer is provided or the pt has errors when being converted
* to an int value, the port provided as the standard is used.
/*! \brief Get default outbound proxy or global proxy */
static struct sip_proxy *obproxy_get(struct sip_pvt *dialog, struct sip_peer *peer)
{
+ if (dialog && dialog->options && dialog->options->outboundproxy) {
+ if (sipdebug) {
+ ast_debug(1, "BLAH\n");
+ }
+ return dialog->options->outboundproxy;
+ }
if (peer && peer->outboundproxy) {
if (sipdebug) {
ast_debug(1, "OBPROXY: Applying peer OBproxy to this call\n");
/*! \brief create address structure from device name
* Or, if peer not found, find it in the global DNS
* returns TRUE (-1) on failure, FALSE on success */
-static int create_addr(struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog, struct ast_sockaddr *remote_address)
+static int create_addr(struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog)
{
struct sip_peer *peer;
char *peername, *peername2, *hostn;
set_socket_transport(&dialog->socket, 0);
}
res = create_addr_from_peer(dialog, peer);
- if (!ast_sockaddr_isnull(remote_address)) {
- ast_sockaddr_copy(&dialog->sa, remote_address);
- }
dialog->relatedpeer = ref_peer(peer, "create_addr: setting dialog's relatedpeer pointer");
unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup");
return res;
if (dumphistory)
sip_dump_history(p);
- if (p->options)
+ if (p->options) {
+ if (p->options->outboundproxy) {
+ ao2_ref(p->options->outboundproxy, -1);
+ }
ast_free(p->options);
+ }
if (p->notify) {
ast_variables_destroy(p->notify->headers);
sip_pvt_lock(pvt);
- if (create_addr(pvt, epa_entry->destination, NULL, TRUE, NULL)) {
+ if (create_addr(pvt, epa_entry->destination, NULL, TRUE)) {
sip_pvt_unlock(pvt);
dialog_unlink_all(pvt);
dialog_unref(pvt, "create_addr failed in transmit_publish. Unref dialog");
}
/* Setup the destination of our subscription */
- if (create_addr(mwi->call, mwi->hostname, &mwi->us, 0, NULL)) {
+ if (create_addr(mwi->call, mwi->hostname, &mwi->us, 0)) {
dialog_unlink_all(mwi->call);
mwi->call = dialog_unref(mwi->call, "unref dialog after unlink_all");
return 0;
return 0;
}
- if (create_addr(p, channame, NULL, 0, NULL)) {
+ if (create_addr(p, channame, NULL, 0)) {
/* Maybe they're not registered, etc. */
dialog_unlink_all(p);
dialog_unref(p, "unref dialog inside for loop" );
}
/* Find address to hostname */
- if (create_addr(p, S_OR(r->peername, r->hostname), &r->us, 0, NULL)) {
+ if (create_addr(p, S_OR(r->peername, r->hostname), &r->us, 0)) {
/* we have what we hope is a temporary network error,
* probably DNS. We need to reschedule a registration try */
dialog_unlink_all(p);
return CLI_FAILURE;
}
- if (create_addr(p, a->argv[i], NULL, 1, NULL)) {
+ if (create_addr(p, a->argv[i], NULL, 1)) {
/* Maybe they're not registered, etc. */
dialog_unlink_all(p);
dialog_unref(p, "unref dialog inside for loop" );
ast_debug(3, "Got 200 OK on subscription for MWI\n");
set_pvt_allowed_methods(p, req);
if (p->options) {
+ if (p->options->outboundproxy) {
+ ao2_ref(p->options->outboundproxy, -1);
+ }
ast_free(p->options);
p->options = NULL;
}
sip_pvt_lock(pvt);
/* Look up the host to contact */
- if (create_addr(pvt, to_host, NULL, TRUE, NULL)) {
+ if (create_addr(pvt, to_host, NULL, TRUE)) {
sip_pvt_unlock(pvt);
dialog_unlink_all(pvt);
dialog_unref(pvt, "create_addr failed sending a MESSAGE");
char dialstring[256];
char *remote_address;
enum sip_transport transport = 0;
- struct ast_sockaddr remote_address_sa = { {0,} };
format_t oldformat = format;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(peerorhost);
}
if (!ast_strlen_zero(remote_address)) {
- if (ast_sockaddr_resolve_first_transport(&remote_address_sa, remote_address, 0, transport)) {
- ast_log(LOG_WARNING, "Unable to find IP address for host %s. We will not use this remote IP address\n", remote_address);
- } else {
- if (!ast_sockaddr_port(&remote_address_sa)) {
- ast_sockaddr_set_port(&remote_address_sa,
- transport & SIP_TRANSPORT_TLS ?
- STANDARD_TLS_PORT :
- STANDARD_SIP_PORT);
- }
+ p->options->outboundproxy = proxy_from_config(remote_address, 0, NULL);
+ if (!p->options->outboundproxy) {
+ ast_log(LOG_WARNING, "Unable to parse outboundproxy %s. We will not use this remote IP address\n", remote_address);
}
}
ext = extension (user part of URI)
dnid = destination of the call (applies to the To: header)
*/
- if (create_addr(p, host, NULL, 1, &remote_address_sa)) {
+ if (create_addr(p, host, NULL, 1)) {
*cause = AST_CAUSE_UNREGISTERED;
ast_debug(3, "Cant create SIP call - target device not registered\n");
dialog_unlink_all(p);
} else if (!strcasecmp(v->name, "fromuser")) {
ast_string_field_set(peer, fromuser, v->value);
} else if (!strcasecmp(v->name, "outboundproxy")) {
- char *host, *proxyname, *sep;
-
+ struct sip_proxy *proxy;
if (ast_strlen_zero(v->value)) {
ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf\n", v->lineno);
continue;
}
-
- if (!peer->outboundproxy) {
- peer->outboundproxy = ao2_alloc(sizeof(*peer->outboundproxy), NULL);
- if (!peer->outboundproxy) {
- ast_log(LOG_WARNING, "Unable to allocate config storage for outboundproxy\n");
- continue;
- }
- }
-
- host = ast_strdupa(v->value);
- if (!host) {
- ast_log(LOG_WARNING, "Unable to allocate stack space for parsing outboundproxy\n");
- continue;
- }
-
- host = ast_skip_blanks(host);
- sep = strchr(host, ',');
- if (sep) {
- *sep++ = '\0';
- peer->outboundproxy->force = !strncasecmp(ast_skip_blanks(sep), "force", 5);
- } else {
- peer->outboundproxy->force = FALSE;
- }
-
- sip_parse_host(host, v->lineno, &proxyname,
- &peer->outboundproxy->port,
- &peer->outboundproxy->transport);
-
- if (ast_strlen_zero(proxyname)) {
- ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf\n", v->lineno);
- sip_cfg.outboundproxy.name[0] = '\0';
+ proxy = proxy_from_config(v->value, v->lineno, peer->outboundproxy);
+ if (!proxy) {
+ ast_log(LOG_WARNING, "failure parsing the outbound proxy on line %d of sip.conf.\n", v->lineno);
continue;
}
-
- ast_copy_string(peer->outboundproxy->name, proxyname, sizeof(peer->outboundproxy->name));
-
- proxy_update(peer->outboundproxy);
+ peer->outboundproxy = proxy;
} else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) {
/* They'll register with us */
default_fromdomainport = STANDARD_SIP_PORT;
}
} else if (!strcasecmp(v->name, "outboundproxy")) {
- char *host, *proxyname, *sep;
-
+ struct sip_proxy *proxy;
if (ast_strlen_zero(v->value)) {
ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf\n", v->lineno);
continue;
}
-
- host = ast_strdupa(v->value);
- if (!host) {
- ast_log(LOG_WARNING, "Unable to allocate stack space for parsing outboundproxy\n");
- continue;
- }
-
- host = ast_skip_blanks(host);
- sep = strchr(host, ',');
- if (sep) {
- *sep++ = '\0';
- sip_cfg.outboundproxy.force = !strncasecmp(ast_skip_blanks(sep), "force", 5);
- } else {
- sip_cfg.outboundproxy.force = FALSE;
- }
-
- sip_parse_host(host, v->lineno, &proxyname,
- &sip_cfg.outboundproxy.port,
- &sip_cfg.outboundproxy.transport);
-
- if (ast_strlen_zero(proxyname)) {
- ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf\n", v->lineno);
- sip_cfg.outboundproxy.name[0] = '\0';
+ proxy = proxy_from_config(v->value, v->lineno, &sip_cfg.outboundproxy);
+ if (!proxy) {
+ ast_log(LOG_WARNING, "failure parsing the outbound proxy on line %d of sip.conf.\n", v->lineno);
continue;
}
-
- ast_copy_string(sip_cfg.outboundproxy.name, proxyname, sizeof(sip_cfg.outboundproxy.name));
-
- proxy_update(&sip_cfg.outboundproxy);
} else if (!strcasecmp(v->name, "autocreatepeer")) {
sip_cfg.autocreatepeer = ast_true(v->value);
} else if (!strcasecmp(v->name, "match_auth_username")) {