This repository has been archived on 2024-05-23. You can view files and clone it, but cannot push or open issues or pull requests.
dns-toy/lib/network.ml

60 lines
2 KiB
OCaml
Raw Permalink Normal View History

2023-06-11 10:54:58 +02:00
open Unix
open Query
2023-07-04 13:12:59 +02:00
open Types
2023-06-11 10:54:58 +02:00
2023-07-04 10:50:15 +02:00
let send_request dns url record_type =
let query = build url record_type in
2023-06-11 10:54:58 +02:00
let sock = socket PF_INET SOCK_DGRAM 0 in
let server_addr = ADDR_INET (inet_addr_of_string dns, 53) in
ignore (sendto sock query 0 (Bytes.length query) [] server_addr);
let buffer_size = 1024 in
let response = Bytes.create buffer_size in
let len, _ = recvfrom sock response 0 buffer_size [] in
Bytes.sub response 0 len
;;
2023-06-19 23:23:13 +02:00
let lookup_domain domain =
2023-07-04 10:50:15 +02:00
let response = send_request "8.8.8.8" domain Types.DNSType.a in
2023-06-19 23:23:13 +02:00
let dns_packet = Response.parse_dns_packet response in
2023-07-04 10:50:15 +02:00
if dns_packet.header.num_answers > 0
then Some (List.nth dns_packet.answers 0).data
else None
;;
let send ip_address domain_name record_type =
let query = send_request ip_address domain_name record_type in
Response.parse_dns_packet query
2023-06-19 23:23:13 +02:00
;;
2023-07-04 13:12:59 +02:00
let rec resolve domain_name record_type = resolve_aux "198.41.0.4" domain_name record_type
and resolve_aux nameserver domain_name record_type =
Printf.printf "Querying %s for %s\n" nameserver domain_name;
let response = send nameserver domain_name record_type in
match get_answer response with
| Some ip -> String.of_bytes ip
| None ->
(match get_nameserver_ip response with
| Some ns_ip -> resolve_aux ns_ip domain_name record_type
| None ->
(match get_nameserver response with
| Some ns_domain ->
resolve_aux (resolve ns_domain DNSType.a) domain_name record_type
| None -> raise (Failure "Something went wrong")))
and get_answer packet =
match List.find_opt (fun el -> el.type_ = DNSType.a) packet.answers with
| Some record -> Some record.data
| None -> None
and get_nameserver_ip packet =
match List.find_opt (fun el -> el.type_ = DNSType.a) packet.additionals with
| Some record -> Some (String.of_bytes record.data)
| None -> None
and get_nameserver packet =
match List.find_opt (fun el -> el.type_ = DNSType.ns) packet.authorities with
| Some record -> Some (String.of_bytes record.data)
| None -> None
;;