diff options
Diffstat (limited to 'erts/preloaded/src/socket.erl')
-rw-r--r-- | erts/preloaded/src/socket.erl | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index 5695e45ac5..acda4e3811 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -94,6 +94,8 @@ ip_mreq/0, ip_mreq_source/0, ip_pmtudisc/0, + ip_msfilter_mode/0, + ip_msfilter/0, ipv6_mreq/0, ipv6_pmtudisc/0, sctp_event_subscribe/0, @@ -196,6 +198,17 @@ -type ip_pmtudisc() :: want | dont | do | probe. +%% multiaddr: Multicast group address +%% interface: Address of local interface +%% mode: Filter mode +%% slist: List of source addresses +-type ip_msfilter_mode() :: include | exclude. + +-type ip_msfilter() :: #{multiaddr => ip4_address(), + interface => ip4_address(), + mode => ip_msfilter_mode(), + slist => [ip4_address()]}. + -type ipv6_mreq() :: #{multiaddr := ip6_address(), interface := non_neg_integer()}. @@ -604,13 +617,13 @@ -define(SOCKET_OPT_IP_ADD_MEMBERSHIP, 1). -define(SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP, 2). -define(SOCKET_OPT_IP_BLOCK_SOURCE, 3). -%% -define(SOCKET_OPT_IP_DONTFRAG, 4). +%% -define(SOCKET_OPT_IP_DONTFRAG, 4). % FreeBSD -define(SOCKET_OPT_IP_DROP_MEMBERSHIP, 5). -define(SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP, 6). -define(SOCKET_OPT_IP_FREEBIND, 7). %% -define(SOCKET_OPT_IP_HDRINCL, 8). -define(SOCKET_OPT_IP_MINTTL, 9). -%% -define(SOCKET_OPT_IP_MSFILTER, 10). +-define(SOCKET_OPT_IP_MSFILTER, 10). -define(SOCKET_OPT_IP_MTU, 11). -define(SOCKET_OPT_IP_MTU_DISCOVER, 12). -define(SOCKET_OPT_IP_MULTICAST_ALL, 13). @@ -2197,6 +2210,18 @@ enc_setopt_value(ip, freebind, V, _D, _T, _P) when is_boolean(V) -> V; enc_setopt_value(ip, minttl, V, _D, _T, _P) when is_integer(V) -> V; +enc_setopt_value(ip, msfilter, null = V, _D, _T, _P) -> + V; +enc_setopt_value(ip, msfilter, #{multiaddr := MA, + interface := IF, + fmode := FMode, + slist := SL} = V, _D, _T, _P) + when (is_tuple(MA) andalso (size(MA) =:= 4)) andalso + (is_tuple(IF) andalso (size(IF) =:= 4)) andalso + ((FMode =:= include) orelse (FMode =:= exclude)) andalso + is_list(SL) -> + ensure_ip_msfilter_slist(SL), + V; enc_setopt_value(ip, mtu_discover, V, _D, _T, _P) when (V =:= want) orelse (V =:= dont) orelse @@ -2656,8 +2681,8 @@ enc_sockopt_key(ip = L, hdrincl = Opt, _Dir, _D, raw = _T, _P) -> %% FreeBSD only? enc_sockopt_key(ip = _L, minttl = _Opt, _Dir, _D, raw = _T, _P) -> ?SOCKET_OPT_IP_MINTTL; -enc_sockopt_key(ip = L, msfilter = Opt, _Dir, _D, _T, _P) -> - not_supported({L, Opt}); +enc_sockopt_key(ip = _L, msfilter = _Opt, set = _Dir, _D, _T, _P) -> + ?SOCKET_OPT_IP_MSFILTER; enc_sockopt_key(ip = _L, mtu = _Opt, get = _Dir, _D, _T, _P) -> ?SOCKET_OPT_IP_MTU; enc_sockopt_key(ip = _L, mtu_discover = _Opt, _Dir, _D, _T, _P) -> @@ -2922,6 +2947,13 @@ enc_shutdown_how(read_write) -> %% %% =========================================================================== +ensure_ip_msfilter_slist(SL) -> + EnsureSA = fun(SA) when is_tuple(SA) andalso (size(SA) =:= 4) -> ok; + (_) -> einval() + end, + lists:foreach(EnsureSA, SL). + + ensure_sockaddr(#{family := inet} = SockAddr) -> maps:merge(?SOCKADDR_IN4_DEFAULTS, SockAddr); ensure_sockaddr(#{family := inet6} = SockAddr) -> |