Esempio n. 1
0
static int ki_set_source_address(sip_msg_t *msg, str *saddr)
{
	sr_phostp_t rp;
	union sockaddr_union faddr;
	char cproto;
	int ret;

	if(msg==NULL || saddr==NULL || saddr->len<=0) {
		LM_ERR("bad parameters\n");
		return -1;
	}

	if(parse_protohostport(saddr, &rp)<0) {
		LM_ERR("failed to parse the address [%.*s]\n", saddr->len, saddr->s);
		return -1;
	}

	cproto = (char)rp.proto;
	ret = sip_hostport2su(&faddr, &rp.host, (unsigned short)rp.port, &cproto);
	if(ret!=0) {
		LM_ERR("failed to resolve address [%.*s]\n", saddr->len, saddr->s);
		return -1;
	}

	msg->rcv.src_su=faddr;
	su2ip_addr(&msg->rcv.src_ip, &faddr);
	msg->rcv.src_port=rp.port;

	return 1;
}
Esempio n. 2
0
int select_next_hop_src_ip(str* res, select_t* s, struct sip_msg* msg) {
	struct socket_info* socket_info;
	union sockaddr_union to;
	char proto;
	struct sip_uri *u, next_hop;
	str *dst_host;

	if (msg->first_line.type!=SIP_REQUEST) 
		return -1;

	if (msg->force_send_socket) {
		*res = msg->force_send_socket->address_str;
		return 0;
	}

	if (msg->dst_uri.len) {
		if (parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop) < 0)
			return -1;
		u = &next_hop;
	}
	else {
		if (parse_sip_msg_uri(msg) < 0)
			return -1;
		u = &msg->parsed_uri;
	}
#ifdef USE_TLS
	if (u->type==SIPS_URI_T)
		proto = PROTO_TLS;
	else
#endif
		proto = u->proto;

#ifdef HONOR_MADDR
	if (u->maddr_val.s && u->maddr_val.len)
		dst_host = &u->maddr_val;
	else
#endif
		dst_host = &u->host;

	if (sip_hostport2su(&to, dst_host, u->port_no, &proto) < 0)
		return -1;
	socket_info = get_send_socket(msg, &to, proto);
	if (!socket_info)
		return -1;

	*res = socket_info->address_str;
	return 0;
}
Esempio n. 3
0
int mod_register(char *path, int *dlflags, void *p1, void *p2)
{
	str dest = {0};
	int ret = 0;
	struct sip_uri next_hop, *u;
	char *p;

	if(_km_log_engine_type==0 || _km_log_engine_data==0)
		return 0;


	if(strcasecmp(_km_log_engine_type, "udp")!=0)
		return 0;

	dest.s = _km_log_engine_data;
	dest.len = strlen(dest.s);

	init_dest_info(&_lc_udp_dst);

	u = &next_hop;
	u->port_no = 5060;
	u->host = dest;
	p = dest.s;
	/* detect ipv6 */
	p = memchr(p, ']', dest.len);
	if (p) p++;
	else p = dest.s;
	p = memchr(p, ':', dest.len - (p - dest.s));
	if (p) {
		u->host.len = p - dest.s;
		p++;
		u->port_no = str2s(p, dest.len - (p - dest.s), NULL);
	}

	ret = sip_hostport2su(&_lc_udp_dst.to, &u->host, u->port_no,
			&_lc_udp_dst.proto);
	if(ret!=0) {
		LM_ERR("failed to resolve [%.*s]\n", u->host.len,
				ZSW(u->host.s));
		return -1;
	}

	sr_kemi_modules_add(sr_kemi_log_custom_exports);
	return 0;
}
Esempio n. 4
0
/* forwards a request to dst
 * parameters:
 *   msg       - sip msg
 *   dst       - destination name, if non-null it will be resolved and
 *               send_info updated with the ip/port. Even if dst is non
 *               null send_info must contain the protocol and if a non
 *               default port or non srv. lookup is desired, the port must
 *               be !=0 
 *   port      - used only if dst!=0 (else the port in send_info->to is used)
 *   send_info - value/result partially filled dest_info structure:
 *                 - send_info->proto and comp are used
 *                 - send_info->to will be filled (dns)
 *                 - send_info->send_flags is filled from the message
 *                 - if the send_socket member is null, a send_socket will be 
 *                   chosen automatically
 * WARNING: don't forget to zero-fill all the  unused members (a non-zero 
 * random id along with proto==PROTO_TCP can have bad consequences, same for
 *   a bogus send_socket value)
 */
