diff options
author | Serge Aleynikov <[email protected]> | 2015-12-30 13:29:34 -0500 |
---|---|---|
committer | Serge Aleynikov <[email protected]> | 2016-01-12 11:18:12 -0500 |
commit | e293ad1b08b2f937555a102e6f3b4336574773c8 (patch) | |
tree | b2eb8a92e8386e9d9589503929b2cf8afac13068 /lib/kernel/src/inet.erl | |
parent | 1237669f7c59714f0c27d3df748241dfd655c0be (diff) | |
download | otp-e293ad1b08b2f937555a102e6f3b4336574773c8.tar.gz otp-e293ad1b08b2f937555a102e6f3b4336574773c8.tar.bz2 otp-e293ad1b08b2f937555a102e6f3b4336574773c8.zip |
Assign externally open fd to gen_tcp (UDS support)
When a AF_LOCAL file descriptor is created externally (e.g. Unix
Domain Socket) and passed to `gen_tcp:listen(0, [{fd, FD}])`, the
implementation incorrectly assigned the address family to be equal
to `inet`, which in the inet_drv driver translated to AF_INET instead
of AF_LOCAL (or AF_UNIX), and an `einval` error code was returned.
This patch fixes this problem such that the file descriptors of the
`local` address family are supported in the inet:fdopen/5,
gen_tcp:connect/3, gen_tcp:listen/2, gen_udp:open/2 calls
Diffstat (limited to 'lib/kernel/src/inet.erl')
-rw-r--r-- | lib/kernel/src/inet.erl | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index b573112445..8840f05fa1 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -40,7 +40,7 @@ -export([i/0, i/1, i/2]). --export([getll/1, getfd/1, open/8, fdopen/6]). +-export([getll/1, getfd/1, open/8, fdopen/6, getfamily/1]). -export([tcp_controlling_process/2, udp_controlling_process/2, tcp_close/1, udp_close/1]). @@ -133,7 +133,7 @@ 'running' | 'multicast' | 'loopback']} | {'hwaddr', ether_address()}. --type address_family() :: 'inet' | 'inet6'. +-type address_family() :: 'inet' | 'inet6' | 'local'. -type socket_protocol() :: 'tcp' | 'udp' | 'sctp'. -type socket_type() :: 'stream' | 'dgram' | 'seqpacket'. -type stat_option() :: @@ -711,6 +711,7 @@ con_opt([Opt | Opts], #connect_opts{} = R, As) -> {tcp_module,_} -> con_opt(Opts, R, As); inet -> con_opt(Opts, R, As); inet6 -> con_opt(Opts, R, As); + local -> con_opt(Opts, R#connect_opts { family = local }, As); {netns,NS} -> BinNS = filename2binary(NS), case prim_inet:is_sockopt_val(netns, BinNS) of @@ -783,6 +784,7 @@ list_opt([Opt | Opts], #listen_opts{} = R, As) -> {tcp_module,_} -> list_opt(Opts, R, As); inet -> list_opt(Opts, R, As); inet6 -> list_opt(Opts, R, As); + local -> list_opt(Opts, R#listen_opts { family = local }, As); {netns,NS} -> BinNS = filename2binary(NS), case prim_inet:is_sockopt_val(netns, BinNS) of @@ -839,8 +841,9 @@ udp_opt([Opt | Opts], #udp_opts{} = R, As) -> binary -> udp_add(mode, binary, R, Opts, As); list -> udp_add(mode, list, R, Opts, As); {udp_module,_} -> udp_opt(Opts, R, As); - inet -> udp_opt(Opts, R, As); - inet6 -> udp_opt(Opts, R, As); + inet -> udp_opt(Opts, R, As); + inet6 -> udp_opt(Opts, R, As); + local -> udp_opt(Opts, R#udp_opts { family = local }, As); {netns,NS} -> BinNS = filename2binary(NS), case prim_inet:is_sockopt_val(netns, BinNS) of @@ -1318,7 +1321,7 @@ fdopen(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) -> Bound = Port == 0 andalso IsAnyAddr, case prim_inet:fdopen(Protocol, Family, Type, Fd, Bound) of {ok, S} -> - case prim_inet:setopts(S, Opts) of + case prim_inet:setopts(S, Opts -- [local]) of ok -> case if Bound -> @@ -1345,6 +1348,13 @@ fdopen(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) -> Error -> Error end. +-spec getfamily(list()) -> atom(). +getfamily(Options) when is_list(Options) -> + case lists:member(local, Options) of + true -> local; + false -> inet + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% socket stat %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |