Esempio n. 1
0
/** initializes a net structure from a string.
 * @param dst - net structure that will be filled
 * @param s - string of the form "ip", "ip/mask_len" or "ip/ip_mak".
 * @return -1 on error, 0 on succes
 */
int mk_net_str(struct net* dst, str* s)
{
	struct ip_addr* t;
	char* p;
	struct ip_addr ip;
	str addr;
	str mask;
	unsigned int bitlen;
	
	/* test for ip only */
	t = str2ip(s);
	if (unlikely(t == 0))
		t = str2ip6(s);
	if (likely(t))
		return mk_net_bitlen(dst, t, t->len*8);
	/* not a simple ip, maybe an ip/netmask pair */
	p = q_memchr(s->s, '/', s->len);
	if (likely(p)) {
		addr.s = s->s;
		addr.len = (int)(long)(p - s->s);
		mask.s = p + 1;
		mask.len = s->len - (addr.len + 1);
		/* allow '/' enclosed by whitespace */
		trim_trailing(&addr);
		trim_leading(&mask);
		t = str2ip(&addr);
		if (likely(t)) {
			/* it can be a number */
			if (str2int(&mask, &bitlen) == 0)
				return mk_net_bitlen(dst, t, bitlen);
			ip = *t;
			t = str2ip(&mask);
			if (likely(t))
				return mk_net(dst, &ip, t);
			/* error */
			return -1;
		}
		else {
			t = str2ip6(&addr);
			if (likely(t)) {
				/* it can be a number */
				if (str2int(&mask, &bitlen) == 0)
					return mk_net_bitlen(dst, t, bitlen);
				ip = *t;
				t = str2ip6(&mask);
				if (likely(t))
					return mk_net(dst, &ip, t);
				/* error */
				return -1;
			}
		}
	}
	return -1;
}
Esempio n. 2
0
/* Adds a new entry to the blacklist */
void dst_blst_add(rpc_t* rpc, void* ctx)
{
	str ip;
	int port, proto, flags;
	unsigned char err_flags;
	struct ip_addr *ip_addr;

	if (!cfg_get(core, core_cfg, use_dst_blacklist)){
		rpc->fault(ctx, 500, "dst blacklist support disabled");
		return;
	}
	if (rpc->scan(ctx, "Sddd", &ip, &port, &proto, &flags) < 4)
		return;

	err_flags = (unsigned char)flags;
	/* sanity checks */
	if ((unsigned char)proto > PROTO_SCTP) {
		rpc->fault(ctx, 400, "Unknown protocol");
		return;
	}

	if (err_flags & BLST_IS_IPV6) {
#ifdef USE_IPV6
		/* IPv6 address is specified */
		ip_addr = str2ip6(&ip);
#else  /* USE_IPV6 */
		rpc->fault(ctx, 400, "IPv6 support disabled");
		return;
#endif /* USE_IPV6 */
	} else {
		/* try IPv4 first, than IPv6 */
		ip_addr = str2ip(&ip);
		if (!ip_addr) {
#ifdef USE_IPV6
			ip_addr = str2ip6(&ip);
			err_flags |= BLST_IS_IPV6;
#else  /* USE_IPV6 */
			rpc->fault(ctx, 400, "Malformed or IPv6 ip address");
			return;
#endif /* USE_IPV6 */
		}
	}
	if (!ip_addr) {
		rpc->fault(ctx, 400, "Malformed ip address");
		return;
	}

	if (dst_blacklist_add_ip(err_flags, proto, ip_addr, port, 
				    S_TO_TICKS(cfg_get(core, core_cfg, blst_timeout))))
		rpc->fault(ctx, 400, "Failed to add the entry to the blacklist");
}
Esempio n. 3
0
static int parse_ipv6(struct ip_addr* ip, cfg_token_t* token, 
					  cfg_parser_t* st)
{
	int ret;
	cfg_token_t t;
	struct ip_addr* ipv6;
	str ip6_str;

	while(1) {
		ret = cfg_get_token(&t, st, 0);
		if (ret != 0) goto err;
		if (t.type == ']') break;
		if (t.type != CFG_TOKEN_ALPHA && t.type != ':') goto err;
	}
	ip6_str.s = t.val.s;
	ip6_str.len = (int)(long)(t.val.s - ip6_str.s);

	ipv6 = str2ip6(&ip6_str);
	if (ipv6 == 0) goto err;
	*ip = *ipv6;
	return 0;

 err:
	ERR("%s:%d:%d: Invalid IPv6 address\n", 
	    st->file, token->start.line, token->start.col);
	return -1;
}
Esempio n. 4
0
static int parse_ipv6(struct ip_addr* ip, cfg_token_t* token,
		cfg_parser_t* st)
{
	int ret;
	cfg_token_t t;
	struct ip_addr* ipv6;
	str ip6_str;
	char ip6_buff[IP_ADDR_MAX_STR_SIZE+3];

	ip6_buff[0] = '\0';
	while(1) {
		ret = cfg_get_token(&t, st, 0);
		if (ret != 0) goto err;
		if (t.type == ']') break;
		if (t.type != CFG_TOKEN_ALPHA && t.type != ':') goto err;
		strncat(ip6_buff, t.val.s, t.val.len);
	}
	ip6_str.s = ip6_buff;
	ip6_str.len = strlen(ip6_buff);
	LM_DBG("found IPv6 address [%.*s]\n", ip6_str.len, ip6_str.s);
	ipv6 = str2ip6(&ip6_str);
	if (ipv6 == 0) goto err;
	*ip = *ipv6;
	return 0;

err:
	LM_ERR("%s:%d:%d: Invalid IPv6 address\n",
			st->file, token->start.line, token->start.col);
	return -1;
}
Esempio n. 5
0
/** internal sip naptr resolver function: resolves a host name trying:
 * - NAPTR lookup if the address is not an ip and *proto==0 and *port==0.
 *   The result of the NAPTR query will be used for a SRV lookup
 * - SRV lookup if the address is not an ip *port==0. The result of the SRV
 *   query will be used for an A/AAAA lookup.
 *  - normal A/AAAA lookup (either fallback from the above or if *port!=0
 *   and *proto!=0 or port==0 && proto==0)
 * when performing SRV lookup (*port==0) it will use proto to look for
 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
 * returns: hostent struct & *port filled with the port from the SRV record;
 *  0 on error
 */