int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
							struct dest_info* send_info)
{
	unsigned int len;
	char* buf;
	char md5[MD5_LEN];
	struct socket_info* orig_send_sock; /* initial send_sock */
	int ret;
	struct ip_addr ip; /* debugging only */
	char proto;
#ifdef USE_DNS_FAILOVER
	struct socket_info* prev_send_sock;
	int err;
	struct dns_srv_handle dns_srv_h;
	
	prev_send_sock=0;
	err=0;
#endif
	
	
	buf=0;
	orig_send_sock=send_info->send_sock;
	proto=send_info->proto;
	ret=0;

	if(dst){
#ifdef USE_DNS_FAILOVER
		if (cfg_get(core, core_cfg, use_dns_failover)){
			dns_srv_handle_init(&dns_srv_h);
			err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
									&proto, dns_flags);
			if (err!=0){
				LOG(L_ERR, "ERROR: forward_request: resolving \"%.*s\""
						" failed: %s [%d]\n", dst->len, ZSW(dst->s),
						dns_strerror(err), err);
				ret=E_BAD_ADDRESS;
				goto error;
			}
		}else
#endif
		if (sip_hostport2su(&send_info->to, dst, port, &proto)<0){
			LOG(L_ERR, "ERROR: forward_request: bad host name %.*s,"
						" dropping packet\n", dst->len, ZSW(dst->s));
			ret=E_BAD_ADDRESS;
			goto error;
		}
	}/* dst */
	send_info->send_flags=msg->fwd_send_flags;
	/* calculate branch for outbound request;  if syn_branch is turned off,
	   calculate is from transaction key, i.e., as an md5 of From/To/CallID/
	   CSeq exactly the same way as TM does; good for reboot -- than messages
	   belonging to transaction lost due to reboot will still be forwarded
	   with the same branch parameter and will be match-able downstream
	
	   if it is turned on, we don't care about reboot; we simply put a simple
	   value in there; better for performance
	*/
	if (syn_branch ) {
	        memcpy(msg->add_to_branch_s, "z9hG4bKcydzigwkX", 16);
		msg->add_to_branch_len=16;
	} else {
		if (!char_msg_val( msg, md5 )) 	{ /* parses transaction key */
			LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
			ret=E_UNSPEC;
			goto error;
		}
		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
		if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */,
					msg->add_to_branch_s, &msg->add_to_branch_len )) {
			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
			ret=E_UNSPEC;
			goto error;
		}
	}
	/* try to send the message until success or all the ips are exhausted
	 *  (if dns lookup is performed && the dns cache used ) */
#ifdef USE_DNS_FAILOVER
	do{
#endif
		if (orig_send_sock==0) /* no forced send_sock => find it **/
			send_info->send_sock=get_send_socket(msg, &send_info->to, proto);
		if (send_info->send_sock==0){
			LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
						"no corresponding listening socket\n",
						send_info->to.s.sa_family, proto);
			ret=ser_error=E_NO_SOCKET;
#ifdef USE_DNS_FAILOVER
			/* continue, maybe we find a socket for some other ip */
			continue;
#else
			goto error;
#endif
		}
	
#ifdef USE_DNS_FAILOVER
		if (prev_send_sock!=send_info->send_sock){
			/* rebuild the message only if the send_sock changed */
			prev_send_sock=send_info->send_sock;
#endif
			if (buf) pkg_free(buf);
			send_info->proto=proto;
			buf = build_req_buf_from_sip_req(msg, &len, send_info, 0);
			if (!buf){
				LOG(L_ERR, "ERROR: forward_request: building failed\n");
				ret=E_OUT_OF_MEM; /* most probable */
				goto error;
			}
#ifdef USE_DNS_FAILOVER
		}
#endif
		 /* send it! */
		DBG("Sending:\n%.*s.\n", (int)len, buf);
		DBG("orig. len=%d, new_len=%d, proto=%d\n",
				msg->len, len, send_info->proto );
	
		if (run_onsend(msg, send_info, buf, len)==0){
			su2ip_addr(&ip, &send_info->to);
			LOG(L_INFO, "forward_request: request to %s:%d(%d) dropped"
					" (onsend_route)\n", ip_addr2a(&ip),
						su_getport(&send_info->to), send_info->proto);
			ser_error=E_OK; /* no error */
			ret=E_ADM_PROHIBITED;
#ifdef USE_DNS_FAILOVER
			continue; /* try another ip */
#else
			goto error; /* error ? */
#endif
		}
