mirror of
https://github.com/mirage/qubes-mirage-firewall.git
synced 2024-10-01 01:05:39 -04:00
62aec06be9
Before, when resetting the NAT table to handle an out-of-memory condition we tried to allocate the new table while still holding the reference to the old one. It should be more reliable to drop the old reference first. Log showed: 2016-01-31 19:33.47: INF [firewall] added NAT redirect 10.137.3.12:32860 -> 53:firewall:52517 -> 53:net-vm 2016-01-31 19:33.52: WRN [firewall] Out_of_memory adding NAT rule. Dropping NAT table... --- End dump --- Fatal error: exception Out of memory Raised by primitive operation at file "hashtbl.ml", line 63, characters 52-70 Called from file "router.ml", line 47, characters 11-30 Called from file "src/core/lwt.ml", line 907, characters 20-24 Mirage exiting with status 2 Do_exit called!
54 lines
1.7 KiB
OCaml
54 lines
1.7 KiB
OCaml
(* Copyright (C) 2015, Thomas Leonard <thomas.leonard@unikernel.com>
|
|
See the README file for details. *)
|
|
|
|
open Utils
|
|
|
|
let src = Logs.Src.create "router" ~doc:"Router"
|
|
module Log = (val Logs.src_log src : Logs.LOG)
|
|
|
|
(* The routing table *)
|
|
|
|
type t = {
|
|
client_eth : Client_eth.t;
|
|
mutable nat : Nat_lookup.t;
|
|
uplink : interface;
|
|
}
|
|
|
|
let create ~client_eth ~uplink =
|
|
let nat = Nat_lookup.empty () in
|
|
{ client_eth; nat; uplink }
|
|
|
|
let target t buf =
|
|
let open Wire_structs.Ipv4_wire in
|
|
let dst_ip = get_ipv4_dst buf |> Ipaddr.V4.of_int32 in
|
|
if Ipaddr.V4.Prefix.mem dst_ip (Client_eth.prefix t.client_eth) then (
|
|
match Client_eth.lookup t.client_eth dst_ip with
|
|
| Some client_link -> Some (client_link :> interface)
|
|
| None ->
|
|
Log.warn (fun f -> f "Packet to unknown internal client %a - dropping"
|
|
Ipaddr.V4.pp_hum dst_ip);
|
|
None
|
|
) else Some t.uplink
|
|
|
|
let add_client t = Client_eth.add_client t.client_eth
|
|
let remove_client t = Client_eth.remove_client t.client_eth
|
|
|
|
let classify t ip =
|
|
if ip = Ipaddr.V4 t.uplink#my_ip then `Firewall_uplink
|
|
else if ip = Ipaddr.V4 t.uplink#other_ip then `NetVM
|
|
else (Client_eth.classify t.client_eth ip :> Packet.host)
|
|
|
|
let resolve t = function
|
|
| `Firewall_uplink -> Ipaddr.V4 t.uplink#my_ip
|
|
| `NetVM -> Ipaddr.V4 t.uplink#other_ip
|
|
| #Client_eth.host as host -> Client_eth.resolve t.client_eth host
|
|
|
|
(* To avoid needing to allocate a new NAT table when we've run out of
|
|
memory, pre-allocate the new one ahead of time. *)
|
|
let next_nat = ref (Nat_lookup.empty ())
|
|
let reset t =
|
|
t.nat <- !next_nat;
|
|
(* (at this point, the big old NAT table can be GC'd, so allocating
|
|
a new one should be OK) *)
|
|
next_nat := Nat_lookup.empty ()
|