Skip to content

Commit

Permalink
Fix reusage of proxy_l structures.
Browse files Browse the repository at this point in the history
As proxy_l structures contain information about the DNS-based failover (iteration in he struct, which SRV or NAPTR records were used or not), such structure cannot be used more then once for sending a message out.
Fixes:
- do not use the same proxy_l for multiple functions in script (remove the add_proxy() and find_proxy() )
- avoid using the same proxy_l structure for all the calls of same function (when proxy_l is a function parameter)

Fixes #224
Many thanks for Chris Maciejewski ( @l7s ) for support on troublehsooting this.

(cherry picked from commit f7f2cb4)
  • Loading branch information
bogdan-iancu committed May 7, 2014
1 parent a1317bc commit 0196aa8
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 49 deletions.
19 changes: 15 additions & 4 deletions action.c
Expand Up @@ -499,7 +499,14 @@ int do_action(struct action* a, struct sip_msg* msg)
pkg_free(p);
if (ret==0) ret=1;
}else if ((a->elem[0].type==PROXY_ST)) {
ret=forward_request(msg,(struct proxy_l*)a->elem[0].u.data);
if (0==(p=clone_proxy((struct proxy_l*)a->elem[0].u.data))) {
LM_ERR("failed to clone proxy, dropping packet\n");
ret=E_OUT_OF_MEM;
goto error_fwd_uri;
}
ret=forward_request(msg, p);
free_proxy(p); /* frees only p content, not p itself */
pkg_free(p);
if (ret==0) ret=1;
}else{
LM_ALERT("BUG in forward() types %d, %d\n",
Expand Down Expand Up @@ -532,9 +539,11 @@ int do_action(struct action* a, struct sip_msg* msg)
ret=E_OUT_OF_MEM;
break;
}

p=(struct proxy_l*)a->elem[0].u.data;

if (0==(p=clone_proxy((struct proxy_l*)a->elem[0].u.data))) {
LM_ERR("failed to clone proxy, dropping packet\n");
ret=E_OUT_OF_MEM;
break;
}
ret=hostent2su(to, &p->host, p->addr_idx,
(p->port)?p->port:SIP_PORT );
if (ret==0){
Expand Down Expand Up @@ -571,6 +580,8 @@ int do_action(struct action* a, struct sip_msg* msg)
if (ret!=0 && p->host.h_addr_list[p->addr_idx+1])
p->addr_idx++;
}
free_proxy(p); /* frees only p content, not p itself */
pkg_free(p);
pkg_free(to);
if (ret==0)
ret=1;
Expand Down
18 changes: 14 additions & 4 deletions modules/tm/tm.c
Expand Up @@ -1186,22 +1186,27 @@ static inline int t_relay_inerr2scripterr(void)

inline static int w_t_relay( struct sip_msg *p_msg , char *proxy, char *flags)
{
struct proxy_l *p = NULL;
struct cell *t;
int ret;

t=get_t();

if (proxy && (p=clone_proxy((struct proxy_l*)proxy))==0) {
LM_ERR("failed to clone proxy, dropping packet\n");
return -1;
}

if (!t || t==T_UNDEFINED) {
/* no transaction yet */
if (route_type==FAILURE_ROUTE) {
LM_CRIT(" BUG - undefined transaction in failure route\n");
return -1;
}
ret = t_relay_to( p_msg, (struct proxy_l *)proxy, (int)(long)flags );
ret = t_relay_to( p_msg, p, (int)(long)flags );
if (ret<0) {
ret = t_relay_inerr2scripterr();
}
return ret?ret:1;
} else {
/* transaction already created */

Expand All @@ -1219,14 +1224,19 @@ inline static int w_t_relay( struct sip_msg *p_msg , char *proxy, char *flags)
if (((int)(long)flags)&TM_T_REPLY_reason_FLAG)
t->flags|=T_CANCEL_REASON_FLAG;

ret = t_forward_nonack( t, p_msg, (struct proxy_l *)proxy);
ret = t_forward_nonack( t, p_msg, p);
if (ret<=0 ) {
LM_ERR("t_forward_nonack failed\n");
ret = t_relay_inerr2scripterr();
}
return ret?ret:1;
}

if (p) {
free_proxy(p);
pkg_free(p);
}
return ret?ret:1;

route_err:
LM_CRIT("unsupported route type: %d\n", route_type);
return 0;
Expand Down
76 changes: 40 additions & 36 deletions proxy.c
Expand Up @@ -56,21 +56,6 @@ struct proxy_l* proxies=0;

int disable_dns_failover=0;

/* searches for the proxy named 'name', on port 'port' with
proto 'proto'; if proto==0 => proto wildcard (will match any proto)
returns: pointer to proxy_l on success or 0 if not found */
static struct proxy_l* find_proxy(str *name, unsigned short port, int proto)
{
struct proxy_l* t;
for(t=proxies; t; t=t->next)
if (((t->name.len == name->len) &&
((proto==PROTO_NONE)||(t->proto==proto))&&
(strncasecmp(t->name.s, name->s, name->len)==0)) &&
(t->port==port))
break;
return t;
}


int hostent_shm_cpy(struct hostent *dst, struct hostent* src)
{
Expand Down Expand Up @@ -207,26 +192,7 @@ void free_hostent(struct hostent *dst)



struct proxy_l* add_proxy( str* name, unsigned short port,
unsigned short proto)
{
struct proxy_l* p;

if ((p=find_proxy(name, port, proto))!=0) return p;
if ((p=mk_proxy(name, port, proto, 0))==0) goto error;
/* add p to the proxy list */
p->next=proxies;
proxies=p;
return p;

error:
return 0;
}




/* same as add_proxy, but it doesn't add the proxy to the list
/* Creates a proxy structure out of the host, port and proto
* uses also SRV if possible & port==0 (quick hack) */

struct proxy_l* mk_proxy(str* name, unsigned short port, unsigned short proto,
Expand Down Expand Up @@ -267,7 +233,8 @@ struct proxy_l* mk_proxy(str* name, unsigned short port, unsigned short proto,



/* same as mk_proxy, but get the host as an ip*/
/* same as mk_proxy, but in shared memory
* uses also SRV if possible & port==0 (quick hack) */
struct proxy_l* mk_proxy_from_ip(struct ip_addr* ip, unsigned short port,
unsigned short proto)
{
Expand Down Expand Up @@ -359,3 +326,40 @@ struct proxy_l* mk_shm_proxy(str* name, unsigned short port, unsigned short prot
error:
return 0;
}

/* clones a proxy into pkg memory */
struct proxy_l* clone_proxy(struct proxy_l *sp)
{
struct proxy_l *dp;

dp = (struct proxy_l*)pkg_malloc(sizeof(struct proxy_l));
if (dp==NULL) {
LM_ERR("no more pkg memory\n");
return 0;
}
memset( dp , 0 , sizeof(struct proxy_l));

dp->port = sp->port;
dp->proto = sp->proto;
dp->addr_idx = sp->addr_idx;

/* clone the hostent */
if (hostent_cpy( &dp->host, &sp->host)!=0)
goto error0;

/* clone the dns resolver */
if (sp->dn) {
dp->dn = dns_res_copy(sp->dn);
if (dp->dn==NULL)
goto error1;
}

return dp;
error1:
free_hostent(&dp->host);
error0:
pkg_free(dp);
return 0;
}


8 changes: 4 additions & 4 deletions proxy.h
Expand Up @@ -39,7 +39,6 @@ struct dns_node;
#define PROXY_SHM_FLAG (1<<0)

struct proxy_l{
struct proxy_l* next;
str name; /* original name */
unsigned short flags;
unsigned short port;
Expand All @@ -48,14 +47,13 @@ struct proxy_l{
unsigned short addr_idx; /* crt. addr. idx. */
struct hostent host; /* addresses */

/* tree with the DNS resolving status
* NOTE: this is all the time in SHM */
struct dns_node *dn;
};

extern struct proxy_l* proxies;

struct proxy_l* add_proxy( str* name, unsigned short port,
unsigned short proto);

struct proxy_l* mk_proxy( str* name, unsigned short port, unsigned short proto,
int is_sips);
struct proxy_l* mk_shm_proxy(str* name, unsigned short port, unsigned short proto,
Expand All @@ -74,6 +72,8 @@ int hostent_shm_cpy(struct hostent *dst, struct hostent* src);

void free_shm_hostent(struct hostent *dst);

struct proxy_l* clone_proxy(struct proxy_l *sp);

#include "resolve.h"

#endif
Expand Down
2 changes: 1 addition & 1 deletion route.c
Expand Up @@ -328,7 +328,7 @@ static int fix_actions(struct action* a)
ret = E_CFG;
goto error;
}
p = add_proxy( &host,(unsigned short)port, proto);
p = mk_proxy( &host,(unsigned short)port, proto, 0);
if (p==0) {
LM_ERR("forward/send failed to add proxy");
ret = E_CFG;
Expand Down

0 comments on commit 0196aa8

Please sign in to comment.