core: respect order field in NAPTR, as required by RFC 2915
authorØyvind Kolbu <oyvind.kolbu@usit.uio.no>
Tue, 12 Nov 2013 14:47:30 +0000 (15:47 +0100)
committerDaniel-Constantin Mierla <miconda@gmail.com>
Tue, 12 Nov 2013 14:49:37 +0000 (15:49 +0100)
- the beaviour is controlled by core parameter dns_naptr_ignore_rfc
- default is 1, preserving current behaviouf to ignore rfc requirements
  (for backward compatibility)

cfg.lex
cfg.y
cfg_core.c
cfg_core.h
dns_cache.c
resolve.c
resolve.h

diff --git a/cfg.lex b/cfg.lex
index 127fce5..8e60c1e 100644 (file)
--- 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; }
 <INITIAL>{DNS_SEARCH_FMATCH}   { count(); yylval.strval=yytext;
                                                                return DNS_SEARCH_FMATCH; }
+<INITIAL>{DNS_NAPTR_IGNORE_RFC}        { count(); yylval.strval=yytext;
+                                                               return DNS_NAPTR_IGNORE_RFC; }
 <INITIAL>{DNS_CACHE_INIT}      { count(); yylval.strval=yytext;
                                                                return DNS_CACHE_INIT; }
 <INITIAL>{DNS_USE_CACHE}       { count(); yylval.strval=yytext;
diff --git a/cfg.y b/cfg.y
index 2533f72..195593b 100644 (file)
--- 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); }
index ac67b11..06edb86 100644 (file)
@@ -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,
index 4bfbfbb..3739acb 100644 (file)
@@ -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;
index d9737c8..f3bdda9 100644 (file)
@@ -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;
                                                }
                                        }
index 7450b6f..d0ef16c 100644 (file)
--- 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<PROTO_LAST;i++) {
-                       tmp.proto_pref = proto_pref_score(i);
+                       tmp.proto_pref = srv_proto_pref_score(i);
                        /* if -1 so disabled continue with next protocol*/
                        if (naptr_proto_supported(i) == 0) {
                                continue;
@@ -1470,7 +1511,7 @@ size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list) {
                }
                if (default_order){
                        for (i=0; i<list_len;i++) {
-                               list[i].proto_pref=proto_pref_score(i);
+                               list[i].proto_pref=srv_proto_pref_score(i);
                        }
                }
 
index b3e6eba..2d67da7 100644 (file)
--- a/resolve.h
+++ b/resolve.h
@@ -455,7 +455,7 @@ int resolv_init(void);
 void resolv_reinit(str *gname, str *name);
 int dns_reinit_fixup(void *handle, str *gname, str *name, void **val);
 int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val);
-void reinit_naptr_proto_prefs(str *gname, str *name);
+void reinit_proto_prefs(str *gname, str *name);
 
 struct dns_srv_proto {
        char proto;