2015-12-30 04:52:24 -05:00
|
|
|
(* Copyright (C) 2015, Thomas Leonard <thomas.leonard@unikernel.com>
|
|
|
|
See the README file for details. *)
|
|
|
|
|
|
|
|
open Lwt
|
|
|
|
open Qubes
|
|
|
|
|
|
|
|
let src = Logs.Src.create "unikernel" ~doc:"Main unikernel code"
|
|
|
|
module Log = (val Logs.src_log src : Logs.LOG)
|
|
|
|
|
2017-03-02 09:52:55 -05:00
|
|
|
module Main (Clock : Mirage_clock_lwt.MCLOCK) = struct
|
2015-12-30 08:59:13 -05:00
|
|
|
module Uplink = Uplink.Make(Clock)
|
2015-12-30 04:52:24 -05:00
|
|
|
|
2015-12-30 08:59:13 -05:00
|
|
|
(* Set up networking and listen for incoming packets. *)
|
2017-03-02 09:52:55 -05:00
|
|
|
let network ~clock nat qubesDB =
|
2015-12-30 08:59:13 -05:00
|
|
|
(* Read configuration from QubesDB *)
|
2019-04-28 11:06:03 -04:00
|
|
|
Dao.read_network_config qubesDB >>= fun config ->
|
2015-12-30 08:59:13 -05:00
|
|
|
(* Initialise connection to NetVM *)
|
2017-03-02 09:52:55 -05:00
|
|
|
Uplink.connect ~clock config >>= fun uplink ->
|
2015-12-30 08:59:13 -05:00
|
|
|
(* Report success *)
|
|
|
|
Dao.set_iptables_error qubesDB "" >>= fun () ->
|
|
|
|
(* Set up client-side networking *)
|
|
|
|
let client_eth = Client_eth.create
|
2016-09-25 09:38:17 -04:00
|
|
|
~client_gw:config.Dao.clients_our_ip in
|
2015-12-30 08:59:13 -05:00
|
|
|
(* Set up routing between networks and hosts *)
|
|
|
|
let router = Router.create
|
|
|
|
~client_eth
|
2017-03-02 09:52:55 -05:00
|
|
|
~uplink:(Uplink.interface uplink)
|
|
|
|
~nat
|
|
|
|
in
|
2015-12-30 08:59:13 -05:00
|
|
|
(* Handle packets from both networks *)
|
2016-10-01 05:47:19 -04:00
|
|
|
Lwt.choose [
|
2015-12-30 08:59:13 -05:00
|
|
|
Client_net.listen router;
|
|
|
|
Uplink.listen uplink router
|
|
|
|
]
|
|
|
|
|
2016-01-17 08:19:40 -05:00
|
|
|
(* We don't use the GUI, but it's interesting to keep an eye on it.
|
2019-01-10 07:39:39 -05:00
|
|
|
If the other end dies, don't let it take us with it (can happen on logout). *)
|
2016-01-17 08:19:40 -05:00
|
|
|
let watch_gui gui =
|
|
|
|
Lwt.async (fun () ->
|
|
|
|
Lwt.try_bind
|
2019-01-10 07:39:39 -05:00
|
|
|
(fun () ->
|
|
|
|
gui >>= fun gui ->
|
|
|
|
Log.info (fun f -> f "GUI agent connected");
|
|
|
|
GUI.listen gui
|
|
|
|
)
|
2016-01-17 08:19:40 -05:00
|
|
|
(fun `Cant_happen -> assert false)
|
|
|
|
(fun ex ->
|
|
|
|
Log.warn (fun f -> f "GUI thread failed: %s" (Printexc.to_string ex));
|
|
|
|
return ()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2015-12-30 08:59:13 -05:00
|
|
|
(* Main unikernel entry point (called from auto-generated main.ml). *)
|
2017-03-02 09:52:55 -05:00
|
|
|
let start clock =
|
|
|
|
let start_time = Clock.elapsed_ns clock in
|
2015-12-30 04:52:24 -05:00
|
|
|
(* Start qrexec agent, GUI agent and QubesDB agent in parallel *)
|
|
|
|
let qrexec = RExec.connect ~domid:0 () in
|
2019-01-10 07:39:39 -05:00
|
|
|
GUI.connect ~domid:0 () |> watch_gui;
|
2015-12-30 04:52:24 -05:00
|
|
|
let qubesDB = DB.connect ~domid:0 () in
|
|
|
|
(* Wait for clients to connect *)
|
|
|
|
qrexec >>= fun qrexec ->
|
|
|
|
let agent_listener = RExec.listen qrexec Command.handler in
|
|
|
|
qubesDB >>= fun qubesDB ->
|
2017-03-02 09:52:55 -05:00
|
|
|
let startup_time =
|
|
|
|
let (-) = Int64.sub in
|
|
|
|
let time_in_ns = Clock.elapsed_ns clock - start_time in
|
|
|
|
Int64.to_float time_in_ns /. 1e9
|
|
|
|
in
|
2019-01-10 07:39:39 -05:00
|
|
|
Log.info (fun f -> f "QubesDB and qrexec agents connected in %.3f s" startup_time);
|
2015-12-30 04:52:24 -05:00
|
|
|
(* Watch for shutdown requests from Qubes *)
|
2016-01-08 06:31:27 -05:00
|
|
|
let shutdown_rq =
|
|
|
|
OS.Lifecycle.await_shutdown_request () >>= fun (`Poweroff | `Reboot) ->
|
|
|
|
return () in
|
2015-12-30 04:52:24 -05:00
|
|
|
(* Set up networking *)
|
2017-03-10 11:09:36 -05:00
|
|
|
let get_time () = Clock.elapsed_ns clock in
|
2017-03-15 04:56:24 -04:00
|
|
|
let max_entries = Key_gen.nat_table_size () in
|
|
|
|
My_nat.create ~get_time ~max_entries >>= fun nat ->
|
2017-03-02 09:52:55 -05:00
|
|
|
let net_listener = network ~clock nat qubesDB in
|
2016-01-02 10:59:59 -05:00
|
|
|
(* Report memory usage to XenStore *)
|
|
|
|
Memory_pressure.init ();
|
2015-12-30 04:52:24 -05:00
|
|
|
(* Run until something fails or we get a shutdown request. *)
|
2015-12-30 08:59:13 -05:00
|
|
|
Lwt.choose [agent_listener; net_listener; shutdown_rq] >>= fun () ->
|
2015-12-30 04:52:24 -05:00
|
|
|
(* Give the console daemon time to show any final log messages. *)
|
2017-03-02 09:52:55 -05:00
|
|
|
OS.Time.sleep_ns (1.0 *. 1e9 |> Int64.of_float)
|
2015-12-30 04:52:24 -05:00
|
|
|
end
|