Module: sip-router
Branch: misi/dns_srv
Commit: fd1a5bf99af922eccf33756f6421f00998ccaed9
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=fd1a5bf…
Author: Mihály Mészáros <misi(a)niif.hu>
Committer: Mihály Mészáros <misi(a)niif.hu>
Date: Mon Nov 12 16:02:48 2012 +0100
core/dns: dns SRV lookup, if no NAPTR available
- Resolving the first most preferred and available SRV record if no NAPTR found.
It reuse the dns protocol preference scores. Sort protocols based on this preference.
---
dns_cache.c | 2 +-
resolve.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 137 insertions(+), 3 deletions(-)
diff --git a/dns_cache.c b/dns_cache.c
index 1a7f1c5..1f4ae82 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -2890,7 +2890,7 @@ struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short*
port,
dns_hash_put(e);
}
naptr_not_found:
- return dns_srv_sip_resolvehost(name, port, proto);
+ return no_naptr_srv_sip_resolvehost(name,port,proto);
}
#endif /* USE_NAPTR */
diff --git a/resolve.c b/resolve.c
index faabb96..9b094ec 100644
--- a/resolve.c
+++ b/resolve.c
@@ -1448,8 +1448,142 @@ end:
return 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_t {
+ char proto;
+ int proto_pref;
+ } srv_proto_list[PROTO_LAST], tmp_srv_element;
+ struct hostent* he;
+ 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;
+
+ 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==0){
+ 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;
+ if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0) {
+ return he;
+ }
+ }
+ }
+ return 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.
@@ -1515,8 +1649,8 @@ struct hostent* naptr_sip_resolvehost(str* name, unsigned short*
port,
" trying SRV lookup...\n", name->len, name->s);
#endif
}
- /* fallback to normal srv lookup */
- he=srv_sip_resolvehost(name, 0, port, proto, 0, 0);
+ /* fallback to srv lookup */
+ no_naptr_srv_sip_resolvehost(name,port,proto);
end:
if (naptr_head)
free_rdata_list(naptr_head);