Exemplo n.º 1
0
/* iterates over a naptr rr list, returning each time a "good" naptr record
 * is found.( srv type, no regex and a supported protocol)
 * params:
 *         naptr_head - naptr rr list head
 *         tried      - bitmap used to keep track of the already tried records
 *                      (no more then sizeof(tried)*8 valid records are 
 *                      ever walked
 *         srv_name   - if succesfull, it will be set to the selected record
 *                      srv name (naptr repl.)
 *         proto      - if succesfull it will be set to the selected record
 *                      protocol
 * returns  0 if no more records found or a pointer to the selected record
 *  and sets  protocol and srv_name
 * WARNING: when calling first time make sure you run first 
 *           naptr_iterate_init(&tried)
 */
struct rdata* naptr_sip_iterate(struct rdata* naptr_head, 
										naptr_bmp_t* tried,
										str* srv_name, char* proto)
{
	int i, idx;
	struct rdata* l;
	struct rdata* l_saved;
	struct naptr_rdata* naptr;
	struct naptr_rdata* naptr_saved;
	char saved_proto;
	char naptr_proto;

	idx=0;
	naptr_proto=PROTO_NONE;
	naptr_saved=0;
	l_saved=0;
	saved_proto=0;
	i=0;
	for(l=naptr_head; l && (i<MAX_NAPTR_RRS); l=l->next){
		if (l->type!=T_NAPTR) continue; 
		naptr=(struct naptr_rdata*) l->rdata;
		if (naptr==0){
				LOG(L_CRIT, "naptr_iterate: BUG: null rdata\n");
			goto end;
		}
		/* check if valid and get proto */
		if ((naptr_proto=naptr_get_sip_proto(naptr))<=0) continue;
		if (*tried& (1<<i)){
			i++;
			continue; /* already tried */
		}
#ifdef NAPTR_DBG
		DBG("naptr_iterate: found a valid sip NAPTR rr %.*s,"
					" proto %d\n", naptr->repl_len, naptr->repl, 
					(int)naptr_proto);
#endif
		if ((naptr_proto_supported(naptr_proto))){
			if (naptr_choose(&naptr_saved, &saved_proto,
								naptr, naptr_proto))
				idx=i;
				l_saved=l;
			}
		i++;
	}
	if (naptr_saved){
		/* found something */
#ifdef NAPTR_DBG
		DBG("naptr_iterate: choosed NAPTR rr %.*s, proto %d"
					" tried: 0x%x\n", naptr_saved->repl_len, 
					naptr_saved->repl, (int)saved_proto, *tried);
#endif
		*tried|=1<<idx;
		*proto=saved_proto;
		srv_name->s=naptr_saved->repl;
		srv_name->len=naptr_saved->repl_len;
		return l_saved;
	}
end:
	return 0;
}
Exemplo n.º 2
0
size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list) {
	struct dns_srv_proto tmp;
	size_t i,j,list_len;
	int default_order,max;

	/* if proto available, then add only the forced protocol to the list */
	if (proto && *proto!=PROTO_NONE){
		list[0].proto=*proto;
		list_len=1;
	} else {
		list_len = 0;
		/*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.proto_pref = srv_proto_pref_score(i);
			/* if -1 so disabled continue with next protocol*/
			if (naptr_proto_supported(i) == 0) {
				continue;
			} else {
				list[i-1].proto_pref=tmp.proto_pref;
				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(list[0].proto_pref!=list[i].proto_pref){
				default_order=0;
			}
		}
		if (default_order){
			for (i=0; i<list_len;i++) {
				list[i].proto_pref=srv_proto_pref_score(i);
			}
		}

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

	}
	return list_len;
}
Exemplo n.º 3
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;

}