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
type r = Mac of Macaddr.t | Arp of Ipaddr.V4.t
let routing network gateway ~src ~dst =
if Ipaddr.V4.Prefix.(mem dst loopback) || Ipaddr.V4.Prefix.(mem src loopback)
then
Error `Loopback
else if
Ipaddr.V4.(compare broadcast) dst == 0
|| Ipaddr.V4.(compare (Prefix.broadcast network)) dst == 0
then
Ok (Mac Macaddr.broadcast)
else if Ipaddr.V4.is_multicast dst then
Ok (Mac (Ipaddr.V4.multicast_to_mac dst))
else if Ipaddr.V4.Prefix.mem dst network then
Ok (Arp dst)
else
match gateway with
| None -> Error `Gateway
| Some gateway -> Ok (Arp gateway)
let ( let* ) = Result.bind
let destination_macaddr network gateway arp ~src ~dst =
let* it = routing network gateway ~src ~dst in
match it with Mac x -> Ok x | Arp ip -> ARPv4.query arp ip
let destination_macaddr_without_interruption network gateway arp ~src ~dst =
match routing network gateway ~src ~dst with
| Error _ -> None
| Ok (Mac x) -> Some x
| Ok (Arp ip) -> ARPv4.ask arp ip