|
1 | | -let broadcast = Ok Macaddr.broadcast |
| 1 | +type r = Mac of Macaddr.t | Arp of Ipaddr.V4.t |
2 | 2 |
|
3 | | -let macaddr_of_multicast ipaddr = |
4 | | - let buf = Ipaddr.V4.to_octets ipaddr in |
5 | | - let mac = Bytes.create 6 in |
6 | | - Bytes.set_uint8 mac 0 0x01; |
7 | | - Bytes.set_uint8 mac 1 0x00; |
8 | | - Bytes.set_uint8 mac 2 0x5e; |
9 | | - Bytes.set_uint8 mac 3 (String.get_uint8 buf 1 land 0x7f); |
10 | | - Bytes.set_uint8 mac 4 (String.get_uint8 buf 2); |
11 | | - Bytes.set_uint8 mac 5 (String.get_uint8 buf 3); |
12 | | - Macaddr.of_octets_exn (Bytes.unsafe_to_string mac) |
13 | | - |
14 | | -let destination_macaddr network gateway arp ipaddr = |
15 | | - if |
16 | | - Ipaddr.V4.(compare broadcast) ipaddr == 0 |
17 | | - || Ipaddr.V4.(compare any) ipaddr == 0 |
18 | | - || Ipaddr.V4.(compare (Prefix.broadcast network)) ipaddr == 0 |
19 | | - then broadcast |
20 | | - else if Ipaddr.V4.is_multicast ipaddr then Ok (macaddr_of_multicast ipaddr) |
21 | | - else if Ipaddr.V4.Prefix.mem ipaddr network then ARPv4.query arp ipaddr |
| 3 | +let routing network gateway ~src ~dst = |
| 4 | + if Ipaddr.V4.Prefix.(mem dst loopback) || Ipaddr.V4.Prefix.(mem src loopback) |
| 5 | + then |
| 6 | + (* avoid packets to or from 127.0.0.0/8 *) |
| 7 | + Error `Loopback |
| 8 | + else if |
| 9 | + Ipaddr.V4.(compare broadcast) dst == 0 |
| 10 | + || Ipaddr.V4.(compare (Prefix.broadcast network)) dst == 0 |
| 11 | + then |
| 12 | + (* use broadcast mac *) |
| 13 | + Ok (Mac Macaddr.broadcast) |
| 14 | + else if Ipaddr.V4.is_multicast dst then |
| 15 | + (* filter multicast *) |
| 16 | + Ok (Mac (Ipaddr.V4.multicast_to_mac dst)) |
| 17 | + else if Ipaddr.V4.Prefix.mem dst network then |
| 18 | + (* direct to this network *) |
| 19 | + Ok (Arp dst) |
22 | 20 | else |
| 21 | + (* send to gateway *) |
23 | 22 | match gateway with |
24 | 23 | | None -> Error `Gateway |
25 | | - | Some gateway -> ARPv4.query arp gateway |
| 24 | + | Some gateway -> Ok (Arp gateway) |
| 25 | + |
| 26 | +let ( let* ) = Result.bind |
| 27 | + |
| 28 | +let destination_macaddr network gateway arp ~src ~dst = |
| 29 | + let* it = routing network gateway ~src ~dst in |
| 30 | + match it with Mac x -> Ok x | Arp ip -> ARPv4.query arp ip |
26 | 31 |
|
27 | | -let destination_macaddr_without_interruption network gateway arp ipaddr = |
28 | | - if |
29 | | - Ipaddr.V4.(compare broadcast) ipaddr == 0 |
30 | | - || Ipaddr.V4.(compare any) ipaddr == 0 |
31 | | - || Ipaddr.V4.(compare (Prefix.broadcast network)) ipaddr == 0 |
32 | | - then Result.to_option broadcast |
33 | | - else if Ipaddr.V4.is_multicast ipaddr then Some (macaddr_of_multicast ipaddr) |
34 | | - else if Ipaddr.V4.Prefix.mem ipaddr network then ARPv4.ask arp ipaddr |
35 | | - else match gateway with None -> None | Some gateway -> ARPv4.ask arp gateway |
| 32 | +let destination_macaddr_without_interruption network gateway arp ~src ~dst = |
| 33 | + match routing network gateway ~src ~dst with |
| 34 | + | Error _ -> None |
| 35 | + | Ok (Mac x) -> Some x |
| 36 | + | Ok (Arp ip) -> ARPv4.ask arp ip |
0 commit comments