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

76 lines
2.5 KiB
OCaml
Raw Normal View History

2023-06-13 02:36:32 +02:00
open Types
open Utils
let parse_header 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-14 16:37:30 +02:00
let rec parse_question reader =
let name, offset_name = decode_name_simple 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"
and decode_name_simple 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 (
let decoded_name = decode_compressed_name reader length in
length + 1, 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
(*
---
def decode_compressed_name(length, reader):
pointer_bytes = bytes([length & 0b0011_1111]) + reader.read(1)
pointer = struct.unpack("!H", pointer_bytes)[0]
current_pos = reader.tell()
reader.seek(pointer)
result = decode_name(reader)
reader.seek(current_pos)
return result
---
*)
and decode_compressed_name _reader _length =
(* TODO *)
String.empty
2023-06-14 16:34:49 +02:00
;;
2023-06-14 16:54:55 +02:00
(*
---
def parse_record(reader):
name = decode_name_simple(reader)
# the the type, class, TTL, and data length together are 10 bytes (2 + 2 + 4 + 2 = 10)
# so we read 10 bytes
data = reader.read(10)
# HHIH means 2-byte int, 2-byte-int, 4-byte int, 2-byte int
type_, class_, ttl, data_len = struct.unpack("!HHIH", data)
data = reader.read(data_len)
return DNSRecord(name, type_, class_, ttl, data)
---
*)
let parse_record reader =
let name, _offset_name = decode_name_simple reader in
(* TODO *)
let type_, class_, ttl, data = 0, 0, 0, Bytes.empty in
2023-06-14 16:54:55 +02:00
{ name; type_; class_; ttl; data }
;;