aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml21
-rw-r--r--lib/kernel/doc/src/gen_udp.xml19
-rw-r--r--lib/kernel/doc/src/inet.xml53
-rw-r--r--lib/kernel/src/gen_tcp.erl12
-rw-r--r--lib/kernel/src/gen_udp.erl10
-rw-r--r--lib/kernel/src/inet.erl91
-rw-r--r--lib/kernel/src/inet_int.hrl1
-rw-r--r--lib/kernel/src/local_tcp.erl10
-rw-r--r--lib/kernel/src/local_udp.erl9
9 files changed, 166 insertions, 60 deletions
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index b75d42d198..88135ea43d 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -153,17 +153,17 @@ do_recv(Sock, Bs) ->
<c><anno>Address</anno></c> can be a hostname or an IP address.</p>
<p>The following options are available:</p>
<taglist>
- <tag><c>{ip, ip_address()}</c></tag>
+ <tag><c>{ip, Address}</c></tag>
<item><p>If the host has many network interfaces, this option
specifies which one to use.</p></item>
- <tag><c>{ifaddr, ip_address()}</c></tag>
- <item><p>Same as <c>{ip, ip_address()}</c>. If the host has many
+ <tag><c>{ifaddr, Address}</c></tag>
+ <item><p>Same as <c>{ip, Address}</c>. If the host has many
network interfaces, this option specifies which one to use.</p>
</item>
<tag><c>{fd, integer() >= 0}</c></tag>
<item><p>If a socket has somehow been connected without using
<c>gen_tcp</c>, use this option to pass the file descriptor
- for it. If <c>{ip, ip_address()}</c> and/or
+ for it. If <c>{ip, Address}</c> and/or
<c>{port, port_number()}</c> is combined with this option, the
<c>fd</c> is bound to the specified interface and port before
connecting. If these options are not specified, it is assumed that
@@ -175,9 +175,10 @@ do_recv(Sock, Bs) ->
<tag><c>local</c></tag>
<item>
<p>
- Sets up the socket for local address family. This option is only
- valid together with <c>{fd, integer()}</c> when the file descriptor
- is of local address family (e.g. a Unix Domain Socket)
+ Sets up a Unix Domain Socket. See
+ <seealso marker="inet#type-local_address">
+ <c>inet:local_address()</c>
+ </seealso>
</p>
</item>
<tag><c>{port, Port}</c></tag>
@@ -254,7 +255,7 @@ do_recv(Sock, Bs) ->
<item><p><c>B</c> is an integer &gt;= <c>0</c>. The backlog value
defines the maximum length that the queue of pending connections
can grow to. Defaults to <c>5</c>.</p></item>
- <tag><c>{ip, ip_address()}</c></tag>
+ <tag><c>{ip, Address}</c></tag>
<item><p>If the host has many network interfaces, this option
specifies which one to listen on.</p></item>
<tag><c>{port, Port}</c></tag>
@@ -263,8 +264,8 @@ do_recv(Sock, Bs) ->
<item><p>If a socket has somehow been connected without using
<c>gen_tcp</c>, use this option to pass the file
descriptor for it.</p></item>
- <tag><c>{ifaddr, ip_address()}</c></tag>
- <item><p>Same as <c>{ip, ip_address()}</c>. If the host has many
+ <tag><c>{ifaddr, Address}</c></tag>
+ <item><p>Same as <c>{ip, Address}</c>. If the host has many
network interfaces, this option specifies which one to use.</p>
</item>
<tag><c>inet6</c></tag>
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index ca9d9c978c..3f88a0272d 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -85,11 +85,11 @@
<item><p>Received <c>Packet</c> is delivered as a list.</p></item>
<tag><c>binary</c></tag>
<item><p>Received <c>Packet</c> is delivered as a binary.</p></item>
- <tag><c>{ip, ip_address()}</c></tag>
+ <tag><c>{ip, Address}</c></tag>
<item><p>If the host has many network interfaces, this option
specifies which one to use.</p></item>
- <tag><c>{ifaddr, ip_address()}</c></tag>
- <item><p>Same as <c>{ip, ip_address()}</c>. If the host has many
+ <tag><c>{ifaddr, Address}</c></tag>
+ <item><p>Same as <c>{ip, Address}</c>. If the host has many
network interfaces, this option specifies which one to
use.</p></item>
<tag><c>{fd, integer() >= 0}</c></tag>
@@ -107,9 +107,10 @@
<tag><c>local</c></tag>
<item>
<p>
- Sets up the socket for local address family. This option is only
- valid together with <c>{fd, integer()}</c> when the file descriptor
- is of local address family (e.g. a Unix Domain Socket)
+ Sets up a Unix Domain Socket. See
+ <seealso marker="inet#type-local_address">
+ <c>inet:local_address()</c>
+ </seealso>
</p>
</item>
<tag><c>{udp_module, module()}</c></tag>
@@ -184,8 +185,10 @@
<name name="send" arity="4"/>
<fsummary>Send a packet.</fsummary>
<desc>
- <p>Sends a packet to the specified address and port. Argument
- <c><anno>Address</anno></c> can be a hostname or an IP address.</p>
+ <p>
+ Sends a packet to the specified address and port. Argument
+ <c><anno>Address</anno></c> can be a hostname or a socket address.
+ </p>
</desc>
</func>
</funcs>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 5ff167bcb3..c0dce2f50c 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -118,6 +118,59 @@ fe80::204:acff:fe17:bf38
<name name="port_number"/>
</datatype>
<datatype>
+ <name name="local_address"/>
+ <desc>
+ <p>
+ This address family only works on Unix-like systems.
+ </p>
+ <p>
+ <c><anno>File</anno></c> is normally a file pathname
+ in a local filesystem. It is limited in length by the
+ operating system, traditionally to 108 bytes.
+ </p>
+ <p>
+ A <c>binary()</c> is passed as is to the operating system,
+ but a <c>string()</c> is encoded according to the
+ <seealso marker="file#native_name_encoding/0">
+ system filename encoding mode.
+ </seealso>
+ </p>
+ <p>
+ Other addresses are possible, for example Linux implements
+ "Abstract Addresses". See the documentation for
+ Unix Domain Sockets on your system,
+ normally <c>unix</c> in manual section 7.
+ </p>
+ <p>
+ In most API functions where you can use
+ this address family the port number must be <c>0</c>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="socket_address"/>
+ </datatype>
+ <datatype>
+ <name name="returned_non_ip_address"/>
+ <desc>
+ <p>
+ Addresses besides
+ <seealso marker="#type-ip_address">
+ <c>ip_address()</c>
+ </seealso>
+ ones that are returned from socket API functions.
+ See in particular
+ <seealso marker="#type-local_address">
+ <c>local_address()</c>.
+ </seealso>
+ The <c>unspec</c> family corresponds to AF_UNSPEC and can
+ occur if the other side has no socket address.
+ The <c>undefined</c> family can only occur in the unlikely
+ event of an address family that the VM does not recognize.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="posix"/>
<desc>
<p>An atom that is named from the POSIX error codes used in Unix,
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index 2b3afcd44c..1a21541b7c 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -96,17 +96,17 @@
tos |
ipv6_v6only.
-type connect_option() ::
- {ip, inet:ip_address()} |
+ {ip, inet:socket_address()} |
{fd, Fd :: non_neg_integer()} |
- {ifaddr, inet:ip_address()} |
+ {ifaddr, inet:socket_address()} |
inet:address_family() |
{port, inet:port_number()} |
{tcp_module, module()} |
option().
-type listen_option() ::
- {ip, inet:ip_address()} |
+ {ip, inet:socket_address()} |
{fd, Fd :: non_neg_integer()} |
- {ifaddr, inet:ip_address()} |
+ {ifaddr, inet:socket_address()} |
inet:address_family() |
{port, inet:port_number()} |
{backlog, B :: non_neg_integer()} |
@@ -122,7 +122,7 @@
%%
-spec connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} when
- Address :: inet:ip_address() | inet:hostname(),
+ Address :: inet:socket_address() | inet:hostname(),
Port :: inet:port_number(),
Options :: [connect_option()],
Socket :: socket(),
@@ -133,7 +133,7 @@ connect(Address, Port, Opts) ->
-spec connect(Address, Port, Options, Timeout) ->
{ok, Socket} | {error, Reason} when
- Address :: inet:ip_address() | inet:hostname(),
+ Address :: inet:socket_address() | inet:hostname(),
Port :: inet:port_number(),
Options :: [connect_option()],
Timeout :: timeout(),
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 2227bb3562..98d2f0bcfb 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -92,9 +92,9 @@ open(Port) ->
-spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when
Port :: inet:port_number(),
Opts :: [Option],
- Option :: {ip, inet:ip_address()}
+ Option :: {ip, inet:socket_address()}
| {fd, non_neg_integer()}
- | {ifaddr, inet:ip_address()}
+ | {ifaddr, inet:socket_address()}
| inet:address_family()
| {port, inet:port_number()}
| option(),
@@ -114,7 +114,7 @@ close(S) ->
-spec send(Socket, Address, Port, Packet) -> ok | {error, Reason} when
Socket :: socket(),
- Address :: inet:ip_address() | inet:hostname(),
+ Address :: inet:socket_address() | inet:hostname(),
Port :: inet:port_number(),
Packet :: iodata(),
Reason :: not_owner | inet:posix().
@@ -148,7 +148,7 @@ send(S, Packet) when is_port(S) ->
{ok, {Address, Port, Packet}} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
- Address :: inet:ip_address(),
+ Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
@@ -166,7 +166,7 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
Socket :: socket(),
Length :: non_neg_integer(),
Timeout :: timeout(),
- Address :: inet:ip_address(),
+ Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index de43ea792b..20c64a39ca 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -73,8 +73,9 @@
-export([start_timer/1, timeout/1, timeout/2, stop_timer/1]).
-export_type([address_family/0, hostent/0, hostname/0, ip4_address/0,
- ip6_address/0, ip_address/0, posix/0, socket/0,
- port_number/0]).
+ ip6_address/0, ip_address/0, port_number/0,
+ local_address/0, socket_address/0, returned_non_ip_address/0,
+ posix/0, socket/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -98,6 +99,11 @@
0..65535,0..65535,0..65535,0..65535}.
-type ip_address() :: ip4_address() | ip6_address().
-type port_number() :: 0..65535.
+-type local_address() :: {local, File :: binary() | string()}.
+-type returned_non_ip_address() ::
+ {local, binary()} |
+ {unspec, <<>>} |
+ {undefined, any()}.
-type posix() :: exbadport | exbadseq | file:posix().
-type socket() :: port().
@@ -138,7 +144,7 @@
-type socket_protocol() :: 'tcp' | 'udp' | 'sctp'.
-type socket_type() :: 'stream' | 'dgram' | 'seqpacket'.
-type socket_address() ::
- ip_address() | {address_family(), any()} | 'any' | 'loopback'.
+ ip_address() | 'any' | 'loopback' | local_address().
-type stat_option() ::
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
@@ -163,26 +169,33 @@ close(Socket) ->
end.
--spec peername(Socket) -> {ok, {Address, Port}} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec peername(Socket :: socket()) ->
+ {ok,
+ {ip_address(), port_number()} |
+ returned_non_ip_address()} |
+ {error, posix()}.
peername(Socket) ->
prim_inet:peername(Socket).
--spec setpeername(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
- 'ok' | {'error', any()}.
+-spec setpeername(
+ Socket :: socket(),
+ Address ::
+ {ip_address() | 'any' | 'loopback',
+ port_number()} |
+ socket_address()) ->
+ 'ok' | {'error', any()}.
setpeername(Socket, {IP,Port}) ->
prim_inet:setpeername(Socket, {IP,Port});
setpeername(Socket, undefined) ->
prim_inet:setpeername(Socket, undefined).
--spec peernames(Socket) -> {ok, [{Address, Port}]} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec peernames(Socket :: socket()) ->
+ {ok,
+ [{ip_address(), port_number()} |
+ returned_non_ip_address()]} |
+ {error, posix()}.
peernames(Socket) ->
prim_inet:peernames(Socket).
@@ -198,15 +211,21 @@ peernames(Socket, Assoc) ->
prim_inet:peernames(Socket, Assoc).
--spec sockname(Socket) -> {ok, {Address, Port}} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec sockname(Socket :: socket()) ->
+ {ok,
+ {ip_address(), port_number()} |
+ returned_non_ip_address()} |
+ {error, posix()}.
sockname(Socket) ->
prim_inet:sockname(Socket).
--spec setsockname(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
+-spec setsockname(
+ Socket :: socket(),
+ Address ::
+ {ip_address() | 'any' | 'loopback',
+ port_number()} |
+ socket_address()) ->
'ok' | {'error', any()}.
setsockname(Socket, {IP,Port}) ->
@@ -214,10 +233,11 @@ setsockname(Socket, {IP,Port}) ->
setsockname(Socket, undefined) ->
prim_inet:setsockname(Socket, undefined).
--spec socknames(Socket) -> {ok, [{Address, Port}]} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec socknames(Socket :: socket()) ->
+ {ok,
+ [{ip_address(), port_number()} |
+ returned_non_ip_address()]} |
+ {error, posix()}.
socknames(Socket) ->
prim_inet:socknames(Socket).
@@ -1296,7 +1316,17 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
end.
-spec open(Fd_or_OpenOpts :: integer() | list(),
- Addr :: socket_address(),
+ Addr ::
+ socket_address() |
+ {ip_address() | 'any' | 'loopback', % Unofficial
+ port_number()} |
+ {inet, % Unofficial
+ {ip4_address() | 'any' | 'loopback',
+ port_number()}} |
+ {inet6, % Unofficial
+ {ip6_address() | 'any' | 'loopback',
+ port_number()}} |
+ undefined, % Internal - no bind()
Port :: port_number(),
Opts :: [socket_setopt()],
Protocol :: socket_protocol(),
@@ -1316,11 +1346,16 @@ open(FdO, Addr, Port, Opts, Protocol, Family, Type, Module)
{ok,S} ->
case prim_inet:setopts(S, Opts) of
ok ->
- case if is_list(Addr) ->
- bindx(S, Addr, Port);
- true ->
- prim_inet:bind(S, Addr, Port)
- end of
+ case
+ case Addr of
+ undefined ->
+ {ok, undefined};
+ _ when is_list(Addr) ->
+ bindx(S, Addr, Port);
+ _ ->
+ prim_inet:bind(S, Addr, Port)
+ end
+ of
{ok, _} ->
inet_db:register_socket(S, Module),
{ok,S};
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 32d09fb63c..c8a8962e78 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -25,6 +25,7 @@
%%
%% family codes to open
+-define(INET_AF_UNSPEC, 0).
-define(INET_AF_INET, 1).
-define(INET_AF_INET6, 2).
-define(INET_AF_ANY, 3). % Fake for ANY in any address family
diff --git a/lib/kernel/src/local_tcp.erl b/lib/kernel/src/local_tcp.erl
index 64085ec42e..e3c67dfbb7 100644
--- a/lib/kernel/src/local_tcp.erl
+++ b/lib/kernel/src/local_tcp.erl
@@ -107,8 +107,14 @@ do_connect(Addr = {?FAMILY, _}, 0, Opts, Time) ->
when tuple_size(BAddr) =:= 2, element(1, BAddr) =:= ?FAMILY;
BAddr =:= any ->
case inet:open(
- Fd, BAddr, 0, SockOpts,
- ?PROTO, ?FAMILY, ?TYPE, ?MODULE) of
+ Fd,
+ case BAddr of
+ any ->
+ undefined;
+ _ ->
+ BAddr
+ end,
+ 0, SockOpts, ?PROTO, ?FAMILY, ?TYPE, ?MODULE) of
{ok, S} ->
case prim_inet:connect(S, Addr, 0, Time) of
ok -> {ok,S};
diff --git a/lib/kernel/src/local_udp.erl b/lib/kernel/src/local_udp.erl
index ebb4d2b33f..481a8c4910 100644
--- a/lib/kernel/src/local_udp.erl
+++ b/lib/kernel/src/local_udp.erl
@@ -59,7 +59,14 @@ open(0, Opts) ->
when tuple_size(BAddr) =:= 2, element(1, BAddr) =:= ?FAMILY;
BAddr =:= any ->
inet:open(
- Fd, BAddr, 0, SockOpts, ?PROTO, ?FAMILY, ?TYPE, ?MODULE);
+ Fd,
+ case BAddr of
+ any ->
+ undefined;
+ _ ->
+ BAddr
+ end,
+ 0, SockOpts, ?PROTO, ?FAMILY, ?TYPE, ?MODULE);
{ok, _} -> exit(badarg)
end.