summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaimo Niskanen <raimo@erlang.org>2021-04-23 16:23:17 +0200
committerRaimo Niskanen <raimo@erlang.org>2021-07-02 12:33:01 +0200
commitd5f0138841ccc48592ac68283c5383297a986381 (patch)
treef1efdaa806c0bd0d875c63f709065061d2913df4
parent0edbe63c02d0362ebcfe3b1c3bfbdce47d2d146f (diff)
downloaderlang-d5f0138841ccc48592ac68283c5383297a986381.tar.gz
Use case insensitive domain compare
-rw-r--r--lib/kernel/src/inet_db.erl39
-rw-r--r--lib/kernel/src/inet_res.erl4
2 files changed, 39 insertions, 4 deletions
diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl
index 90e2f66365..2741810360 100644
--- a/lib/kernel/src/inet_db.erl
+++ b/lib/kernel/src/inet_db.erl
@@ -71,7 +71,7 @@
-export([res_gethostbyaddr/2,res_hostent_by_domain/3]).
-export([res_update_conf/0, res_update_hosts/0]).
%% inet help functions
--export([tolower/1]).
+-export([tolower/1, eq_domains/2]).
-ifdef(DEBUG).
-define(dbg(Fmt, Args), io:format(Fmt, Args)).
-else.
@@ -1818,13 +1818,48 @@ match_rr_key(
%% does not follow RFC 4343.
%%
tolower([]) -> [];
-tolower([C|Cs]) when is_integer(C) ->
+tolower([C|Cs]) when is_integer(C), 0 =< C, C =< 16#10FFFF ->
if C >= $A, C =< $Z ->
[(C-$A)+$a|tolower(Cs)];
true ->
[C|tolower(Cs)]
end.
+%% Case insensitive domain name comparison according to RFC 4343
+%% "Domain Name System (DNS) Case Insensitivity Clarification",
+%% i.e regard $a through $z as equal to $A through $Z.
+%%
+eq_domains([A | As], [B | Bs]) ->
+ if
+ is_integer(A), 0 =< A, A =< 16#10FFFF,
+ is_integer(B), 0 =< B, B =< 16#10FFFF ->
+ %% An upper bound of 255 would be right right now,
+ %% but this algorithm works for any integer. That
+ %% guard just gives the compiler the opportuinity
+ %% to optimize bit operations for machine word size,
+ %% so we might as well use the Unicode upper bound instead.
+ Xor = (A bxor B),
+ if
+ Xor =:= 0 ->
+ eq_domains(As, Bs);
+ Xor =:= ($A bxor $a) ->
+ And = (A band B),
+ if
+ ($A band $a) =< And, And =< ($Z band $z) ->
+ eq_domains(As, Bs);
+ true ->
+ false
+ end;
+ true ->
+ false
+ end
+ end;
+eq_domains([], []) ->
+ true;
+eq_domains(As, Bs) when is_list(As), is_list(Bs) ->
+ false.
+
+
dn_ip6_int(A,B,C,D,E,F,G,H) ->
dnib(H) ++ dnib(G) ++ dnib(F) ++ dnib(E) ++
dnib(D) ++ dnib(C) ++ dnib(B) ++ dnib(A) ++ "ip6.int".
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index 1b6344f372..e238cfd2a1 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -1110,8 +1110,8 @@ decode_answer_noerror(
andalso
(RR#dns_query.type =:= Q_RR#dns_query.type)
andalso
- (inet_db:tolower(RR#dns_query.domain) =:=
- inet_db:tolower(Q_RR#dns_query.domain))
+ inet_db:eq_domains(
+ RR#dns_query.domain, Q_RR#dns_query.domain)
of
true ->
{ok, Msg};