struct hostent* naptr_sip_resolvehost(str* name,  unsigned short* port,
										char* proto)
{
	struct hostent* he;
	struct ip_addr* ip;
	static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups and
	                                  null. term  strings */
	struct rdata* l;
	struct rdata* naptr_head;
	char n_proto;
	str srv_name;
	naptr_bmp_t tried_bmp; /* tried bitmap */
	char origproto;

	if(proto) origproto = *proto;
	naptr_head=0;
	he=0;
	if (name->len >= MAX_DNS_NAME) {
		LM_ERR("domain name too long\n");
		goto end;
	}
	/* try NAPTR if no port or protocol is specified and NAPTR lookup is
	 * enabled */
	if (port && proto && (*proto==0) && (*port==0)){
		*proto=PROTO_UDP; /* just in case we don't find another */
		if ( ((ip=str2ip(name))!=0)
			  || ((ip=str2ip6(name))!=0)
		){
			/* we are lucky, this is an ip address */
			he=ip_addr2he(name,ip);
			*port=SIP_PORT;
			goto end;
		}
		memcpy(tmp, name->s, name->len);
		tmp[name->len] = '\0';
		naptr_head=get_record(tmp, T_NAPTR, RES_AR);
		naptr_iterate_init(&tried_bmp);
		while((l=naptr_sip_iterate(naptr_head, &tried_bmp,
										&srv_name, &n_proto))!=0){
			if ((he=srv_sip_resolvehost(&srv_name, 1, port, proto, 1, l))!=0){
				*proto=n_proto;
				return he;
			}
		}
		/*clean up on exit*/
		LM_DBG("no NAPTR record found for %.*s, trying SRV lookup...\n",
					name->len, name->s);
	}
	/* fallback to srv lookup */
	if(proto) *proto = origproto;
	he=no_naptr_srv_sip_resolvehost(name,port,proto);
	/* fallback all the way down to A/AAAA */
	if (he==0) {
		he=dns_get_he(name,dns_flags);
	}
end:
	if (naptr_head)
		free_rdata_list(naptr_head);
	return he;
}
Esempio n. 6
0
static inline ip_addr_t *strtoipX(str *ips)
{
	/* try to figure out INET class */
	if(ips->s[0] == '[' || memchr(ips->s, ':', ips->len)!=NULL)
	{
		/* IPv6 */
		return str2ip6(ips);
	} else {
		/* IPv4 */
		return str2ip(ips);
	}
}
Esempio n. 7
0
/**
 * Evaluate if next hop is a strict or loose router, by looking at the
 * retr. buffer of the original INVITE.
 * Assumes:
 * 	orig_inv is a parsed SIP message;
 * 	rtset is not NULL.
 * @return:
 * 	F_RB_NH_LOOSE : next hop was loose router;
 * 	F_RB_NH_STRICT: nh is strict;
 * 	0 on error.
 */
