static int trace_send_duplicate(char *buf, int len, struct dest_info *dst2) { struct dest_info dst; struct proxy_l * p = NULL; if(buf==NULL || len <= 0) return -1; if(dup_uri_str.s==0 || dup_uri==NULL) return 0; init_dest_info(&dst); /* create a temporary proxy*/ dst.proto = PROTO_UDP; p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, dst.proto); if (p==0) { LM_ERR("bad host name in uri\n"); return -1; } if (!dst2){ init_dest_info(&dst); /* create a temporary proxy*/ dst.proto = PROTO_UDP; p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, dst.proto); if (p==0){ LM_ERR("bad host name in uri\n"); return -1; } hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); dst.send_sock=get_send_socket(0, &dst.to, dst.proto); if (dst.send_sock==0){ LM_ERR("can't forward to af %d, proto %d no corresponding" " listening socket\n", dst.to.s.sa_family, dst.proto); goto error; } } if (msg_send((dst2)?dst2:&dst, buf, len)<0) { LM_ERR("cannot send duplicate message\n"); goto error; } if (p){ free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } return 0; error: if (p){ free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } return -1; }
static HRESULT create_proxy( WS_CHANNEL *channel, const WS_PROXY_PROPERTY *properties, ULONG count, WS_SERVICE_PROXY **handle ) { struct proxy *proxy; HRESULT hr; ULONG i; if (!(proxy = alloc_proxy())) return E_OUTOFMEMORY; for (i = 0; i < count; i++) { hr = prop_set( proxy->prop, proxy->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); if (hr != S_OK) { free_proxy( proxy ); return hr; } } proxy->channel = channel; *handle = (WS_SERVICE_PROXY *)proxy; return S_OK; }
/* * The implementation of spdylay_on_stream_close_callback type. We use * this function to know the response is fully received. Since we just * fetch 1 resource in this program, after reception of the response, * we submit GOAWAY and close the session. */ static void spdy_cb_on_stream_close(spdylay_session *session, int32_t stream_id, spdylay_status_code status_code, void *user_data) { (void)status_code; (void)user_data; struct Proxy * proxy = spdylay_session_get_stream_user_data(session, stream_id); assert(NULL != proxy); --glob_opt.streams_opened; --proxy->spdy_connection->streams_opened; PRINT_INFO2("closing stream: str opened %i; remove proxy %i", glob_opt.streams_opened, proxy->id); DLL_remove(proxy->spdy_connection->proxies_head, proxy->spdy_connection->proxies_tail, proxy); if(proxy->http_active) { proxy->spdy_active = false; } else { free_proxy(proxy); } }
void spdy_free_connection(struct SPDY_Connection * connection) { struct Proxy *proxy; struct Proxy *proxy_next; if(NULL != connection) { for(proxy = connection->proxies_head; NULL != proxy; proxy=proxy_next) { proxy_next = proxy->next; DLL_remove(connection->proxies_head, connection->proxies_tail, proxy); proxy->spdy_active = false; proxy->spdy_error = true; PRINT_INFO2("spdy_free_connection for id %i", proxy->id); if(!proxy->http_active) { free_proxy(proxy); } } spdylay_session_del(connection->session); SSL_free(connection->ssl); free(connection->host); free(connection); //connection->session = NULL; } }
/************************************************************************** * WsFreeServiceProxy [webservices.@] */ void WINAPI WsFreeServiceProxy( WS_SERVICE_PROXY *handle ) { struct proxy *proxy = (struct proxy *)handle; TRACE( "%p\n", handle ); free_proxy( proxy ); }
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, p, (int)(long)flags ); if (ret<0) { ret = t_relay_inerr2scripterr(); } } else { /* transaction already created */ if ( route_type!=REQUEST_ROUTE && route_type!=FAILURE_ROUTE ) goto route_err; if (p_msg->REQ_METHOD==METHOD_ACK) { /* local ACK*/ t_release_transaction(t); return 1; } if (((int)(long)flags)&TM_T_REPLY_nodnsfo_FLAG) t->flags|=T_NO_DNS_FAILOVER_FLAG; if (((int)(long)flags)&TM_T_REPLY_reason_FLAG) t->flags|=T_CANCEL_REASON_FLAG; update_cloned_msg_from_msg( t->uas.request, p_msg); ret = t_forward_nonack( t, p_msg, p); if (ret<=0 ) { LM_ERR("t_forward_nonack failed\n"); ret = t_relay_inerr2scripterr(); } } 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; }
static int trace_send_duplicate(char *buf, int len) { union sockaddr_union* to; struct socket_info* send_sock; struct proxy_l * p; int proto; int ret; if(buf==NULL || len <= 0) return -1; if(dup_uri_str.s==0 || dup_uri==NULL) return 0; to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union)); if (to==0){ LM_ERR("out of pkg memory\n"); return -1; } /* create a temporary proxy*/ proto = PROTO_UDP; p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, proto, 0); if (p==0){ LM_ERR("bad host name in uri\n"); pkg_free(to); return -1; } hostent2su(to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); ret = -1; do { send_sock=get_send_socket(0, to, proto); if (send_sock==0){ LM_ERR("can't forward to af %d, proto %d no corresponding listening socket\n", to->s.sa_family,proto); continue; } if (msg_send(send_sock, proto, to, 0, buf, len, NULL)<0){ LM_ERR("cannot send duplicate message\n"); continue; } ret = 0; break; }while( get_next_su( p, to, 0)==0 ); free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); pkg_free(to); return ret; }
static int fixup_siptrace(void** param, int param_no) { char *duri = (char*) *param; struct sip_uri dup_uri; struct dest_info *dst = NULL; struct proxy_l * p = NULL; str dup_uri_str = { 0, 0 }; if (param_no != 1) { LM_DBG("params:%s\n", (char*)*param); return 0; } if (!(*duri)) { LM_ERR("invalid dup URI\n"); return -1; } LM_DBG("sip_trace URI:%s\n", (char*)*param); dup_uri_str.s = duri; dup_uri_str.len = strlen(dup_uri_str.s); memset(&dup_uri, 0, sizeof(struct sip_uri)); if (parse_uri(dup_uri_str.s, dup_uri_str.len, &dup_uri) < 0) { LM_ERR("bad dup uri\n"); return -1; } dst = (struct dest_info *) pkg_malloc(sizeof(struct dest_info)); if (dst == 0) { LM_ERR("no more pkg memory left\n"); return -1; } init_dest_info(dst); /* create a temporary proxy*/ dst->proto = PROTO_UDP; p = mk_proxy(&dup_uri.host, (dup_uri.port_no) ? dup_uri.port_no : SIP_PORT, dst->proto); if (p == 0) { LM_ERR("bad host name in uri\n"); pkg_free(dst); return -1; } hostent2su(&dst->to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT); pkg_free(*param); /* free temporary proxy*/ if (p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } *param = (void*) dst; return 0; }
void http_cb_request_completed (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe) { (void)cls; (void)connection; struct HTTP_URI *http_uri; struct Proxy *proxy; http_uri = (struct HTTP_URI *)*con_cls; if(NULL == http_uri) return; proxy = (struct Proxy *)http_uri->proxy; assert(NULL != proxy); PRINT_INFO2("http_cb_request_completed %i for %s; id %i",toe, http_uri->uri, proxy->id); if(NULL != proxy->http_response) { MHD_destroy_response (proxy->http_response); proxy->http_response = NULL; } if(proxy->spdy_active) { proxy->http_active = false; if(MHD_REQUEST_TERMINATED_COMPLETED_OK != toe) { proxy->http_error = true; if(proxy->stream_id > 0 /*&& NULL != proxy->spdy_connection->session*/) { //send RST_STREAM_STATUS_CANCEL PRINT_INFO2("send rst_stream %i %i",proxy->spdy_active, proxy->stream_id ); spdylay_submit_rst_stream(proxy->spdy_connection->session, proxy->stream_id, 5); } /*else { DLL_remove(proxy->spdy_connection->proxies_head, proxy->spdy_connection->proxies_tail, proxy); free_proxy(proxy); }*/ } } else { PRINT_INFO2("proxy free http id %i ", proxy->id); free_proxy(proxy); } --glob_opt.responses_pending; }
inline static int w_t_replicate_to( struct sip_msg *p_msg , char *proto_par, char *addr_par ) { struct proxy_l *proxy; int r = -1; proxy = t_protoaddr2proxy(proto_par, addr_par); if (proxy) { r = t_replicate(p_msg, proxy, proxy->proto); free_proxy(proxy); } return r; }
inline static int w_t_forward_nonack_to( struct sip_msg *p_msg , char *proto_par, char *addr_par ) { struct proxy_l *proxy; int r = -1; proxy = t_protoaddr2proxy(proto_par, addr_par); if (proxy) { r = _w_t_forward_nonack(p_msg, proxy, proxy->proto); free_proxy(proxy); } return r; }
static void _cp_service_unavail (GUPnPControlPoint *cp, GUPnPServiceProxy *proxy, GUPnPSimpleIgd *self) { guint i; for (i=0; i < self->priv->service_proxies->len; i++) { struct Proxy *prox = g_ptr_array_index (self->priv->service_proxies, i); if (prox->cp == cp && !strcmp (gupnp_service_info_get_udn (GUPNP_SERVICE_INFO (proxy)), gupnp_service_info_get_udn (GUPNP_SERVICE_INFO (prox->proxy)))) { free_proxy (prox); g_ptr_array_remove_index_fast (self->priv->service_proxies, i); break; } } }
/************************************************************************** * WsFreeServiceProxy [webservices.@] */ void WINAPI WsFreeServiceProxy( WS_SERVICE_PROXY *handle ) { struct proxy *proxy = (struct proxy *)handle; TRACE( "%p\n", handle ); if (!proxy) return; EnterCriticalSection( &proxy->cs ); if (proxy->magic != PROXY_MAGIC) { LeaveCriticalSection( &proxy->cs ); return; } proxy->magic = 0; LeaveCriticalSection( &proxy->cs ); free_proxy( proxy ); }
void radproxy_destroy(struct radproxy_data *data) { if (data) { struct radproxy_client *c = data->clients; struct radproxy_desc *p = data->proxys; while (c) { struct radproxy_client *q =c; c = c->next; free_client(q); } while (p) { struct radproxy_desc *q =p; p = p->next; free_proxy(q); } free(data); } }
/* introduce a new uac to transaction; returns its branch id (>=0) or error (<0); it doesn't send a message yet -- a reply to it might interfere with the processes of adding multiple branches */ static int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, unsigned int bflags, str* path, struct proxy_l *proxy) { unsigned short branch; struct sip_msg_body *body_clone=NO_BODY_CLONE_MARKER; int do_free_proxy; int ret; branch=t->nr_of_outgoings; if (branch==MAX_BRANCHES) { LM_ERR("maximum number of branches exceeded\n"); ret=E_CFG; goto error; } /* check existing buffer -- rewriting should never occur */ if (t->uac[branch].request.buffer.s) { LM_CRIT("buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* set proper RURI to request to reflect the branch */ request->new_uri=*uri; request->parsed_uri_ok=0; request->dst_uri=*next_hop; request->path_vec=*path; request->ruri_bflags=bflags; if ( pre_print_uac_request( t, branch, request, &body_clone)!= 0 ) { ret = -1; goto error01; } /* check DNS resolution */ if (proxy){ do_free_proxy = 0; }else { proxy=uri2proxy( request->dst_uri.len ? &request->dst_uri:&request->new_uri, request->force_send_socket ? request->force_send_socket->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error01; } do_free_proxy = 1; } msg_callback_process(request, REQ_PRE_FORWARD, (void *)proxy); if ( !(t->flags&T_NO_DNS_FAILOVER_FLAG) ) { t->uac[branch].proxy = shm_clone_proxy( proxy , do_free_proxy ); if (t->uac[branch].proxy==NULL) { ret = E_OUT_OF_MEM; goto error02; } } /* use the first address */ hostent2su( &t->uac[branch].request.dst.to, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); t->uac[branch].request.dst.proto = proxy->proto; /* do print of the uac request */ if ( update_uac_dst( request, &t->uac[branch] )!=0) { ret = ser_error; goto error02; } /* things went well, move ahead */ t->uac[branch].uri.s=t->uac[branch].request.buffer.s+ request->first_line.u.request.method.len+1; t->uac[branch].uri.len=request->new_uri.len; t->uac[branch].br_flags = request->ruri_bflags; t->uac[branch].added_rr = count_local_rr( request ); t->nr_of_outgoings++; /* done! */ ret=branch; error02: if(do_free_proxy) { free_proxy( proxy ); pkg_free( proxy ); } error01: post_print_uac_request( request, uri, next_hop, body_clone); if (ret < 0) { /* destroy all the bavps added, the path vector and the destination, * since this branch will never be properly added to * the UAC list, otherwise we'll have memory leaks - razvanc */ clean_branch(t->uac[branch]); memset(&t->uac[branch], 0, sizeof(t->uac[branch])); init_branch(&t->uac[branch], branch, t->wait_tl.set, t); } error: return ret; }
int add_dst( rt_data_t *r, /* id */ char *id, /* ip address */ char* ip, /* strip len */ int strip, /* pri prefix */ char* pri, /* dst type*/ int type, /* dst attrs*/ char* attrs, /* probe_mode */ int probing, /* socket */ struct socket_info *sock, /* state */ int state ) { static unsigned id_counter = 0; pgw_t *pgw=NULL, *tmp=NULL; struct sip_uri uri; int l_ip,l_pri,l_attrs,l_id; #define GWABUF_MAX_SIZE 512 char gwabuf[GWABUF_MAX_SIZE]; union sockaddr_union sau; struct proxy_l *proxy; unsigned int sip_prefix; str gwas; if (NULL==r || NULL==ip) { LM_ERR("invalid parametres\n"); goto err_exit; } l_id = strlen(id); l_ip = strlen(ip); l_pri = pri?strlen(pri):0; l_attrs = attrs?strlen(attrs):0; /* check if GW address starts with 'sip' or 'sips' */ if (l_ip>5) { if ( strncasecmp("sip:", ip, 4)==0) sip_prefix = 4; else if ( strncasecmp("sips:", ip, 5)==0) sip_prefix = 5; else sip_prefix = 0; } else sip_prefix = 0; if( sip_prefix==0 ) { if(l_ip+4>=GWABUF_MAX_SIZE) { LM_ERR("GW address (%d) longer " "than %d\n",l_ip+4,GWABUF_MAX_SIZE); goto err_exit; } memcpy(gwabuf, "sip:", 4); memcpy(gwabuf+4, ip, l_ip); gwas.s = gwabuf; gwas.len = 4+l_ip; } else { gwas.s = ip; gwas.len = l_ip; } /* parse the normalized address as a SIP URI */ memset(&uri, 0, sizeof(struct sip_uri)); if(parse_uri(gwas.s, gwas.len, &uri)!=0) { LM_ERR("invalid uri <%.*s>\n", gwas.len, gwas.s); goto err_exit; } /* update the sip_prefix to skip to domain part */ if (uri.user.len) sip_prefix += uri.host.s - uri.user.s; /* allocate new structure */ pgw = (pgw_t*)shm_malloc(sizeof(pgw_t) + l_id + (l_ip-sip_prefix) + l_pri + l_attrs); if (NULL==pgw) { LM_ERR("no more shm mem (%u)\n", (unsigned int)(sizeof(pgw_t)+l_id+l_ip-sip_prefix+l_pri +l_attrs)); goto err_exit; } memset(pgw,0,sizeof(pgw_t)); /* set probing related flags */ switch(probing) { case 0: break; case 1: pgw->flags |= DR_DST_PING_DSBL_FLAG; break; case 2: pgw->flags |= DR_DST_PING_PERM_FLAG; break; default: goto err_exit; } /* set state related flags */ switch(state) { case 0: break; case 1: pgw->flags |= DR_DST_STAT_DSBL_FLAG|DR_DST_STAT_NOEN_FLAG; break; case 2: pgw->flags |= DR_DST_STAT_DSBL_FLAG; break; default: goto err_exit; } /* set outbound socket */ pgw->sock = sock; pgw->_id = ++id_counter; pgw->id.len= l_id; pgw->id.s = (char*)(pgw+1); memcpy(pgw->id.s, id, l_id); pgw->ip_str.len= l_ip-sip_prefix; pgw->ip_str.s = (char*)(pgw+1)+l_id; memcpy(pgw->ip_str.s, ip+sip_prefix, l_ip-sip_prefix); if (pri) { pgw->pri.len = l_pri; pgw->pri.s = ((char*)(pgw+1))+l_id+l_ip-sip_prefix; memcpy(pgw->pri.s, pri, l_pri); } if (attrs) { pgw->attrs.len = l_attrs; pgw->attrs.s = ((char*)(pgw+1))+l_id+l_ip-sip_prefix+l_pri; memcpy(pgw->attrs.s, attrs, l_attrs); } pgw->strip = strip; pgw->type = type; /* add address in the global list of destinations/GWs */ proxy = mk_proxy(&uri.host,uri.port_no,uri.proto,(uri.type==SIPS_URI_T)); if (proxy==NULL) { if(dr_force_dns) { LM_ERR("cannot resolve <%.*s>\n", uri.host.len, uri.host.s); goto err_exit; } else { LM_DBG("cannot resolve <%.*s> - won't be used" " by is_from_gw()\n", uri.host.len, uri.host.s); goto done; } } hostent2ip_addr( &pgw->ips[0], &proxy->host, proxy->addr_idx); pgw->ports[0] = proxy->port; LM_DBG("first gw ip addr [%s]\n", ip_addr2a(&pgw->ips[0])); pgw->ips_no = 1; while (pgw->ips_no<DR_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &pgw->ips[pgw->ips_no], &sau); pgw->ports[pgw->ips_no] = proxy->port; LM_DBG("additional gw ip addr [%s]\n", ip_addr2a( &pgw->ips[pgw->ips_no] ) ); pgw->ips_no++; } free_proxy(proxy); pkg_free(proxy); done: if(NULL==r->pgw_l) r->pgw_l = pgw; else { tmp = r->pgw_l; while(NULL != tmp->next) tmp = tmp->next; tmp->next = pgw; } return 0; err_exit: if(NULL!=pgw) shm_free(pgw); return -1; }
/* introduce a new uac to transaction; returns its branch id (>=0) or error (<0); it doesn't send a message yet -- a reply to it might interfere with the processes of adding multiple branches */ static int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, str* path, struct proxy_l *proxy) { unsigned short branch; int do_free_proxy; int ret; branch=t->nr_of_outgoings; if (branch==MAX_BRANCHES) { LM_ERR("maximum number of branches exceeded\n"); ret=E_CFG; goto error; } /* check existing buffer -- rewriting should never occur */ if (t->uac[branch].request.buffer.s) { LM_CRIT("buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* set proper RURI to request to reflect the branch */ request->new_uri=*uri; request->parsed_uri_ok=0; request->dst_uri=*next_hop; request->path_vec=*path; if ( pre_print_uac_request( t, branch, request)!= 0 ) { ret = -1; goto error01; } /* check DNS resolution */ if (proxy){ do_free_proxy = 0; }else { proxy=uri2proxy( request->dst_uri.len ? &request->dst_uri:&request->new_uri, PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error01; } do_free_proxy = 1; } msg_callback_process(request, REQ_PRE_FORWARD, (void *)proxy); if ( !(t->flags&T_NO_DNS_FAILOVER_FLAG) ) { t->uac[branch].proxy = shm_clone_proxy( proxy , do_free_proxy ); if (t->uac[branch].proxy==NULL) { ret = E_OUT_OF_MEM; goto error02; } } /* use the first address */ hostent2su( &t->uac[branch].request.dst.to, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); t->uac[branch].request.dst.proto = proxy->proto; if ( update_uac_dst( request, &t->uac[branch] )!=0) { ret = ser_error; goto error02; } /* things went well, move ahead */ t->uac[branch].uri.s=t->uac[branch].request.buffer.s+ request->first_line.u.request.method.len+1; t->uac[branch].uri.len=request->new_uri.len; t->uac[branch].br_flags = getb0flags(); t->uac[branch].added_rr = count_local_rr( request ); t->nr_of_outgoings++; /* done! */ ret=branch; error02: if(do_free_proxy) { free_proxy( proxy ); pkg_free( proxy ); } error01: post_print_uac_request( request, uri, next_hop); error: return ret; }
static int trace_send_hep_duplicate(str *body, str *fromproto, str *fromip, unsigned short fromport, str *toproto, str *toip, unsigned short toport) { struct proxy_l * p=NULL /* make gcc happy */; int ret; union sockaddr_union from_su; union sockaddr_union to_su; unsigned int proto; struct socket_info* send_sock; union sockaddr_union* to = NULL; int heplen; char *hepbuf; if(body->s==NULL || body->len <= 0) return -1; if(dup_uri_str.s==0 || dup_uri==NULL) return 0; /* Convert proto:ip:port to sockaddress union SRC IP */ if (pipport2su(fromproto, fromip, fromport, &from_su, &proto)==-1 || (pipport2su(toproto, toip, toport, &to_su, &proto)==-1)) goto error; /* check if from and to are in the same family*/ if(from_su.s.sa_family != to_su.s.sa_family) { LM_ERR("ERROR: trace_send_hep_duplicate: interworking detected ?\n"); goto error; } /* create a temporary proxy*/ proto = PROTO_UDP; p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,proto, 0); if (p==0){ LM_ERR("bad host name in uri\n"); return -1; } to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union)); if (to==0){ LM_ERR("out of pkg memory\n"); return -1; } hostent2su(to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); if (hep_api.pack_hep(&from_su, to, proto, body->s, body->len, &hepbuf, &heplen)) { LM_ERR("failed to do hep packing\n"); return -1; } ret = -1; do { send_sock=get_send_socket(0, to, proto); if (send_sock==0){ LM_ERR("can't forward to af %d, proto %d no corresponding listening socket\n", to->s.sa_family,proto); continue; } if (msg_send(send_sock, PROTO_HEP, to, 0, hepbuf, heplen, NULL)<0){ LM_ERR("cannot send duplicate message\n"); continue; } ret = 0; break; }while( get_next_su( p, to, 0)==0 ); free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); pkg_free(to); pkg_free(hepbuf); return ret; error: if(p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } if(to) pkg_free(to); return -1; }
static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info * dst2) { struct dest_info dst; struct socket_info *si; struct dest_info* dst_fin = NULL; struct proxy_l * p=NULL /* make gcc happy */; void* buffer = NULL; union sockaddr_union from_su; union sockaddr_union to_su; unsigned int len, buflen, proto; struct hep_hdr hdr; struct hep_iphdr hep_ipheader; struct hep_timehdr hep_time; struct timeval tvb; struct timezone tz; struct hep_ip6hdr hep_ip6header; if(body->s==NULL || body->len <= 0) return -1; if(dup_uri_str.s==0 || dup_uri==NULL) return 0; gettimeofday( &tvb, &tz ); /* message length */ len = body->len + sizeof(struct hep_ip6hdr) + sizeof(struct hep_hdr) + sizeof(struct hep_timehdr);; /* The packet is too big for us */ if (unlikely(len>BUF_SIZE)){ goto error; } /* Convert proto:ip:port to sockaddress union SRC IP */ if (pipport2su(from->s, &from_su, &proto)==-1 || (pipport2su(to->s, &to_su, &proto)==-1)) goto error; /* check if from and to are in the same family*/ if(from_su.s.sa_family != to_su.s.sa_family) { LM_ERR("interworking detected ?\n"); goto error; } if (!dst2){ init_dest_info(&dst); /* create a temporary proxy*/ dst.proto = PROTO_UDP; p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, dst.proto); if (p==0) { LM_ERR("bad host name in uri\n"); goto error; } hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); LM_DBG("setting up the socket_info\n"); dst_fin = &dst; } else { dst_fin = dst2; } if (force_send_sock_str.s) { LM_DBG("force_send_sock activated, grep for the sock_info\n"); si = grep_sock_info(&force_send_sock_uri->host, (force_send_sock_uri->port_no)?force_send_sock_uri->port_no:SIP_PORT, PROTO_UDP); if (!si) { LM_WARN("cannot grep socket info\n"); } else { LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len, si->name.s, si->address_str.len, si->address_str.s); dst_fin->send_sock = si; } } if (dst_fin->send_sock == 0) { dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto); if (dst_fin->send_sock == 0) { LM_ERR("can't forward to af %d, proto %d no corresponding" " listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto); goto error; } } /* Version && proto && length */ hdr.hp_l = sizeof(struct hep_hdr); hdr.hp_v = hep_version; hdr.hp_p = proto; /* AND the last */ if (from_su.s.sa_family==AF_INET){ /* prepare the hep headers */ hdr.hp_f = AF_INET; hdr.hp_sport = htons(from_su.sin.sin_port); hdr.hp_dport = htons(to_su.sin.sin_port); hep_ipheader.hp_src = from_su.sin.sin_addr; hep_ipheader.hp_dst = to_su.sin.sin_addr; len = sizeof(struct hep_iphdr); } else if (from_su.s.sa_family==AF_INET6){ /* prepare the hep6 headers */ hdr.hp_f = AF_INET6; hdr.hp_sport = htons(from_su.sin6.sin6_port); hdr.hp_dport = htons(to_su.sin6.sin6_port); hep_ip6header.hp6_src = from_su.sin6.sin6_addr; hep_ip6header.hp6_dst = to_su.sin6.sin6_addr; len = sizeof(struct hep_ip6hdr); } else { LM_ERR("Unsupported protocol family\n"); goto error;; } hdr.hp_l +=len; if (hep_version == 2){ len += sizeof(struct hep_timehdr); } len += sizeof(struct hep_hdr) + body->len; buffer = (void *)pkg_malloc(len+1); if (buffer==0){ LM_ERR("out of memory\n"); goto error; } /* Copy job */ memset(buffer, '\0', len+1); /* copy hep_hdr */ memcpy((void*)buffer, &hdr, sizeof(struct hep_hdr)); buflen = sizeof(struct hep_hdr); /* hep_ip_hdr */ if(from_su.s.sa_family==AF_INET) { memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); buflen += sizeof(struct hep_iphdr); } else { memcpy((void*)buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); buflen += sizeof(struct hep_ip6hdr); } if(hep_version == 2) { hep_time.tv_sec = tvb.tv_sec; hep_time.tv_usec = tvb.tv_usec; hep_time.captid = hep_capture_id; memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr)); buflen += sizeof(struct hep_timehdr); } /* PAYLOAD */ memcpy((void*)(buffer + buflen) , (void*)body->s, body->len); buflen +=body->len; if (msg_send_buffer(dst_fin, buffer, buflen, 1)<0) { LM_ERR("cannot send hep duplicate message\n"); goto error; } if (p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } pkg_free(buffer); return 0; error: if(p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } if(buffer) pkg_free(buffer); return -1; }
/* introduce a new uac to transaction; returns its branch id (>=0) or error (<0); it doesn't send a message yet -- a reply to it might interfere with the processes of adding multiple branches */ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, struct proxy_l *proxy, int proto ) { int ret; short temp_proxy; union sockaddr_union to; unsigned short branch; struct socket_info* send_sock; char *shbuf; unsigned int len; branch=t->nr_of_outgoings; if (branch==MAX_BRANCHES) { LOG(L_ERR, "ERROR: add_uac: maximum number of branches exceeded\n"); ret=E_CFG; goto error; } /* check existing buffer -- rewriting should never occur */ if (t->uac[branch].request.buffer) { LOG(L_CRIT, "ERROR: add_uac: buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* check DNS resolution */ if (proxy) { temp_proxy=0; proto=get_proto(proto, proxy->proto); } else { proxy=uri2proxy( next_hop ? next_hop : uri, proto ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error; } proto=proxy->proto; /* uri2proxy will fix it for us */ temp_proxy=1; } if (proxy->ok==0) { if (proxy->host.h_addr_list[proxy->addr_idx+1]) proxy->addr_idx++; else proxy->addr_idx=0; proxy->ok=1; } hostent2su( &to, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); send_sock=get_send_socket( request, &to , proto); if (send_sock==0) { LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d " " (no corresponding listening socket)\n", to.s.sa_family, proto ); ret=ser_error=E_NO_SOCKET; goto error01; } /* now message printing starts ... */ shbuf=print_uac_request( t, request, branch, uri, &len, send_sock, proto ); if (!shbuf) { ret=ser_error=E_OUT_OF_MEM; goto error01; } /* things went well, move ahead and install new buffer! */ t->uac[branch].request.dst.to=to; t->uac[branch].request.dst.send_sock=send_sock; t->uac[branch].request.dst.proto=proto; t->uac[branch].request.dst.proto_reserved1=0; t->uac[branch].request.buffer=shbuf; t->uac[branch].request.buffer_len=len; t->uac[branch].uri.s=t->uac[branch].request.buffer+ request->first_line.u.request.method.len+1; t->uac[branch].uri.len=uri->len; t->nr_of_outgoings++; /* update stats */ proxy->tx++; proxy->tx_bytes+=len; /* done! */ ret=branch; error01: if (temp_proxy) { free_proxy( proxy ); pkg_free( proxy ); } error: return ret; }
int t_relay_to( struct sip_msg *p_msg , struct proxy_l *proxy, int flags) { int ret; int new_tran; int reply_ret; struct cell *t; context_p ctx_backup; ret=0; new_tran = t_newtran( p_msg, 1/*full UAS cloning*/ ); /* parsing error, memory alloc, whatever ... */ if (new_tran<0) { ret = new_tran; goto done; } /* if that was a retransmission, break from script */ if (new_tran==0) { goto done; } /* new transaction */ /* ACKs do not establish a transaction and are fwd-ed statelessly */ if ( p_msg->REQ_METHOD==METHOD_ACK) { LM_DBG("forwarding ACK\n"); /* send it out */ if (proxy==0) { proxy=uri2proxy(GET_NEXT_HOP(p_msg), p_msg->force_send_socket ? p_msg->force_send_socket->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto done; } ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; free_proxy( proxy ); pkg_free( proxy ); } else { ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; } goto done; } /* if replication flag is set, mark the transaction as local so that replies will not be relaied */ t=get_t(); if (flags&TM_T_REPLY_repl_FLAG) t->flags|=T_IS_LOCAL_FLAG; if (flags&TM_T_REPLY_nodnsfo_FLAG) t->flags|=T_NO_DNS_FAILOVER_FLAG; if (flags&TM_T_REPLY_reason_FLAG) t->flags|=T_CANCEL_REASON_FLAG; /* INVITE processing might take long, particularly because of DNS look-ups -- let upstream know we're working on it */ if ( p_msg->REQ_METHOD==METHOD_INVITE && !(flags&(TM_T_REPLY_no100_FLAG|TM_T_REPLY_repl_FLAG)) ) { ctx_backup = current_processing_ctx; current_processing_ctx = NULL; t_reply( t, p_msg , 100 , &relay_reason_100); current_processing_ctx = ctx_backup; } /* now go ahead and forward ... */ ret=t_forward_nonack( t, p_msg, proxy); if (ret<=0) { LM_DBG("t_forward_nonack returned error \n"); /* we don't want to pass upstream any reply regarding replicating * a request; replicated branch must stop at us*/ if (!(flags&(TM_T_REPLY_repl_FLAG|TM_T_REPLY_noerr_FLAG))) { reply_ret = kill_transaction( t ); if (reply_ret>0) { /* we have taken care of all -- do nothing in script */ LM_DBG("generation of a stateful reply on error succeeded\n"); ret=0; } else { LM_DBG("generation of a stateful reply on error failed\n"); } } } else { LM_DBG("new transaction fwd'ed\n"); } done: return ret; }
int add_dst( rt_data_t *r, /* id */ int id, /* ip address */ char* ip, /* strip len */ int strip, /* pri prefix */ char* pri, /* dst type*/ int type, /* dst attrs*/ char* attrs, /* probe_mode */ int probing ) { pgw_t *pgw=NULL, *tmp=NULL; struct sip_uri uri; int l_ip,l_pri,l_attrs; #define GWABUF_MAX_SIZE 512 char gwabuf[GWABUF_MAX_SIZE]; union sockaddr_union sau; struct proxy_l *proxy; str gwas; if (NULL==r || NULL==ip) { LM_ERR("invalid parametres\n"); goto err_exit; } l_ip = strlen(ip); l_pri = pri?strlen(pri):0; l_attrs = attrs?strlen(attrs):0; pgw = (pgw_t*)shm_malloc(sizeof(pgw_t) + l_ip + l_pri + l_attrs); if (NULL==pgw) { LM_ERR("no more shm mem (%u)\n", (unsigned int)(sizeof(pgw_t)+l_ip+l_pri +l_attrs)); goto err_exit; } memset(pgw,0,sizeof(pgw_t)); switch(probing) { case 0: pgw->flags = 0; break; case 1: pgw->flags = DR_DST_PING_DSBL_FLAG; break; case 2: pgw->flags = DR_DST_PING_PERM_FLAG; break; default: goto err_exit; } pgw->ip_str.len= l_ip; pgw->ip_str.s = (char*)(pgw+1); memcpy(pgw->ip_str.s, ip, l_ip); if (pri) { pgw->pri.len = l_pri; pgw->pri.s = ((char*)(pgw+1))+l_ip; memcpy(pgw->pri.s, pri, l_pri); } if (attrs) { pgw->attrs.len = l_attrs; pgw->attrs.s = ((char*)(pgw+1))+l_ip+l_pri; memcpy(pgw->attrs.s, attrs, l_attrs); } pgw->id = id; pgw->strip = strip; pgw->type = type; /* add address in the list */ if(pgw->ip_str.len<5 || (strncasecmp("sip:", ip, 4) && strncasecmp("sips:", ip, 5))) { if(pgw->ip_str.len+4>=GWABUF_MAX_SIZE) { LM_ERR("GW address (%d) longer " "than %d\n",pgw->ip_str.len+4,GWABUF_MAX_SIZE); goto err_exit; } memcpy(gwabuf, "sip:", 4); memcpy(gwabuf+4, ip, l_ip); gwas.s = gwabuf; gwas.len = 4+l_ip; } else { gwas.s = ip; gwas.len = l_ip; } memset(&uri, 0, sizeof(struct sip_uri)); if(parse_uri(gwas.s, gwas.len, &uri)!=0) { LM_ERR("invalid uri <%.*s>\n", gwas.len, gwas.s); goto err_exit; } proxy = mk_proxy(&uri.host,uri.port_no,uri.proto,(uri.type==SIPS_URI_T)); if (proxy==NULL) { if(dr_force_dns) { LM_ERR("cannot resolve <%.*s>\n", uri.host.len, uri.host.s); goto err_exit; } else { LM_DBG("cannot resolve <%.*s> - won't be used" " by is_from_gw()\n", uri.host.len, uri.host.s); goto done; } } hostent2ip_addr( &pgw->ips[0], &proxy->host, proxy->addr_idx); pgw->port = uri.port_no; LM_DBG("first gw ip addr [%s]\n", ip_addr2a(&pgw->ips[0])); pgw->ips_no = 1; while (pgw->ips_no<DR_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &pgw->ips[pgw->ips_no], &sau); LM_DBG("additional gw ip addr [%s]\n", ip_addr2a( &pgw->ips[pgw->ips_no] ) ); pgw->ips_no++; } free_proxy(proxy); pkg_free(proxy); done: if(NULL==r->pgw_l) r->pgw_l = pgw; else { tmp = r->pgw_l; while(NULL != tmp->next) tmp = tmp->next; tmp->next = pgw; } return 0; err_exit: if(NULL!=pgw) shm_free(pgw); return -1; }
/* ret= 0! if action -> end of list(e.g DROP), > 0 to continue processing next actions and <0 on error */ int do_action(struct action* a, struct sip_msg* msg) { int ret; int v; union sockaddr_union* to; struct socket_info* send_sock; struct proxy_l* p; char* tmp; char *new_uri, *end, *crt; int len; int user; struct sip_uri uri, next_hop; struct sip_uri* u; unsigned short port; int proto; /* reset the value of error to E_UNSPEC so avoid unknowledgable functions to return with errror (status<0) and not setting it leaving there previous error; cache the previous value though for functions which want to process it */ prev_ser_error=ser_error; ser_error=E_UNSPEC; ret=E_BUG; switch ((unsigned char)a->type){ case DROP_T: ret=0; break; case FORWARD_T: #ifdef USE_TCP case FORWARD_TCP_T: #endif #ifdef USE_TLS case FORWARD_TLS_T: #endif case FORWARD_UDP_T: if (a->type==FORWARD_UDP_T) proto=PROTO_UDP; #ifdef USE_TCP else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP; #endif #ifdef USE_TLS else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS; #endif else proto=msg->rcv.proto; if (a->p1_type==URIHOST_ST){ /*parse uri*/ if (msg->dst_uri.len) { ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop); u = &next_hop; } else { ret = parse_sip_msg_uri(msg); u = &msg->parsed_uri; } if (ret<0) { LOG(L_ERR, "ERROR: do_action: forward: bad_uri " " dropping packet\n"); break; } switch (a->p2_type){ case URIPORT_ST: port=u->port_no; break; case NUMBER_ST: port=a->p2.number; break; default: LOG(L_CRIT, "BUG: do_action bad forward 2nd" " param type (%d)\n", a->p2_type); ret=E_UNSPEC; goto error_fwd_uri; } switch(u->proto){ case PROTO_NONE: proto=PROTO_UDP; break; case PROTO_UDP: #ifdef USE_TCP case PROTO_TCP: #endif #ifdef USE_TLS case PROTO_TLS: #endif proto=u->proto; break; default: LOG(L_ERR,"ERROR: do action: forward: bad uri" " transport %d\n", u->proto); ret=E_BAD_PROTO; goto error_fwd_uri; } #ifdef USE_TLS if (u->secure){ if (u->proto==PROTO_UDP){ LOG(L_ERR, "ERROR: do_action: forward: secure uri" " incompatible with transport %d\n", u->proto); ret=E_BAD_PROTO; goto error_fwd_uri; } proto=PROTO_TLS; } #endif /* create a temporary proxy*/ p=mk_proxy(&u->host, port, proto); if (p==0){ LOG(L_ERR, "ERROR: bad host name in uri," " dropping packet\n"); ret=E_BAD_ADDRESS; goto error_fwd_uri; } ret=forward_request(msg, p, proto); /*free_uri(&uri); -- no longer needed, in sip_msg*/ free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); if (ret>=0) ret=1; }else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){ ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto); if (ret>=0) ret=1; }else{ LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; } break; case SEND_T: case SEND_TCP_T: if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){ LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; break; } to=(union sockaddr_union*) pkg_malloc(sizeof(union sockaddr_union)); if (to==0){ LOG(L_ERR, "ERROR: do_action: " "memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } p=(struct proxy_l*)a->p1.data; if (p->ok==0){ if (p->host.h_addr_list[p->addr_idx+1]) p->addr_idx++; else p->addr_idx=0; p->ok=1; } ret=hostent2su( to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT ); if (ret==0){ p->tx++; p->tx_bytes+=msg->len; if (a->type==SEND_T){ /*udp*/ send_sock=get_send_socket(to, PROTO_UDP); if (send_sock!=0){ ret=udp_send(send_sock, msg->buf, msg->len, to); }else{ ret=-1; } } #ifdef USE_TCP else{ /*tcp*/ ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0); } #endif } pkg_free(to); if (ret<0){ p->errors++; p->ok=0; }else ret=1; break; case LOG_T: if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){ LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; break; } LOG(a->p1.number, a->p2.string); ret=1; break; /* jku -- introduce a new branch */ case APPEND_BRANCH_T: if ((a->p1_type!=STRING_ST)) { LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n", a->p1_type ); ret=E_BUG; break; } ret=append_branch( msg, a->p1.string, a->p1.string ? strlen(a->p1.string):0 ); break; /* jku begin: is_length_greater_than */ case LEN_GT_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n", a->p1_type ); ret=E_BUG; break; } /* DBG("XXX: message length %d, max %d\n", msg->len, a->p1.number ); */ ret = msg->len >= a->p1.number ? 1 : -1; break; /* jku end: is_length_greater_than */ /* jku - begin : flag processing */ case SETFLAG_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n", a->p1_type ); ret=E_BUG; break; } if (!flag_in_range( a->p1.number )) { ret=E_CFG; break; } setflag( msg, a->p1.number ); ret=1; break; case RESETFLAG_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n", a->p1_type ); ret=E_BUG; break; } if (!flag_in_range( a->p1.number )) { ret=E_CFG; break; } resetflag( msg, a->p1.number ); ret=1; break; case ISFLAGSET_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n", a->p1_type ); ret=E_BUG; break; } if (!flag_in_range( a->p1.number )) { ret=E_CFG; break; } ret=isflagset( msg, a->p1.number ); break; /* jku - end : flag processing */ case ERROR_T: if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){ LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; break; } LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") " "not implemented yet\n", a->p1.string, a->p2.string); ret=1; break; case ROUTE_T: if (a->p1_type!=NUMBER_ST){ LOG(L_CRIT, "BUG: do_action: bad route() type %d\n", a->p1_type); ret=E_BUG; break; } if ((a->p1.number>RT_NO)||(a->p1.number<0)){ LOG(L_ERR, "ERROR: invalid routing table number in" "route(%lu)\n", a->p1.number); ret=E_CFG; break; } ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1; break; case EXEC_T: if (a->p1_type!=STRING_ST){ LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n", a->p1_type); ret=E_BUG; break; } LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented," " using dumb version...\n", a->p1.string); ret=system(a->p1.string); if (ret!=0){ LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret); } ret=1; break; case REVERT_URI_T: if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; msg->new_uri.s=0; msg->parsed_uri_ok=0; /* invalidate current parsed uri*/ }; ret=1; break; case SET_HOST_T: case SET_HOSTPORT_T: case SET_USER_T: case SET_USERPASS_T: case SET_PORT_T: case SET_URI_T: case PREFIX_T: case STRIP_T: case STRIP_TAIL_T: user=0; if (a->type==STRIP_T || a->type==STRIP_TAIL_T) { if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n", a->p1_type); break; } } else if (a->p1_type!=STRING_ST){ LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n", a->p1_type); ret=E_BUG; break; } if (a->type==SET_URI_T){ if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; } msg->parsed_uri_ok=0; len=strlen(a->p1.string); msg->new_uri.s=pkg_malloc(len+1); if (msg->new_uri.s==0){ LOG(L_ERR, "ERROR: do_action: memory allocation" " failure\n"); ret=E_OUT_OF_MEM; break; } memcpy(msg->new_uri.s, a->p1.string, len); msg->new_uri.s[len]=0; msg->new_uri.len=len; ret=1; break; } if (msg->new_uri.s) { tmp=msg->new_uri.s; len=msg->new_uri.len; }else{ tmp=msg->first_line.u.request.uri.s; len=msg->first_line.u.request.uri.len; } if (parse_uri(tmp, len, &uri)<0){ LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping" " packet\n", tmp); ret=E_UNSPEC; break; } new_uri=pkg_malloc(MAX_URI_SIZE); if (new_uri==0){ LOG(L_ERR, "ERROR: do_action: memory allocation " " failure\n"); ret=E_OUT_OF_MEM; break; } end=new_uri+MAX_URI_SIZE; crt=new_uri; /* begin copying */ len=strlen("sip:"); if(crt+len>end) goto error_uri; memcpy(crt,"sip:",len);crt+=len; /* user */ /* prefix (-jiri) */ if (a->type==PREFIX_T) { tmp=a->p1.string; len=strlen(tmp); if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; /* whatever we had before, with prefix we have username now */ user=1; } if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) { tmp=a->p1.string; len=strlen(tmp); } else if (a->type==STRIP_T) { if (a->p1.number>uri.user.len) { LOG(L_WARN, "Error: too long strip asked; " " deleting username: %lu of <%.*s>\n", a->p1.number, uri.user.len, uri.user.s ); len=0; } else if (a->p1.number==uri.user.len) { len=0; } else { tmp=uri.user.s + a->p1.number; len=uri.user.len - a->p1.number; } } else if (a->type==STRIP_TAIL_T) { if (a->p1.number>uri.user.len) { LOG(L_WARN, "WARNING: too long strip_tail asked; " " deleting username: %lu of <%.*s>\n", a->p1.number, uri.user.len, uri.user.s ); len=0; } else if (a->p1.number==uri.user.len) { len=0; } else { tmp=uri.user.s; len=uri.user.len - a->p1.number; } } else { tmp=uri.user.s; len=uri.user.len; } if (len){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; user=1; /* we have an user field so mark it */ } if (a->type==SET_USERPASS_T) tmp=0; else tmp=uri.passwd.s; /* passwd */ if (tmp){ len=uri.passwd.len; if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* host */ if (user || tmp){ /* add @ */ if(crt+1>end) goto error_uri; *crt='@'; crt++; } if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) { tmp=a->p1.string; if (tmp) len = strlen(tmp); else len=0; } else { tmp=uri.host.s; len = uri.host.len; } if (tmp){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; } /* port */ if (a->type==SET_HOSTPORT_T) tmp=0; else if (a->type==SET_PORT_T) { tmp=a->p1.string; if (tmp) len = strlen(tmp); else len = 0; } else { tmp=uri.port.s; len = uri.port.len; } if (tmp){ if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* params */ tmp=uri.params.s; if (tmp){ len=uri.params.len; if(crt+len+1>end) goto error_uri; *crt=';'; crt++; memcpy(crt,tmp,len);crt+=len; } /* headers */ tmp=uri.headers.s; if (tmp){ len=uri.headers.len; if(crt+len+1>end) goto error_uri; *crt='?'; crt++; memcpy(crt,tmp,len);crt+=len; } *crt=0; /* null terminate the thing */ /* copy it to the msg */ if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri.s=new_uri; msg->new_uri.len=crt-new_uri; msg->parsed_uri_ok=0; ret=1; break; case IF_T: /* if null expr => ignore if? */ if ((a->p1_type==EXPR_ST)&&a->p1.data){ v=eval_expr((struct expr*)a->p1.data, msg); if (v<0){ if (v==EXPR_DROP){ /* hack to quit on DROP*/ ret=0; break; }else{ LOG(L_WARN,"WARNING: do_action:" "error in expression\n"); } } ret=1; /*default is continue */ if (v>0) { if ((a->p2_type==ACTIONS_ST)&&a->p2.data){ ret=run_actions((struct action*)a->p2.data, msg); } }else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){ ret=run_actions((struct action*)a->p3.data, msg); } } break; case MODULE_T: if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&& ((a->p2_type==STRING_ST)&&a->p2.data)*/ ){ ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data, (char*)a->p3.data); }else{ LOG(L_CRIT,"BUG: do_action: bad module call\n"); } break; case FORCE_RPORT_T: msg->msg_flags|=FL_FORCE_RPORT; ret=1; /* continue processing */ break; case SET_ADV_ADDR_T: if (a->p1_type!=STR_ST){ LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() " "type %d\n", a->p1_type); ret=E_BUG; break; } msg->set_global_address=*((str*)a->p1.data); ret=1; /* continue processing */ break; case SET_ADV_PORT_T: if (a->p1_type!=STR_ST){ LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() " "type %d\n", a->p1_type); ret=E_BUG; break; } msg->set_global_port=*((str*)a->p1.data); ret=1; /* continue processing */ break; default: LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type); } /*skip:*/ return ret; error_uri: LOG(L_ERR, "ERROR: do_action: set*: uri too long\n"); if (new_uri) pkg_free(new_uri); return E_UNSPEC; error_fwd_uri: /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/ return ret; }
int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri, char* resource, unsigned int flags) { struct lb_res_str_list *lb_rl; struct lb_res_str *r; struct lb_dst *dst; struct lb_resource *res; struct sip_uri puri; struct proxy_l *proxy; union sockaddr_union sau; int len; int i; LM_DBG("uri=<%s>, grp=%d, res=<%s>\n",uri, group, resource); /* check uri */ len = strlen(uri); if(parse_uri(uri, len, &puri)!=0 ) { LM_ERR("bad uri [%.*s] for destination\n", len, uri); return -1; } /* parse the resources string */ lb_rl = parse_resources_list( resource, 1); if (lb_rl==NULL) { LM_ERR("failed to parse resourse string <%s>\n",resource); return -1; } /*add new destination */ dst = (struct lb_dst*)shm_malloc( sizeof(struct lb_dst) + lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*))); if (dst==NULL) { LM_ERR("failed to get shmem\n"); goto error; } memset( dst, 0, sizeof(struct lb_dst)+ lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*)) ); dst->rmap = (struct lb_resource_map*)(dst+1); dst->uri.s = (char*)(dst->rmap + lb_rl->n); dst->uri.len = len; memcpy( dst->uri.s , uri, len); dst->profile_id.s = dst->uri.s + len; dst->profile_id.len = snprintf(dst->profile_id.s, 2+2*sizeof(struct lb_dst*), "%X", id); dst->id = id; dst->group = group; dst->rmap_no = lb_rl->n; dst->flags = flags; /* add or update resource list */ for( i=0 ; i<lb_rl->n ; i++) { r = lb_rl->resources + i; LM_DBG(" setting for uri=<%s> (%d) resource=<%.*s>, val=%d\n", uri, data->dst_no+1, r->name.len, r->name.s, r->val); res = get_resource_by_name( data, &r->name); if (res==NULL) { /* add new resource */ res = add_lb_resource(data, &r->name); if (res==NULL) { LM_ERR("failed to create new resource\n"); goto error; } } /* set the proper bit in the resource */ if (lb_set_resource_bitmask( res, data->dst_no)==-1 ) { LM_ERR("failed to set destination bit\n"); goto error; } /* set the pointer and the max load */ dst->rmap[i].resource = res; dst->rmap[i].max_load = r->val; } /* Do a SIP wise DNS-Lookup for the domain part */ proxy = mk_proxy( &puri.host, puri.port_no, puri.proto, (puri.type==SIPS_URI_T)); if (proxy==NULL) { LM_ERR("could not resolve %.*s\n", puri.host.len, puri.host.s); goto error; } hostent2ip_addr( &dst->ips[0], &proxy->host, proxy->addr_idx); dst->ports[0] = proxy->port; dst->ips_cnt = 1; LM_DBG("first dst ip addr [%s]:%d\n", ip_addr2a(&dst->ips[0]), dst->ports[0]); /* get the next available IPs from DNS */ while (dst->ips_cnt<LB_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &dst->ips[dst->ips_cnt], &sau); dst->ports[dst->ips_cnt] = proxy->port; LM_DBG("additional dst ip addr [%s]:%d\n", ip_addr2a(&dst->ips[dst->ips_cnt]), dst->ports[dst->ips_cnt]); /* one more IP found */ dst->ips_cnt++; } /* free al the helper structures */ free_proxy(proxy); pkg_free(proxy); /* link at the end */ if (data->last_dst==NULL) { data->dsts = data->last_dst = dst; } else { data->last_dst->next = dst; data->last_dst = dst; } data->dst_no++; pkg_free(lb_rl); return 0; error: shm_free(dst); pkg_free(lb_rl); return -1; }
/* * Send a request using data from the dialog structure */ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,release_tmcb_param release_func) { union sockaddr_union to_su, new_to_su; struct cell *new_cell; struct cell *backup_cell; struct retr_buf *request; static struct sip_msg *req; struct usr_avp **backup; char *buf, *buf1; int buf_len, buf_len1; int ret, flags, sflag_bk; int backup_route_type; int sip_msg_len; unsigned int hi; struct socket_info *new_send_sock; str h_to, h_from, h_cseq, h_callid; struct proxy_l *proxy, *new_proxy; unsigned short dst_changed; ret=-1; /*** added by dcm * - needed by external ua to send a request within a dlg */ if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0) goto error3; if(dialog->obp.s) dialog->hooks.next_hop = &dialog->obp; LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); /* calculate the socket corresponding to next hop */ proxy = uri2proxy( dialog->hooks.next_hop, dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error3; } /* use the first address */ hostent2su( &to_su, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); /* check/discover the send socket */ if (dialog->send_sock) { /* if already set, the protocol of send sock must have the the same type as the proto required by destination URI */ if (proxy->proto != dialog->send_sock->proto) dialog->send_sock = NULL; } if (dialog->send_sock==NULL) { /* get the send socket */ dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto); if (!dialog->send_sock) { LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family); ser_error = E_NO_SOCKET; goto error2; } } LM_DBG("sending socket is %.*s \n", dialog->send_sock->name.len,dialog->send_sock->name.s); /* ***** Create TRANSACTION and all related ***** */ new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/); if (!new_cell) { ret=E_OUT_OF_MEM; LM_ERR("short of cell shmem\n"); goto error2; } /* pass the transaction flags from dialog to transaction */ new_cell->flags |= dialog->T_flags; /* add the callback the transaction for LOCAL_COMPLETED event */ flags = TMCB_LOCAL_COMPLETED; /* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */ if (pass_provisional_replies || pass_provisional(new_cell)) flags |= TMCB_LOCAL_RESPONSE_OUT; if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){ ret=E_OUT_OF_MEM; LM_ERR("short of tmcb shmem\n"); goto error2; } if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags |= T_IS_LOCAL_FLAG; request = &new_cell->uac[0].request; if (dialog->forced_to_su.s.sa_family == AF_UNSPEC) request->dst.to = to_su; else request->dst.to = dialog->forced_to_su; request->dst.send_sock = dialog->send_sock; request->dst.proto = dialog->send_sock->proto; request->dst.proto_reserved1 = 0; hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); /* copy AVPs into transaction */ new_cell->user_avps = dialog->avps; dialog->avps = NULL; /* ***** Create the message buffer ***** */ buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len); if (!buf) { LM_ERR("failed to build message\n"); ret=E_OUT_OF_MEM; goto error1; } if (local_rlist.a) { LM_DBG("building sip_msg from buffer\n"); req = buf_to_sip_msg(buf, buf_len, dialog); if (req==NULL) { LM_ERR("failed to build sip_msg from buffer\n"); } else { /* set this transaction as active one */ backup_cell = get_t(); set_t( new_cell ); /* set transaction AVP list */ backup = set_avp_list( &new_cell->user_avps ); /* backup script flags */ sflag_bk = getsflags(); /* disable parallel forking */ set_dset_state( 0 /*disable*/); /* run the route */ swap_route_type( backup_route_type, LOCAL_ROUTE); run_top_route( local_rlist.a, req); set_route_type( backup_route_type ); /* transfer current message context back to t */ new_cell->uac[0].br_flags = getb0flags(req); /* restore the prevoius active transaction */ set_t( backup_cell ); set_dset_state( 1 /*enable*/); setsflagsval(sflag_bk); set_avp_list( backup ); /* check for changes - if none, do not regenerate the buffer */ dst_changed = 1; if (req->new_uri.s || req->force_send_socket!=dialog->send_sock || req->dst_uri.len != dialog->hooks.next_hop->len || memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) || (dst_changed=0)==0 || req->add_rm || req->body_lumps){ new_send_sock = NULL; /* do we also need to change the destination? */ if (dst_changed) { /* calculate the socket corresponding to next hop */ new_proxy = uri2proxy( req->dst_uri.s ? &(req->dst_uri) : &req->new_uri, PROTO_NONE ); if (new_proxy==0) goto abort_update; /* use the first address */ hostent2su( &new_to_su, &new_proxy->host, new_proxy->addr_idx, new_proxy->port ? new_proxy->port:SIP_PORT); /* get the send socket */ new_send_sock = get_send_socket( req, &new_to_su, new_proxy->proto); if (!new_send_sock) { free_proxy( new_proxy ); pkg_free( new_proxy ); LM_ERR("no socket found for the new destination\n"); goto abort_update; } } /* if interface change, we need to re-build the via */ if (new_send_sock && new_send_sock != dialog->send_sock) { LM_DBG("Interface change in local route -> " "rebuilding via\n"); if (!del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len,0)) { LM_ERR("Failed to remove initial via \n"); goto abort_update; } memcpy(req->add_to_branch_s,req->via1->branch->value.s, req->via1->branch->value.len); req->add_to_branch_len = req->via1->branch->value.len; /* update also info about new destination and send sock */ dialog->send_sock = new_send_sock; free_proxy( proxy ); pkg_free( proxy ); proxy = new_proxy; request->dst.send_sock = new_send_sock; request->dst.proto = new_send_sock->proto; request->dst.proto_reserved1 = 0; /* build the shm buffer now */ set_init_lump_flags(LUMPFLAG_BRANCH); buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, new_send_sock, new_send_sock->proto, MSG_TRANS_SHM_FLAG); reset_init_lump_flags(); del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH); } else { LM_DBG("Change in local route -> rebuilding buffer\n"); /* build the shm buffer now */ buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, dialog->send_sock, dialog->send_sock->proto, MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG); /* now as it used, hide the original VIA header */ del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len, 0); } if (!buf1) { LM_ERR("no more shm mem\n"); /* keep original buffer */ goto abort_update; } /* update shortcuts */ if(!req->add_rm && !req->new_uri.s) { /* headers are not affected, simply tranlate */ new_cell->from.s = new_cell->from.s - buf + buf1; new_cell->to.s = new_cell->to.s - buf + buf1; new_cell->callid.s = new_cell->callid.s - buf + buf1; new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1; } else { /* use heavy artilery :D */ if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to, &h_cseq, &h_callid)!=0 ) { LM_ERR("failed to update shortcut pointers\n"); shm_free(buf1); goto abort_update; } new_cell->from = h_from; new_cell->to = h_to; new_cell->callid = h_callid; new_cell->cseq_n = h_cseq; } /* here we rely on how build_uac_req() builds the first line */ new_cell->uac[0].uri.s = buf1 + req->first_line.u.request.method.len + 1; new_cell->uac[0].uri.len = GET_RURI(req)->len; /* update also info about new destination and send sock */ if (new_send_sock) request->dst.to = new_to_su; shm_free(buf); buf = buf1; buf_len = buf_len1; /* use new buffer */ } else { /* no changes over the message, buffer is already generated, just hide the original VIA for potential further branches */ del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0); } abort_update: /* save the SIP message into transaction */ new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1); if (new_cell->uas.request==NULL) { /* reset any T triggering */ new_cell->on_negative = 0; new_cell->on_reply = 0; } else { new_cell->uas.end_request= ((char*)new_cell->uas.request)+sip_msg_len; } /* no parallel support in UAC transactions */ new_cell->on_branch = 0; free_sip_msg(req); } } /* for DNS based failover, copy the DNS proxy into transaction */ if (!disable_dns_failover) { new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/); if (new_cell->uac[0].proxy==NULL) LM_ERR("failed to store DNS info -> no DNS based failover\n"); } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer.s = buf; request->buffer.len = buf_len; new_cell->nr_of_outgoings++; if(last_localT) { *last_localT = new_cell; REF_UNSAFE(new_cell); } if (SEND_BUFFER(request) == -1) { LM_ERR("attempt to send to '%.*s' failed\n", dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); } if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) { t_release_transaction(new_cell); } else { start_retr(request); } free_proxy( proxy ); pkg_free( proxy ); return 1; error1: LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); free_cell(new_cell); error2: free_proxy( proxy ); pkg_free( proxy ); error3: return ret; }
int t_relay_to( struct sip_msg *p_msg , struct proxy_l *proxy, int proto, int replicate) { int ret; int new_tran; str *uri; int reply_ret; /* struct hdr_field *hdr; */ struct cell *t; ret=0; new_tran = t_newtran( p_msg ); /* parsing error, memory alloc, whatever ... if via is bad and we are forced to reply there, return with 0 (->break), pass error status otherwise */ if (new_tran<0) { ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran; goto done; } /* if that was a retransmission, return we are happily done */ if (new_tran==0) { ret = 1; goto done; } /* new transaction */ /* ACKs do not establish a transaction and are fwd-ed statelessly */ if ( p_msg->REQ_METHOD==METHOD_ACK) { DBG("DEBUG:tm:t_relay: forwarding ACK statelessly \n"); if (proxy==0) { uri = GET_RURI(p_msg); proxy=uri2proxy(GET_NEXT_HOP(p_msg), proto); if (proxy==0) { ret=E_BAD_ADDRESS; goto done; } proto=proxy->proto; /* uri2proxy set it correctly */ ret=forward_request( p_msg , proxy, proto) ; free_proxy( proxy ); pkg_free( proxy ); } else { proto=get_proto(proto, proxy->proto); ret=forward_request( p_msg , proxy, proto ) ; } goto done; } /* if replication flag is set, mark the transaction as local so that replies will not be relaied */ t=get_t(); if (replicate) t->flags|=T_IS_LOCAL_FLAG; /* INVITE processing might take long, particularly because of DNS look-ups -- let upstream know we're working on it */ if (p_msg->REQ_METHOD==METHOD_INVITE ) { DBG("DEBUG:tm:t_relay: new INVITE\n"); if (!t_reply( t, p_msg , 100 , "trying -- your call is important to us")) DBG("SER: ERROR: t_reply (100)\n"); } /* now go ahead and forward ... */ ret=t_forward_nonack(t, p_msg, proxy, proto); if (ret<=0) { DBG( "ERROR:tm:t_relay_to: t_forward_nonack returned error \n"); /* we don't want to pass upstream any reply regarding replicating * a request; replicated branch must stop at us*/ if (!replicate) { reply_ret=kill_transaction( t ); if (reply_ret>0) { /* we have taken care of all -- do nothing in script */ DBG("ERROR: generation of a stateful reply " "on error succeeded\n"); ret=0; } else { DBG("ERROR: generation of a stateful reply " "on error failed\n"); } } } else { DBG( "SER: new transaction fwd'ed\n"); } done: return ret; }
/* ret= 0! if action -> end of list(e.g DROP), > 0 to continue processing next actions and <0 on error */ int do_action(struct action* a, struct sip_msg* msg) { int ret; int v; int sec,usec; union sockaddr_union* to; struct proxy_l* p; char* tmp; char *new_uri, *end, *crt; int len,i; int user = 0; int expires = 0; str vals[5]; str result; struct sip_uri uri, next_hop; struct sip_uri *u; unsigned short port; int cmatch; struct action *aitem; struct action *adefault; pv_spec_t *spec; pv_elem_p model; pv_value_t val; pv_elem_t *pve; str name_s; struct timeval start; int end_time; action_elem_t *route_params_bak; int route_params_number_bak; /* reset the value of error to E_UNSPEC so avoid unknowledgable functions to return with error (status<0) and not setting it leaving there previous error; cache the previous value though for functions which want to process it */ prev_ser_error=ser_error; ser_error=E_UNSPEC; start_expire_timer(start,execmsgthreshold); ret=E_BUG; switch ((unsigned char)a->type){ case DROP_T: script_trace("core", "drop", msg, a->line) ; action_flags |= ACT_FL_DROP; case EXIT_T: script_trace("core", "exit", msg, a->line) ; ret=0; action_flags |= ACT_FL_EXIT; break; case RETURN_T: script_trace("core", "return", msg, a->line) ; if (a->elem[0].type == SCRIPTVAR_ST) { spec = (pv_spec_t*)a->elem[0].u.data; if(pv_get_spec_value(msg, spec, &val)!=0 || (val.flags&PV_VAL_NULL)) { ret=-1; } else { if(!(val.flags&PV_VAL_INT)) ret = 1; else ret = val.ri; } pv_value_destroy(&val); } else { ret=a->elem[0].u.number; } action_flags |= ACT_FL_RETURN; break; case FORWARD_T: script_trace("core", "forward", msg, a->line) ; if (a->elem[0].type==NOSUBTYPE){ /* parse uri and build a proxy */ if (msg->dst_uri.len) { ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop); u = &next_hop; } else { ret = parse_sip_msg_uri(msg); u = &msg->parsed_uri; } if (ret<0) { LM_ERR("forward: bad_uri dropping packet\n"); break; } /* create a temporary proxy*/ p=mk_proxy(u->maddr_val.len?&u->maddr_val:&u->host, u->port_no, u->proto, (u->type==SIPS_URI_T)?1:0 ); if (p==0){ LM_ERR("bad host name in uri, dropping packet\n"); ret=E_BAD_ADDRESS; 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 if ((a->elem[0].type==PROXY_ST)) { ret=forward_request(msg,(struct proxy_l*)a->elem[0].u.data); if (ret==0) ret=1; }else{ LM_ALERT("BUG in forward() types %d, %d\n", a->elem[0].type, a->elem[1].type); ret=E_BUG; } break; case SEND_T: script_trace("core", "send", msg, a->line) ; if (a->elem[0].type!= PROXY_ST){ LM_ALERT("BUG in send() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (a->elem[1].u.data) { if (a->elem[1].type != SCRIPTVAR_ELEM_ST){ LM_ALERT("BUG in send() header type %d\n",a->elem[1].type); ret=E_BUG; break; } else { pve = (pv_elem_t *)a->elem[1].u.data; } } else { pve = NULL; } to=(union sockaddr_union*) pkg_malloc(sizeof(union sockaddr_union)); if (to==0){ LM_ERR("memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } p=(struct proxy_l*)a->elem[0].u.data; ret=hostent2su(to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT ); if (ret==0){ if (pve) { if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_UNSPEC; break; } /* build new msg */ tmp = pkg_malloc(msg->len + name_s.len); if (!tmp) { LM_ERR("memory allocation failure\n"); ret = E_OUT_OF_MEM; break; } LM_DBG("searching for first line %d\n", msg->first_line.len); /* search first line of previous msg */ /* copy headers */ len = msg->first_line.len; memcpy(tmp, msg->buf, len); memcpy(tmp + len, name_s.s, name_s.len); memcpy(tmp + len + name_s.len, msg->buf + len, msg->len - len); ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/, tmp, msg->len + name_s.len); pkg_free(tmp); } else { ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/, msg->buf, msg->len); } if (ret!=0 && p->host.h_addr_list[p->addr_idx+1]) p->addr_idx++; } pkg_free(to); if (ret==0) ret=1; break; case LOG_T: script_trace("core", "log", msg, a->line) ; if ((a->elem[0].type!=NUMBER_ST)|(a->elem[1].type!=STRING_ST)){ LM_ALERT("BUG in log() types %d, %d\n", a->elem[0].type, a->elem[1].type); ret=E_BUG; break; } LM_GEN1(a->elem[0].u.number, "%s", a->elem[1].u.string); ret=1; break; case APPEND_BRANCH_T: script_trace("core", "append_branch", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in append_branch %d\n", a->elem[0].type ); ret=E_BUG; break; } if (a->elem[0].u.s.s==NULL) { ret = append_branch(msg, 0, &msg->dst_uri, &msg->path_vec, get_ruri_q(), getb0flags(), msg->force_send_socket); /* reset all branch info */ msg->force_send_socket = 0; setb0flags(0); set_ruri_q(Q_UNSPECIFIED); if(msg->dst_uri.s!=0) pkg_free(msg->dst_uri.s); msg->dst_uri.s = 0; msg->dst_uri.len = 0; if(msg->path_vec.s!=0) pkg_free(msg->path_vec.s); msg->path_vec.s = 0; msg->path_vec.len = 0; } else { ret = append_branch(msg, &a->elem[0].u.s, &msg->dst_uri, &msg->path_vec, a->elem[1].u.number, getb0flags(), msg->force_send_socket); } break; case REMOVE_BRANCH_T: script_trace("core", "remove_branch", msg, a->line) ; if (a->elem[0].type == SCRIPTVAR_ST) { spec = (pv_spec_t*)a->elem[0].u.data; if( pv_get_spec_value(msg, spec, &val)!=0 || (val.flags&PV_VAL_NULL) || !(val.flags&PV_VAL_INT) ) { ret=-1; break; } i = val.ri; } else { i=a->elem[0].u.number; } ret = (remove_branch((unsigned int)i)==0)?1:-1; break; case LEN_GT_T: script_trace("core", "len_gt", msg, a->line) ; if (a->elem[0].type!=NUMBER_ST) { LM_ALERT("BUG in len_gt type %d\n", a->elem[0].type ); ret=E_BUG; break; } ret = (msg->len >= (unsigned int)a->elem[0].u.number) ? 1 : -1; break; case SET_DEBUG_T: script_trace("core", "set_debug", msg, a->line) ; if (a->elem[0].type==NUMBER_ST) set_proc_debug_level(a->elem[0].u.number); else reset_proc_debug_level(); ret = 1; break; case SETFLAG_T: script_trace("core", "setflag", msg, a->line) ; ret = setflag( msg, a->elem[0].u.number ); break; case RESETFLAG_T: script_trace("core", "resetflag", msg, a->line) ; ret = resetflag( msg, a->elem[0].u.number ); break; case ISFLAGSET_T: script_trace("core", "isflagset", msg, a->line) ; ret = isflagset( msg, a->elem[0].u.number ); break; case SETSFLAG_T: script_trace("core", "setsflag", msg, a->line) ; ret = setsflag( a->elem[0].u.number ); break; case RESETSFLAG_T: script_trace("core", "resetsflag", msg, a->line) ; ret = resetsflag( a->elem[0].u.number ); break; case ISSFLAGSET_T: script_trace("core", "issflagset", msg, a->line) ; ret = issflagset( a->elem[0].u.number ); break; case SETBFLAG_T: script_trace("core", "setbflag", msg, a->line) ; ret = setbflag( a->elem[0].u.number, a->elem[1].u.number ); break; case RESETBFLAG_T: script_trace("core", "resetbflag", msg, a->line) ; ret = resetbflag( a->elem[0].u.number, a->elem[1].u.number ); break; case ISBFLAGSET_T: script_trace("core", "isbflagset", msg, a->line) ; ret = isbflagset( a->elem[0].u.number, a->elem[1].u.number ); break; case ERROR_T: script_trace("core", "error", msg, a->line) ; if ((a->elem[0].type!=STRING_ST)|(a->elem[1].type!=STRING_ST)){ LM_ALERT("BUG in error() types %d, %d\n", a->elem[0].type, a->elem[1].type); ret=E_BUG; break; } LM_ERR("error(\"%s\", \"%s\") not implemented yet\n", a->elem[0].u.string, a->elem[1].u.string); ret=1; break; case ROUTE_T: script_trace("route", rlist[a->elem[0].u.number].name, msg, a->line) ; if (a->elem[0].type!=NUMBER_ST){ LM_ALERT("BUG in route() type %d\n", a->elem[0].type); ret=E_BUG; break; } if ((a->elem[0].u.number>RT_NO)||(a->elem[0].u.number<0)){ LM_ALERT("BUG - invalid routing table number in" "route(%lu)\n", a->elem[0].u.number); ret=E_CFG; break; } /* check if the route has parameters */ if (a->elem[1].type != 0) { if (a->elem[1].type != NUMBER_ST || a->elem[2].type != SCRIPTVAR_ELEM_ST) { LM_ALERT("BUG in route() type %d/%d\n", a->elem[1].type, a->elem[2].type); ret=E_BUG; break; } route_params_bak = route_params; route_params = (action_elem_t *)a->elem[2].u.data; route_params_number_bak = route_params_number; route_params_number = a->elem[1].u.number; return_code=run_actions(rlist[a->elem[0].u.number].a, msg); route_params = route_params_bak; route_params_number = route_params_number_bak; } else { return_code=run_actions(rlist[a->elem[0].u.number].a, msg); } ret=return_code; break; case REVERT_URI_T: script_trace("core", "revert_uri", msg, a->line) ; if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; msg->new_uri.s=0; msg->parsed_uri_ok=0; /* invalidate current parsed uri*/ }; ret=1; break; case SET_HOST_T: case SET_HOSTPORT_T: case SET_USER_T: case SET_USERPASS_T: case SET_PORT_T: case SET_URI_T: case PREFIX_T: case STRIP_T: case STRIP_TAIL_T: script_trace("core", (unsigned char)a->type == SET_HOST_T ? "set_host" : (unsigned char)a->type == SET_HOSTPORT_T ? "set_hostport" : (unsigned char)a->type == SET_USER_T ? "set_user" : (unsigned char)a->type == SET_USERPASS_T ? "set_userpass" : (unsigned char)a->type == SET_PORT_T ? "set_port" : (unsigned char)a->type == SET_URI_T ? "set_uri" : (unsigned char)a->type == PREFIX_T ? "prefix" : (unsigned char)a->type == STRIP_T ? "strip" : "strip_tail", msg, a->line); user=0; if (a->type==STRIP_T || a->type==STRIP_TAIL_T) { if (a->elem[0].type!=NUMBER_ST) { LM_ALERT("BUG in set*() type %d\n", a->elem[0].type); break; } } else if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in set*() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (a->type==SET_URI_T) { if (set_ruri( msg, &a->elem[0].u.s) ) { LM_ERR("failed to set new RURI\n"); ret=E_OUT_OF_MEM; break; } ret=1; break; } if (msg->new_uri.s) { tmp=msg->new_uri.s; len=msg->new_uri.len; }else{ tmp=msg->first_line.u.request.uri.s; len=msg->first_line.u.request.uri.len; } if (parse_uri(tmp, len, &uri)<0){ LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp); ret=E_UNSPEC; break; } new_uri=pkg_malloc(MAX_URI_SIZE); if (new_uri==0){ LM_ERR("memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } end=new_uri+MAX_URI_SIZE; crt=new_uri; /* begin copying */ len = (uri.user.len?uri.user.s:uri.host.s) - tmp; if (crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; if (a->type==PREFIX_T) { if (crt+a->elem[0].u.s.len>end) goto error_uri; memcpy( crt, a->elem[0].u.s.s, a->elem[0].u.s.len); crt+=a->elem[0].u.s.len; /* whatever we had before, with prefix we have username now */ user=1; } if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) { tmp=a->elem[0].u.s.s; len=a->elem[0].u.s.len; } else if (a->type==STRIP_T) { if (a->elem[0].u.number>uri.user.len) { LM_WARN("too long strip asked; " " deleting username: %lu of <%.*s>\n", a->elem[0].u.number, uri.user.len, uri.user.s); len=0; } else if (a->elem[0].u.number==uri.user.len) { len=0; } else { tmp=uri.user.s + a->elem[0].u.number; len=uri.user.len - a->elem[0].u.number; } } else if (a->type==STRIP_TAIL_T) { if (a->elem[0].u.number>uri.user.len) { LM_WARN("too long strip_tail asked;" " deleting username: %lu of <%.*s>\n", a->elem[0].u.number, uri.user.len, uri.user.s); len=0; } else if (a->elem[0].u.number==uri.user.len) { len=0; } else { tmp=uri.user.s; len=uri.user.len - a->elem[0].u.number; } } else { tmp=uri.user.s; len=uri.user.len; } if (len){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; user=1; /* we have an user field so mark it */ } if (a->type==SET_USERPASS_T) tmp=0; else tmp=uri.passwd.s; /* passwd */ if (tmp){ len=uri.passwd.len; if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* host */ if (user || tmp){ /* add @ */ if(crt+1>end) goto error_uri; *crt='@'; crt++; } if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) { tmp=a->elem[0].u.s.s; len=a->elem[0].u.s.len; } else { tmp=uri.host.s; len = uri.host.len; } if (tmp){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; } /* port */ if (a->type==SET_HOSTPORT_T) tmp=0; else if (a->type==SET_PORT_T) { tmp=a->elem[0].u.s.s; len=a->elem[0].u.s.len; } else { tmp=uri.port.s; len = uri.port.len; } if (tmp && len>0){ if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* params */ tmp=uri.params.s; if (tmp){ /* include in param string the starting ';' */ len=uri.params.len+1; tmp--; if(crt+len+1>end) goto error_uri; /* if a maddr param is present, strip it out */ if (uri.maddr.len && (a->type==SET_HOSTPORT_T || a->type==SET_HOST_T)) { memcpy(crt,tmp,uri.maddr.s-tmp-1); crt+=uri.maddr.s-tmp-1; memcpy(crt,uri.maddr_val.s+uri.maddr_val.len, tmp+len-uri.maddr_val.s-uri.maddr_val.len); crt+=tmp+len-uri.maddr_val.s-uri.maddr_val.len; } else { memcpy(crt,tmp,len);crt+=len; } } /* headers */ tmp=uri.headers.s; if (tmp){ len=uri.headers.len; if(crt+len+1>end) goto error_uri; *crt='?'; crt++; memcpy(crt,tmp,len);crt+=len; } *crt=0; /* null terminate the thing */ /* copy it to the msg */ if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri.s=new_uri; msg->new_uri.len=crt-new_uri; msg->parsed_uri_ok=0; ret=1; break; case SET_DSTURI_T: script_trace("core", "set_dsturi", msg, a->line) ; if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in setdsturi() type %d\n", a->elem[0].type); ret=E_BUG; break; } if(set_dst_uri(msg, &a->elem[0].u.s)!=0) ret = -1; else ret = 1; break; case SET_DSTHOST_T: case SET_DSTPORT_T: script_trace("core", (unsigned char) a->type == SET_DSTHOST_T ? "set_dsturi" : "set_dstport", msg, a->line); if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in domain setting type %d\n", a->elem[0].type); ret=E_BUG; break; } tmp = msg->dst_uri.s; len = msg->dst_uri.len; if (tmp == NULL || len == 0) { LM_ERR("failure - null uri\n"); ret = E_UNSPEC; break; } if (a->type == SET_DSTHOST_T && (a->elem[0].u.s.s == NULL || a->elem[0].u.s.len == 0)) { LM_ERR("cannot set a null uri domain\n"); break; } if (parse_uri(tmp, len, &uri)<0) { LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp); break; } new_uri=pkg_malloc(MAX_URI_SIZE); if (new_uri == NULL) { LM_ERR("memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } end=new_uri+MAX_URI_SIZE; crt=new_uri; len = (uri.user.len?uri.user.s:uri.host.s) - tmp; if (crt+len>end) goto error_uri; memcpy(crt,tmp,len); crt += len; /* user */ tmp = uri.user.s; len = uri.user.len; if (tmp) { if (crt+len>end) goto error_uri; memcpy(crt,tmp,len); crt += len; user = 1; } /* passwd */ tmp = uri.passwd.s; len = uri.passwd.len; if (user || tmp) { if (crt+len+1>end) goto error_uri; *crt++=':'; memcpy(crt, tmp, len); crt += len; } /* host */ if (a->type==SET_DSTHOST_T) { tmp = a->elem[0].u.s.s; len = a->elem[0].u.s.len; } else { tmp = uri.host.s; len = uri.host.len; } if (tmp) { if (user) { if (crt+1>end) goto error_uri; *crt++='@'; } if (crt+len+1>end) goto error_uri; memcpy(crt, tmp, len); crt += len; } /* port */ if (a->type==SET_DSTPORT_T) { tmp = a->elem[0].u.s.s; len = a->elem[0].u.s.len; } else { tmp = uri.port.s; len = uri.port.len; } if (tmp) { if (crt+len+1>end) goto error_uri; *crt++=':'; memcpy(crt, tmp, len); crt += len; } /* params */ tmp=uri.params.s; if (tmp){ len=uri.params.len; if(crt+len+1>end) goto error_uri; *crt++=';'; memcpy(crt,tmp,len); crt += len; } /* headers */ tmp=uri.headers.s; if (tmp){ len=uri.headers.len; if(crt+len+1>end) goto error_uri; *crt++='?'; memcpy(crt,tmp,len); crt += len; } *crt=0; /* null terminate the thing */ /* copy it to the msg */ pkg_free(msg->dst_uri.s); msg->dst_uri.s=new_uri; msg->dst_uri.len=crt-new_uri; ret = 1; break; case RESET_DSTURI_T: script_trace("core", "reset_dsturi", msg, a->line) ; if(msg->dst_uri.s!=0) pkg_free(msg->dst_uri.s); msg->dst_uri.s = 0; msg->dst_uri.len = 0; ret = 1; break; case ISDSTURISET_T: script_trace("core", "isdsturiset", msg, a->line) ; if(msg->dst_uri.s==0 || msg->dst_uri.len<=0) ret = -1; else ret = 1; break; case IF_T: script_trace("core", "if", msg, a->line) ; /* if null expr => ignore if? */ if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){ v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0); /* set return code to expr value */ if (v<0 || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ /* hack to quit on DROP*/ ret=0; return_code = 0; break; }else{ LM_WARN("error in expression (l=%d)\n", a->line); } } ret=1; /*default is continue */ if (v>0) { if ((a->elem[1].type==ACTIONS_ST)&&a->elem[1].u.data){ ret=run_action_list( (struct action*)a->elem[1].u.data,msg ); return_code = ret; } else return_code = v; }else{ if ((a->elem[2].type==ACTIONS_ST)&&a->elem[2].u.data){ ret=run_action_list( (struct action*)a->elem[2].u.data,msg); return_code = ret; } else return_code = v; } } break; case WHILE_T: script_trace("core", "while", msg, a->line) ; /* if null expr => ignore if? */ if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){ len = 0; while(1) { if(len++ >= max_while_loops) { LM_INFO("max while loops are encountered\n"); break; } v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0); /* set return code to expr value */ if (v<0 || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ ret=0; return_code = 0; break; }else{ LM_WARN("error in expression (l=%d)\n", a->line); } } ret=1; /*default is continue */ if (v>0) { if ((a->elem[1].type==ACTIONS_ST) &&a->elem[1].u.data){ ret=run_action_list( (struct action*)a->elem[1].u.data,msg ); /* check if return was done */ if ((action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ break; } return_code = ret; } else { /* we should not get here */ return_code = v; break; } } else { /* condition was false */ return_code = v; break; } } } break; case CACHE_STORE_T: script_trace("core", "cache_store", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_store() - first argument not of" " type string [%d]\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_store() - second argument not of " "type string [%d]\n", a->elem[1].type ); ret=E_BUG; break; } if ((a->elem[2].type!=STR_ST)) { LM_ALERT("BUG in cache_store() - third argument not of type" " string%d\n", a->elem[2].type ); ret=E_BUG; break; } str val_s; /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } /* parse the value argument */ pve = (pv_elem_t *)a->elem[2].u.data; if ( pv_printf_s(msg, pve, &val_s)!=0 || val_s.len == 0 || val_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } /* get the expires value */ if ( a->elem[3].type == SCRIPTVAR_ST ) { spec = (pv_spec_t*)a->elem[3].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, spec, &val) < 0) { LM_DBG("Failed to get scriptvar value while executing cache_store\n"); ret=E_BUG; break; } if (!(val.flags&PV_VAL_INT)) { LM_ERR("Wrong value for cache_store expires, not an integer [%.*s]\n", val.rs.len, val.rs.s); } expires = val.ri; } else if ( a->elem[3].type == NUMBER_ST ) { expires = (int)a->elem[3].u.number; } ret = cachedb_store( &a->elem[0].u.s, &name_s, &val_s,expires); break; case CACHE_REMOVE_T: script_trace("core", "cache_remove", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_remove() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_remove() %d\n", a->elem[1].type ); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } ret = cachedb_remove( &a->elem[0].u.s, &name_s); break; case CACHE_FETCH_T: script_trace("core", "cache_fetch", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[1].type ); ret=E_BUG; break; } if (a->elem[2].type!=SCRIPTVAR_ST){ LM_ALERT("BUG in cache_fetch() type %d\n", a->elem[2].type); ret=E_BUG; break; } str aux = {0, 0}; /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } ret = cachedb_fetch( &a->elem[0].u.s, &name_s, &aux); if(ret > 0) { val.rs = aux; val.flags = PV_VAL_STR; spec = (pv_spec_t*)a->elem[2].u.data; if (pv_set_value(msg, spec, 0, &val) < 0) { LM_ERR("cannot set the variable value\n"); pkg_free(aux.s); return -1; } pkg_free(aux.s); } break; case CACHE_COUNTER_FETCH_T: script_trace("core", "cache_counter_fetch", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[1].type ); ret=E_BUG; break; } if (a->elem[2].type!=SCRIPTVAR_ST){ LM_ALERT("BUG in cache_fetch() type %d\n", a->elem[2].type); ret=E_BUG; break; } int aux_counter; /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } ret = cachedb_counter_fetch( &a->elem[0].u.s, &name_s, &aux_counter); if(ret > 0) { val.ri = aux_counter; val.flags = PV_TYPE_INT|PV_VAL_INT; spec = (pv_spec_t*)a->elem[2].u.data; if (pv_set_value(msg, spec, 0, &val) < 0) { LM_ERR("cannot set the variable value\n"); pkg_free(aux.s); return -1; } } break; case CACHE_ADD_T: script_trace("core", "cache_add", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_add() - first argument not of" " type string [%d]\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_add() - second argument not of " "type string [%d]\n", a->elem[1].type ); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } int increment=0; /* get the increment value */ if ( a->elem[2].type == SCRIPTVAR_ST ) { spec = (pv_spec_t*)a->elem[2].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, spec, &val) < 0) { LM_DBG("Failed to get scriptvar value while executing cache_add\n"); ret=E_BUG; break; } if (!(val.flags&PV_VAL_INT)) { LM_ERR("Wrong value for cache_add, not an integer [%.*s]\n", val.rs.len, val.rs.s); } increment = val.ri; } else if ( a->elem[2].type == NUMBER_ST ) { increment = (int)a->elem[2].u.number; } expires = (int)a->elem[3].u.number; /* TODO - return the new value to script ? */ ret = cachedb_add(&a->elem[0].u.s, &name_s, increment,expires,NULL); break; case CACHE_SUB_T: script_trace("core", "cache_sub", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_sub() - first argument not of" " type string [%d]\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_sub() - second argument not of " "type string [%d]\n", a->elem[1].type ); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } int decrement=0; /* get the increment value */ if ( a->elem[2].type == SCRIPTVAR_ST ) { spec = (pv_spec_t*)a->elem[2].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, spec, &val) < 0) { LM_DBG("Failed to get scriptvar value while executing cache_sub\n"); ret=E_BUG; break; } if (!(val.flags&PV_VAL_INT)) { LM_ERR("Wrong value for cache_sub, not an integer [%.*s]\n", val.rs.len, val.rs.s); } decrement = val.ri; } else if ( a->elem[2].type == NUMBER_ST ) { decrement = (int)a->elem[2].u.number; } expires = (int)a->elem[3].u.number; /* TODO - return new value to script ? */ ret = cachedb_sub(&a->elem[0].u.s, &name_s, decrement,expires,NULL); break; case CACHE_RAW_QUERY_T: if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[1].type ); ret=E_BUG; break; } if (a->elem[2].u.data != NULL && a->elem[2].type!=STR_ST){ LM_ALERT("BUG in cache_raw_query() type %d\n", a->elem[2].type); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } cdb_raw_entry **cdb_reply; int val_number=0,i,j; int key_number=0; pvname_list_t *cdb_res,*it; int_str avp_val; int_str avp_name; unsigned short avp_type; if (a->elem[2].u.data) { cdb_res = (pvname_list_t*)a->elem[2].u.data; for (it=cdb_res;it;it=it->next) val_number++; LM_DBG("The query expects %d results back\n",val_number); ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, &cdb_reply,val_number,&key_number); if (ret >= 0 && val_number > 0) { for (i=key_number-1; i>=0;i--) { it=cdb_res; for (j=0;j < val_number;j++) { avp_type = 0; if (pv_get_avp_name(msg,&it->sname.pvp,&avp_name.n, &avp_type) != 0) { LM_ERR("cannot get avp name [%d/%d]\n",i,j); goto next_avp; } switch (cdb_reply[i][j].type) { case CDB_INT: avp_val.n = cdb_reply[i][j].val.n; break; case CDB_STR: avp_type |= AVP_VAL_STR; avp_val.s = cdb_reply[i][j].val.s; break; default: LM_WARN("Unknown type %d\n",cdb_reply[i][j].type); goto next_avp; } if (add_avp(avp_type,avp_name.n,avp_val) != 0) { LM_ERR("Unable to add AVP\n"); free_raw_fetch(cdb_reply,val_number,key_number); return -1; } next_avp: if (it) { it = it->next; if (it==NULL); break; } } } free_raw_fetch(cdb_reply,val_number,key_number); } } else ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, NULL,0,NULL); break; case XDBG_T: script_trace("core", "xdbg", msg, a->line) ; if (a->elem[0].type == SCRIPTVAR_ELEM_ST) { if (xdbg(msg, a->elem[0].u.data, val.rs.s) < 0) { LM_ALERT("Cannot print message"); break; } } else { LM_ALERT("BUG in xdbg() type %d\n", a->elem[0].type); ret=E_BUG; } break; case XLOG_T: script_trace("core", "xlog", msg, a->line) ; if (a->elem[1].u.data != NULL) { if (a->elem[1].type != SCRIPTVAR_ELEM_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[1].type); ret=E_BUG; break; } if (a->elem[0].type != STR_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (xlog_2(msg,a->elem[0].u.data, a->elem[1].u.data) < 0) { LM_ALERT("Cannot print xlog debug message"); break; } } else { if (a->elem[0].type != SCRIPTVAR_ELEM_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (xlog_1(msg,a->elem[0].u.data, val.rs.s) < 0) { LM_ALERT("Cannot print xlog debug message"); break; } } break; case RAISE_EVENT_T: script_trace("core", "raise_event", msg, a->line) ; if (a->elem[0].type != NUMBER_ST) { LM_ERR("invalid event id\n"); ret=E_BUG; break; } if (a->elem[2].u.data) { /* three parameters specified */ ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number, a->elem[1].u.data, a->elem[2].u.data); } else { /* two parameters specified */ ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number, NULL, a->elem[1].u.data); } if (ret <= 0) { LM_ERR("cannot raise event\n"); ret=E_UNSPEC; break; } break; case SUBSCRIBE_EVENT_T: script_trace("core", "subscribe_event", msg, a->line) ; if (a->elem[0].type != STR_ST || a->elem[1].type != STR_ST) { LM_ERR("BUG in subscribe arguments\n"); ret=E_BUG; break; } if (a->elem[2].u.data) { if (a->elem[2].type != NUMBER_ST) { LM_ERR("BUG in subscribe expiration time\n"); ret=E_BUG; break; } else { i = a->elem[2].u.number; } } else { i = 0; } name_s.s = a->elem[0].u.data; name_s.len = strlen(name_s.s); /* result should be the socket */ result.s = a->elem[1].u.data; result.len = strlen(result.s); ret = evi_event_subscribe(name_s, result, i, 0); break; case CONSTRUCT_URI_T: script_trace("core", "construct_uri", msg, a->line) ; for (i=0;i<5;i++) { pve = (pv_elem_t *)a->elem[i].u.data; if (pve->spec.getf) { if ( pv_printf_s(msg, pve, &vals[i])!=0 || vals[i].len == 0 || vals[i].s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; return -1; } } else vals[i] = pve->text; } result.s = construct_uri(&vals[0],&vals[1],&vals[2],&vals[3],&vals[4], &result.len); if (result.s) { int_str res; int avp_name; unsigned short avp_type; spec = (pv_spec_t*)a->elem[5].u.data; if (pv_get_avp_name( msg, &(spec->pvp), &avp_name, &avp_type)!=0){ LM_CRIT("BUG in getting AVP name\n"); return -1; } res.s = result; if (add_avp(AVP_VAL_STR|avp_type, avp_name, res)<0){ LM_ERR("cannot add AVP\n"); return -1; } } break; case GET_TIMESTAMP_T: script_trace("core", "get_timestamp", msg, a->line) ; if (get_timestamp(&sec,&usec) == 0) { int avp_name; int_str res; unsigned short avp_type; spec = (pv_spec_t*)a->elem[0].u.data; if (pv_get_avp_name(msg, &(spec->pvp), &avp_name, &avp_type) != 0) { LM_CRIT("BUG in getting AVP name\n"); return -1; } res.n = sec; if (add_avp(avp_type, avp_name, res) < 0) { LM_ERR("cannot add AVP\n"); return -1; } spec = (pv_spec_t*)a->elem[1].u.data; if (pv_get_avp_name(msg, &(spec->pvp), &avp_name, &avp_type) != 0) { LM_CRIT("BUG in getting AVP name\n"); return -1; } res.n = usec; if (add_avp(avp_type, avp_name, res) < 0) { LM_ERR("cannot add AVP\n"); return -1; } } else { LM_ERR("failed to get time\n"); return -1; } break; case SWITCH_T: script_trace("core", "switch", msg, a->line) ; if (a->elem[0].type!=SCRIPTVAR_ST){ LM_ALERT("BUG in switch() type %d\n", a->elem[0].type); ret=E_BUG; break; } spec = (pv_spec_t*)a->elem[0].u.data; if(pv_get_spec_value(msg, spec, &val)!=0) { LM_ALERT("BUG - no value in switch()\n"); ret=E_BUG; break; } /* get the value of pvar */ if(a->elem[1].type!=ACTIONS_ST) { LM_ALERT("BUG in switch() actions\n"); ret=E_BUG; break; } return_code=1; adefault = NULL; aitem = (struct action*)a->elem[1].u.data; cmatch=0; while(aitem) { if((unsigned char)aitem->type==DEFAULT_T) adefault=aitem; if(cmatch==0) { if(aitem->elem[0].type==STR_ST) { if(val.flags&PV_VAL_STR && val.rs.len==aitem->elem[0].u.s.len && strncasecmp(val.rs.s, aitem->elem[0].u.s.s, val.rs.len)==0) cmatch = 1; } else { /* number */ if(val.flags&PV_VAL_INT && val.ri==aitem->elem[0].u.number) cmatch = 1; } } if(cmatch==1) { if(aitem->elem[1].u.data) { return_code=run_action_list( (struct action*)aitem->elem[1].u.data, msg); if ((action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT)) break; } if(aitem->elem[2].u.number==1) break; } aitem = aitem->next; } if((cmatch==0) && (adefault!=NULL)) { LM_DBG("switch: running default statement\n"); if(adefault->elem[0].u.data) return_code=run_action_list( (struct action*)adefault->elem[0].u.data, msg); } ret=return_code; break; case MODULE_T: script_trace("module", ((cmd_export_t*)(a->elem[0].u.data))->name, msg, a->line) ; if ( (a->elem[0].type==CMD_ST) && a->elem[0].u.data ) { ret=((cmd_export_t*)(a->elem[0].u.data))->function(msg, (char*)a->elem[1].u.data, (char*)a->elem[2].u.data, (char*)a->elem[3].u.data, (char*)a->elem[4].u.data, (char*)a->elem[5].u.data, (char*)a->elem[6].u.data); }else{ LM_ALERT("BUG in module call\n"); } break; case FORCE_RPORT_T: script_trace("core", "force_rport", msg, a->line) ; msg->msg_flags|=FL_FORCE_RPORT; ret=1; /* continue processing */ break; case FORCE_LOCAL_RPORT_T: script_trace("core", "force_local_rport", msg, a->line) ; msg->msg_flags|=FL_FORCE_LOCAL_RPORT; ret=1; /* continue processing */ break; case SET_ADV_ADDR_T: script_trace("core", "set_adv_addr", msg, a->line) ; if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in set_advertised_address() " "type %d\n", a->elem[0].type); ret=E_BUG; break; } str adv_addr; pve = (pv_elem_t *)a->elem[0].u.data; if ( pv_printf_s(msg, pve, &adv_addr)!=0 || adv_addr.len == 0 || adv_addr.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } LM_DBG("adv address = [%.*s]\n",adv_addr.len,adv_addr.s); msg->set_global_address=adv_addr; ret=1; /* continue processing */ break; case SET_ADV_PORT_T: script_trace("core", "set_adv_port", msg, a->line) ; if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in set_advertised_port() " "type %d\n", a->elem[0].type); ret=E_BUG; break; } msg->set_global_port=*((str*)a->elem[0].u.data); ret=1; /* continue processing */ break; #ifdef USE_TCP case FORCE_TCP_ALIAS_T: script_trace("core", "force_tcp_alias", msg, a->line) ; if ( msg->rcv.proto==PROTO_TCP #ifdef USE_TLS || msg->rcv.proto==PROTO_TLS #endif ){ if (a->elem[0].type==NOSUBTYPE) port=msg->via1->port; else if (a->elem[0].type==NUMBER_ST) port=(int)a->elem[0].u.number; else{ LM_ALERT("BUG in force_tcp_alias" " port type %d\n", a->elem[0].type); ret=E_BUG; break; } if (tcpconn_add_alias(msg->rcv.proto_reserved1, port, msg->rcv.proto)!=0){ LM_ERR("tcp alias failed\n"); ret=E_UNSPEC; break; } } #endif ret=1; /* continue processing */ break; case FORCE_SEND_SOCKET_T: script_trace("core", "force_send_socket", msg, a->line) ; if (a->elem[0].type!=SOCKETINFO_ST){ LM_ALERT("BUG in force_send_socket argument" " type: %d\n", a->elem[0].type); ret=E_BUG; break; } msg->force_send_socket=(struct socket_info*)a->elem[0].u.data; ret=1; /* continue processing */ break; case SERIALIZE_BRANCHES_T: script_trace("core", "serialize_branches", msg, a->line) ; if (a->elem[0].type!=NUMBER_ST){ LM_ALERT("BUG in serialize_branches argument" " type: %d\n", a->elem[0].type); ret=E_BUG; break; } if (serialize_branches(msg,(int)a->elem[0].u.number)!=0) { LM_ERR("serialize_branches failed\n"); ret=E_UNSPEC; break; } ret=1; /* continue processing */ break; case NEXT_BRANCHES_T: script_trace("core", "next_branches", msg, a->line) ; if ((ret=next_branches(msg))<0) { LM_ERR("next_branches failed\n"); ret=E_UNSPEC; break; } /* continue processing */ break; case EQ_T: case COLONEQ_T: case PLUSEQ_T: case MINUSEQ_T: case DIVEQ_T: case MULTEQ_T: case MODULOEQ_T: case BANDEQ_T: case BOREQ_T: case BXOREQ_T: ret = do_assign(msg, a); break; case USE_BLACKLIST_T: script_trace("core", "use_blacklist", msg, a->line) ; mark_for_search((struct bl_head*)a->elem[0].u.data, 1); break; case UNUSE_BLACKLIST_T: script_trace("core", "unuse_blacklist", msg, a->line); mark_for_search((struct bl_head*)a->elem[0].u.data, 0); break; case PV_PRINTF_T: script_trace("core", "pv_printf", msg, a->line); ret = -1; spec = (pv_spec_p)a->elem[0].u.data; if(!pv_is_w(spec)) { LM_ERR("read only PV in first parameter of pv_printf\n"); goto error; } model = (pv_elem_p)a->elem[1].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_printf_s(msg, model, &val.rs)!=0) { LM_ERR("cannot eval second parameter\n"); goto error; } val.flags = PV_VAL_STR; if(pv_set_value(msg, spec, EQ_T, &val)<0) { LM_ERR("setting PV failed\n"); goto error; } ret = 1; break; case SCRIPT_TRACE_T: script_trace("core", "script_trace", msg, a->line); if (a->elem[0].type==NOSUBTYPE) { use_script_trace = 0; } else { use_script_trace = 1; if (a->elem[0].type != NUMBER_ST || a->elem[1].type != SCRIPTVAR_ELEM_ST) { LM_ERR("BUG in use_script_trace() arguments\n"); ret=E_BUG; break; } if (a->elem[2].type!=NOSUBTYPE) { script_trace_info = (char *)a->elem[2].u.data; } else { script_trace_info = NULL; } script_trace_log_level = (int)a->elem[0].u.number; script_trace_elem = *(pv_elem_p)a->elem[1].u.data; } break; default: LM_ALERT("BUG - unknown type %d\n", a->type); goto error; } if((unsigned char)a->type!=IF_T && (unsigned char)a->type!=ROUTE_T) return_code = ret; /*skip:*/ update_longest_action(); return ret; error: LM_ERR("error at line: %d\n", a->line); update_longest_action(); return ret; error_uri: LM_ERR("set*: uri too long\n"); if (new_uri) pkg_free(new_uri); update_longest_action(); return E_UNSPEC; error_fwd_uri: update_longest_action(); return ret; }
/* Actions are composed as follows: * (the action length and type as always= 5 bytes) * * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_sl_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { struct sip_msg *my_msg; str *uri; struct proxy_l *proxy; rr_t *my_route; int k,retval; //enum sip_protos proto; my_msg=NULL; k=0; proxy=0; if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){ LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type == SIP_REQUEST) LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\ my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s); else LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } my_route = (rr_t*)my_msg->route->parsed; uri=&(my_route->nameaddr.uri); }else{ uri = GET_RURI(my_msg); } set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host, my_msg->via1->port, my_msg->via1->proto) ); /* or also could be: my_msg->force_send_socket=the_as->binds[processor_id].bind_address; not sure which is better... */ /*proxy=uri2proxy(uri,PROTO_NONE); if (proxy==0) { LM_ERR("unable to create proxy from URI \n"); goto error; } proto=proxy->proto; */ //TODO my_msg->recvd if(0>forward_sl_request(my_msg,uri,PROTO_NONE)) goto error; retval=0; goto exit; error: retval = -1; exit: if(proxy){ free_proxy(proxy); pkg_free(proxy); } if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }
int t_relay_to( struct sip_msg *p_msg , struct proxy_l *proxy, int flags) { int ret; int new_tran; int reply_ret; struct cell *t; ret=0; new_tran = t_newtran( p_msg, 1/*full UAS cloning*/ ); /* parsing error, memory alloc, whatever ... */ if (new_tran<0) { ret = new_tran; goto done; } /* if that was a retransmission, break from script */ if (new_tran==0) { goto done; } /* new transaction */ /* ACKs do not establish a transaction and are fwd-ed statelessly */ if ( p_msg->REQ_METHOD==METHOD_ACK) { LM_DBG("forwarding ACK\n"); /* send it out */ if (proxy==0) { proxy=uri2proxy(GET_NEXT_HOP(p_msg), p_msg->force_send_socket ? p_msg->force_send_socket->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto done; } ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; free_proxy( proxy ); pkg_free( proxy ); } else { ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; } goto done; } /* if replication flag is set, mark the transaction as local so that replies will not be relaied */ t=get_t(); if (flags&TM_T_RELAY_repl_FLAG) t->flags|=T_IS_LOCAL_FLAG; if (flags&TM_T_RELAY_nodnsfo_FLAG) t->flags|=T_NO_DNS_FAILOVER_FLAG; if (flags&TM_T_RELAY_reason_FLAG) t->flags|=T_CANCEL_REASON_FLAG; if ((flags&TM_T_RELAY_do_cancel_dis_FLAG) && tm_has_request_disponsition_no_cancel(p_msg)==0 ) t->flags|=T_MULTI_200OK_FLAG; /* now go ahead and forward ... */ ret=t_forward_nonack( t, p_msg, proxy, 0/*no reset*/, 0/*unlocked*/); if (ret<=0) { LM_DBG("t_forward_nonack returned error \n"); /* we don't want to pass upstream any reply regarding replicating * a request; replicated branch must stop at us*/ if (!(flags&(TM_T_RELAY_repl_FLAG|TM_T_RELAY_noerr_FLAG))) { reply_ret = kill_transaction( t ); if (reply_ret>0) { /* we have taken care of all -- do nothing in script */ LM_DBG("generation of a stateful reply on error succeeded\n"); ret=0; } else { LM_DBG("generation of a stateful reply on error failed\n"); } } } else { LM_DBG("new transaction fwd'ed\n"); } done: return ret; }
int add_dest2list(int id, str uri, struct socket_info *sock, int flags, int weight, str attrs, int list_idx, int * setn) { ds_dest_p dp = NULL; ds_set_p sp = NULL; struct sip_uri puri; /* For DNS-Lookups */ struct proxy_l *proxy; union sockaddr_union sau; /* check uri */ if(parse_uri(uri.s, uri.len, &puri)!=0 || puri.host.len>254) { LM_ERR("bad uri [%.*s]\n", uri.len, uri.s); goto err; } /* get dest set */ sp = ds_lists[list_idx]; while(sp) { if(sp->id == id) break; sp = sp->next; } if(sp==NULL) { sp = (ds_set_p)shm_malloc(sizeof(ds_set_t)); if(sp==NULL) { LM_ERR("no more memory.\n"); goto err; } memset(sp, 0, sizeof(ds_set_t)); sp->next = ds_lists[list_idx]; ds_lists[list_idx] = sp; *setn = *setn+1; } sp->id = id; sp->nr++; dp = (ds_dest_p)shm_malloc(sizeof(ds_dest_t)); if(dp==NULL) { LM_ERR("no more memory!\n"); goto err; } memset(dp, 0, sizeof(ds_dest_t)); /* store uri and attrs strings */ dp->uri.s = (char*)shm_malloc( (uri.len+1+attrs.len+1)*sizeof(char)); if(dp->uri.s==NULL) { LM_ERR("no more shm memory!\n"); goto err; } memcpy(dp->uri.s, uri.s, uri.len); dp->uri.s[uri.len]='\0'; dp->uri.len = uri.len; if (attrs.len) { dp->attrs.s = dp->uri.s + dp->uri.len + 1; memcpy(dp->attrs.s, attrs.s, attrs.len); dp->attrs.s[attrs.len]='\0'; dp->attrs.len = attrs.len; } /* copy flags, weight & socket */ dp->flags = flags; dp->weight = weight; dp->sock = sock; /* Do a DNS-Lookup for the Host-Name: */ proxy = mk_proxy( &puri.host, puri.port_no, puri.proto, (puri.type==SIPS_URI_T)); if (proxy==NULL) { LM_ERR("could not resolve %.*s, skipping it\n", puri.host.len, puri.host.s); goto err; } hostent2ip_addr( &dp->ips[0], &proxy->host, proxy->addr_idx); dp->ports[0] = proxy->port; dp->ips_cnt = 1; LM_DBG("first gw ip addr [%s]:%d\n", ip_addr2a(&dp->ips[0]), dp->ports[0]); /* get the next available IPs from DNS */ while (dp->ips_cnt<DS_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &dp->ips[dp->ips_cnt], &sau); dp->ports[dp->ips_cnt] = proxy->port; LM_DBG("additional gw ip addr [%s]:%d\n", ip_addr2a(&dp->ips[dp->ips_cnt]), dp->ports[dp->ips_cnt]); /* one more IP found */ dp->ips_cnt++; } /* free al the helper structures */ free_proxy(proxy); pkg_free(proxy); dp->next = sp->dlist; sp->dlist = dp; LM_DBG("dest [%d/%d] <%.*s> successfully loaded\n", sp->id, sp->nr, dp->uri.len, dp->uri.s); return 0; err: /* free allocated memory */ if(dp!=NULL) { if(dp->uri.s!=NULL) shm_free(dp->uri.s); shm_free(dp); } return -1; }