From a9f92f3d024feffe23303af141dc4b13c7c17aa5 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 16 Jul 2013 09:34:54 +0200 Subject: Implement netns option for TCP and UDP --- lib/kernel/src/inet.erl | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'lib/kernel/src/inet.erl') diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 3ea530a366..0ee3234b05 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -634,6 +634,13 @@ con_opt([Opt | Opts], R, As) -> {tcp_module,_} -> con_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 + true -> + con_opt(Opts, R#connect_opts { fd = [Opt] }, As); + false -> + {error, badarg} + end; {Name,Val} when is_atom(Name) -> con_add(Name, Val, R, Opts, As); _ -> {error, badarg} end; @@ -692,6 +699,13 @@ list_opt([Opt | Opts], R, As) -> {tcp_module,_} -> list_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 + true -> + list_opt(Opts, R#listen_opts { fd = [Opt] }, As); + false -> + {error, badarg} + end; {Name,Val} when is_atom(Name) -> list_add(Name, Val, R, Opts, As); _ -> {error, badarg} end; @@ -738,6 +752,13 @@ udp_opt([Opt | Opts], R, As) -> {udp_module,_} -> udp_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 + true -> + list_opt(Opts, R#udp_opts { fd = [Opt] }, As); + false -> + {error, badarg} + end; {Name,Val} when is_atom(Name) -> udp_add(Name, Val, R, Opts, As); _ -> {error, badarg} end; @@ -1063,7 +1084,7 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) -> Result -> Result end. --spec open(Fd :: integer(), +-spec open(Fd_or_OpenOpts :: integer() | list(), Addr :: ip_address(), Port :: port_number(), Opts :: [socket_setopt()], @@ -1073,8 +1094,14 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) -> Module :: atom()) -> {'ok', socket()} | {'error', posix()}. -open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 -> - case prim_inet:open(Protocol, Family, Type) of +open(FdO, Addr, Port, Opts, Protocol, Family, Type, Module) + when is_integer(FdO), FdO < 0; + is_list(FdO) -> + OpenOpts = + if is_list(FdO) -> FdO; + true -> [] + end, + case prim_inet:open(Protocol, Family, Type, OpenOpts) of {ok,S} -> case prim_inet:setopts(S, Opts) of ok -> @@ -1097,7 +1124,8 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 -> Error -> Error end; -open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) -> +open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) + when is_integer(Fd) -> fdopen(Fd, Opts, Protocol, Family, Type, Module). bindx(S, [Addr], Port0) -> -- cgit v1.2.3 From 08ff3673e25fdd184ff92d45d4609cd423fd1e34 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 16 Jul 2013 15:14:50 +0200 Subject: Implement netns for SCTP + bugfixes --- lib/kernel/src/inet.erl | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/kernel/src/inet.erl') diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 0ee3234b05..e118382bfe 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -828,6 +828,13 @@ sctp_opt([Opt|Opts], Mod, R, As) -> {sctp_module,_} -> sctp_opt (Opts, Mod, R, As); % Done with 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 + true -> + sctp_opt(Opts, Mod, R#sctp_opts { fd = [Opt] }, As); + false -> + {error, badarg} + end; {Name,Val} -> sctp_opt (Opts, Mod, R, As, Name, Val); _ -> {error,badarg} end; -- cgit v1.2.3 From 4b4e9b8edb7c2340dbcdfd18e68981c028ede787 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 17 Jul 2013 11:14:36 +0200 Subject: Make netns option value a string --- lib/kernel/src/inet.erl | 78 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 10 deletions(-) (limited to 'lib/kernel/src/inet.erl') 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}; -- cgit v1.2.3