static unsigned long nhop_type(sip_msg_t *orig_inv, rte_t *rtset,
		const struct dest_info *dst_inv, str *contact)
{
	struct sip_uri puri, topr_uri, lastr_uri, inv_ruri, cont_uri;
	struct ip_addr *uri_ia;
	union sockaddr_union uri_sau;
	unsigned int uri_port, dst_port, inv_port, cont_port, lastr_port;
	rte_t *last_r;
#ifdef TM_LOC_ACK_DO_REV_DNS
	struct ip_addr ia;
	struct hostent *he;
	char **alias;
#endif

#define PARSE_URI(_str_, _uri_) \
	do { \
		/* parse_uri() 0z the puri */ \
		if (parse_uri((_str_)->s, \
				(_str_)->len, _uri_) < 0) { \
			LM_ERR("failed to parse route body '%.*s'.\n", STR_FMT(_str_)); \
			return 0; \
		} \
	} while (0)

#define HAS_LR(_rte_) \
	({ \
		PARSE_URI(&(_rte_)->ptr->nameaddr.uri, &puri); \
		puri.lr.s; \
	})

#define URI_PORT(_puri_, _port) \
	do { \
		if (! (_port = uri2port(_puri_))) \
			return 0; \
	} while (0)

	/* examine the easy/fast & positive cases foremost */

	/* [1] check if 1st route lacks ;lr */
	LM_DBG("checking lack of ';lr' in 1st route.\n");
	if (! HAS_LR(rtset))
		return F_RB_NH_STRICT;
	topr_uri = puri; /* save 1st route's URI */

	/* [2] check if last route shows ;lr */
	LM_DBG("checking presence of ';lr' in last route.\n");
	for (last_r = rtset; last_r->next; last_r = last_r->next)
		/* scroll down to last route */
		;
	if (HAS_LR(last_r))
		return F_RB_NH_LOOSE;

	/* [3] 1st route has ;lr -> check if the destination of original INV
	 * equals the address provided by this route; if does -> loose */
	LM_DBG("checking INVITE's destination against its first route.\n");
	URI_PORT(&topr_uri, uri_port);
	if (! (dst_port = su_getport(&dst_inv->to)))
		return 0; /* not really expected */
	if (dst_port != uri_port)
		return F_RB_NH_STRICT;
	/* if 1st route contains an IP address, comparing it against .dst */
	if ((uri_ia = str2ip(&topr_uri.host))
			|| (uri_ia = str2ip6(&topr_uri.host))
			) {
		/* we have an IP address in route -> comparison can go swiftly */
		if (init_su(&uri_sau, uri_ia, uri_port) < 0)
			return 0; /* not really expected */
		if (su_cmp(&uri_sau, &dst_inv->to))
			/* ;lr and sent there */
			return F_RB_NH_LOOSE;
		else
			/* ;lr and NOT sent there (probably sent to RURI address) */
			return F_RB_NH_STRICT;
	} else {
		/*if 1st route contains a name, rev resolve the .dst and compare*/
		LM_INFO("Failed to decode string '%.*s' in route set element as IP"
				" address. Trying name resolution.\n",STR_FMT(&topr_uri.host));

	/* TODO: alternatively, rev name and compare against dest. IP.  */
#ifdef TM_LOC_ACK_DO_REV_DNS
		ia.af = 0;
		su2ip_addr(&ia, (void *)&dst_inv->to);
		if (! ia.af)
			return 0; /* not really expected */
		if ((he = rev_resolvehost(&ia))) {
			if ((strlen(he->h_name) == topr_uri.host.len) &&
					(memcmp(he->h_name, topr_uri.host.s,
							topr_uri.host.len) == 0))
				return F_RB_NH_LOOSE;
			for (alias = he->h_aliases; *alias; alias ++)
				if ((strlen(*alias) == topr_uri.host.len) &&
						(memcmp(*alias, topr_uri.host.s,
								topr_uri.host.len) == 0))
					return F_RB_NH_LOOSE;
			return F_RB_NH_STRICT;
		} else {
			LM_INFO("failed to resolve address '%s' to a name.\n",
					ip_addr2a(&ia));
		}
#endif
	}

	LM_WARN("failed to establish with certainty the type of next hop;"
			" trying an educated guess.\n");

	/* [4] compare (possibly updated) remote target to original RURI; if
	 * equal, a strict router's address wasn't filled in as RURI -> loose */
	LM_DBG("checking remote target against INVITE's RURI.\n");
	PARSE_URI(contact, &cont_uri);
	PARSE_URI(GET_RURI(orig_inv), &inv_ruri);
	URI_PORT(&cont_uri, cont_port);
	URI_PORT(&inv_ruri, inv_port);
	if ((cont_port == inv_port) && (cont_uri.host.len == inv_ruri.host.len) &&
			(memcmp(cont_uri.host.s, inv_ruri.host.s, cont_uri.host.len) == 0))
		return F_RB_NH_LOOSE;

	/* [5] compare (possibly updated) remote target to last route; if equal,
	 * strict router's address might have been filled as RURI and remote
	 * target appended to route set -> strict */
	LM_DBG("checking remote target against INVITE's last route.\n");
	PARSE_URI(&last_r->ptr->nameaddr.uri, &lastr_uri);
	URI_PORT(&lastr_uri, lastr_port);
	if ((cont_port == lastr_port) &&
			(cont_uri.host.len == lastr_uri.host.len) &&
			(memcmp(cont_uri.host.s, lastr_uri.host.s,
					lastr_uri.host.len) == 0))
		return F_RB_NH_STRICT;

	LM_WARN("failed to establish the type of next hop;"
			" assuming loose router.\n");
	return F_RB_NH_LOOSE;

#undef PARSE_URI
#undef HAS_LR
#undef URI_PORT
}
Esempio n. 8
0
/*! \brief Initialize sipcapture module */
static int mod_init(void) {

	struct ip_addr *ip = NULL;

#ifdef STATISTICS
	/* register statistics */
	if (register_module_stats(exports.name, sipcapture_stats)!=0)
	{
		LM_ERR("failed to register core statistics\n");
		return -1;
	}
#endif

	if(register_mi_mod(exports.name, mi_cmds)!=0)
	{
		LM_ERR("failed to register MI commands\n");
		return -1;
	}
	if(sipcapture_init_rpc()!=0)
	{
		LM_ERR("failed to register RPC commands\n");
		return -1;
	}

	db_url.len = strlen(db_url.s);
	table_name.len = strlen(table_name.s);
	hash_source.len = strlen (hash_source.s);
	mt_mode.len = strlen(mt_mode.s);
	date_column.len = strlen(date_column.s);
	micro_ts_column.len = strlen(micro_ts_column.s);
	method_column.len = strlen(method_column.s); 	
	reply_reason_column.len = strlen(reply_reason_column.s);        
	ruri_column.len = strlen(ruri_column.s);     	
	ruri_user_column.len = strlen(ruri_user_column.s);  
	from_user_column.len = strlen(from_user_column.s);  
	from_tag_column.len = strlen(from_tag_column.s);   
	to_user_column.len = strlen(to_user_column.s);
	pid_user_column.len = strlen(pid_user_column.s);
	contact_user_column.len = strlen(contact_user_column.s);
	auth_user_column.len = strlen(auth_user_column.s);  
	callid_column.len = strlen(callid_column.s);
	via_1_column.len = strlen(via_1_column.s);      
	via_1_branch_column.len = strlen(via_1_branch_column.s); 
	cseq_column.len = strlen(cseq_column.s);     
	diversion_column.len = strlen(diversion_column.s); 
	reason_column.len = strlen(reason_column.s);        
	content_type_column.len = strlen(content_type_column.s);  
	authorization_column.len = strlen(authorization_column.s); 
	user_agent_column.len = strlen(user_agent_column.s);
	source_ip_column.len = strlen(source_ip_column.s);  
	source_port_column.len = strlen(source_port_column.s);	
	dest_ip_column.len = strlen(dest_ip_column.s);
	dest_port_column.len = strlen(dest_port_column.s);		
	contact_ip_column.len = strlen(contact_ip_column.s); 
	contact_port_column.len = strlen(contact_port_column.s);
	orig_ip_column.len = strlen(orig_ip_column.s);      
	orig_port_column.len = strlen(orig_port_column.s);    
	proto_column.len = strlen(proto_column.s); 
	family_column.len = strlen(family_column.s); 
	type_column.len = strlen(type_column.s);  
	rtp_stat_column.len = strlen(rtp_stat_column.s);  
	node_column.len = strlen(node_column.s);  
	msg_column.len = strlen(msg_column.s);   
	capture_node.len = strlen(capture_node.s);     	
	
	if(raw_socket_listen.s) 
		raw_socket_listen.len = strlen(raw_socket_listen.s);     	
	if(raw_interface.s)
		raw_interface.len = strlen(raw_interface.s);     	

	/* Find a database module */
	if (db_bind_mod(&db_url, &db_funcs))
	{
		LM_ERR("unable to bind database module\n");
		return -1;
	}
	if (!DB_CAPABILITY(db_funcs, DB_CAP_INSERT))
	{
		LM_ERR("database modules does not provide all functions needed"
				" by module\n");
		return -1;
	}

	/*Check the table name*/
	if(!table_name.len) {	
		LM_ERR("ERROR: sipcapture: mod_init: table_name is not defined or empty\n");
		return -1;
	}

	if (mt_init () <0)
	{
		return -1;
	}


	if(db_insert_mode) {
                LM_INFO("INFO: sipcapture: mod_init: you have enabled INSERT DELAYED \
                                Make sure your DB can support it\n");
        }

	capture_on_flag = (int*)shm_malloc(sizeof(int));
	if(capture_on_flag==NULL) {
		LM_ERR("no more shm memory left\n");
		return -1;
	}
	
	*capture_on_flag = capture_on;
	
	/* register DGRAM event */
	if(sr_event_register_cb(SREV_NET_DGRAM_IN, hep_msg_received) < 0) {
		LM_ERR("failed to register SREV_NET_DGRAM_IN event\n");
		return -1;		                	
	}

	if(ipip_capture_on && moni_capture_on) {
		LM_ERR("only one RAW mode is supported. Please disable ipip_capture_on or moni_capture_on\n");
		return -1;		                		
	}
	


	/* raw processes for IPIP encapsulation */
	if (ipip_capture_on || moni_capture_on) {
		register_procs(raw_sock_children);
		                		
		if(extract_host_port() && (((ip=str2ip(&raw_socket_listen)) == NULL)
#ifdef  USE_IPV6
		               && ((ip=str2ip6(&raw_socket_listen)) == NULL)
#endif
		         )) 
		{		
			LM_ERR("sipcapture mod_init: bad RAW IP: %.*s\n", raw_socket_listen.len, raw_socket_listen.s); 
			return -1;
		}		
			
        	if(moni_capture_on && !moni_port_start) {
	        	LM_ERR("ERROR:sipcapture:mod_init: Please define port/portrange in 'raw_socket_listen', before \
	        	                        activate monitoring capture\n");
        		return -1;		                		
                }			
Esempio n. 9
0
/*!
 * \brief Convert a STR [proto:]ip[:port] into socket address.
 * [proto:]ip[:port]
 * \param pipport (udp:127.0.0.1:5060 or tcp:2001:0DB8:AC10:FE01:5060)
 * \param tmp_su target structure
 * \param proto uint protocol type
 * \return success / unsuccess
 */
static int pipport2su (str *sproto, str *ip, unsigned short port,
			union sockaddr_union *tmp_su, unsigned int *proto)
{
	struct ip_addr *ip_a;
	str host_uri;

	/*parse protocol */
	if(strncmp(sproto->s, "udp",3) == 0) *proto = IPPROTO_UDP;
	else if(strncmp(sproto->s, "tcp",3) == 0) *proto = IPPROTO_TCP;
	else if(strncmp(sproto->s, "tls",3) == 0) *proto = IPPROTO_IDP;
												/* fake proto type */
	else if(strncmp(sproto->s, "sctp",4) == 0) *proto = IPPROTO_SCTP;
	else if(strncmp(sproto->s, "any",3) == 0) *proto = IPPROTO_UDP;
	else if(strncmp(sproto->s, "ws",2) == 0) *proto = IPPROTO_ESP;
												/* fake proto type */
	else {
		LM_ERR("bad protocol %.*s\n", sproto->len, sproto->s);
		return -1;
	}

	/*check if ip is not null*/
	if (ip->len == 0) {
		LM_ERR("malformed ip address\n");
		return -1;
	}

	if (port == 0) {
		port = SIP_PORT;
	}
	else{
	/*the address contains a port number*/
		if (port<1024  || port>65536)
		{
			LM_ERR("invalid port number; must be in [1024,65536]\n");
			return -1;
		}
	}
	LM_DBG("proto %d, host %.*s , port %d \n",*proto, ip->len, ip->s, port);

	/* now IPv6 address has no brakets. It should be fixed! */
	host_uri = *ip;
	if (host_uri.s[0] == '[') {
		if(host_uri.s[host_uri.len-1] != ']') {
			LM_ERR("bracket not closed\n");
			return -1;
		}
		host_uri.s++;
		host_uri.len -= 2;
	}

	/* check if it's an ip address */
	if (((ip_a = str2ip(&host_uri)) != 0)
			|| ((ip_a = str2ip6 (&host_uri)) != 0)
	) {
		ip_addr2su(tmp_su, ip_a, ntohs(port));
		return 0;
	}

	LM_ERR("host <%.*s> is not an IP\n",host_uri.len,host_uri.s);
	return -1;
}
Esempio n. 10
0
static int w_lb_count_call(struct sip_msg *req, char *ip, char *port, char *grp,
			char *rl, char *dir)
{
	struct lb_grp_param *lbgp = (struct lb_grp_param *)grp;
	struct lb_res_str_list *lb_rl;
	struct lb_res_parse *lbp;
	struct ip_addr *ipa;
	pv_value_t val;
	pv_elem_t *model;
	int grp_no;
	int port_no;
	str dest;
	int ret;

	/* get the ip address */
	if (pv_get_spec_value( req, (pv_spec_t*)ip, &val)!=0) {
		LM_ERR("failed to get IP value from PV\n");
		return -1;
	}
	if ( (val.flags&PV_VAL_STR)==0 ) {
		LM_ERR("IP PV val is not string\n");
		return -1;
	}
	if ( (ipa=str2ip( &val.rs ))==NULL && (ipa=str2ip6( &val.rs ))==NULL) {
		LM_ERR("IP val is not IP <%.*s>\n",val.rs.len,val.rs.s);
		return -1;
	}

	/* get the port */
	if (port) {
		if (fixup_get_ivalue( req, (gparam_p)port, &port_no)!=0) {
			LM_ERR("failed to get PORT value from PV\n");
			return -1;
		}
	} else {
		port_no = 0;
	}

	/* get the group */
	if (lbgp->grp_pv) {
		if (pv_get_spec_value( req, (pv_spec_p)lbgp->grp_pv, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_INT)==0 ) {
			LM_ERR("PV vals is not integer\n");
			return -1;
		}
		grp_no = val.ri;
	} else {
		grp_no = lbgp->grp_no;
	}

	/* get the resources list */
	lbp = (struct lb_res_parse *)rl;
	if (lbp->type & RES_ELEM) {
		model = (pv_elem_p)lbp->param;
		if (pv_printf_s(req, model, &dest) || dest.len <= 0) {
			LM_ERR("cannot create resource string\n");
			return -1;
		}
		lb_rl = parse_resources_list(dest.s, 0);
		if (!lb_rl) {
			LM_ERR("cannot create resource list\n");
			return -1;
		}
	} else
		lb_rl = (struct lb_res_str_list *)lbp->param;

	lock_start_read( ref_lock );

	ret = lb_count_call( *curr_data, req, ipa, port_no, grp_no, lb_rl,
			dir ? (int)*(unsigned int *)dir : 0);

	lock_stop_read( ref_lock );

	if (lbp->type & RES_ELEM)
		pkg_free(lb_rl);

	if (ret<0)
		return ret;
	return 1;
}
Esempio n. 11
0
int w_is_first_hop(sip_msg_t *msg, char *p1, char *p2)
{
	int ret;
	rr_t* r = NULL;
	sip_uri_t puri;
	struct ip_addr *ip;

	if(msg==NULL)
		return -1;

	if(msg->first_line.type == SIP_REQUEST) {
		if (parse_headers( msg, HDR_VIA2_F, 0 )<0
				|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
		{
			/* sip request: if more than one via, then not first hop */
			/* no second via or error */
			LM_DBG("no 2nd via found - first hop\n");
			return 1;
		}
		return -1;
	} else if(msg->first_line.type == SIP_REPLY) {
		/* sip reply: if top record-route is myself
		 * and not received from myself (loop), then is first hop */
		if (parse_headers( msg, HDR_EOH_F, 0 )<0) {
			LM_DBG("error parsing headers\n");
			return -1;
		}
		if(msg->record_route==NULL) {
			LM_DBG("no record-route header - first hop\n");
			return 1;
		}
		if(parse_rr(msg->record_route)<0) {
			LM_DBG("failed to parse first record-route header\n");
			return -1;
		}
		r = (rr_t*)msg->record_route->parsed;
		if(parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &puri)<0) {
			LM_DBG("failed to parse uri in first record-route header\n");
			return -1;
		}
		if (((ip = str2ip(&(puri.host))) == NULL)
				&& ((ip = str2ip6(&(puri.host))) == NULL)) {
			LM_DBG("uri host is not an ip address\n");
			return -1;
		}
		ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0,
				(puri.transport_val.s)?puri.proto:0);
		if(ret!=1) {
			LM_DBG("top record route uri is not myself\n");
			return -1;
		}
		if (ip_addr_cmp(ip, &(msg->rcv.src_ip))
				&& ((msg->rcv.src_port == puri.port_no)
					|| ((puri.port.len == 0) && (msg->rcv.src_port == 5060)))
				&& (puri.proto==msg->rcv.proto
					|| (puri.proto==0 && msg->rcv.proto==PROTO_UDP)) ) {
			LM_DBG("source address matches top record route uri - loop\n");
			return -1;
		}
		/* todo - check spirals */
		return 1;
	} else {
		return -1;
	}
}
Esempio n. 12
0
int ip_set_add_ip_s(struct ip_set *ip_set, str ip_s, str mask_s){

	int fl;
	struct ip_addr *ip, ip_buff;
	unsigned int prefix, i;

	if ( ((ip = str2ip(&ip_s))==0)
					  && ((ip = str2ip6(&ip_s))==0)
									  ){
		ERR("ip_set_add_ip_s: string to ip conversion error '%.*s'\n", ip_s.len, ip_s.s);
		return -1;
	}
	ip_buff = *ip;

	if (mask_s.len > 0) {
		i = 0;
		fl = 0;
		while (i < mask_s.len &&
			   ((mask_s.s[i] >= '0' && mask_s.s[i] <= '9') || 
				(mask_s.s[i] >= 'a' && mask_s.s[i] <= 'f') || 
				(mask_s.s[i] >= 'A' && mask_s.s[i] <= 'F') ||
				mask_s.s[i] == '.' ||
				mask_s.s[i] == ':' ||
				mask_s.s[i] == '[' ||
				mask_s.s[i] == ']'
				) ) {
			fl |= mask_s.s[i] < '0' || mask_s.s[i] > '9';
			i++;
		}
		
		if (fl) {  /* 255.255.255.0 format */
			if ( ((ip = str2ip(&mask_s))==0)
					  && ((ip = str2ip6(&mask_s))==0)
				  ){
				ERR("ip_set_add_ip_s: string to ip mask conversion error '%.*s'\n", mask_s.len, mask_s.s);
				return -1;
			}
			if (ip_buff.af != ip->af) {
				ERR("ip_set_add_ip_s: IPv4 vs. IPv6 near '%.*s' vs. '%.*s'\n", ip_s.len, ip_s.s, mask_s.len, mask_s.s);
				return -1;
			}
			fl = 0;
			prefix = 0;
			for (i=0; i<ip->len; i++) {				
				unsigned char msk;				
				msk = 0x80;
				while (msk) {
					if ((ip->u.addr[i] & msk) != 0) {
						if (fl) {
							ERR("ip_set_add_ip_s: bad IP mask '%.*s'\n", mask_s.len, mask_s.s);
							return -1;
						}
						prefix++;
					}
					else {
						fl = 1;
					}
					msk /= 2;
				}
			}
		}	
		else {     /* 24 format */
			if (str2int(&mask_s, &prefix) < 0) {
				ERR("ip_set_add_ip_s: cannot convert mask '%.*s'\n", mask_s.len, mask_s.s);
				return -1;
			}				
		}
	}
	else {
		prefix = ip_buff.len*8;
	}
	if (ip_set_add_ip(ip_set, &ip_buff, prefix) < 0) {
		ERR("ip_set_add_ip_s: cannot add IP into ip set\n");
		return -1;
	}		
	return 0;
}
Esempio n. 13
0
/** Resolves SRV if no naptr found. 
 * It reuse dns_pref values and according that resolves supported protocols. 
 * If dns_pref are equal then it use udp,tcp,tls,sctp order.
 * returns: hostent struct & *port filled with the port from the SRV record;
 *  0 on error
 */
struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, char* proto)
{
	struct dns_srv_proto srv_proto_list[PROTO_LAST];
	struct hostent* he;
	struct ip_addr* ip;
	str srv_name;
	static char tmp_srv[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
	size_t i,list_len;
	/* init variables */
	he=0;

	/* check if it's an ip address */
	if (((ip=str2ip(name))!=0)
			  || ((ip=str2ip6(name))!=0)
			 ){
		/* we are lucky, this is an ip address */
		/* set proto if needed - default udp */
		if ((proto)&&(*proto==PROTO_NONE))
			*proto=PROTO_UDP;
		/* set port if needed - default 5060/5061 */
		if ((port)&&(*port==0))
			*port=((proto) && (*proto==PROTO_TLS))?SIPS_PORT:SIP_PORT;
		he=ip_addr2he(name, ip);
		return he;
	}

	if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
		LM_WARN("domain name too long (%d), unable to perform SRV lookup\n", name->len);
	} else {
		/* looping on the ordered list until we found a protocol what has srv record */
		list_len = create_srv_pref_list(proto, srv_proto_list);
		for (i=0; i<list_len;i++) {	
			switch (srv_proto_list[i].proto) {
				case PROTO_UDP:
				case PROTO_TCP:
				case PROTO_TLS:
				case PROTO_SCTP:
					create_srv_name(srv_proto_list[i].proto, name, tmp_srv);
					break;
				default:
					LM_CRIT("unknown proto %d\n", (int)srv_proto_list[i].proto);
					return 0;
			}
			/* set default port */
			if ((port)&&(*port==0)){
				*port=(srv_proto_list[i].proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we don't find another */
			}
			if ((proto)&&(*proto==0)){
				*proto = PROTO_UDP;
			}
			srv_name.s=tmp_srv;
			srv_name.len=strlen(tmp_srv);
			#ifdef USE_DNS_CACHE
			he=dns_srv_get_he(&srv_name, port, dns_flags);
			#else
			he=srv_sip_resolvehost(&srv_name, 0, port, proto, 1, 0);
			#endif
			if (he!=0) {
				if(proto) *proto = srv_proto_list[i].proto;
				return he;
			}
		}
	}
	return 0;

} 
Esempio n. 14
0
/* internal sip srv resolver: resolves a host name trying:
 * - SRV lookup if the address is not an ip *port==0. The result of the SRV
 *   query will be used for an A/AAAA lookup.
 *  - normal A/AAAA lookup (either fallback from the above or if *port!=0
 *   and *proto!=0 or port==0 && proto==0)
 * when performing SRV lookup (*port==0) it will use *proto to look for
 * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup
 * If zt is set, name will be assumed to be 0 terminated and some copy 
 * operations will be avoided.
 * If is_srv is set it will assume name has the srv prefixes for sip already
 *  appended and it's already 0-term'ed; if not it will append them internally.
 * If ars !=0, it will first try to look through them and only if the SRV
 *   record is not found it will try doing a DNS query  (ars will not be
 *   freed, the caller should take care of them)
 * returns: hostent struct & *port filled with the port from the SRV record;
 *  0 on error
 */
struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
									char* proto, int is_srv, struct rdata* ars)
{
	struct hostent* he;
	struct ip_addr* ip;
	static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups and
	                                  null. term  strings */
	struct rdata* l;
	struct srv_rdata* srv;
	struct rdata* srv_head;
	char* srv_target;
	char srv_proto;

	/* init */
	srv_head=0;
	srv_target=0;
	if (name->len >= MAX_DNS_NAME) {
		LOG(L_ERR, "sip_resolvehost: domain name too long\n");
		he=0;
		goto end;
	}
#ifdef RESOLVE_DBG
	DBG("srv_sip_resolvehost: %.*s:%d proto=%d\n", name->len, name->s,
			port?(int)*port:-1, proto?(int)*proto:-1);
#endif
	if (is_srv){
		/* skip directly to srv resolving */
		srv_proto=(proto)?*proto:0;
		*port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT;
		if (zt){
			srv_target=name->s; /* name.s must be 0 terminated in
								  this case */
		}else{
			memcpy(tmp, name->s, name->len);
			tmp[name->len] = '\0';
			srv_target=tmp;
		}
		goto do_srv; /* skip to the actual srv query */
	}
	if (proto){ /* makes sure we have a protocol set*/
		if (*proto==0)
			*proto=srv_proto=PROTO_UDP; /* default */
		else
			srv_proto=*proto;
	}else{
		srv_proto=PROTO_UDP;
	}
	/* try SRV if no port specified (draft-ietf-sip-srv-06) */
	if ((port)&&(*port==0)){
		*port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we
														  don't find another */
		/* check if it's an ip address */
		if (((ip=str2ip(name))!=0)
#ifdef	USE_IPV6
			  || ((ip=str2ip6(name))!=0) 
#endif
			 ){
			/* we are lucky, this is an ip address */
			he=ip_addr2he(name, ip);
			goto end;
		}
		if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
			LOG(L_WARN, "WARNING: sip_resolvehost: domain name too long (%d),"
						" unable to perform SRV lookup\n", name->len);
		}else{
			
			switch(srv_proto){
				case PROTO_NONE: /* no proto specified, use udp */
					if (proto)
						*proto=PROTO_UDP;
					/* no break */
				case PROTO_UDP:
					memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
					memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len);
					tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0';
					break;
				case PROTO_TCP:
					memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
					memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len);
					tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0';
					break;
				case PROTO_TLS:
					memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
					memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len);
					tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0';
					break;
				case PROTO_SCTP:
					memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
					memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len);
					tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
					break;
				default:
					LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
							srv_proto);
					he=0;
					goto end;
			}
			srv_target=tmp;
