diff options
-rw-r--r-- | lib/kernel/src/inet.erl | 78 |
1 files changed, 68 insertions, 10 deletions
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index e118382bfe..d2137065b6 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -200,7 +200,14 @@ send(Socket, Packet) -> Options :: [socket_setopt()]. setopts(Socket, Opts) -> - prim_inet:setopts(Socket, Opts). + SocketOpts = + [case Opt of + {netns,NS} -> + {netns,filename2binary(NS)}; + _ -> + Opt + end || Opt <- Opts], + prim_inet:setopts(Socket, SocketOpts). -spec getopts(Socket, Options) -> {'ok', OptionValues} | {'error', posix()} when @@ -209,7 +216,18 @@ setopts(Socket, Opts) -> OptionValues :: [socket_setopt()]. getopts(Socket, Opts) -> - prim_inet:getopts(Socket, Opts). + case prim_inet:getopts(Socket, Opts) of + {ok,OptionValues} -> + {ok, + [case OptionValue of + {netns,Bin} -> + {netns,binary2filename(Bin)}; + _ -> + OptionValue + end || OptionValue <- OptionValues]}; + Other -> + Other + end. -spec getifaddrs(Socket :: socket()) -> {'ok', [string()]} | {'error', posix()}. @@ -635,9 +653,10 @@ con_opt([Opt | Opts], R, As) -> inet -> con_opt(Opts, R, As); inet6 -> con_opt(Opts, R, As); {netns,NS} -> - case prim_inet:is_sockopt_val(netns, NS) of + BinNS = filename2binary(NS), + case prim_inet:is_sockopt_val(netns, BinNS) of true -> - con_opt(Opts, R#connect_opts { fd = [Opt] }, As); + con_opt(Opts, R#connect_opts { fd = [{netns,BinNS}] }, As); false -> {error, badarg} end; @@ -700,9 +719,10 @@ list_opt([Opt | Opts], R, As) -> inet -> list_opt(Opts, R, As); inet6 -> list_opt(Opts, R, As); {netns,NS} -> - case prim_inet:is_sockopt_val(netns, NS) of + BinNS = filename2binary(NS), + case prim_inet:is_sockopt_val(netns, BinNS) of true -> - list_opt(Opts, R#listen_opts { fd = [Opt] }, As); + list_opt(Opts, R#listen_opts { fd = [{netns,BinNS}] }, As); false -> {error, badarg} end; @@ -753,9 +773,10 @@ udp_opt([Opt | Opts], R, As) -> inet -> udp_opt(Opts, R, As); inet6 -> udp_opt(Opts, R, As); {netns,NS} -> - case prim_inet:is_sockopt_val(netns, NS) of + BinNS = filename2binary(NS), + case prim_inet:is_sockopt_val(netns, BinNS) of true -> - list_opt(Opts, R#udp_opts { fd = [Opt] }, As); + list_opt(Opts, R#udp_opts { fd = [{netns,BinNS}] }, As); false -> {error, badarg} end; @@ -829,9 +850,13 @@ sctp_opt([Opt|Opts], Mod, R, As) -> inet -> sctp_opt (Opts, Mod, R, As); % Done with inet6 -> sctp_opt (Opts, Mod, R, As); % Done with {netns,NS} -> - case prim_inet:is_sockopt_val(netns, NS) of + BinNS = filename2binary(NS), + case prim_inet:is_sockopt_val(netns, BinNS) of true -> - sctp_opt(Opts, Mod, R#sctp_opts { fd = [Opt] }, As); + sctp_opt( + Opts, Mod, + R#sctp_opts { fd = [{netns,BinNS}] }, + As); false -> {error, badarg} end; @@ -879,6 +904,39 @@ add_opt(Name, Val, Opts, As) -> end. +%% Passthrough all unknown - catch type errors later +filename2binary(List) when is_list(List) -> + OutEncoding = file:native_name_encoding(), + try unicode:characters_to_binary(List, unicode, OutEncoding) of + Bin when is_binary(Bin) -> + Bin; + _ -> + List + catch + error:badarg -> + List + end; +filename2binary(Bin) -> + Bin. + +binary2filename(Bin) -> + InEncoding = file:native_name_encoding(), + case unicode:characters_to_list(Bin, InEncoding) of + Filename when is_list(Filename) -> + Filename; + _ -> + %% For getopt/setopt of netns this should only happen if + %% a binary with wrong encoding was used when setting the + %% option, hence the user shall eat his/her own medicine. + %% + %% I.e passthrough here too for now. + %% Future usecases will most probably not want this, + %% rather Unicode error or warning + %% depending on emulator flag instead. + Bin + end. + + translate_ip(any, inet) -> {0,0,0,0}; translate_ip(loopback, inet) -> {127,0,0,1}; translate_ip(any, inet6) -> {0,0,0,0,0,0,0,0}; |