@@ -1133,7 +1133,7 @@ module Dns = struct
1133
1133
1134
1134
let resolve_dnssd question =
1135
1135
let open Dns.Packet in
1136
- let query name ty =
1136
+ let query_one name ty =
1137
1137
let query = Dnssd.LowLevel. query (Dns.Name. to_string name) ty in
1138
1138
let socket = Dnssd.LowLevel. socket query in
1139
1139
let t, u = Lwt. task () in
@@ -1164,6 +1164,36 @@ module Dns = struct
1164
1164
) ()
1165
1165
end in
1166
1166
1167
+ let query requested_name ty =
1168
+ (* The DNSServiceRef API will return CNAMEs first, without resolving to
1169
+ A/AAAA/... This function recursively resolves the CNAMES while avoiding
1170
+ returning duplicate records. *)
1171
+ (* NB we only return NoSuchRecord if we find no records. This is because it
1172
+ is possible to query a CNAME which exists, but which points to a non-existent
1173
+ record. *)
1174
+ let open Dnssd in
1175
+ let rec loop acc name ty =
1176
+ query_one name ty
1177
+ >> = function
1178
+ (* When we're recursing, ignore the NoSuchRecord error *)
1179
+ | Error NoSuchRecord when name <> requested_name -> Lwt. return (Ok acc)
1180
+ | Error e -> Lwt. return (Error e)
1181
+ | Ok rrs ->
1182
+ let not_seen_before = List. filter (fun x -> not (List. mem x acc)) rrs in
1183
+ (* If there are any CNAMEs, resolve these too *)
1184
+ let cnames = List. rev @@ List. fold_left (fun acc rr ->
1185
+ match rr.Dns.Packet. rdata with
1186
+ | CNAME name -> name :: acc
1187
+ | _ -> acc
1188
+ ) [] not_seen_before in
1189
+ Lwt_list. fold_left_s
1190
+ (fun acc name -> match acc with
1191
+ | Error e -> Lwt. return (Error e)
1192
+ | Ok acc ->
1193
+ loop acc name ty
1194
+ ) (Ok (acc @ not_seen_before)) cnames in
1195
+ loop [] requested_name ty in
1196
+
1167
1197
begin match question with
1168
1198
| { q_class = Q_IN ; q_name; _ } when q_name = localhost_local ->
1169
1199
Log. debug (fun f -> f " DNS lookup of localhost.local: return NXDomain" );
0 commit comments