summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@vyos.io>2023-02-12 20:38:06 +0000
committerGitHub <noreply@github.com>2023-02-12 20:38:06 +0000
commit2caf68cb0ec8bcb9dbd3b92b3e691343196960b8 (patch)
treece1666aa2b4608e38e4d85036e09ce3929685465
parent4d701e3a8a48465161c003633a2f7530f5b8d99f (diff)
parent04d43b4e9b4b469c281bc3638d6979dd1b43dd18 (diff)
downloadvyos-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/rules7
-rw-r--r--src/iface/func.ml1
-rw-r--r--src/iface/func.mli1
-rw-r--r--src/iface/iface.c38
-rw-r--r--src/iface/list_interfaces.ml121
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"