diff --git a/cfg.lex b/cfg.lex index 127fce5..8e60c1e 100644 --- a/cfg.lex +++ b/cfg.lex @@ -360,6 +360,7 @@ DNS_RETR_NO dns_retr_no DNS_SERVERS_NO dns_servers_no DNS_USE_SEARCH dns_use_search_list DNS_SEARCH_FMATCH dns_search_full_match +DNS_NAPTR_IGNORE_RFC dns_naptr_ignore_rfc /* dns cache */ DNS_CACHE_INIT dns_cache_init DNS_USE_CACHE use_dns_cache @@ -724,6 +725,8 @@ IMPORTFILE "import_file" return DNS_USE_SEARCH; } {DNS_SEARCH_FMATCH} { count(); yylval.strval=yytext; return DNS_SEARCH_FMATCH; } +{DNS_NAPTR_IGNORE_RFC} { count(); yylval.strval=yytext; + return DNS_NAPTR_IGNORE_RFC; } {DNS_CACHE_INIT} { count(); yylval.strval=yytext; return DNS_CACHE_INIT; } {DNS_USE_CACHE} { count(); yylval.strval=yytext; diff --git a/cfg.y b/cfg.y index 2533f72..195593b 100644 --- a/cfg.y +++ b/cfg.y @@ -409,6 +409,7 @@ extern char *finame; %token DNS_SERVERS_NO %token DNS_USE_SEARCH %token DNS_SEARCH_FMATCH +%token DNS_NAPTR_IGNORE_RFC %token DNS_CACHE_INIT %token DNS_USE_CACHE %token DNS_USE_FAILOVER @@ -865,6 +866,8 @@ assign_stm: | DNS_USE_SEARCH error { yyerror("boolean value expected"); } | DNS_SEARCH_FMATCH EQUAL NUMBER { default_core_cfg.dns_search_fmatch=$3; } | DNS_SEARCH_FMATCH error { yyerror("boolean value expected"); } + | DNS_NAPTR_IGNORE_RFC EQUAL NUMBER { default_core_cfg.dns_naptr_ignore_rfc=$3; } + | DNS_NAPTR_IGNORE_RFC error { yyerror("boolean value expected"); } | DNS_CACHE_INIT EQUAL NUMBER { IF_DNS_CACHE(dns_cache_init=$3); } | DNS_CACHE_INIT error { yyerror("boolean value expected"); } | DNS_USE_CACHE EQUAL NUMBER { IF_DNS_CACHE(default_core_cfg.use_dns_cache=$3); } diff --git a/cfg_core.c b/cfg_core.c index ac67b11..06edb86 100644 --- a/cfg_core.c +++ b/cfg_core.c @@ -88,6 +88,7 @@ struct cfg_group_core default_core_cfg = { 1, /*!< dns_search_list */ 1, /*!< dns_search_fmatch */ 0, /*!< dns_reinit */ + 1, /*!< dns_naptr_ignore_rfc */ /* DNS cache */ #ifdef USE_DNS_CACHE 1, /*!< use_dns_cache -- on by default */ @@ -216,13 +217,13 @@ cfg_def_t core_cfg_def[] = { {"dns_try_naptr", CFG_VAR_INT, 0, 1, 0, 0, #endif "enable/disable NAPTR DNS lookups"}, - {"dns_udp_pref", CFG_VAR_INT, 0, 0, 0, reinit_naptr_proto_prefs, + {"dns_udp_pref", CFG_VAR_INT, 0, 0, 0, reinit_proto_prefs, "udp protocol preference when doing NAPTR lookups"}, - {"dns_tcp_pref", CFG_VAR_INT, 0, 0, 0, reinit_naptr_proto_prefs, + {"dns_tcp_pref", CFG_VAR_INT, 0, 0, 0, reinit_proto_prefs, "tcp protocol preference when doing NAPTR lookups"}, - {"dns_tls_pref", CFG_VAR_INT, 0, 0, 0, reinit_naptr_proto_prefs, + {"dns_tls_pref", CFG_VAR_INT, 0, 0, 0, reinit_proto_prefs, "tls protocol preference when doing NAPTR lookups"}, - {"dns_sctp_pref", CFG_VAR_INT, 0, 0, 0, reinit_naptr_proto_prefs, + {"dns_sctp_pref", CFG_VAR_INT, 0, 0, 0, reinit_proto_prefs, "sctp protocol preference when doing NAPTR lookups"}, {"dns_retr_time", CFG_VAR_INT, 0, 0, 0, resolv_reinit, "time in s before retrying a dns request"}, @@ -239,6 +240,8 @@ cfg_def_t core_cfg_def[] = { {"dns_reinit", CFG_VAR_INT|CFG_INPUT_INT, 1, 1, dns_reinit_fixup, resolv_reinit, "set to 1 in order to reinitialize the DNS resolver"}, + {"dns_naptr_ignore_rfc", CFG_VAR_INT, 0, 0, 0, reinit_proto_prefs, + "ignore the Order field required by RFC 2915"}, /* DNS cache */ #ifdef USE_DNS_CACHE {"use_dns_cache", CFG_VAR_INT, 0, 1, use_dns_cache_fixup, 0, diff --git a/cfg_core.h b/cfg_core.h index 4bfbfbb..3739acb 100644 --- a/cfg_core.h +++ b/cfg_core.h @@ -80,6 +80,7 @@ struct cfg_group_core { int dns_search_list; int dns_search_fmatch; int dns_reinit; + int dns_naptr_ignore_rfc; /* DNS cache */ #ifdef USE_DNS_CACHE int use_dns_cache; diff --git a/dns_cache.c b/dns_cache.c index d9737c8..f3bdda9 100644 --- a/dns_cache.c +++ b/dns_cache.c @@ -3291,12 +3291,11 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h, str* name, srv_name.len=strlen(tmp); if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0) { - *proto = srv_proto_list[i].proto; + h->proto = *proto = srv_proto_list[i].proto; #ifdef DNS_CACHE_DEBUG DBG("dns_srv_sip_resolve(%.*s, %d, %d), srv0, ret=%d\n", name->len, name->s, h->srv_no, h->ip_no, ret); #endif - /* proto already set */ return ret; } } diff --git a/resolve.c b/resolve.c index 7450b6f..d0ef16c 100644 --- a/resolve.c +++ b/resolve.c @@ -92,23 +92,58 @@ counter_def_t dns_cnt_defs[] = { #ifdef USE_NAPTR static int naptr_proto_pref[PROTO_LAST+1]; #endif +static int srv_proto_pref[PROTO_LAST+1]; #ifdef USE_NAPTR -void init_naptr_proto_prefs() +static void init_naptr_proto_prefs() { + int ignore_rfc, udp, tcp, tls, sctp; + if ((PROTO_UDP > PROTO_LAST) || (PROTO_TCP > PROTO_LAST) || (PROTO_TLS > PROTO_LAST) || (PROTO_SCTP > PROTO_LAST)){ BUG("init_naptr_proto_prefs: array too small \n"); return; } - naptr_proto_pref[PROTO_UDP]=cfg_get(core, core_cfg, dns_udp_pref); - naptr_proto_pref[PROTO_TCP]=cfg_get(core, core_cfg, dns_tcp_pref); - naptr_proto_pref[PROTO_TLS]=cfg_get(core, core_cfg, dns_tls_pref); - naptr_proto_pref[PROTO_SCTP]=cfg_get(core, core_cfg, dns_sctp_pref); + + ignore_rfc = cfg_get(core, core_cfg, dns_naptr_ignore_rfc); + udp = cfg_get(core, core_cfg, dns_udp_pref); + tcp = cfg_get(core, core_cfg, dns_tcp_pref); + tls = cfg_get(core, core_cfg, dns_tls_pref); + sctp = cfg_get(core, core_cfg, dns_sctp_pref); + + /* Old implementation ignored the Order field in the NAPTR RR and + * thus violated a MUST in RFC 2915. Currently still the default. */ + if (ignore_rfc) { + naptr_proto_pref[PROTO_UDP] = udp; + naptr_proto_pref[PROTO_TCP] = tcp; + naptr_proto_pref[PROTO_TLS] = tls; + naptr_proto_pref[PROTO_SCTP] = sctp; + } else { + /* If value is less than 0, proto is disabled, otherwise + * ignored. */ + naptr_proto_pref[PROTO_UDP] = udp < 0 ? udp : 1; + naptr_proto_pref[PROTO_TCP] = tcp < 0 ? tcp : 1; + naptr_proto_pref[PROTO_TLS] = tls < 0 ? tls : 1; + naptr_proto_pref[PROTO_SCTP] = sctp < 0 ? sctp : 1; + } } #endif /* USE_NAPTR */ +static void init_srv_proto_prefs() +{ + if ((PROTO_UDP > PROTO_LAST) || (PROTO_TCP > PROTO_LAST) || + (PROTO_TLS > PROTO_LAST) || (PROTO_SCTP > PROTO_LAST)){ + BUG("init_srv_proto_prefs: array too small \n"); + return; + } + + srv_proto_pref[PROTO_UDP] = cfg_get(core, core_cfg, dns_udp_pref); + srv_proto_pref[PROTO_TCP] = cfg_get(core, core_cfg, dns_tcp_pref); + srv_proto_pref[PROTO_TLS] = cfg_get(core, core_cfg, dns_tls_pref); + srv_proto_pref[PROTO_SCTP] = cfg_get(core, core_cfg, dns_sctp_pref); +} + #ifdef DNS_WATCHDOG_SUPPORT static on_resolv_reinit on_resolv_reinit_cb = NULL; @@ -178,9 +213,7 @@ int resolv_init(void) int res = -1; _resolv_init(); -#ifdef USE_NAPTR - init_naptr_proto_prefs(); -#endif + reinit_proto_prefs(NULL,NULL); /* init counter API only at startup * This function must be called before DNS cache init method (if available) */ @@ -212,12 +245,13 @@ int dns_reinit_fixup(void *handle, str *gname, str *name, void **val) return 0; } -/* wrapper function to recalculate the naptr protocol preferences */ -void reinit_naptr_proto_prefs(str *gname, str *name) +/* wrapper function to recalculate the naptr and srv protocol preferences */ +void reinit_proto_prefs(str *gname, str *name) { #ifdef USE_NAPTR init_naptr_proto_prefs(); #endif + init_srv_proto_prefs(); } /* fixup function for dns_try_ipv6 @@ -1080,19 +1114,26 @@ char naptr_get_sip_proto(struct naptr_rdata* n) -inline static int proto_pref_score(char proto) +inline static int naptr_proto_pref_score(char proto) { if ((proto>=PROTO_UDP) && (proto<= PROTO_LAST)) return naptr_proto_pref[(int)proto]; return 0; } +inline static int srv_proto_pref_score(char proto) +{ + if ((proto>=PROTO_UDP) && (proto<= PROTO_LAST)) + return srv_proto_pref[(int)proto]; + return 0; +} + /* returns true if we support the protocol */ int naptr_proto_supported(char proto) { - if (proto_pref_score(proto)<0) + if (naptr_proto_pref_score(proto)<0) return 0; switch(proto){ case PROTO_UDP: @@ -1119,7 +1160,7 @@ int naptr_proto_supported(char proto) /* returns true if new_proto is preferred over old_proto */ int naptr_proto_preferred(char new_proto, char old_proto) { - return proto_pref_score(new_proto)>proto_pref_score(old_proto); + return naptr_proto_pref_score(new_proto)>naptr_proto_pref_score(old_proto); } @@ -1451,7 +1492,7 @@ size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list) { list_len = 0; /*get protocols and preference scores, and add availble protocol(s) and score(s) to the list*/ for (i=PROTO_UDP; i