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
let broadcast = Ok Macaddr.broadcast
let macaddr_of_multicast ipaddr =
let buf = Ipaddr.V4.to_octets ipaddr in
let mac = Bytes.create 6 in
Bytes.set_uint8 mac 0 0x01;
Bytes.set_uint8 mac 1 0x00;
Bytes.set_uint8 mac 2 0x5e;
Bytes.set_uint8 mac 3 (String.get_uint8 buf 1 land 0x7f);
Bytes.set_uint8 mac 4 (String.get_uint8 buf 2);
Bytes.set_uint8 mac 5 (String.get_uint8 buf 3);
Macaddr.of_octets_exn (Bytes.unsafe_to_string mac)
let destination_macaddr network gateway arp ipaddr =
if
Ipaddr.V4.(compare broadcast) ipaddr == 0
|| Ipaddr.V4.(compare any) ipaddr == 0
|| Ipaddr.V4.(compare (Prefix.broadcast network)) ipaddr == 0
then broadcast
else if Ipaddr.V4.is_multicast ipaddr then Ok (macaddr_of_multicast ipaddr)
else if Ipaddr.V4.Prefix.mem ipaddr network then ARPv4.query arp ipaddr
else
match gateway with
| None -> Error `Gateway
| Some gateway -> ARPv4.query arp gateway
let destination_macaddr_without_interruption network gateway arp ipaddr =
if
Ipaddr.V4.(compare broadcast) ipaddr == 0
|| Ipaddr.V4.(compare any) ipaddr == 0
|| Ipaddr.V4.(compare (Prefix.broadcast network)) ipaddr == 0
then Result.to_option broadcast
else if Ipaddr.V4.is_multicast ipaddr then Some (macaddr_of_multicast ipaddr)
else if Ipaddr.V4.Prefix.mem ipaddr network then ARPv4.ask arp ipaddr
else match gateway with None -> None | Some gateway -> ARPv4.ask arp gateway