#ifdef USE_DST_BLACKLIST
		if (cfg_get(core, core_cfg, use_dst_blacklist)){
			if (dst_is_blacklisted(send_info, msg)){
				su2ip_addr(&ip, &send_info->to);
				LOG(L_DBG, "DEBUG: blacklisted destination:%s:%d (%d)\n",
							ip_addr2a(&ip), su_getport(&send_info->to),
							send_info->proto);
				ret=ser_error=E_SEND;
#ifdef USE_DNS_FAILOVER
				continue; /* try another ip */
#else
				goto error;
#endif
			}
		}
#endif
		if (msg_send(send_info, buf, len)<0){
			ret=ser_error=E_SEND;
#ifdef USE_DST_BLACKLIST
			(void)dst_blacklist_add(BLST_ERR_SEND, send_info, msg);
#endif
#ifdef USE_DNS_FAILOVER
			continue; /* try another ip */
#else
			goto error;
#endif
		}else{
			ret=ser_error=E_OK;
			/* sent requests stats */
			STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
			/* exit succcesfully */
			goto end;
		}
#ifdef USE_DNS_FAILOVER
	}while(dst && cfg_get(core, core_cfg, use_dns_failover) &&
			dns_srv_handle_next(&dns_srv_h, err) && 
			((err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
										&proto, dns_flags))==0));
	if ((err!=0) && (err!=-E_DNS_EOR)){
		LOG(L_ERR, "ERROR:  resolving %.*s host name in uri"
							" failed: %s [%d] (dropping packet)\n",
									dst->len, ZSW(dst->s),
									dns_strerror(err), err);
		ret=ser_error=E_BAD_ADDRESS;
		goto error;
	}
#endif
	
error:
	STATS_TX_DROPS;
end:
#ifdef USE_DNS_FAILOVER
	if (dst && cfg_get(core, core_cfg, use_dns_failover)){
				dns_srv_handle_put(&dns_srv_h);
	}
