-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdao.ml
142 lines (124 loc) · 4.38 KB
/
dao.ml
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
(* Copyright (C) 2015, Thomas Leonard <[email protected]>
See the README file for details. *)
open Lwt.Infix
open Qubes
let src = Logs.Src.create "dao" ~doc:"QubesDB data access"
module Log = (val Logs.src_log src : Logs.LOG)
(* XXX(dinosaure):
{[
@dom0$ xenstore-ls /local/domain/<unikernel-id>
...
backend = ""
vif = ""
<domid> = ""
<deviceid> = ""
frontend = "/local/domain/<domid>/device/vif/<deviceid>"
frontend-id = "<domainid>"
mac = "..."
ip = "..."
]} *)
module Client_vif = struct
type t = { domid : int; device_id : int }
let pp f { domid; device_id } =
Fmt.pf f "/local/domain/%d/device/vif/%d" domid device_id
let compare = Stdlib.compare
end
module Vif_map = struct
include Map.Make (Client_vif)
let rec of_list = function
| [] -> empty
| (k, v) :: rest -> add k v (of_list rest)
end
let directory ~handle dir =
Xen_os.Xs.directory handle dir >|= function [ "" ] -> [] | items -> items
let db_root client_ip = "/qubes-firewall/" ^ Ipaddr.V4.to_string client_ip
let vifs client domid =
let open Lwt.Syntax in
match int_of_string_opt domid with
| None ->
Log.err (fun f -> f "Invalid domid %S" domid);
Lwt.return []
| Some domid ->
let path = Fmt.str "backend/vif/%d" domid in
let fn handle =
let* entries = directory ~handle path in
let fn device_id =
match int_of_string_opt device_id with
| None ->
Log.err (fun m ->
m "Invalid device ID %S for domid %d" device_id domid);
Lwt.return_none
| Some device_id -> (
let vif = { Client_vif.domid; device_id } in
let fn () =
let* str =
Xen_os.Xs.read handle (Fmt.str "%s/%d/ip" path device_id)
in
let[@warning "-8"] (ip :: _) = String.split_on_char ' ' str in
Lwt.return_some (vif, Ipaddr.V4.of_string_exn ip)
in
Lwt.catch fn @@ function
| Xs_protocol.Enoent _ -> Lwt.return_none
| exn ->
Log.err (fun m ->
m "Error getting IP address of %a: %s" Client_vif.pp vif
(Printexc.to_string exn));
Lwt.return_none)
in
Lwt_list.filter_map_p fn entries
in
Xen_os.Xs.immediate client fn
let watch_clients fn =
let open Lwt.Syntax in
Xen_os.Xs.make () >>= fun xs ->
let backend_vifs = "backend/vif" in
Log.info (fun f -> f "Watching %s" backend_vifs);
let watch handle =
let* items =
Lwt.catch
(fun () -> directory ~handle backend_vifs)
(function Xs_protocol.Enoent _ -> Lwt.return [] | exn -> Lwt.fail exn)
in
let* xs = Xen_os.Xs.make () in
let* items = Lwt_list.map_p (vifs xs) items in
fn (List.concat items |> Vif_map.of_list) >>= fun () ->
Lwt.fail Xs_protocol.Eagain
in
Xen_os.Xs.wait xs watch
type network_config = {
ip : Ipaddr.V4.t; (* The IP address of our interface to NetVM *)
gateway : Ipaddr.V4.t; (* The IP address of NetVM (our gateway) *)
dns : Ipaddr.V4.t * Ipaddr.V4.t;
}
exception Missing_key of string
let try_read_network_config db =
let get name =
match DB.KeyMap.find_opt name db with
| None -> raise (Missing_key name)
| Some value -> Ipaddr.V4.of_string_exn value
in
let ip = get "/qubes-ip" in
let gateway = get "/qubes-gateway" in
let dns = (get "/qubes-primary-dns", get "/qubes-secondary-dns") in
{ ip; gateway; dns }
let read_network_config qubesDB =
let rec go bindings =
try Lwt.return (try_read_network_config bindings)
with Missing_key key ->
Log.warn (fun f ->
f "QubesDB key %S not (yet) present; waiting for QubesDB to change..."
key);
DB.after qubesDB bindings >>= go
in
go (DB.bindings qubesDB)
let print_network_config config =
Log.info (fun f ->
f
"@[<v2>Current network configuration (QubesDB or command line):@,\
NetVM IP on uplink network: %a@,\
Our IP on client networks: %a@,\
DNS primary resolver: %a@,\
DNS secondary resolver: %a@]" Ipaddr.V4.pp config.gateway
Ipaddr.V4.pp config.ip Ipaddr.V4.pp (fst config.dns) Ipaddr.V4.pp
(snd config.dns))
let _set_iptables_error db = Qubes.DB.write db "/qubes-iptables-error"