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/response.ml

95 lines
3.6 KiB
OCaml
Raw Permalink Normal View History

2023-06-13 02:36:32 +02:00
open Types
open Utils
2023-06-19 20:30:47 +02:00
let parse_header (reader : reader) =
2023-06-14 16:34:49 +02:00
let max_size = 6 in
match List.init max_size (fun offset -> unpack_short_be reader.data (offset * 2)) with
2023-06-13 02:36:32 +02:00
| [ id; flags; num_questions; num_answers; num_authorities; num_additionals ] ->
( { reader with pointer = reader.pointer + (max_size * 2) }
2023-06-14 16:34:49 +02:00
, { id; flags; num_questions; num_answers; num_authorities; num_additionals } )
| _ -> failwith "Invalid number of fields"
;;
2023-06-19 20:30:47 +02:00
let rec parse_question (reader : reader) =
2023-06-19 19:38:35 +02:00
let name, offset_name = decode_name reader in
let data = bytes_forward reader.data (reader.pointer + offset_name) in
2023-06-14 16:54:55 +02:00
let max_size = 2 in
match List.init max_size (fun offset -> unpack_short_be data (offset * 2)) with
| [ type_; class_ ] ->
( { reader with pointer = reader.pointer + offset_name + (max_size * 2) }
, { name; type_; class_ } )
2023-06-14 16:37:30 +02:00
| _ -> failwith "Invalid number of fields"
2023-06-19 19:38:35 +02:00
and decode_name reader =
2023-06-14 16:34:49 +02:00
let rec read_parts parts pos =
let length = int_of_char (Bytes.get reader.data (reader.pointer + pos)) in
2023-06-14 16:34:49 +02:00
if length = 0
then 1, parts
else if length land 0b1100_0000 <> 0
then (
2023-07-04 13:12:45 +02:00
let decoded_name =
decode_compressed_name { reader with pointer = reader.pointer + pos } length
in
2023-06-14 18:53:13 +02:00
2, decoded_name :: parts)
2023-06-14 16:34:49 +02:00
else (
let part = Bytes.sub_string reader.data (reader.pointer + pos + 1) length in
2023-06-14 16:34:49 +02:00
let last_length, parts' = read_parts (parts @ [ part ]) (pos + 1 + length) in
last_length + length + 1, parts')
in
let offset, parts = read_parts [] 0 in
String.to_bytes (String.concat "." parts), offset
2023-06-19 19:38:35 +02:00
and decode_compressed_name reader length =
2023-07-04 13:12:45 +02:00
let pointer_bytes =
Bytes.cat
(int_to_bytes (length land 0b0011_1111))
(Bytes.sub reader.data (reader.pointer + 1) 1)
2023-06-19 19:38:35 +02:00
in
2023-07-04 13:12:45 +02:00
let pointer = unpack_short_be pointer_bytes 0 in
2023-06-19 19:38:35 +02:00
String.of_bytes (fst (decode_name { reader with pointer }))
2023-06-14 16:34:49 +02:00
;;
2023-06-14 16:54:55 +02:00
let parse_record reader =
2023-06-19 20:03:27 +02:00
let name, offset_name = decode_name reader in
let data = bytes_forward reader.data (offset_name + reader.pointer) in
2023-06-19 21:52:39 +02:00
let data_len = unpack_short_be data 8 in
let record_len = 10 in
let type_ = unpack_short_be data 0 in
2023-06-19 21:52:39 +02:00
( { reader with pointer = reader.pointer + offset_name + record_len + data_len }
, { name
; type_
2023-06-19 21:52:39 +02:00
; class_ = unpack_short_be data 2
; ttl = unpack_int_be data 4
; data =
(let raw_data = Bytes.sub data record_len data_len in
match type_ with
| t when t = DNSType.ns ->
fst
(decode_name
{ reader with pointer = reader.pointer + offset_name + record_len })
| t when t = DNSType.a -> String.to_bytes (get_ip raw_data)
| _ -> raw_data)
2023-06-19 21:52:39 +02:00
} )
;;
let parse_dns_packet data =
2023-06-19 22:52:01 +02:00
let rec create_list reader n fn acc =
if n = 0
then reader, List.rev acc
else (
let next_reader, res = fn reader in
create_list next_reader (n - 1) fn (res :: acc))
in
let reader, header = parse_header { data; pointer = 0 } in
let reader2, questions = create_list reader header.num_questions parse_question [] in
let reader3, answers = create_list reader2 header.num_answers parse_record [] in
let reader4, authorities = create_list reader3 header.num_authorities parse_record [] in
let _, additionals = create_list reader4 header.num_additionals parse_record [] in
(* print_endline (Debug.dns_header header);
List.iter (fun el -> print_endline (Debug.dns_question el)) questions;
List.iter (fun el -> print_endline (Debug.dns_record el)) answers;
List.iter (fun el -> print_endline (Debug.dns_record el)) authorities;
List.iter (fun el -> print_endline (Debug.dns_record el)) additionals; *)
{ header; questions; answers; authorities; additionals }
2023-06-14 16:54:55 +02:00
;;