Source file udp_packet.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
type t = {
src_port : Cstruct.uint16;
dst_port : Cstruct.uint16;
}
let equal {src_port; dst_port} q =
src_port = q.src_port &&
dst_port = q.dst_port
let pp fmt t =
Format.fprintf fmt "UDP port %d -> %d" t.src_port t.dst_port
module Unmarshal = struct
type error = string
let ( let* ) = Result.bind
let of_cstruct buf =
let open Udp_wire in
let () =
if Cstruct.length buf < sizeof_udp then Error "UDP header too short" else Ok ()
in
let check_payload_length length_of_buffer =
if length_from_header < sizeof_udp then
Error "UDP header claimed a total length < the size of just the header"
else begin
let payload_len = length_from_header - sizeof_udp in
if payload_len > (length_of_buffer - sizeof_udp)
then Error (Printf.sprintf
"UDP header claimed a payload longer than the supplied buffer: %d vs %d."
payload_len length_of_buffer)
else Ok payload_len
end
in
let* () = check_header_length () in
let = get_length buf in
let* payload_len = check_payload_length total_length_from_header (Cstruct.length buf) in
let src_port = get_src_port buf in
let dst_port = get_dst_port buf in
let payload = Cstruct.sub buf sizeof_udp payload_len in
Ok ({ src_port; dst_port; }, payload)
end
module Marshal = struct
type error = string
let unsafe_fill ~ ~payload {src_port; dst_port} udp_buf len =
let open Udp_wire in
let udp_buf = Cstruct.sub udp_buf 0 sizeof_udp in
set_src_port udp_buf src_port;
set_dst_port udp_buf dst_port;
set_length udp_buf len;
set_checksum udp_buf 0;
let csum = Tcpip_checksum.ones_complement_list [ pseudoheader ; udp_buf ; payload ] in
let csum = if csum = 0 then 0xffff else csum in
set_checksum udp_buf csum
let into_cstruct ~ ~payload t udp_buf =
let open Udp_wire in
let () =
if Cstruct.length udp_buf < sizeof_udp then
Error "Not enough space for a UDP header"
else
Ok ()
in
Result.bind (check_header_len ())
(fun () ->
let len = Cstruct.length payload + sizeof_udp in
let buf = Cstruct.sub udp_buf 0 sizeof_udp in
unsafe_fill ~pseudoheader ~payload t buf len;
Ok ())
let make_cstruct ~ ~payload t =
let buf = Cstruct.create Udp_wire.sizeof_udp in
let len = Udp_wire.sizeof_udp + Cstruct.length payload in
unsafe_fill ~pseudoheader ~payload t buf len;
buf
end