示例#1
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;

} 
示例#2
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;

}