#endif
	if (buf) pkg_free(buf);
	/* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
#if defined STATS_REQ_FWD_OK || defined STATS_REQ_FWD_DROP
	if(ret==0)
		STATS_REQ_FWD_OK();
	else
		STATS_REQ_FWD_DROP();
#endif /* STATS_REQ_FWD_* */
	return ret;
}
Esempio n. 5
0
int corex_send_data(str *puri, str *pdata)
{
	struct dest_info dst;
	sip_uri_t next_hop;
	int ret = 0;
	char proto;

	if(parse_uri(puri->s, puri->len, &next_hop)<0)
	{
		LM_ERR("bad dst sip uri <%.*s>\n", puri->len, puri->s);
		return -1;
	}

	init_dest_info(&dst);
	LM_DBG("sending data to sip uri <%.*s>\n", puri->len, puri->s);
	proto = next_hop.proto;
	if(sip_hostport2su(&dst.to, &next_hop.host, next_hop.port_no,
				&proto)!=0) {
		LM_ERR("failed to resolve [%.*s]\n", next_hop.host.len,
			ZSW(next_hop.host.s));
		return -1;
	}
	dst.proto = proto;
	if(dst.proto==PROTO_NONE) dst.proto = PROTO_UDP;

	if (dst.proto == PROTO_UDP)
	{
		dst.send_sock=get_send_socket(0, &dst.to, PROTO_UDP);
		if (dst.send_sock!=0) {
			ret=udp_send(&dst, pdata->s, pdata->len);
		} else {
			LM_ERR("no socket for dst sip uri <%.*s>\n", puri->len, puri->s);
			ret=-1;
		}
	}
#ifdef USE_TCP
	else if(dst.proto == PROTO_TCP) {
		/*tcp*/
		dst.id=0;
		ret=tcp_send(&dst, 0, pdata->s, pdata->len);
	}
#endif
#ifdef USE_TLS
	else if(dst.proto == PROTO_TLS) {
		/*tls*/
		dst.id=0;
		ret=tcp_send(&dst, 0, pdata->s, pdata->len);
	}
#endif
#ifdef USE_SCTP
	else if(dst.proto == PROTO_SCTP) {
		/*sctp*/
		dst.send_sock=get_send_socket(0, &dst.to, PROTO_SCTP);
		if (dst.send_sock!=0) {
			ret=sctp_core_msg_send(&dst, pdata->s, pdata->len);
		} else {
			LM_ERR("no socket for dst sip uri <%.*s>\n", puri->len, puri->s);
			ret=-1;
		}
	}
#endif
	else {
		LM_ERR("unknown proto [%d] for dst sip uri <%.*s>\n",
				dst.proto, puri->len, puri->s);
		ret=-1;
	}

	if (ret>=0) ret=1;

	return ret;
}
Esempio n. 6
0
int corex_send(sip_msg_t *msg, gparam_t *pu, enum sip_protos proto)
{
	str dest = {0};
	int ret = 0;
	struct sip_uri next_hop, *u;
	struct dest_info dst;
	char *p;

	if (pu)
	{
		if (fixup_get_svalue(msg, pu, &dest))
		{
			LM_ERR("cannot get the destination parameter\n");
			return -1;
		}
	}

	init_dest_info(&dst);

	if (dest.len <= 0)
	{
		/*get next hop uri 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) {
			LM_ERR("send() - bad_uri dropping packet\n");
			ret=E_BUG;
			goto error;
		}
	} else {
		u = &next_hop;
		u->port_no = 5060;
		u->host = dest;
		/* detect ipv6 */
		p = memchr(dest.s, ']', dest.len);
		if (p) {
			p++;
			p = memchr(p, ':', dest.s + dest.len - p);
		} else {
			p = memchr(dest.s, ':', dest.len);
		}
		if (p)
		{
			u->host.len = p - dest.s;
			p++;
			u->port_no = str2s(p, dest.len - (p - dest.s), NULL);
		}
	}

	ret = sip_hostport2su(&dst.to, &u->host, u->port_no,
				&dst.proto);
	if(ret!=0) {
		LM_ERR("failed to resolve [%.*s]\n", u->host.len,
			ZSW(u->host.s));
		ret=E_BUG;
		goto error;
	}

	dst.proto = proto;
	if (proto == PROTO_UDP)
	{
		dst.send_sock=get_send_socket(msg, &dst.to, PROTO_UDP);
		if (dst.send_sock!=0){
			ret=udp_send(&dst, msg->buf, msg->len);
		}else{
			ret=-1;
		}
	}
#ifdef USE_TCP
	else{
		/*tcp*/
		dst.id=0;
		ret=tcp_send(&dst, 0, msg->buf, msg->len);
	}
#endif

	if (ret>=0) ret=1;


error:
	return ret;
}
Esempio n. 7
0
struct dest_info *msrp_uri_to_dstinfo(struct dns_srv_handle* dns_h,
		struct dest_info* dst, struct socket_info *force_send_socket,
		snd_flags_t sflags, str *uri)
{
	msrp_uri_t parsed_uri;
	str* host;
	int port;
	int ip_found;
	union sockaddr_union to;
	int err;

	init_dest_info(dst);

	if (msrp_parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
		LM_ERR("bad msrp uri: %.*s\n", uri->len, uri->s );
		return 0;
	}
	
	if (parsed_uri.scheme_no==MSRP_SCHEME_MSRPS){
		dst->proto = PROTO_TLS;
	} else {
		dst->proto = PROTO_TCP;
	}
	
	dst->send_flags=sflags;
	host=&parsed_uri.host;
	port = parsed_uri.port_no;

	if (dns_h && cfg_get(core, core_cfg, use_dns_failover)){
		ip_found=0;
		do{
			/* try all the ips until we find a good send socket */
			err=dns_sip_resolve2su(dns_h, &to, host,
								port, &dst->proto, dns_flags);
			if (err!=0){
				if (ip_found==0){
					if (err!=-E_DNS_EOR)
						LM_ERR("failed to resolve \"%.*s\" :"
								"%s (%d)\n", host->len, ZSW(host->s),
									dns_strerror(err), err);
					return 0; /* error, no ip found */
				}
				break;
			}
			if (ip_found==0){
				dst->to=to;
				ip_found=1;
			}
			dst->send_sock = get_send_socket2(force_send_socket, &to,
												dst->proto, 0);
			if (dst->send_sock){
				dst->to=to;
				return dst; /* found a good one */
			}
		} while(dns_srv_handle_next(dns_h, err));
		ERR("no corresponding socket for \"%.*s\" af %d\n", host->len, 
				ZSW(host->s), dst->to.s.sa_family);
		/* try to continue */
		return dst;
	}

	if (sip_hostport2su(&dst->to, host, port, &dst->proto)!=0){
		ERR("failed to resolve \"%.*s\"\n", host->len, ZSW(host->s));
		return 0;
	}
	dst->send_sock = get_send_socket2(force_send_socket, &dst->to,
			dst->proto, 0);
	if (dst->send_sock==0) {
		ERR("no corresponding socket for af %d\n", dst->to.s.sa_family);
		/* try to continue */
	}
	return dst;
}