diff options
author | Daniil Baturin <daniil@baturin.org> | 2024-11-07 18:02:08 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-07 18:02:08 +0000 |
commit | 196fdd7fdf6dcf751b7364c59e34278bfd0193e3 (patch) | |
tree | cfeff0991481c8281e24cf1698b20a76854059a4 /src/adapter | |
parent | dd9271b4304c6b1a5a2576821d1b2b8fd3aa6bf5 (diff) | |
parent | 9b90d3cc4da72c13ef4270150e4b547ff03fc813 (diff) | |
download | vyconf-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.ml | 30 | ||||
-rw-r--r-- | src/adapter/vy_load_config.ml | 47 | ||||
-rw-r--r-- | src/adapter/vy_set.ml | 77 | ||||
-rw-r--r-- | src/adapter/vyos1x_adapter.ml | 140 | ||||
-rw-r--r-- | src/adapter/vyos1x_adapter.mli | 16 |
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 |