do_srv:
			/* try to find the SRV records inside previous ARs  first*/
			for (l=ars; l; l=l->next){
				if (l->type!=T_SRV) continue; 
				srv=(struct srv_rdata*) l->rdata;
				if (srv==0){
					LOG(L_CRIT, "sip_resolvehost: BUG: null rdata\n");
					/* cleanup on exit only */
					break;
				}
				he=resolvehost(srv->name);
				if (he!=0){
					/* we found it*/
#ifdef RESOLVE_DBG
					DBG("sip_resolvehost: found SRV(%s) = %s:%d in AR\n",
							srv_target, srv->name, srv->port);
#endif
					*port=srv->port;
					/* cleanup on exit */
					goto end;
				}
			}
			srv_head=get_record(srv_target, T_SRV, RES_ONLY_TYPE);
			for(l=srv_head; l; l=l->next){
				if (l->type!=T_SRV) continue; /*should never happen*/
				srv=(struct srv_rdata*) l->rdata;
				if (srv==0){
					LOG(L_CRIT, "sip_resolvehost: BUG: null rdata\n");
					/* cleanup on exit only */
					break;
				}
				he=resolvehost(srv->name);
				if (he!=0){
					/* we found it*/
#ifdef RESOLVE_DBG
					DBG("sip_resolvehost: SRV(%s) = %s:%d\n",
							srv_target, srv->name, srv->port);
#endif
					*port=srv->port;
					/* cleanup on exit */
					goto end;
				}
			}
			if (is_srv){
				/* if the name was already into SRV format it doesn't make
				 * any sense to fall back to A/AAAA */
				he=0;
				goto end;
			}
			/* cleanup on exit */
