summaryrefslogtreecommitdiff
path: root/src/adapter
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2024-11-07 18:02:08 +0000
committerGitHub <noreply@github.com>2024-11-07 18:02:08 +0000
commit196fdd7fdf6dcf751b7364c59e34278bfd0193e3 (patch)
treecfeff0991481c8281e24cf1698b20a76854059a4 /src/adapter
parentdd9271b4304c6b1a5a2576821d1b2b8fd3aa6bf5 (diff)
parent9b90d3cc4da72c13ef4270150e4b547ff03fc813 (diff)
downloadvyconf-196fdd7fdf6dcf751b7364c59e34278bfd0193e3.tar.gz
vyconf-196fdd7fdf6dcf751b7364c59e34278bfd0193e3.zip
Merge pull request #11 from jestabro/vyconf-minimal
T6718: use the vyconf daemon for validation of set commands
Diffstat (limited to 'src/adapter')
-rw-r--r--src/adapter/vy_delete.ml30
-rw-r--r--src/adapter/vy_load_config.ml47
-rw-r--r--src/adapter/vy_set.ml77
-rw-r--r--src/adapter/vyos1x_adapter.ml140
-rw-r--r--src/adapter/vyos1x_adapter.mli16
5 files changed, 310 insertions, 0 deletions
diff --git a/src/adapter/vy_delete.ml b/src/adapter/vy_delete.ml
new file mode 100644
index 0000000..304e74b
--- /dev/null
+++ b/src/adapter/vy_delete.ml
@@ -0,0 +1,30 @@
+let () =
+ let path_list = Array.to_list (Array.sub Sys.argv 1 (Array.length Sys.argv - 1))
+ in
+ let () =
+ if List.length path_list = 0 then
+ (Printf.printf "no path specified\n"; exit 1)
+ in
+ let handle =
+ let h = Vyos1x_adapter.cstore_handle_init () in
+ if not (Vyos1x_adapter.cstore_in_config_session_handle h) then
+ (Vyos1x_adapter.cstore_handle_free h;
+ Printf.printf "not in config session\n"; exit 1)
+ else Some h
+ in
+ let output =
+ match handle with
+ | Some h -> Vyos1x_adapter.cstore_delete_path h path_list
+ | None -> "missing session handle"
+ in
+ let ret =
+ if output = "" then 0
+ else 1
+ in
+ let () =
+ match handle with
+ | Some h -> Vyos1x_adapter.cstore_handle_free h
+ | None -> ()
+ in
+ let () = print_endline output in
+ exit ret
diff --git a/src/adapter/vy_load_config.ml b/src/adapter/vy_load_config.ml
new file mode 100644
index 0000000..66bbfb8
--- /dev/null
+++ b/src/adapter/vy_load_config.ml
@@ -0,0 +1,47 @@
+(* Adapter load_config
+ *)
+
+open Vyos1x
+
+let read_config filename =
+ let ch = open_in filename in
+ let s = really_input_string ch (in_channel_length ch) in
+ let ct =
+ try
+ Ok (Parser.from_string s)
+ with Vyos1x.Util.Syntax_error (opt, msg) ->
+ begin
+ match opt with
+ | None -> Error msg
+ | Some (line, pos) ->
+ let out = Printf.sprintf "%s line %d pos %d\n" msg line pos
+ in Error out
+ end
+ in
+ close_in ch;
+ ct
+
+let read_configs f g =
+ let l = read_config f in
+ let r = read_config g in
+ match l, r with
+ | Ok left, Ok right -> Ok (left, right)
+ | Error msg_l, Error msg_r -> Error (msg_l ^ msg_r)
+ | Error msg_l, _ -> Error msg_l
+ | _, Error msg_r -> Error msg_r
+
+
+let args = []
+let usage = Printf.sprintf "Usage: %s <config> <new config>" Sys.argv.(0)
+
+let () = if Array.length Sys.argv <> 3 then (Arg.usage args usage; exit 1)
+
+let () =
+let left_name = Sys.argv.(1) in
+let right_name = Sys.argv.(2) in
+let read = read_configs left_name right_name in
+let res =
+ match read with
+ | Ok (left, right) -> Vyos1x_adapter.load_config left right
+ | Error msg -> msg
+in Printf.printf "%s\n" res
diff --git a/src/adapter/vy_set.ml b/src/adapter/vy_set.ml
new file mode 100644
index 0000000..b631de0
--- /dev/null
+++ b/src/adapter/vy_set.ml
@@ -0,0 +1,77 @@
+let valid = ref false
+
+let format_out l =
+ let fl = List.filter (fun s -> (String.length s) > 0) l in
+ String.concat "\n\n" fl
+
+let is_valid v =
+ match v with
+ | None -> true
+ | Some _ -> false
+
+let valid_err v =
+ Option.value v ~default:""
+
+let () =
+ let path_list = Array.to_list (Array.sub Sys.argv 1 (Array.length Sys.argv - 1))
+ in
+ let () =
+ if List.length path_list = 0 then
+ (Printf.printf "no path specified\n"; exit 1)
+ in
+ let legacy =
+ try
+ let _ = Sys.getenv "LEGACY_VALIDATE" in
+ true
+ with Not_found -> false
+ in
+ let no_set =
+ try
+ let _ = Sys.getenv "LEGACY_NO_SET" in
+ true
+ with Not_found -> false
+ in
+ let handle =
+ if legacy || not no_set then
+ let h = Vyos1x_adapter.cstore_handle_init () in
+ if not (Vyos1x_adapter.cstore_in_config_session_handle h) then
+ (Vyos1x_adapter.cstore_handle_free h;
+ Printf.printf "not in config session\n"; exit 1)
+ else Some h
+ else None
+ in
+ let valid =
+ if not legacy then
+ Vyos1x_adapter.vyconf_validate_path path_list
+ else
+ begin
+ let out =
+ match handle with
+ | Some h -> Vyos1x_adapter.legacy_validate_path h path_list
+ | None -> "missing session handle"
+ in
+ match out with
+ | "" -> None
+ | _ -> Some out
+ end
+ in
+ let res =
+ if not no_set && (is_valid valid) then
+ match handle with
+ | Some h ->
+ Vyos1x_adapter.cstore_set_path h path_list
+ | None -> "missing session handle"
+ else ""
+ in
+ let ret =
+ if (is_valid valid) && (res = "") then 0
+ else 1
+ in
+ let output = format_out [(valid_err valid); res] in
+ let () =
+ match handle with
+ | Some h -> Vyos1x_adapter.cstore_handle_free h
+ | None -> ()
+ in
+ let () = print_endline output in
+ exit ret
diff --git a/src/adapter/vyos1x_adapter.ml b/src/adapter/vyos1x_adapter.ml
new file mode 100644
index 0000000..5835f5a
--- /dev/null
+++ b/src/adapter/vyos1x_adapter.ml
@@ -0,0 +1,140 @@
+open Ctypes
+open Foreign
+
+let libvyatta = Dl.dlopen ~flags:[Dl.RTLD_LAZY] ~filename:"libvyatta-cfg.so"
+
+let cstore_init = foreign ~from:libvyatta "vy_cstore_init" (void @-> returning uint64_t)
+let cstore_free = foreign ~from:libvyatta "vy_cstore_free" (uint64_t @-> returning void)
+let in_session = foreign ~from:libvyatta "vy_in_session" (uint64_t @-> returning int)
+let cstore_set_path = foreign ~from:libvyatta "vy_set_path" (uint64_t @-> (ptr void) @-> size_t @-> returning string)
+let cstore_del_path = foreign ~from:libvyatta "vy_delete_path" (uint64_t @-> (ptr void) @-> size_t @-> returning string)
+let cstore_validate_path = foreign ~from:libvyatta "vy_validate_path" (uint64_t @-> (ptr void) @-> size_t @-> returning string)
+let cstore_legacy_set_path = foreign ~from:libvyatta "vy_legacy_set_path" (uint64_t @-> (ptr void) @-> size_t @-> returning string)
+
+let cstore_handle_init () = Unsigned.UInt64.to_int (cstore_init ())
+let cstore_handle_free h = cstore_free (Unsigned.UInt64.of_int h)
+let cstore_in_config_session_handle h = in_session (Unsigned.UInt64.of_int h) = 1
+let cstore_in_config_session () = cstore_in_config_session_handle (cstore_handle_init ())
+
+let cstore_set_path handle path =
+ let len = List.length path in
+ let arr = CArray.of_list string path in
+ cstore_set_path (Unsigned.UInt64.of_int handle) (to_voidp (CArray.start arr)) (Unsigned.Size_t.of_int len)
+
+let legacy_validate_path handle path =
+ let len = List.length path in
+ let arr = CArray.of_list string path in
+ cstore_validate_path (Unsigned.UInt64.of_int handle) (to_voidp (CArray.start arr)) (Unsigned.Size_t.of_int len)
+
+let legacy_set_path handle path =
+ let len = List.length path in
+ let arr = CArray.of_list string path in
+ cstore_legacy_set_path (Unsigned.UInt64.of_int handle) (to_voidp (CArray.start arr)) (Unsigned.Size_t.of_int len)
+
+let cstore_delete_path handle path =
+ let len = List.length path in
+ let arr = CArray.of_list string path in
+ cstore_del_path (Unsigned.UInt64.of_int handle) (to_voidp (CArray.start arr)) (Unsigned.Size_t.of_int len)
+
+let set_path_reversed handle path _len =
+ let path = List.rev path in
+ cstore_set_path handle path
+
+let delete_path_reversed handle path _len =
+ let path = List.rev path in
+ cstore_delete_path handle path
+
+module VC = Client.Vyconf_client_session
+
+let get_sockname =
+ "/var/run/vyconfd.sock"
+
+let vyconf_validate_path path =
+ let socket = get_sockname in
+ let token = VC.session_init socket in
+ match token with
+ | Error e -> Some e
+ | Ok token ->
+ let out = VC.session_validate_path socket token path in
+ let _ = VC.session_free socket token in
+ match out with
+ | Ok _ -> None
+ | Error e -> Some e
+
+open Vyos1x
+
+module CT = Config_tree
+module CD = Config_diff
+
+module ValueSet = Set.Make(String)
+
+let add_value handle acc out v =
+ let acc = v :: acc in
+ out ^ (set_path_reversed handle acc (List.length acc))
+
+let add_values handle acc out vs =
+ match vs with
+ | [] -> out ^ (set_path_reversed handle acc (List.length acc))
+ | _ -> List.fold_left (add_value handle acc) out vs
+
+let rec add_path handle acc out (node : CT.t) =
+ let acc = (Vytree.name_of_node node) :: acc in
+ let children = Vytree.children_of_node node in
+ match children with
+ | [] -> let data = Vytree.data_of_node node in
+ let values = data.values in
+ add_values handle acc out values
+ | _ -> List.fold_left (add_path handle acc) out children
+
+let del_value handle acc out v =
+ let acc = v :: acc in
+ out ^ (delete_path_reversed handle acc (List.length acc))
+
+let del_values handle acc out vs =
+ match vs with
+ | [] -> out ^ (delete_path_reversed handle acc (List.length acc))
+ | _ -> List.fold_left (del_value handle acc) out vs
+
+let del_path handle path out =
+ out ^ (cstore_delete_path handle path)
+
+(*
+let update_data (CD.Diff_cstore data) m =
+ CD.Diff_cstore { data with out = m; }
+*)
+
+let cstore_diff ?recurse:_ (path : string list) (CD.Diff_cstore res) (m : CD.change) =
+ let handle = res.handle in
+ match m with
+ | Added -> let node = Vytree.get res.right path in
+ let acc = List.tl (List.rev path) in
+ CD.Diff_cstore { res with out = add_path handle acc res.out node }
+ | Subtracted -> CD.Diff_cstore { res with out = del_path handle path res.out }
+ | Unchanged -> CD.Diff_cstore (res)
+ | Updated v ->
+ let ov = CT.get_values res.left path in
+ let acc = List.rev path in
+ match ov, v with
+ | [x], [y] -> let out = del_value handle acc res.out x in
+ let out = add_value handle acc out y in
+ CD.Diff_cstore { res with out = out }
+ | _, _ -> let ov_set = ValueSet.of_list ov in
+ let v_set = ValueSet.of_list v in
+ let sub_vals = ValueSet.elements (ValueSet.diff ov_set v_set) in
+ let add_vals = ValueSet.elements (ValueSet.diff v_set ov_set) in
+ let out = del_values handle acc res.out sub_vals in
+ let out = add_values handle acc out add_vals in
+ CD.Diff_cstore { res with out = out }
+
+let load_config left right =
+ let h = cstore_handle_init () in
+ if not (cstore_in_config_session_handle h) then
+ (cstore_handle_free h;
+ let out = "not in config session\n" in
+ out)
+ else
+ let dcstore = CD.make_diff_cstore left right h in
+ let dcstore = CD.diff [] cstore_diff dcstore (Option.some left, Option.some right) in
+ let ret = CD.eval_result dcstore in
+ cstore_handle_free h;
+ ret.out
diff --git a/src/adapter/vyos1x_adapter.mli b/src/adapter/vyos1x_adapter.mli
new file mode 100644
index 0000000..cb40e2b
--- /dev/null
+++ b/src/adapter/vyos1x_adapter.mli
@@ -0,0 +1,16 @@
+open Vyos1x
+
+val cstore_handle_init : unit -> int
+val cstore_handle_free : int -> unit
+val cstore_in_config_session_handle : int -> bool
+val cstore_in_config_session : unit -> bool
+val cstore_set_path : int -> string list -> string
+val legacy_validate_path : int -> string list -> string
+val legacy_set_path : int -> string list -> string
+val cstore_delete_path : int -> string list -> string
+val set_path_reversed : int -> string list -> int -> string
+val delete_path_reversed : int -> string list -> int -> string
+
+val vyconf_validate_path : string list -> string option
+
+val load_config : Config_tree.t -> Config_tree.t -> string