diff options
author | Micael Karlberg <bmk@erlang.org> | 2019-11-27 10:38:26 +0100 |
---|---|---|
committer | Micael Karlberg <bmk@erlang.org> | 2019-11-27 10:38:26 +0100 |
commit | 7e2ee5d8efa9d75688d649441ad524466375c034 (patch) | |
tree | 023a3837023bde39c3c0047bbe16557780247b4b /lib/kernel/src/net.erl | |
parent | 28a90a039dc513a702fb2825076e8e4de1df4445 (diff) | |
parent | 171cf38c343e50ae7a4f28a6c1a1a58acad17407 (diff) | |
download | erlang-7e2ee5d8efa9d75688d649441ad524466375c034.tar.gz |
Merge branch 'bmk/erts/esock/20191125/add_getifaddrs_in_net/OTP-16212' into maint
Diffstat (limited to 'lib/kernel/src/net.erl')
-rw-r--r-- | lib/kernel/src/net.erl | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/kernel/src/net.erl b/lib/kernel/src/net.erl index 207f023bbe..a81666885b 100644 --- a/lib/kernel/src/net.erl +++ b/lib/kernel/src/net.erl @@ -37,6 +37,7 @@ gethostname/0, getnameinfo/1, getnameinfo/2, getaddrinfo/1, getaddrinfo/2, + getifaddrs/0, getifaddrs/1, getifaddrs/2, if_name2index/1, if_index2name/1, @@ -54,8 +55,11 @@ %% Should we define these here or refer to the prim_net module -export_type([ address_info/0, + ifaddrs/0, name_info/0, + ifaddrs_flag/0, + name_info_flags/0, name_info_flag/0, name_info_flag_ext/0, @@ -73,6 +77,24 @@ -deprecated({sleep, 1, eventually}). +-type ifaddrs_flag() :: up | broadcast | debug | loopback | pointopoint | + notrailers | running | noarp | promisc | master | slave | + multicast | portsel | automedia | dynamic. + +%% Note that not all of these fields are mandatory. +%% Actually there are (error) cases when only the name will be included. +%% And broadaddr and dstaddr are mutually exclusive! + +-type ifaddrs() :: #{name := string(), + flags := [ifaddrs_flag()], + addr := socket:sockaddr(), + netmask := socket:sockaddr(), + broadaddr := socket:sockaddr(), + dstaddr := socket:sockaddr()}. + +-type ifaddrs_filter_map() :: #{family := default | inet | inet6 | packet | all, + flags := any | [ifaddrs_flag()]}. + -type name_info_flags() :: [name_info_flag()|name_info_flag_ext()]. -type name_info_flag() :: namereqd | dgram | @@ -272,6 +294,106 @@ getaddrinfo(Host, Service) %% =========================================================================== %% +%% getifaddrs - Get interface addresses +%% + +-spec getifaddrs() -> {ok, IfAddrs} | {error, Reason} when + IfAddrs :: [ifaddrs()], + Reason :: term(). + +-ifdef(USE_ESOCK). +getifaddrs() -> + getifaddrs(getifaddrs_filter_map_default()). +-else. +getifaddrs() -> + erlang:error(notsup). +-endif. + + +-spec getifaddrs(FilterMap) -> {ok, IfAddrs} | {error, Reason} when + FilterMap :: ifaddrs_filter_map(), + IfAddrs :: [ifaddrs()], + Reason :: term(); + (Namespace) -> {ok, IfAddrs} | {error, Reason} when + Namespace :: file:filename_all(), + IfAddrs :: [ifaddrs()], + Reason :: term(). + +-ifdef(USE_ESOCK). +getifaddrs(Namespace) when is_list(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, flags := FFlags}, + #{addr := #{family := Family}, flags := Flags} = _Entry) + when (FFamily =:= default) andalso + ((Family =:= inet) orelse (Family =:= inet6)) -> + getifaddrs_filter_flags(FFlags, Flags); +getifaddrs_filter(#{family := FFamily, flags := FFlags}, + #{addr := #{family := Family}, flags := Flags} = _Entry) + when (FFamily =:= inet) andalso (Family =:= inet) -> + getifaddrs_filter_flags(FFlags, Flags); +getifaddrs_filter(#{family := FFamily, flags := FFlags}, + #{addr := #{family := Family}, flags := Flags} = _Entry) + when (FFamily =:= inet6) andalso (Family =:= inet6) -> + getifaddrs_filter_flags(FFlags, Flags); +getifaddrs_filter(#{family := FFamily, flags := FFlags}, + #{addr := #{family := Family}, flags := Flags} = _Entry) + when (FFamily =:= packet) andalso (Family =:= packet) -> + getifaddrs_filter_flags(FFlags, Flags); +getifaddrs_filter(#{family := FFamily, flags := FFlags}, + #{flags := Flags} = _Entry) + when (FFamily =:= all) -> + getifaddrs_filter_flags(FFlags, Flags); +getifaddrs_filter(_Filter, _Entry) -> + false. + + +getifaddrs_filter_flags(any, _Flags) -> + true; +getifaddrs_filter_flags(FilterFlags, Flags) -> + [] =:= (FilterFlags -- Flags). + + + +%% =========================================================================== +%% %% if_name2index - Mappings between network interface names and indexes: %% name -> idx %% |