[sr-dev] Patch: Respect Order field in NAPTR, as required by RFC 2915

Øyvind Kolbu oyvind.kolbu at usit.uio.no
Mon Nov 11 14:48:46 CET 2013


On 2013-10-29 at 09:34, Daniel-Constantin Mierla wrote:
> On 10/18/13 3:14 PM, Øyvind Kolbu wrote:
> > Made a core option, dns_naptr_ignore_rfc, default off, to preserve today's
> > behavior.
> did I get it wrong or the dns_naptr_ignore_rfc has to be 1 (on) to 
> preserve current behaviour? You said 'off' (expect 0) which collides 
> with the 'ignore' in the name of the parameter.

Hi and sorry for the late reply. Been offline on vacation.

Yes, the value has to be 1 to actually ignore the rfc. The code
was correct, but the default value not. Fixed in the attached patch.

> > One implementation detail is that one currently can disable a protocol
> > by setting the priority to -1. In my patch that is currently ignored.
> > Can add a check for that in init_naptr_proto_prefs() before setting
> > a protocol's preference to 1.
> 
> Can you add the check for ignoring a protocol? Sometime it might be 
> needed. Resend the patch and I will push it to repo.

Fixed in the new patch.

-- 
Øyvind Kolbu
-------------- next part --------------
diff --git a/cfg.lex b/cfg.lex
index 5a7ce8a..03fde61 100644
--- a/cfg.lex
+++ b/cfg.lex
@@ -359,6 +359,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
@@ -747,6 +748,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 0c4fb5d..c472e54 100644
--- a/cfg.y
+++ b/cfg.y
@@ -418,6 +418,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
@@ -896,6 +897,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 55a5638..6bb6399 100644
--- a/cfg_core.c
+++ b/cfg_core.c
@@ -92,6 +92,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 */
@@ -220,13 +221,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"},
@@ -243,6 +244,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 8d86c02..4a690d3 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -3341,12 +3341,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 bced952..77102bb 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
@@ -1097,19 +1131,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:
@@ -1136,7 +1177,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);
 }
 
 
@@ -1470,7 +1511,7 @@ size_t create_srv_pref_list(char *proto, struct dns_srv_proto_t *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;
@@ -1489,7 +1530,7 @@ size_t create_srv_pref_list(char *proto, struct dns_srv_proto_t *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);
 			}
 		}
 
@@ -1581,6 +1622,7 @@ struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, ch
 			he=srv_sip_resolvehost(&srv_name, 0, port, proto, 1, 0);
 			#endif
 			if (he!=0) {
+				*proto = srv_proto_list[i].proto;
 				return he;
 			}
 		}
diff --git a/resolve.h b/resolve.h
index 1d67e3d..c7e1e0f 100644
--- a/resolve.h
+++ b/resolve.h
@@ -485,7 +485,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_t {
 	char proto;


More information about the sr-dev mailing list