#ifdef RESOLVE_DBG
			DBG("sip_resolvehost: no SRV record found for %.*s," 
					" trying 'normal' lookup...\n", name->len, name->s);
#endif
		}
	}
/*skip_srv:*/
	if (likely(!zt)){
		memcpy(tmp, name->s, name->len);
		tmp[name->len] = '\0';
		he=resolvehost(tmp);
	}else{
		he=resolvehost(name->s);
	}
end:
#ifdef RESOLVE_DBG
	DBG("srv_sip_resolvehost: returning %p (%.*s:%d proto=%d)\n",
			he, name->len, name->s,
			port?(int)*port:-1, proto?(int)*proto:-1);
#endif
	if (srv_head)
		free_rdata_list(srv_head);
	return he;
}
Esempio n. 15
0
/* checks if the proto: host:port is one of the address we listen on
 * and returns the corresponding socket_info structure.
 * if port==0, the  port number is ignored
 * if proto==0 (PROTO_NONE) the protocol is ignored
 * returns  0 if not found
 * WARNING: uses str2ip6 so it will overwrite any previous
 *  unsaved result of this function (static buffer)
 */
struct socket_info* grep_sock_info(str* host, unsigned short port,
												unsigned short proto)
{
	char* hname;
	int h_len;
	struct socket_info* si;
	struct socket_info** list;
	unsigned short c_proto;
#ifdef USE_IPV6
	struct ip_addr* ip6;
#endif
	h_len=host->len;
	hname=host->s;
#ifdef USE_IPV6
	if ((h_len>2)&&((*hname)=='[')&&(hname[h_len-1]==']')){
		/* ipv6 reference, skip [] */
		hname++;
		h_len-=2;
	}
#endif
	c_proto=proto?proto:PROTO_UDP;
	do{
		/* get the proper sock_list */
		if (c_proto==PROTO_NONE)
			list=&udp_listen;
		else
			list=get_sock_info_list(c_proto);
	
		if (list==0){
			LOG(L_WARN, "WARNING: grep_sock_info: "
						"unknown proto %d\n", c_proto);
			goto not_found; /* false */
		}
		for (si=*list; si; si=si->next){
			DBG("grep_sock_info - checking if host==us: %d==%d && "
					" [%.*s] == [%.*s]\n", 
						h_len,
						si->name.len,
						h_len, hname,
						si->name.len, si->name.s
				);
			if (port) {
				DBG("grep_sock_info - checking if port %d matches port %d\n", 
						si->port_no, port);
				if (si->port_no!=port) {
					continue;
				}
			}
			if ( (h_len==si->name.len) && 
				(strncasecmp(hname, si->name.s,
						 si->name.len)==0) /*slower*/)
				/* comp. must be case insensitive, host names
				 * can be written in mixed case, it will also match
				 * ipv6 addresses if we are lucky*/
				goto found;
		/* check if host == ip address */
#ifdef USE_IPV6
			/* ipv6 case is uglier, host can be [3ffe::1] */
			ip6=str2ip6(host);
			if (ip6){
				if (ip_addr_cmp(ip6, &si->address))
					goto found; /* match */
				else
					continue; /* no match, but this is an ipv6 address
								 so no point in trying ipv4 */
			}
#endif
			/* ipv4 */
			if ( 	(!(si->flags&SI_IS_IP)) &&
					(h_len==si->address_str.len) && 
				(memcmp(hname, si->address_str.s, 
									si->address_str.len)==0)
				)
				goto found;
		}
	}while( (proto==0) && (c_proto=next_proto(c_proto)) );
not_found:
	return 0;
found:
	return si;
}
Esempio n. 16
0
static int w_ip_is_trusted(struct sip_msg* msg, char* _ip_set, char* _ip) {
	str ip_set_s, ip_s;
	struct ip_addr *ip, ip_buf;
	struct ip_set new_ip_set, *ip_set;
	struct ip_set_list_item *isli = NULL;
	int kind;
	kind = ((struct ip_set_param*)_ip_set)->kind;
	if (kind == IP_SET_PARAM_KIND_LOCAL) {
		if (get_str_fparam(&ip_set_s, msg, ((struct ip_set_param*)_ip_set)->u.local.fparam) < 0) {
		    ERR(MODULE_NAME": ip_is_trusted: Error while obtaining ip_set parameter value\n");
			return -1;
		}
		if (is_ip_set_name(&ip_set_s)) {
			isli = ip_set_list_find_by_name(ip_set_s);
			if (!isli) {
				ERR(MODULE_NAME": ip_is_trusted: ip set '%.*s' is not declared\n", ip_set_s.len, ip_set_s.s);
				return -1;
			}
			kind = IP_SET_PARAM_KIND_GLOBAL;
			goto force_global;
		}		
		ip_set = &((struct ip_set_param*)_ip_set)->u.local.ip_set;
	}
	else {
		isli = ((struct ip_set_param*)_ip_set)->u.global.ip_set;
	force_global:
		if (!isli->ip_set) return -1; /* empty ip set */
		
		if (unlikely(isli->ip_set != ip_set_list_local[isli->idx])) {   /* global ip set has changed ? */
			if (ip_set_list_local[isli->idx]) {
				if (atomic_dec_and_test(&ip_set_list_local[isli->idx]->refcnt)) {
					ip_set_destroy(&ip_set_list_local[isli->idx]->ip_set);
					shm_free(ip_set_list_local[isli->idx]);
					ip_set_list_local[isli->idx] = NULL;
				}
			}
			lock_get(&isli->read_lock);			
			atomic_inc(&isli->ip_set->refcnt);
			ip_set_list_local[isli->idx] = isli->ip_set;
			lock_release(&isli->read_lock);
		}
		ip_set = &ip_set_list_local[isli->idx]->ip_set;
	}
	
	if (get_str_fparam(&ip_s, msg, (fparam_t*)_ip) < 0) {
	    ERR(MODULE_NAME": ip_is_trusted: Error while obtaining ip parameter value\n");
	    return -1;
	}
	if (!ip_s.len || !ip_set_s.len) return -1;
	switch (ip_s.s[0]) {
		case 's':	/* src */
		case 'S':
			ip = &msg->rcv.src_ip;
			break;
		case 'd':	/* dst */
		case 'D':
			ip = &msg->rcv.dst_ip;
			break;
		case 'r':	/* rcv */
		case 'R':
			ip = &msg->rcv.bind_address->address;
			break;			
		default:
			/* string -> ip */

			if ( ((ip = str2ip(&ip_s))==0)
			                  && ((ip = str2ip6(&ip_s))==0)
							                  ){
				ERR(MODULE_NAME": ip_is_trusted: string to ip conversion error '%.*s'\n", ip_s.len, ip_s.s);
				return -1;
			}
			ip_buf = *ip;
			ip = &ip_buf;  /* value has been in static buffer */			
			break;
	}

	/* test if ip_set string has changed since last call */
	if (kind == IP_SET_PARAM_KIND_LOCAL) {
		if (((struct ip_set_param*)_ip_set)->u.local.s.len != ip_set_s.len || 
			memcmp(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.s, ip_set_s.len) != 0) {

			ip_set_init(&new_ip_set, 0);
			if (ip_set_add_list(&new_ip_set, ip_set_s) < 0) {
				ip_set_destroy(&new_ip_set);
				return -1;
			};
			if (((struct ip_set_param*)_ip_set)->u.local.sz < ip_set_s.len) {
				void *p;
				p = pkg_realloc(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.len);
				if (!p) {
					ip_set_destroy(&new_ip_set);
					return E_OUT_OF_MEM;
				}
				((struct ip_set_param*)_ip_set)->u.local.s.s = p;			
				((struct ip_set_param*)_ip_set)->u.local.sz = ip_set_s.len;			
			}
			memcpy(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.s, ip_set_s.len);
			((struct ip_set_param*)_ip_set)->u.local.s.len = ip_set_s.len;
			ip_set_destroy(&((struct ip_set_param*)_ip_set)->u.local.ip_set);
			((struct ip_set_param*)_ip_set)->u.local.ip_set = new_ip_set;
		}
	}
/* ip_set_print(stderr, &ip_set); */
	switch (ip_set_ip_exists(ip_set, ip)) {
		case IP_TREE_FIND_FOUND:
		case IP_TREE_FIND_FOUND_UPPER_SET:
			return 1;
		default:
			return -1;
	}
}
Esempio n. 17
0
struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, char* proto)
{
	struct dns_srv_proto_t {
		char proto;
		int proto_pref;
	} srv_proto_list[PROTO_LAST], tmp_srv_element;
	struct hostent* he;
	struct ip_addr* ip;
	str srv_name;
	static char tmp_srv[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */
	int len;
	unsigned char i,j,max,default_order=0,list_len=0;
	/* init variables */
	he=0;
	len=0;

	/* check if it's an ip address */
	if (((ip=str2ip(name))!=0)
#ifdef	USE_IPV6
			  || ((ip=str2ip6(name))!=0)
#endif
			 ){
		/* we are lucky, this is an ip address */
		/* set proto if needed - default udp */
		if ((proto)&&(*proto==PROTO_NONE))
			*proto=PROTO_UDP;
		/* set port if needed - default 5060/5061 */
		if ((port)&&(*port==0))
			*port=((proto) && (*proto==PROTO_TLS))?SIPS_PORT:SIP_PORT;
		he=ip_addr2he(name, ip);
		return he;
	}

	if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){
		LOG(L_WARN, "WARNING: no_naptr_srv_sip_resolvehost: domain name too long"
						" (%d), unable to perform SRV lookup\n", name->len);
	} else {
		/* if proto available, then add only the forced protocol to the list */
		if (proto && *proto!=PROTO_NONE){
			srv_proto_list[0].proto=*proto;
			list_len=1;
		} else {
	
			/*get protocols and preference scores, and add availble protocol(s) and score(s) to the list*/
			for (i=PROTO_UDP; i<PROTO_LAST;i++) {
				tmp_srv_element.proto_pref = proto_pref_score(i);
				/* if -1 so disabled continue with next protocol*/
				if (naptr_proto_supported(i) == 0 ) {
					continue;
				} else {
					srv_proto_list[i-1].proto_pref=tmp_srv_element.proto_pref;
					srv_proto_list[i-1].proto=i;
					list_len++;
				}
			};

			/* if all protocol prefence scores equal, then set the perference to default values: udp,tcp,tls,sctp */
			for (i=1; i<list_len;i++) {
				if(srv_proto_list[0].proto_pref!=srv_proto_list[i].proto_pref){
					default_order=0;
				}
			}
			if (default_order){
				for (i=0; i<list_len;i++) {
					switch ( srv_proto_list[i].proto) {
						case PROTO_UDP:
							srv_proto_list[i].proto_pref=4;
							break;
						case PROTO_TCP:
							srv_proto_list[i].proto_pref=3;
							break;
						case PROTO_TLS:
							srv_proto_list[i].proto_pref=2;
							break;
						case PROTO_SCTP:
							srv_proto_list[i].proto_pref=1;
							break;
					}
				}
			}

			/* sorting the list */
			for (i=0;i<list_len-1;i++) {
				max=i;
				for (j=i+1;j<list_len;j++) {
					if (srv_proto_list[j].proto_pref>srv_proto_list[max].proto_pref) { 
						max=j; 
					}
				}
				if (i!=max) {
					tmp_srv_element=srv_proto_list[i];
					srv_proto_list[i]=srv_proto_list[max];
					srv_proto_list[max]=tmp_srv_element;
				}
			}

		}
		/* looping on the ordered list until we found a protocol what has srv record */
		for (i=0; i<list_len;i++) {	
			switch (srv_proto_list[i].proto) {
				case PROTO_NONE: /* no proto specified, use udp */
					if (proto)
						*proto=PROTO_UDP;
					/* no break */
				case PROTO_UDP:
					memcpy(tmp_srv, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN);
					memcpy(tmp_srv+SRV_UDP_PREFIX_LEN, name->s, name->len);
					tmp_srv[SRV_UDP_PREFIX_LEN + name->len] = '\0';
					len=SRV_UDP_PREFIX_LEN + name->len;
					break;
				case PROTO_TCP:
					memcpy(tmp_srv, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN);
					memcpy(tmp_srv+SRV_TCP_PREFIX_LEN, name->s, name->len);
					tmp_srv[SRV_TCP_PREFIX_LEN + name->len] = '\0';
					len=SRV_TCP_PREFIX_LEN + name->len;
					break;
				case PROTO_TLS:
					memcpy(tmp_srv, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN);
					memcpy(tmp_srv+SRV_TLS_PREFIX_LEN, name->s, name->len);
					tmp_srv[SRV_TLS_PREFIX_LEN + name->len] = '\0';
					len=SRV_TLS_PREFIX_LEN + name->len;
					break;
				case PROTO_SCTP:
					memcpy(tmp_srv, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN);
					memcpy(tmp_srv+SRV_SCTP_PREFIX_LEN, name->s, name->len);
					tmp_srv[SRV_SCTP_PREFIX_LEN + name->len] = '\0';
					len=SRV_SCTP_PREFIX_LEN + name->len;
					break;
				default:
					LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n",
							(int)srv_proto_list[i].proto);
					return 0;
			}
			/* set default port */
			if ((port)&&(*port==0)){
				*port=(srv_proto_list[i].proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we don't find another */
			}
			srv_name.s=tmp_srv;
			srv_name.len=len;
			#ifdef USE_DNS_CACHE
			he=dns_srv_get_he(&srv_name, port, dns_flags);
			#else
			he=srv_sip_resolvehost(&srv_name, 0, port, proto, 1, 0);
			#endif
			if (he!=0) {
				return he;
			}
		}
	}
	return 0;

} 
Esempio n. 18
0
/*!
 * \brief Convert a STR [proto:]ip[:port] into socket address.
 * [proto:]ip[:port]
 * \param pipport (udp:127.0.0.1:5060 or tcp:2001:0DB8:AC10:FE01:5060)
 * \param tmp_su target structure
 * \param proto uint protocol type
 * \return success / unsuccess
 */
