diff options
author | Daniil Baturin <daniil@vyos.io> | 2023-02-12 20:38:06 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-12 20:38:06 +0000 |
commit | 2caf68cb0ec8bcb9dbd3b92b3e691343196960b8 (patch) | |
tree | ce1666aa2b4608e38e4d85036e09ce3929685465 | |
parent | 4d701e3a8a48465161c003633a2f7530f5b8d99f (diff) | |
parent | 04d43b4e9b4b469c281bc3638d6979dd1b43dd18 (diff) | |
download | vyos-utils-2caf68cb0ec8bcb9dbd3b92b3e691343196960b8.tar.gz vyos-utils-2caf68cb0ec8bcb9dbd3b92b3e691343196960b8.zip |
Merge pull request #11 from jestabro/iface
T4952: add wrapper to getifaddrs for completion helper list_interfaces
-rwxr-xr-x[-rw-r--r--] | debian/rules | 7 | ||||
-rw-r--r-- | src/iface/func.ml | 1 | ||||
-rw-r--r-- | src/iface/func.mli | 1 | ||||
-rw-r--r-- | src/iface/iface.c | 38 | ||||
-rw-r--r-- | src/iface/list_interfaces.ml | 121 |
5 files changed, 168 insertions, 0 deletions
diff --git a/debian/rules b/debian/rules index d222fe8..6640e33 100644..100755 --- a/debian/rules +++ b/debian/rules @@ -12,6 +12,12 @@ override_dh_auto_build: ocamlfind ocamlopt -o _build/file-path -package fileutils -linkpkg src/file_path.ml ocamlfind ocamlopt -o _build/url -package pcre -linkpkg src/url.ml ocamlfind ocamlopt -o _build/validate-value -package pcre,unix,containers -linkpkg src/validate_value.ml +# list_interfaces + ocamlfind ocamlopt -c src/iface/func.mli + ocamlfind ocamlopt -I src/iface -c src/iface/func.ml + ocamlfind ocamlopt -I src/iface -c src/iface/iface.c + ocamlfind ocamlopt -I src/iface -package pcre -c src/iface/list_interfaces.ml + ocamlfind ocamlopt -I src/iface func.cmx iface.o list_interfaces.cmx -o _build/list_interfaces -package pcre -linkpkg override_dh_auto_install: mkdir -p $(DIR)/usr/libexec/vyos/validators @@ -19,6 +25,7 @@ override_dh_auto_install: cp _build/validate-value $(DIR)/usr/libexec/vyos/ cp _build/file-path $(DIR)/usr/libexec/vyos/validators cp _build/url $(DIR)/usr/libexec/vyos/validators + cp _build/list_interfaces $(DIR)/usr/libexec/vyos/completion override_dh_auto_test: echo "No tests yet" diff --git a/src/iface/func.ml b/src/iface/func.ml new file mode 100644 index 0000000..13e1860 --- /dev/null +++ b/src/iface/func.ml @@ -0,0 +1 @@ +external list_interfaces: unit -> string list = "interface_list" diff --git a/src/iface/func.mli b/src/iface/func.mli new file mode 100644 index 0000000..b16d373 --- /dev/null +++ b/src/iface/func.mli @@ -0,0 +1 @@ +external list_interfaces : unit -> string list = "interface_list" diff --git a/src/iface/iface.c b/src/iface/iface.c new file mode 100644 index 0000000..bf2f025 --- /dev/null +++ b/src/iface/iface.c @@ -0,0 +1,38 @@ +/* + * Simple wrapper of getifaddrs for OCaml list of interfaces + */ +#include <ifaddrs.h> +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/alloc.h> + +CAMLprim value interface_list(value unit) { + struct ifaddrs *ifaddr; + struct ifaddrs *ifa; + + CAMLparam1( unit ); + CAMLlocal2( cli, cons ); + + cli = Val_emptylist; + + if (getifaddrs(&ifaddr) == -1) { + CAMLreturn(cli); + } + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_name == NULL) + continue; + + CAMLlocal1( ml_s ); + cons = caml_alloc(2, 0); + + ml_s = caml_copy_string(ifa->ifa_name); + Store_field( cons, 0, ml_s ); + Store_field( cons, 1, cli ); + + cli = cons; + } + + freeifaddrs(ifaddr); + + CAMLreturn(cli); +} diff --git a/src/iface/list_interfaces.ml b/src/iface/list_interfaces.ml new file mode 100644 index 0000000..2daa509 --- /dev/null +++ b/src/iface/list_interfaces.ml @@ -0,0 +1,121 @@ +(* + *) +let intf_type = ref "" +let broadcast = ref false +let bridgeable = ref false +let bondable = ref false + +let args = [ + ("--type", Arg.String (fun s -> intf_type := s), "List interfaces of specified type"); + ("--broadcast", Arg.Unit (fun () -> broadcast := true), "List broadcast interfaces"); + ("--bridgeable", Arg.Unit (fun () -> bridgeable := true), "List bridgeable interfaces"); + ("--bondable", Arg.Unit (fun () -> bondable := true), "List bondable interfaces"); +] +let usage = Printf.sprintf "Usage: %s [OPTIONS] <number>" Sys.argv.(0) + +let () = Arg.parse args (fun _ -> ()) usage + +let type_to_prefix it = + match it with + | "" -> "" + | "bonding" -> "bond" + | "bridge" -> "br" + | "dummy" -> "dum" + | "ethernet" -> "eth" + | "geneve" -> "gnv" + | "input" -> "ifb" + | "l2tpeth" -> "l2tpeth" + | "loopback" -> "lo" + | "macsec" -> "macsec" + | "openvpn" -> "vtun" + | "pppoe" -> "pppoe" + | "pseudo-ethernet" -> "peth" + | "sstpc" -> "sstpc" + | "tunnel" -> "tun" + | "virtual-ethernet" -> "veth" + | "vti" -> "vti" + | "vxlan" -> "vxlan" + | "wireguard" -> "wg" + | "wireless" -> "wlan" + | "wwan" -> "wwan" + | _ -> "" + +(* filter_section to match the constraint of python.vyos.ifconfig.section + *) +let rx = Pcre.regexp {|\d(\d|v|\.)*$|} + +let filter_section s = + let r = Pcre.qreplace_first ~rex:rx ~templ:"" s in + match r with + |"bond"|"br"|"dum"|"eth"|"gnv"|"ifb"|"l2tpeth"|"lo"|"macsec" -> true + |"peth"|"pppoe"|"sstpc"|"tun"|"veth"|"vti"|"vtun"|"vxlan"|"wg"|"wlan"|"wwan" -> true + | _ -> false + +let filter_from_prefix p s = + let pattern = Printf.sprintf "^%s(.*)$" p + in + try + let _ = Pcre.exec ~pat:pattern s in + true + with Not_found -> false + +let filter_from_type it = + let pre = type_to_prefix it in + match pre with + | "" -> None + | _ -> Some (filter_from_prefix pre) + +let filter_broadcast s = + let pattern = {|^(bond|br|eth)(.*)$|} + in + try + let _ = Pcre.exec ~pat:pattern s in + true + with Not_found -> false + +let filter_bridgeable s = + let pattern = {|^(bond|eth|gnv|l2tpeth|lo|tun|veth|vtun|wlan)(.*)$|} + in + try + let _ = Pcre.exec ~pat:pattern s in + true + with Not_found -> false + +let filter_bondable s = + let pattern = {|^(eth)(.*)$|} + in + try + let _ = Pcre.exec ~pat:pattern s in + true + with Not_found -> false + +let get_interfaces = + let intf_type = !intf_type in + let fltr = + if String.length(intf_type) > 0 then + filter_from_type intf_type + else None + in + let l = Func.list_interfaces () in + let res = List.sort_uniq compare l in + let res = + if !broadcast then List.filter filter_broadcast res + else res + in + let res = + if !bridgeable then List.filter filter_bridgeable res + else res + in + let res = + if !bondable then List.filter filter_bondable res + else res + in + let res = List.filter filter_section res in + match fltr with + | Some f -> List.filter f res + | None -> res + +let () = + let res = get_interfaces in + List.iter (Printf.printf "%s ") res; + Printf.printf "\n" |