summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicael Karlberg <bmk@erlang.org>2019-11-19 17:06:50 +0100
committerMicael Karlberg <bmk@erlang.org>2019-11-25 18:28:27 +0100
commite83a4a1c6ab164c39e3d8aa353119725924ca08c (patch)
treed44aed8b7e6ef2f7a1eed964d5d2aead4844b05f
parentd1c6ba0ab9e9379cf5e3aa058e6b9893d0d06307 (diff)
downloaderlang-e83a4a1c6ab164c39e3d8aa353119725924ca08c.tar.gz
[enet] Add first version of filter arg to getifaddrs
Added the function getifaddrs/1,2 that takes a filter argument, which makes it possible to filter out only those interfaces that "belong" to that specific (socket) address family. OTP-16212
-rw-r--r--lib/kernel/src/net.erl62
1 files changed, 59 insertions, 3 deletions
diff --git a/lib/kernel/src/net.erl b/lib/kernel/src/net.erl
index e2ccbdc9c5..331582c47a 100644
--- a/lib/kernel/src/net.erl
+++ b/lib/kernel/src/net.erl
@@ -37,7 +37,7 @@
gethostname/0,
getnameinfo/1, getnameinfo/2,
getaddrinfo/1, getaddrinfo/2,
- getifaddrs/0, getifaddrs/1,
+ getifaddrs/0, getifaddrs/1, getifaddrs/2,
if_name2index/1,
if_index2name/1,
@@ -94,6 +94,9 @@
broadaddr := socket:sockaddr(),
dstaddr := socket:sockaddr()}.
+-type ifaddrs_filter_map() :: #{family := default | inet | inet6 | all,
+ flags := any | ifaddrs_flags()}.
+
-type name_info_flags() :: [name_info_flag()|name_info_flag_ext()].
-type name_info_flag() :: namereqd |
dgram |
@@ -287,7 +290,7 @@ getaddrinfo(Host, Service)
-ifdef(USE_ESOCK).
getifaddrs() ->
- prim_net:getifaddrs(#{}).
+ getifaddrs(getifaddrs_filter_map_default()).
-else.
getifaddrs() ->
erlang:error(notsup).
@@ -297,18 +300,71 @@ getifaddrs() ->
-spec getifaddrs(Namespace) -> {ok, IfAddrs} | {error, Reason} when
Namespace :: file:filename_all(),
IfAddrs :: [ifaddrs()],
+ Reason :: term();
+ (FilterMap) -> {ok, IfAddrs} | {error, Reason} when
+ FilterMap :: ifaddrs_filter_map(),
+ IfAddrs :: [ifaddrs()],
Reason :: term().
-ifdef(USE_ESOCK).
getifaddrs(Namespace) when is_list(Namespace) ->
- prim_net:getifaddrs(#{netns => Namespace}).
+ prim_net:getifaddrs(#{netns => Namespace});
+getifaddrs(FilterMap) when is_map(FilterMap) ->
+ do_getifaddrs(getifaddrs_filter_map(FilterMap),
+ fun() -> prim_net:getifaddrs(#{}) end).
-else.
-dialyzer({nowarn_function, getifaddrs/1}).
getifaddrs(Namespace) when is_list(Namespace) ->
+ erlang:error(notsup);
+getifaddrs(FilterMap) when is_map(FilterMap) ->
erlang:error(notsup).
-endif.
+-spec getifaddrs(FilterMap, Namespace) -> {ok, IfAddrs} | {error, Reason} when
+ FilterMap :: ifaddrs_filter_map(),
+ Namespace :: file:filename_all(),
+ IfAddrs :: [ifaddrs()],
+ Reason :: term().
+
+getifaddrs(FilterMap, Namespace)
+ when is_map(FilterMap) andalso is_list(Namespace) ->
+ do_getifaddrs(getifaddrs_filter_map(FilterMap),
+ fun() -> getifaddrs(Namespace) end).
+
+do_getifaddrs(FilterMap, GetIfAddrs) ->
+ case GetIfAddrs() of
+ {ok, IfAddrs0} ->
+ Filter = fun(Elem) -> getifaddrs_filter(FilterMap, Elem) end,
+ {ok, lists:filtermap(Filter, IfAddrs0)};
+ {error, _} = ERROR ->
+ ERROR
+ end.
+
+getifaddrs_filter_map(FilterMap) ->
+ maps:merge(getifaddrs_filter_map_default(), FilterMap).
+
+getifaddrs_filter_map_default() ->
+ #{family => default, flags => any}.
+
+getifaddrs_filter(#{family := FFamily},
+ #{addr := #{family := Family}} = _Entry)
+ when (FFamily =:= default) andalso
+ ((Family =:= inet) orelse (Family =:= inet6)) ->
+ true;
+getifaddrs_filter(#{family := FFamily},
+ #{addr := #{family := Family}} = _Entry)
+ when (FFamily =:= inet) andalso (Family =:= inet) ->
+ true;
+getifaddrs_filter(#{family := FFamily},
+ #{addr := #{family := Family}} = _Entry)
+ when (FFamily =:= inet6) andalso (Family =:= inet6) ->
+ true;
+getifaddrs_filter(#{family := FFamily}, _Entry)
+ when (FFamily =:= all) ->
+ true;
+getifaddrs_filter(_Filter, _Entry) ->
+ false.
%% ===========================================================================