static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto)
{
	unsigned int port_no, cutlen = 4;
	struct ip_addr *ip;
	char *p, *host_s;
	str port_str, host_uri;
	unsigned len = 0;
	char tmp_piport[256];

	/*parse protocol */
	if(strncmp(pipport, "udp:",4) == 0) *proto = IPPROTO_UDP;
	else if(strncmp(pipport, "tcp:",4) == 0) *proto = IPPROTO_TCP;
	else if(strncmp(pipport, "tls:",4) == 0) *proto = IPPROTO_IDP; /* fake proto type */
	else if(strncmp(pipport, "ws:",3) == 0) *proto = IPPROTO_IDP; /* fake proto type */
	else if(strncmp(pipport, "wss:",4) == 0) *proto = IPPROTO_IDP; /* fake proto type */
#ifdef USE_SCTP
	else if(strncmp(pipport, "sctp:",5) == 0) cutlen = 5, *proto = IPPROTO_SCTP;
#endif
	else if(strncmp(pipport, "any:",4) == 0) *proto = IPPROTO_UDP;
	else {
		LM_ERR("bad protocol %s\n", pipport);
		return -1;
	}

	if((len = strlen(pipport)) >= 256) {
		LM_ERR("too big pipport\n");
		goto error;
	}

	/* our tmp string */
	strncpy(tmp_piport, pipport, len+1);

	len = 0;

	/*separate proto and host */
	p = tmp_piport+cutlen;
	if( (*(p)) == '\0') {
		LM_ERR("malformed ip address\n");
		goto error;
	}
	host_s=p;

	if( (p = strrchr(p+1, ':')) == 0 ) {
		LM_DBG("no port specified\n");
		port_no = 0;
	}
	else {
		/*the address contains a port number*/
		*p = '\0';
		p++;
		port_str.s = p;
		port_str.len = strlen(p);
		LM_DBG("the port string is %s\n", p);
		if(str2int(&port_str, &port_no) != 0 ) {
			LM_ERR("there is not a valid number port\n");
			goto error;
		}
		*p = '\0';
	}

	/* now IPv6 address has no brakets. It should be fixed! */
	if (host_s[0] == '[') {
		len = strlen(host_s + 1) - 1;
		if(host_s[len+1] != ']') {
			LM_ERR("bracket not closed\n");
			goto error;
		}
		memmove(host_s, host_s + 1, len);
		host_s[len] = '\0';
	}

	host_uri.s = host_s;
	host_uri.len = strlen(host_s);

	/* check if it's an ip address */
	if (((ip=str2ip(&host_uri))!=0)
			|| ((ip=str2ip6(&host_uri))!=0)
	   ) {
		ip_addr2su(tmp_su, ip, ntohs(port_no));
		return 0;	

	}

error:
	return -1;
}