From a626ab534224cc244d58259e622b9a59703223f6 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Sat, 27 Oct 2018 22:17:16 +0200 Subject: sid: optionally handle big endian in packet format codec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Oddly enough this only has an effect on the sub_auths since the 48 bits of “identifier authority” are always handled in big endian. --- sid.ml | 68 +++++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'sid.ml') diff --git a/sid.ml b/sid.ml index 9f1e591..ddfb8e1 100644 --- a/sid.ml +++ b/sid.ml @@ -80,10 +80,9 @@ module StringFmt = struct let decode s = let n = String.length s in if n <= 4 then - raise - (Invalid_argument - (Printf.sprintf - "Invalid SID: ‘%s’ too short to be a SID in string format" s)) + Error + (Printf.sprintf + "Invalid SID: ‘%s’ too short to be a SID in string format" s) else expect_char s 'S' 0; expect_char s '-' 1; @@ -98,15 +97,9 @@ module StringFmt = struct sa := d :: !sa; p' := np done; - { sid_ident_auth = ia - ; sid_sub_auths = Array.of_list (List.rev !sa) - } - - let from_string_res s = - try Ok (decode s) with Invalid_argument msg -> Error msg - - let from_string_opt s = - try Some (decode s) with Invalid_argument _ -> None + Ok { sid_ident_auth = ia + ; sid_sub_auths = Array.of_list (List.rev !sa) + } let fmt_ident_auth b ia = Buffer.add_string b (U64.to_string ia) @@ -129,17 +122,24 @@ end (* [module StringFmt] *) module PacketRep = struct (* [MS-DTYP] 2.4.22 *) - (* XXX configurable endianness *) + type endian = Big | Little - let encode s = + let wordlen = 4 (* sizeof int *) + let min_pktrep_len = 1 + 1 + sizeof_ident_auth + let max_pktrep_len = 1 + 1 + + sizeof_ident_auth + + max_subauth_count * sizeof_sub_auth + let pktrep_sa_off = min_pktrep_len + + let encode ?(endian=Little) s = let nsa = Array.length s.sid_sub_auths in let l = 8 + nsa * sizeof_sub_auth in - let b = Buffer.create l in + let b = Bytes.create l in + let o = ref 0 in + let pushbyte c = char_of_int c |> Bytes.set b !o; incr o in assert (0 <= nsa && nsa <= 15); - let pushbyte c = char_of_int c |> Buffer.add_char b in - pushbyte 1; pushbyte nsa; @@ -148,20 +148,19 @@ module PacketRep = struct (* [MS-DTYP] 2.4.22 *) in (* big endian!, cf. [MS-DTYP] 2.4.1.1 *) getia 5; getia 4; getia 3; getia 2; getia 1; getia 0; - let getsa sa n = pushbyte (U32.to_int (U32.shift_right sa n) land 0xff) in - Array.iter - (fun sa -> getsa sa 0; getsa sa 1; getsa sa 2; getsa sa 3) + let write_u32 = + match endian with + | Big -> U32.to_bytes_big_endian + | Little -> U32.to_bytes_little_endian + in + Array.iteri + (fun i sa -> + let o' = !o + i * wordlen in + write_u32 sa b o') s.sid_sub_auths; - Bytes.unsafe_of_string (Buffer.contents b) + b - let wordlen = 4 (* sizeof int *) - let min_pktrep_len = 1 + 1 + sizeof_ident_auth - let max_pktrep_len = 1 + 1 - + sizeof_ident_auth - + max_subauth_count * sizeof_sub_auth - let pktrep_sa_off = min_pktrep_len - - let decode b = + let decode ?(endian=Little) b = let l = Bytes.length b in if l < min_pktrep_len || max_pktrep_len < l then Error (Printf.sprintf @@ -188,10 +187,15 @@ module PacketRep = struct (* [MS-DTYP] 2.4.22 *) let ia = U64.zero |> getbyte 2 |> getbyte 3 |> getbyte 4 |> getbyte 5 |> getbyte 6 |> getbyte 7 in - let sas = Array.make nsa (U32.zero) in + let sas = Array.make nsa (U32.zero) + and read_u32 = + match endian with + | Big -> U32.of_bytes_big_endian + | Little -> U32.of_bytes_little_endian + in for i = 0 to (nsa - 1) do let off = pktrep_sa_off + i * sizeof_sub_auth in - sas.(i) <- U32.of_bytes_little_endian b off + sas.(i) <- read_u32 b off done; Ok { sid_ident_auth = ia ; sid_sub_auths = sas -- cgit v1.2.3